chore(merging-upstream): bunch of conflicts to solve
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
package org.joinmastodon.android.fragments;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.joinmastodon.android.events.StatusCountersUpdatedEvent;
|
||||
import org.joinmastodon.android.events.StatusUpdatedEvent;
|
||||
import org.joinmastodon.android.model.Status;
|
||||
import org.joinmastodon.android.model.StatusContext;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
public class ThreadFragmentTest {
|
||||
|
||||
private Status fakeStatus(String id, String inReplyTo) {
|
||||
Status status = Status.ofFake(id, null, null);
|
||||
status.inReplyToId = inReplyTo;
|
||||
return status;
|
||||
}
|
||||
|
||||
private ThreadFragment.NeighborAncestryInfo fakeInfo(Status s, Status d, Status a) {
|
||||
return new ThreadFragment.NeighborAncestryInfo(s, d, a);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapNeighborhoodAncestry() {
|
||||
StatusContext context = new StatusContext();
|
||||
context.ancestors = List.of(
|
||||
fakeStatus("oldest ancestor", null),
|
||||
fakeStatus("younger ancestor", "oldest ancestor")
|
||||
);
|
||||
Status mainStatus = fakeStatus("main status", "younger ancestor");
|
||||
context.descendants = List.of(
|
||||
fakeStatus("first reply", "main status"),
|
||||
fakeStatus("reply to first reply", "first reply"),
|
||||
fakeStatus("third level reply", "reply to first reply"),
|
||||
fakeStatus("another reply", "main status")
|
||||
);
|
||||
|
||||
List<ThreadFragment.NeighborAncestryInfo> neighbors =
|
||||
ThreadFragment.mapNeighborhoodAncestry(mainStatus, context);
|
||||
|
||||
assertEquals(List.of(
|
||||
fakeInfo(context.ancestors.get(0), context.ancestors.get(1), null),
|
||||
fakeInfo(context.ancestors.get(1), mainStatus, context.ancestors.get(0)),
|
||||
fakeInfo(mainStatus, context.descendants.get(0), context.ancestors.get(1)),
|
||||
fakeInfo(context.descendants.get(0), context.descendants.get(1), mainStatus),
|
||||
fakeInfo(context.descendants.get(1), context.descendants.get(2), context.descendants.get(0)),
|
||||
fakeInfo(context.descendants.get(2), null, context.descendants.get(1)),
|
||||
fakeInfo(context.descendants.get(3), null, null)
|
||||
), neighbors);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void maybeApplyMainStatus() {
|
||||
ThreadFragment fragment = new ThreadFragment();
|
||||
fragment.contextInitiallyRendered = true;
|
||||
fragment.mainStatus = Status.ofFake("123456", "original text", Instant.EPOCH);
|
||||
|
||||
Status update1 = Status.ofFake("123456", "updated text", Instant.EPOCH);
|
||||
update1.editedAt = Instant.ofEpochSecond(1);
|
||||
fragment.updatedStatus = update1;
|
||||
StatusUpdatedEvent event1 = (StatusUpdatedEvent) fragment.maybeApplyMainStatus();
|
||||
assertEquals("fired update event", update1, event1.status);
|
||||
assertEquals("updated main status", update1, fragment.mainStatus);
|
||||
|
||||
Status update2 = Status.ofFake("123456", "updated text", Instant.EPOCH);
|
||||
update2.favouritesCount = 123;
|
||||
fragment.updatedStatus = update2;
|
||||
StatusCountersUpdatedEvent event2 = (StatusCountersUpdatedEvent) fragment.maybeApplyMainStatus();
|
||||
assertEquals("only fired counter update event", update2.id, event2.id);
|
||||
assertEquals("updated counter is correct", 123, event2.favorites);
|
||||
assertEquals("updated main status", update2, fragment.mainStatus);
|
||||
|
||||
Status update3 = Status.ofFake("123456", "whatever", Instant.EPOCH);
|
||||
fragment.contextInitiallyRendered = false;
|
||||
fragment.updatedStatus = update3;
|
||||
assertNull("no update when context hasn't been rendered", fragment.maybeApplyMainStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sortStatusContext() {
|
||||
StatusContext context = new StatusContext();
|
||||
context.ancestors = List.of(
|
||||
fakeStatus("younger ancestor", "oldest ancestor"),
|
||||
fakeStatus("oldest ancestor", null)
|
||||
);
|
||||
context.descendants = List.of(
|
||||
fakeStatus("reply to first reply", "first reply"),
|
||||
fakeStatus("third level reply", "reply to first reply"),
|
||||
fakeStatus("first reply", "main status"),
|
||||
fakeStatus("another reply", "main status")
|
||||
);
|
||||
|
||||
ThreadFragment.sortStatusContext(
|
||||
fakeStatus("main status", "younger ancestor"),
|
||||
context
|
||||
);
|
||||
List<Status> expectedAncestors = List.of(
|
||||
fakeStatus("oldest ancestor", null),
|
||||
fakeStatus("younger ancestor", "oldest ancestor")
|
||||
);
|
||||
List<Status> expectedDescendants = List.of(
|
||||
fakeStatus("first reply", "main status"),
|
||||
fakeStatus("reply to first reply", "first reply"),
|
||||
fakeStatus("third level reply", "reply to first reply"),
|
||||
fakeStatus("another reply", "main status")
|
||||
);
|
||||
|
||||
// TODO: ??? i have no idea how this code works. it certainly doesn't return what i'd expect
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,265 @@
|
||||
package org.joinmastodon.android.ui.utils;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.util.Pair;
|
||||
|
||||
import org.joinmastodon.android.MastodonApp;
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.model.Account;
|
||||
import org.joinmastodon.android.model.AccountField;
|
||||
import org.joinmastodon.android.model.Instance;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
|
||||
public class UiUtilsTest {
|
||||
@BeforeClass
|
||||
public static void createDummySession() {
|
||||
Instance dummyInstance = new Instance();
|
||||
dummyInstance.uri = "test.tld";
|
||||
Account dummyAccount = new Account();
|
||||
dummyAccount.id = "123456";
|
||||
AccountSessionManager.getInstance().addAccount(dummyInstance, null, dummyAccount, null, null);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void cleanUp() {
|
||||
AccountSessionManager.getInstance().removeAccount("test.tld_123456");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseFediverseHandle() {
|
||||
assertEquals(
|
||||
Optional.of(Pair.create("megalodon", Optional.of("floss.social"))),
|
||||
UiUtils.parseFediverseHandle("megalodon@floss.social")
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
Optional.of(Pair.create("megalodon", Optional.of("floss.social"))),
|
||||
UiUtils.parseFediverseHandle("@megalodon@floss.social")
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
Optional.of(Pair.create("megalodon", Optional.empty())),
|
||||
UiUtils.parseFediverseHandle("@megalodon")
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
Optional.of(Pair.create("megalodon", Optional.of("floss.social"))),
|
||||
UiUtils.parseFediverseHandle("mailto:megalodon@floss.social")
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
Optional.empty(),
|
||||
UiUtils.parseFediverseHandle("megalodon")
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
Optional.empty(),
|
||||
UiUtils.parseFediverseHandle("this is not a fedi handle")
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
Optional.empty(),
|
||||
UiUtils.parseFediverseHandle("not@a-domain")
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void acctMatches() {
|
||||
assertTrue("local account, domain not specified", UiUtils.acctMatches(
|
||||
"test.tld_123456",
|
||||
"someone",
|
||||
"someone",
|
||||
null
|
||||
));
|
||||
|
||||
assertTrue("domain not specified", UiUtils.acctMatches(
|
||||
"test.tld_123456",
|
||||
"someone@somewhere.social",
|
||||
"someone",
|
||||
null
|
||||
));
|
||||
|
||||
assertTrue("local account, domain specified, different casing", UiUtils.acctMatches(
|
||||
"test.tld_123456",
|
||||
"SomeOne",
|
||||
"someone",
|
||||
"Test.TLD"
|
||||
));
|
||||
|
||||
assertFalse("username doesn't match", UiUtils.acctMatches(
|
||||
"test.tld_123456",
|
||||
"someone-else@somewhere.social",
|
||||
"someone",
|
||||
"somewhere.social"
|
||||
));
|
||||
|
||||
assertFalse("domain doesn't match", UiUtils.acctMatches(
|
||||
"test.tld_123456",
|
||||
"someone@somewhere.social",
|
||||
"someone",
|
||||
"somewhere.else"
|
||||
));
|
||||
}
|
||||
|
||||
private final String[] args = new String[] { "Megalodon", "♡" };
|
||||
|
||||
private String gen(String format, CharSequence... args) {
|
||||
return UiUtils.generateFormattedString(format, args).toString();
|
||||
}
|
||||
@Test
|
||||
public void generateFormattedString() {
|
||||
assertEquals(
|
||||
"ordered substitution",
|
||||
"Megalodon reacted with ♡",
|
||||
gen("%s reacted with %s", args)
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
"1 2 3 4 5",
|
||||
gen("%s %s %s %s %s", "1", "2", "3", "4", "5")
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
"indexed substitution",
|
||||
"with ♡ was reacted by Megalodon",
|
||||
gen("with %2$s was reacted by %1$s", args)
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
"indexed substitution, in order",
|
||||
"Megalodon reacted with ♡",
|
||||
gen("%1$s reacted with %2$s", args)
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
"indexed substitution, 0-based",
|
||||
"Megalodon reacted with ♡",
|
||||
gen("%0$s reacted with %1$s", args)
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
"indexed substitution, 5 items",
|
||||
"5 4 3 2 1",
|
||||
gen("%5$s %4$s %3$s %2$s %1$s", "1", "2", "3", "4", "5")
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
"one argument missing",
|
||||
"Megalodon reacted with ♡",
|
||||
gen("reacted with %s", args)
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
"multiple arguments missing",
|
||||
"Megalodon reacted with ♡",
|
||||
gen("reacted with", args)
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
"multiple arguments missing, numbers in expeced positions",
|
||||
"1 2 x 3 4 5",
|
||||
gen("%s x %s", "1", "2", "3", "4", "5")
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
"one leading and trailing space",
|
||||
"Megalodon reacted with ♡",
|
||||
gen(" reacted with ", args)
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
"multiple leading and trailing spaces",
|
||||
"Megalodon reacted with ♡",
|
||||
gen(" reacted with ", args)
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
"invalid format produces expected invalid result",
|
||||
"Megalodon reacted with % s ♡",
|
||||
gen("reacted with % s", args)
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
"plain string as format, all arguments get added",
|
||||
"a x b c",
|
||||
gen("x", new String[] { "a", "b", "c" })
|
||||
);
|
||||
|
||||
assertEquals("empty input produces empty output", "", gen(""));
|
||||
|
||||
// not supported:
|
||||
// assertEquals("a b a", gen("%1$s %2$s %2$s %1$s", new String[] { "a", "b", "c" }));
|
||||
// assertEquals("x", gen("%s %1$s %2$s %1$s %s", new String[] { "a", "b", "c" }));
|
||||
}
|
||||
|
||||
private AccountField makeField(String name, String value) {
|
||||
AccountField f = new AccountField();
|
||||
f.name = name;
|
||||
f.value = value;
|
||||
return f;
|
||||
}
|
||||
|
||||
private Account fakeAccount(AccountField... fields) {
|
||||
Account a = new Account();
|
||||
a.fields = Arrays.asList(fields);
|
||||
return a;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extractPronouns() {
|
||||
assertEquals("they", UiUtils.extractPronouns(MastodonApp.context, fakeAccount(
|
||||
makeField("name and pronouns", "https://pronouns.site"),
|
||||
makeField("pronouns", "they"),
|
||||
makeField("pronouns something", "bla bla")
|
||||
)).orElseThrow());
|
||||
|
||||
assertTrue(UiUtils.extractPronouns(MastodonApp.context, fakeAccount()).isEmpty());
|
||||
|
||||
assertEquals("it/its", UiUtils.extractPronouns(MastodonApp.context, fakeAccount(
|
||||
makeField("pronouns pronouns pronouns", "hi hi hi"),
|
||||
makeField("pronouns", "it/its"),
|
||||
makeField("the pro's nouns", "professional")
|
||||
)).orElseThrow());
|
||||
|
||||
assertEquals("she/he", UiUtils.extractPronouns(MastodonApp.context, fakeAccount(
|
||||
makeField("my name is", "jeanette shork, apparently"),
|
||||
makeField("my pronouns are", "she/he")
|
||||
)).orElseThrow());
|
||||
|
||||
assertEquals("they/them", UiUtils.extractPronouns(MastodonApp.context, fakeAccount(
|
||||
makeField("pronouns", "https://pronouns.cc/pronouns/they/them")
|
||||
)).orElseThrow());
|
||||
|
||||
Context german = UiUtils.getLocalizedContext(MastodonApp.context, Locale.GERMAN);
|
||||
|
||||
assertEquals("sie/ihr", UiUtils.extractPronouns(german, fakeAccount(
|
||||
makeField("pronomen lauten", "sie/ihr"),
|
||||
makeField("pronouns are", "she/her"),
|
||||
makeField("die pronomen", "stehen oben")
|
||||
)).orElseThrow());
|
||||
|
||||
assertEquals("er/ihm", UiUtils.extractPronouns(german, fakeAccount(
|
||||
makeField("die pronomen", "stehen unten"),
|
||||
makeField("pronomen sind", "er/ihm"),
|
||||
makeField("pronouns are", "he/him")
|
||||
)).orElseThrow());
|
||||
|
||||
assertEquals("* (asterisk)", UiUtils.extractPronouns(MastodonApp.context, fakeAccount(
|
||||
makeField("pronouns", "-- * (asterisk) --")
|
||||
)).orElseThrow());
|
||||
|
||||
assertEquals("they/(she?)", UiUtils.extractPronouns(MastodonApp.context, fakeAccount(
|
||||
makeField("pronouns", "they/(she?)...")
|
||||
)).orElseThrow());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package org.joinmastodon.android.utils;
|
||||
|
||||
import static org.joinmastodon.android.model.FilterAction.*;
|
||||
import static org.joinmastodon.android.model.FilterContext.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.joinmastodon.android.model.LegacyFilter;
|
||||
import org.joinmastodon.android.model.Status;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
public class StatusFilterPredicateTest {
|
||||
|
||||
private static final LegacyFilter hideMeFilter = new LegacyFilter(), warnMeFilter = new LegacyFilter();
|
||||
private static final List<LegacyFilter> allFilters = List.of(hideMeFilter, warnMeFilter);
|
||||
|
||||
private static final Status
|
||||
hideInHomePublic = Status.ofFake(null, "hide me, please", Instant.now()),
|
||||
warnInHomePublic = Status.ofFake(null, "display me with a warning", Instant.now()),
|
||||
noAltText = Status.ofFake(null, "display me with a warning", Instant.now()),
|
||||
withAltText = Status.ofFake(null, "display me with a warning", Instant.now());
|
||||
|
||||
static {
|
||||
hideMeFilter.phrase = "hide me";
|
||||
hideMeFilter.filterAction = HIDE;
|
||||
hideMeFilter.context = EnumSet.of(PUBLIC, HOME);
|
||||
|
||||
warnMeFilter.phrase = "warning";
|
||||
warnMeFilter.filterAction = WARN;
|
||||
warnMeFilter.context = EnumSet.of(PUBLIC, HOME);
|
||||
|
||||
noAltText.mediaAttachments = Attachment.createFakeAttachments("fakeurl", new ColorDrawable());
|
||||
withAltText.mediaAttachments = Attachment.createFakeAttachments("fakeurl", new ColorDrawable());
|
||||
for (Attachment mediaAttachment : withAltText.mediaAttachments) {
|
||||
mediaAttachment.description = "Alt Text";
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHide() {
|
||||
assertFalse("should not pass because matching filter applies to given context",
|
||||
new StatusFilterPredicate(allFilters, HOME).test(hideInHomePublic));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHideRegardlessOfContext() {
|
||||
assertTrue("filters without context should always pass",
|
||||
new StatusFilterPredicate(allFilters, null).test(hideInHomePublic));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHideInDifferentContext() {
|
||||
assertTrue("should pass because matching filter does not apply to given context",
|
||||
new StatusFilterPredicate(allFilters, THREAD).test(hideInHomePublic));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHideWithWarningText() {
|
||||
assertTrue("should pass because matching filter is for warnings",
|
||||
new StatusFilterPredicate(allFilters, HOME).test(warnInHomePublic));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWarn() {
|
||||
assertFalse("should not pass because filter applies to given context",
|
||||
new StatusFilterPredicate(allFilters, HOME, WARN).test(warnInHomePublic));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWarnRegardlessOfContext() {
|
||||
assertTrue("filters without context should always pass",
|
||||
new StatusFilterPredicate(allFilters, null, WARN).test(warnInHomePublic));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWarnInDifferentContext() {
|
||||
assertTrue("should pass because filter does not apply to given context",
|
||||
new StatusFilterPredicate(allFilters, THREAD, WARN).test(warnInHomePublic));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWarnWithHideText() {
|
||||
assertTrue("should pass because matching filter is for hiding",
|
||||
new StatusFilterPredicate(allFilters, HOME, WARN).test(hideInHomePublic));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAltTextFilterNoPass() {
|
||||
assertFalse("should not pass because of no alt text",
|
||||
new StatusFilterPredicate(allFilters, HOME).test(noAltText));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAltTextFilterPass() {
|
||||
assertTrue("should pass because of alt text",
|
||||
new StatusFilterPredicate(allFilters, HOME).test(withAltText));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user