Fix #4347: Remove leading and trailing spaces in title (#5141)

* Update method to remove leading whitespace

* Update test cases testing remove whitespace method

* Remove unused whitespace check method

* Add comment about use of strip and trim in dealing with whitespace
This commit is contained in:
Chan Jun Da 2023-02-10 15:31:45 +08:00 committed by GitHub
parent 654a0fce33
commit f85efeba97
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 45 additions and 42 deletions

View file

@ -1,7 +1,6 @@
package fr.free.nrw.commons.upload; package fr.free.nrw.commons.upload;
import android.app.Dialog; import android.app.Dialog;
import android.content.Intent;
import android.text.Editable; import android.text.Editable;
import android.text.InputFilter; import android.text.InputFilter;
import android.text.TextUtils; import android.text.TextUtils;
@ -23,7 +22,6 @@ import butterknife.BindView;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import com.google.android.material.textfield.TextInputLayout; import com.google.android.material.textfield.TextInputLayout;
import fr.free.nrw.commons.R; import fr.free.nrw.commons.R;
import fr.free.nrw.commons.contributions.MainActivity;
import fr.free.nrw.commons.recentlanguages.Language; import fr.free.nrw.commons.recentlanguages.Language;
import fr.free.nrw.commons.recentlanguages.RecentLanguagesAdapter; import fr.free.nrw.commons.recentlanguages.RecentLanguagesAdapter;
import fr.free.nrw.commons.recentlanguages.RecentLanguagesDao; import fr.free.nrw.commons.recentlanguages.RecentLanguagesDao;
@ -32,10 +30,8 @@ import fr.free.nrw.commons.utils.AbstractTextWatcher;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Objects; import java.util.Objects;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.inject.Inject;
import timber.log.Timber; import timber.log.Timber;
public class UploadMediaDetailAdapter extends RecyclerView.Adapter<UploadMediaDetailAdapter.ViewHolder> { public class UploadMediaDetailAdapter extends RecyclerView.Adapter<UploadMediaDetailAdapter.ViewHolder> {
@ -198,7 +194,8 @@ public class UploadMediaDetailAdapter extends RecyclerView.Adapter<UploadMediaDe
removeButton.setOnClickListener(v -> removeDescription(uploadMediaDetail, position)); removeButton.setOnClickListener(v -> removeDescription(uploadMediaDetail, position));
captionListener = new AbstractTextWatcher( captionListener = new AbstractTextWatcher(
captionText -> uploadMediaDetails.get(position).setCaptionText(convertIdeographicSpaceToLatinSpace(removeTrailingWhitespace(captionText)))); captionText -> uploadMediaDetails.get(position).setCaptionText(convertIdeographicSpaceToLatinSpace(
removeLeadingAndTrailingWhitespace(captionText))));
descriptionListener = new AbstractTextWatcher( descriptionListener = new AbstractTextWatcher(
descriptionText -> uploadMediaDetails.get(position).setDescriptionText(descriptionText)); descriptionText -> uploadMediaDetails.get(position).setDescriptionText(descriptionText));
captionItemEditText.addTextChangedListener(captionListener); captionItemEditText.addTextChangedListener(captionListener);
@ -421,28 +418,35 @@ public class UploadMediaDetailAdapter extends RecyclerView.Adapter<UploadMediaDe
} }
/** /**
* Checks if the source string contains trailing whitespace * Removes any leading and trailing whitespace from the source text.
* @param source input string * @param source input string
* @return true if contains trailing whitespace and false otherwise * @return a string without leading and trailing whitespace
*/ */
public Boolean checkTrailingWhitespace(String source) { public String removeLeadingAndTrailingWhitespace(String source) {
int len = source.length(); // This method can be replaced with the inbuilt String::strip when updated to JDK 11.
if (len == 0) { // Note that String::trim does not adequately remove all whitespace chars.
return false; int firstNonWhitespaceIndex = 0;
while (firstNonWhitespaceIndex < source.length()) {
if (Character.isWhitespace(source.charAt(firstNonWhitespaceIndex))) {
firstNonWhitespaceIndex++;
} else {
break;
} }
return Character.isWhitespace(source.charAt(len - 1)); }
if (firstNonWhitespaceIndex == source.length()) {
return "";
} }
/** int lastNonWhitespaceIndex = source.length() - 1;
* Removes any trailing whitespace from the source text. while (lastNonWhitespaceIndex > firstNonWhitespaceIndex) {
* @param source input string if (Character.isWhitespace(source.charAt(lastNonWhitespaceIndex))) {
* @return a string without trailing whitespace lastNonWhitespaceIndex--;
*/ } else {
public String removeTrailingWhitespace(String source) { break;
while (checkTrailingWhitespace(source)) {
source = source.substring(0, source.length() - 1);
} }
return source; }
return source.substring(firstNonWhitespaceIndex, lastNonWhitespaceIndex + 1);
} }
/** /**

View file

@ -248,39 +248,39 @@ class UploadMediaDetailAdapterUnitTest {
} }
@Test @Test
fun testRemoveTrailingWhitespace() { fun testRemoveLeadingAndTrailingWhitespace() {
// empty space // empty space
val test1 = " test " val test1 = " test "
val expected1 = "test" val expected1 = "test"
Assert.assertTrue(viewHolder.checkTrailingWhitespace(test1)); Assert.assertEquals(expected1, viewHolder.removeLeadingAndTrailingWhitespace(test1))
Assert.assertEquals(expected1, viewHolder.removeTrailingWhitespace(test1))
val test2 = " test test " val test2 = " test test "
val expected2 = "test test" val expected2 = "test test"
Assert.assertTrue(viewHolder.checkTrailingWhitespace(test2)); Assert.assertEquals(expected2, viewHolder.removeLeadingAndTrailingWhitespace(test2))
Assert.assertEquals(expected2, viewHolder.removeTrailingWhitespace(test2))
// No whitespace // No whitespace
val test3 = "No trailing space"; val test3 = "No trailing space";
val expected3 = "No trailing space"; val expected3 = "No trailing space";
Assert.assertFalse(viewHolder.checkTrailingWhitespace(test3)) Assert.assertEquals(expected3, viewHolder.removeLeadingAndTrailingWhitespace(test3))
Assert.assertEquals(expected3, viewHolder.removeTrailingWhitespace(test3))
// blank string
val test4 = " \r \t "
val expected4 = "";
Assert.assertEquals(expected4, viewHolder.removeLeadingAndTrailingWhitespace(test4))
} }
@Test @Test
fun testRemoveTrailingInstanceTab() { fun testRemoveLeadingAndTrailingInstanceTab() {
val test = "test\t" val test = "\ttest\t"
val expected = "test" val expected = "test"
Assert.assertTrue(viewHolder.checkTrailingWhitespace(test)); Assert.assertEquals(expected, viewHolder.removeLeadingAndTrailingWhitespace(test))
Assert.assertEquals(expected, viewHolder.removeTrailingWhitespace(test))
} }
@Test @Test
fun testRemoveTrailingCarriageReturn() { fun testRemoveLeadingAndTrailingCarriageReturn() {
val test = "test\r" val test = "\rtest\r"
val expected = "test" val expected = "test"
Assert.assertTrue(viewHolder.checkTrailingWhitespace(test)); Assert.assertEquals(expected, viewHolder.removeLeadingAndTrailingWhitespace(test))
Assert.assertEquals(expected, viewHolder.removeTrailingWhitespace(test))
} }
@Test @Test
@ -289,9 +289,8 @@ class UploadMediaDetailAdapterUnitTest {
val expected1 = "テスト テスト" val expected1 = "テスト テスト"
Assert.assertEquals(expected1, viewHolder.convertIdeographicSpaceToLatinSpace(test1)); Assert.assertEquals(expected1, viewHolder.convertIdeographicSpaceToLatinSpace(test1));
val test2 = "テスト \r \t " val test2 = " \r \t テスト \r \t "
val expected2 = "テスト" val expected2 = "テスト"
Assert.assertTrue(viewHolder.checkTrailingWhitespace(test2)); Assert.assertEquals(expected2, viewHolder.removeLeadingAndTrailingWhitespace(test2))
Assert.assertEquals(expected2, viewHolder.removeTrailingWhitespace(test2))
} }
} }