Fix test compilation

This commit is contained in:
Dimitry Ivanov 2019-05-28 19:01:41 +03:00
parent 5bf21bc940
commit 64af306e53
9 changed files with 63 additions and 712 deletions

View File

@ -5,27 +5,12 @@ import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import java.util.List;
import ru.noties.markwon.core.CorePlugin;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@Config(manifest = Config.NONE) @Config(manifest = Config.NONE)
public class AbstractMarkwonPluginTest { public class AbstractMarkwonPluginTest {
@Test
public void priority() {
// returns CorePlugin dependency
final Priority priority = new AbstractMarkwonPlugin() {
}.priority();
final List<Class<? extends MarkwonPlugin>> after = priority.after();
assertEquals(1, after.size());
assertEquals(CorePlugin.class, after.get(0));
}
@Test @Test
public void process_markdown() { public void process_markdown() {
// returns supplied argument (no-op) // returns supplied argument (no-op)

View File

@ -1,6 +1,5 @@
package ru.noties.markwon; package ru.noties.markwon;
import android.support.annotation.NonNull;
import android.text.Spanned; import android.text.Spanned;
import android.widget.TextView; import android.widget.TextView;
@ -8,183 +7,57 @@ import org.commonmark.node.Node;
import org.commonmark.parser.Parser; import org.commonmark.parser.Parser;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.ArgumentMatchers;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import ru.noties.markwon.core.CorePlugin;
import ru.noties.markwon.core.MarkwonTheme; import ru.noties.markwon.core.MarkwonTheme;
import ru.noties.markwon.html.MarkwonHtmlRenderer; import ru.noties.markwon.html.MarkwonHtmlRenderer;
import ru.noties.markwon.image.AsyncDrawableLoader;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.isA;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static ru.noties.markwon.MarkwonBuilderImpl.ensureImplicitCoreIfHasDependents;
import static ru.noties.markwon.MarkwonBuilderImpl.preparePlugins;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@Config(manifest = Config.NONE) @Config(manifest = Config.NONE)
public class MarkwonBuilderImplTest { public class MarkwonBuilderImplTest {
@Test
public void implicit_core_created() {
// a plugin explicitly requests CorePlugin, but CorePlugin is not added manually by user
// we validate that default CorePlugin instance is added
final MarkwonPlugin plugin = new AbstractMarkwonPlugin() {
@NonNull
@Override
public Priority priority() {
// strictly speaking we do not need to override this method
// as all children of AbstractMarkwonPlugin specify CorePlugin as a dependency.
// but we still add it to make things explicit and future proof, if this
// behavior changes
return Priority.after(CorePlugin.class);
}
};
final List<MarkwonPlugin> plugins = ensureImplicitCoreIfHasDependents(Collections.singletonList(plugin));
assertThat(plugins, hasSize(2));
assertThat(plugins, hasItem(isA(CorePlugin.class)));
}
@Test
public void implicit_core_no_dependents_not_added() {
final MarkwonPlugin a = new AbstractMarkwonPlugin() {
@NonNull
@Override
public Priority priority() {
return Priority.none();
}
};
final MarkwonPlugin b = new AbstractMarkwonPlugin() {
@NonNull
@Override
public Priority priority() {
return Priority.after(a.getClass());
}
};
final List<MarkwonPlugin> plugins = ensureImplicitCoreIfHasDependents(Arrays.asList(a, b));
assertThat(plugins, hasSize(2));
assertThat(plugins, not(hasItem(isA(CorePlugin.class))));
}
@Test
public void implicit_core_present() {
// if core is present it won't be added (whether or not there are dependents)
final MarkwonPlugin plugin = new AbstractMarkwonPlugin() {
@NonNull
@Override
public Priority priority() {
return Priority.after(CorePlugin.class);
}
};
final CorePlugin corePlugin = CorePlugin.create();
final List<MarkwonPlugin> plugins = ensureImplicitCoreIfHasDependents(Arrays.asList(plugin, corePlugin));
assertThat(plugins, hasSize(2));
assertThat(plugins, hasItem(plugin));
assertThat(plugins, hasItem(corePlugin));
}
@Test
public void implicit_core_subclass_present() {
// core was subclassed by a user and provided (implicit core won't be added)
final MarkwonPlugin plugin = new AbstractMarkwonPlugin() {
@NonNull
@Override
public Priority priority() {
return Priority.after(CorePlugin.class);
}
};
// our subclass
final CorePlugin corePlugin = new CorePlugin() {
};
final List<MarkwonPlugin> plugins = ensureImplicitCoreIfHasDependents(Arrays.asList(plugin, corePlugin));
assertThat(plugins, hasSize(2));
assertThat(plugins, hasItem(plugin));
assertThat(plugins, hasItem(corePlugin));
}
@Test @Test
public void prepare_plugins() { public void prepare_plugins() {
// validate that prepare plugins is calling `ensureImplicitCoreIfHasDependents` and // validate that prepare plugins is calling `ensureImplicitCoreIfHasDependents` and
// priority processor // priority processor
final PriorityProcessor priorityProcessor = mock(PriorityProcessor.class); // final PriorityProcessor priorityProcessor = mock(PriorityProcessor.class);
when(priorityProcessor.process(ArgumentMatchers.<MarkwonPlugin>anyList())) // when(priorityProcessor.process(ArgumentMatchers.<MarkwonPlugin>anyList()))
.thenAnswer(new Answer<Object>() { // .thenAnswer(new Answer<Object>() {
@Override // @Override
public Object answer(InvocationOnMock invocation) { // public Object answer(InvocationOnMock invocation) {
return invocation.getArgument(0); // return invocation.getArgument(0);
} // }
}); // });
//
// final MarkwonPlugin plugin = new AbstractMarkwonPlugin() {
// @NonNull
// @Override
// public Priority priority() {
// return Priority.after(CorePlugin.class);
// }
// };
//
// final List<MarkwonPlugin> plugins = preparePlugins(priorityProcessor, Collections.singletonList(plugin));
// assertThat(plugins, hasSize(2));
// assertThat(plugins, hasItem(plugin));
// assertThat(plugins, hasItem(isA(CorePlugin.class)));
//
// verify(priorityProcessor, times(1))
// .process(ArgumentMatchers.<MarkwonPlugin>anyList());
final MarkwonPlugin plugin = new AbstractMarkwonPlugin() { fail();
@NonNull
@Override
public Priority priority() {
return Priority.after(CorePlugin.class);
}
};
final List<MarkwonPlugin> plugins = preparePlugins(priorityProcessor, Collections.singletonList(plugin));
assertThat(plugins, hasSize(2));
assertThat(plugins, hasItem(plugin));
assertThat(plugins, hasItem(isA(CorePlugin.class)));
verify(priorityProcessor, times(1))
.process(ArgumentMatchers.<MarkwonPlugin>anyList());
}
@Test
public void user_supplied_priority_processor() {
// verify that if user supplied priority processor it will be used
final PriorityProcessor priorityProcessor = mock(PriorityProcessor.class);
final MarkwonBuilderImpl impl = new MarkwonBuilderImpl(RuntimeEnvironment.application);
// add some plugin (we do not care which one, but it must be present as we do not
// allow empty plugins list)
impl.usePlugin(new AbstractMarkwonPlugin() {
@NonNull
@Override
public Priority priority() {
return Priority.none();
}
});
impl.priorityProcessor(priorityProcessor);
impl.build();
verify(priorityProcessor, times(1)).process(ArgumentMatchers.<MarkwonPlugin>anyList());
} }
@Test @Test
@ -204,22 +77,19 @@ public class MarkwonBuilderImplTest {
// verify that all configuration methods (applicable) are called // verify that all configuration methods (applicable) are called
final MarkwonPlugin plugin = mock(MarkwonPlugin.class); final MarkwonPlugin plugin = mock(MarkwonPlugin.class);
when(plugin.priority()).thenReturn(Priority.none());
final MarkwonBuilderImpl impl = new MarkwonBuilderImpl(RuntimeEnvironment.application); final MarkwonBuilderImpl impl = new MarkwonBuilderImpl(RuntimeEnvironment.application);
impl.usePlugin(plugin).build(); impl.usePlugin(plugin).build();
verify(plugin, times(1)).configure(any(MarkwonPlugin.Registry.class));
verify(plugin, times(1)).configureParser(any(Parser.Builder.class)); verify(plugin, times(1)).configureParser(any(Parser.Builder.class));
verify(plugin, times(1)).configureTheme(any(MarkwonTheme.Builder.class)); verify(plugin, times(1)).configureTheme(any(MarkwonTheme.Builder.class));
verify(plugin, times(1)).configureImages(any(AsyncDrawableLoader.Builder.class));
verify(plugin, times(1)).configureConfiguration(any(MarkwonConfiguration.Builder.class)); verify(plugin, times(1)).configureConfiguration(any(MarkwonConfiguration.Builder.class));
verify(plugin, times(1)).configureVisitor(any(MarkwonVisitor.Builder.class)); verify(plugin, times(1)).configureVisitor(any(MarkwonVisitor.Builder.class));
verify(plugin, times(1)).configureSpansFactory(any(MarkwonSpansFactory.Builder.class)); verify(plugin, times(1)).configureSpansFactory(any(MarkwonSpansFactory.Builder.class));
verify(plugin, times(1)).configureHtmlRenderer(any(MarkwonHtmlRenderer.Builder.class)); verify(plugin, times(1)).configureHtmlRenderer(any(MarkwonHtmlRenderer.Builder.class));
// we do not know how many times exactly, but at least once it must be called
verify(plugin, atLeast(1)).priority();
// note, no render props -> they must be configured on render stage // note, no render props -> they must be configured on render stage
verify(plugin, times(0)).processMarkdown(anyString()); verify(plugin, times(0)).processMarkdown(anyString());
verify(plugin, times(0)).beforeRender(any(Node.class)); verify(plugin, times(0)).beforeRender(any(Node.class));

View File

@ -191,13 +191,6 @@ public class CorePluginTest {
assertEquals(impl.map.toString(), 0, impl.map.size()); assertEquals(impl.map.toString(), 0, impl.map.size());
} }
@Test
public void priority_none() {
// CorePlugin returns none as priority (thus 0)
assertEquals(0, CorePlugin.create().priority().after().size());
}
@Test @Test
public void plugin_methods() { public void plugin_methods() {
// checks that only expected plugin methods are overridden // checks that only expected plugin methods are overridden

View File

@ -2,7 +2,6 @@ package ru.noties.markwon.image;
import android.content.Context; import android.content.Context;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import org.commonmark.node.Image; import org.commonmark.node.Image;
import org.junit.Test; import org.junit.Test;
@ -18,7 +17,6 @@ import ru.noties.markwon.MarkwonSpansFactory;
import ru.noties.markwon.RenderProps; import ru.noties.markwon.RenderProps;
import ru.noties.markwon.SpanFactory; import ru.noties.markwon.SpanFactory;
import ru.noties.markwon.core.CorePlugin; import ru.noties.markwon.core.CorePlugin;
import ru.noties.markwon.core.MarkwonTheme;
import ru.noties.markwon.test.TestSpan.Document; import ru.noties.markwon.test.TestSpan.Document;
import ru.noties.markwon.test.TestSpanMatcher; import ru.noties.markwon.test.TestSpanMatcher;
@ -39,7 +37,6 @@ public class ImageTest {
final Context context = RuntimeEnvironment.application; final Context context = RuntimeEnvironment.application;
final Markwon markwon = Markwon.builder(context) final Markwon markwon = Markwon.builder(context)
.usePlugin(CorePlugin.create()) .usePlugin(CorePlugin.create())
.usePlugin(new ImagesPlugin(context, false))
.usePlugin(new AbstractMarkwonPlugin() { .usePlugin(new AbstractMarkwonPlugin() {
@Override @Override
public void configureSpansFactory(@NonNull MarkwonSpansFactory.Builder builder) { public void configureSpansFactory(@NonNull MarkwonSpansFactory.Builder builder) {

View File

@ -1,494 +0,0 @@
package ru.noties.markwon.priority;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import ru.noties.markwon.AbstractMarkwonPlugin;
import ru.noties.markwon.MarkwonPlugin;
import ru.noties.markwon.core.CorePlugin;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@RunWith(RobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public class PriorityProcessorTest {
private PriorityProcessor processor;
@Before
public void before() {
processor = PriorityProcessor.create();
}
@Test
public void empty_list() {
final List<MarkwonPlugin> plugins = Collections.emptyList();
assertEquals(0, processor.process(plugins).size());
}
@Test
public void simple_two_plugins() {
final MarkwonPlugin first = new AbstractMarkwonPlugin() {
@NonNull
@Override
public Priority priority() {
return Priority.none();
}
};
final MarkwonPlugin second = new AbstractMarkwonPlugin() {
@NonNull
@Override
public Priority priority() {
return Priority.after(first.getClass());
}
};
final List<MarkwonPlugin> plugins = processor.process(Arrays.asList(second, first));
assertEquals(2, plugins.size());
assertEquals(first, plugins.get(0));
assertEquals(second, plugins.get(1));
}
@Test
public void plugin_after_self() {
final MarkwonPlugin plugin = new AbstractMarkwonPlugin() {
@NonNull
@Override
public Priority priority() {
return Priority.after(getClass());
}
};
try {
processor.process(Collections.singletonList(plugin));
fail();
} catch (IllegalStateException e) {
assertTrue(e.getMessage(), e.getMessage().contains("defined self as a dependency"));
}
}
@Test
public void unsatisfied_dependency() {
final MarkwonPlugin plugin = new AbstractMarkwonPlugin() {
@NonNull
@Override
public Priority priority() {
return Priority.after(ImagesPlugin.class);
}
};
try {
processor.process(Collections.singletonList(plugin));
fail();
} catch (IllegalStateException e) {
assertTrue(e.getMessage(), e.getMessage().contains("Markwon unsatisfied dependency found"));
}
}
@Test
public void subclass_found() {
// when a plugin comes after another, but _another_ was subclassed and placed in the list
final MarkwonPlugin core = new CorePlugin() {
};
final MarkwonPlugin plugin = new AbstractMarkwonPlugin() {
@NonNull
@Override
public Priority priority() {
return Priority.after(CorePlugin.class);
}
};
final List<MarkwonPlugin> plugins = processor.process(Arrays.asList(plugin, core));
assertEquals(2, plugins.size());
assertEquals(core, plugins.get(0));
assertEquals(plugin, plugins.get(1));
}
@Test
public void three_plugins_sequential() {
final MarkwonPlugin first = new AbstractMarkwonPlugin() {
@NonNull
@Override
public Priority priority() {
return Priority.none();
}
};
final MarkwonPlugin second = new AbstractMarkwonPlugin() {
@NonNull
@Override
public Priority priority() {
return Priority.after(first.getClass());
}
};
final MarkwonPlugin third = new AbstractMarkwonPlugin() {
@NonNull
@Override
public Priority priority() {
return Priority.after(second.getClass());
}
};
final List<MarkwonPlugin> plugins = processor.process(Arrays.asList(third, second, first));
assertEquals(3, plugins.size());
assertEquals(first, plugins.get(0));
assertEquals(second, plugins.get(1));
assertEquals(third, plugins.get(2));
}
@Test
public void five_plugins_sequential() {
final MarkwonPlugin a = new NamedPlugin("a") {
};
final MarkwonPlugin b = new NamedPlugin("b", a) {
};
final MarkwonPlugin c = new NamedPlugin("c", b) {
};
final MarkwonPlugin d = new NamedPlugin("d", c) {
};
final MarkwonPlugin e = new NamedPlugin("e", d) {
};
final List<MarkwonPlugin> plugins = processor.process(Arrays.asList(d, e, a, c, b));
assertEquals(5, plugins.size());
assertEquals(a, plugins.get(0));
assertEquals(b, plugins.get(1));
assertEquals(c, plugins.get(2));
assertEquals(d, plugins.get(3));
assertEquals(e, plugins.get(4));
}
@Test
public void plugin_duplicate() {
final MarkwonPlugin plugin = new AbstractMarkwonPlugin() {
@NonNull
@Override
public Priority priority() {
return Priority.none();
}
};
try {
processor.process(Arrays.asList(plugin, plugin));
fail();
} catch (IllegalStateException e) {
assertTrue(e.getMessage(), e.getMessage().contains("Markwon duplicate plugin found"));
}
}
@Test
public void multiple_after_3() {
final MarkwonPlugin a1 = new AbstractMarkwonPlugin() {
@NonNull
@Override
public Priority priority() {
return Priority.none();
}
};
final MarkwonPlugin b1 = new AbstractMarkwonPlugin() {
@NonNull
@Override
public Priority priority() {
return Priority.after(a1.getClass());
}
};
final MarkwonPlugin c1 = new AbstractMarkwonPlugin() {
@NonNull
@Override
public Priority priority() {
return Priority.after(a1.getClass(), b1.getClass());
}
};
final List<MarkwonPlugin> plugins = processor.process(Arrays.asList(c1, a1, b1));
assertEquals(3, plugins.size());
assertEquals(a1, plugins.get(0));
assertEquals(b1, plugins.get(1));
assertEquals(c1, plugins.get(2));
}
@Test
public void multiple_after_4() {
final MarkwonPlugin a1 = new AbstractMarkwonPlugin() {
@NonNull
@Override
public Priority priority() {
return Priority.none();
}
};
final MarkwonPlugin b1 = new AbstractMarkwonPlugin() {
@NonNull
@Override
public Priority priority() {
return Priority.after(a1.getClass());
}
};
final MarkwonPlugin c1 = new AbstractMarkwonPlugin() {
@NonNull
@Override
public Priority priority() {
return Priority.after(a1.getClass(), b1.getClass());
}
};
final MarkwonPlugin d1 = new AbstractMarkwonPlugin() {
@NonNull
@Override
public Priority priority() {
return Priority.builder()
.after(a1.getClass())
.after(b1.getClass())
.after(c1.getClass())
.build();
}
};
final List<MarkwonPlugin> plugins = processor.process(Arrays.asList(c1, d1, a1, b1));
assertEquals(4, plugins.size());
assertEquals(a1, plugins.get(0));
assertEquals(b1, plugins.get(1));
assertEquals(c1, plugins.get(2));
assertEquals(d1, plugins.get(3));
}
@Test
public void cycle() {
final class Holder {
Class<? extends MarkwonPlugin> type;
}
final Holder holder = new Holder();
final MarkwonPlugin first = new AbstractMarkwonPlugin() {
@NonNull
@Override
public Priority priority() {
return Priority.after(holder.type);
}
};
final MarkwonPlugin second = new AbstractMarkwonPlugin() {
{
holder.type = getClass();
}
@NonNull
@Override
public Priority priority() {
return Priority.after(first.getClass());
}
};
try {
processor.process(Arrays.asList(second, first));
fail();
} catch (IllegalStateException e) {
assertTrue(e.getMessage(), e.getMessage().contains("being referenced by own dependency (cycle)"));
}
}
@Test
public void bigger_cycle() {
final class Plugin extends NamedPlugin {
private Priority priority;
private Plugin(@NonNull String name) {
super(name);
}
private void set(@NonNull MarkwonPlugin plugin) {
priority = Priority.after(plugin.getClass());
}
@NonNull
@Override
public Priority priority() {
return priority;
}
}
final Plugin a = new Plugin("a");
final List<MarkwonPlugin> plugins = new ArrayList<>();
plugins.add(a);
plugins.add(new NamedPlugin("b", plugins.get(plugins.size() - 1)) {
});
plugins.add(new NamedPlugin("c", plugins.get(plugins.size() - 1)) {
});
plugins.add(new NamedPlugin("d", plugins.get(plugins.size() - 1)) {
});
plugins.add(new NamedPlugin("e", plugins.get(plugins.size() - 1)) {
});
plugins.add(new NamedPlugin("f", plugins.get(plugins.size() - 1)) {
});
plugins.add(new NamedPlugin("g", plugins.get(plugins.size() - 1)) {
});
// link with the last one
a.set(plugins.get(plugins.size() - 1));
try {
processor.process(plugins);
fail();
} catch (IllegalStateException e) {
assertTrue(e.getMessage(), e.getMessage().contains("being referenced by own dependency (cycle)"));
}
}
@Test
public void deep_tree() {
// we must create subclasses in order to register them like this (otherwise -> duplicates)
final MarkwonPlugin a = new NamedPlugin("a") {
};
final MarkwonPlugin b1 = new NamedPlugin("b1", a) {
};
final MarkwonPlugin b2 = new NamedPlugin("b2", a) {
};
final MarkwonPlugin c1 = new NamedPlugin("c1", b1) {
};
final MarkwonPlugin c2 = new NamedPlugin("c2", b1) {
};
final MarkwonPlugin c3 = new NamedPlugin("c3", b2) {
};
final MarkwonPlugin c4 = new NamedPlugin("c4", b2) {
};
final MarkwonPlugin d1 = new NamedPlugin("d1", c1) {
};
final MarkwonPlugin e1 = new NamedPlugin("e1", d1, c2, c3, c4) {
};
final List<MarkwonPlugin> plugins = processor.process(Arrays.asList(b2, b1,
a, e1, c4, c3, c2, c1, d1));
// a is first
// b1 + b2 -> second+third
// c1 + c2 + c3 + c4 -> forth, fifth, sixth, seventh
// d1 -> 8th
// e1 -> 9th
assertEquals(9, plugins.size());
assertEquals(a, plugins.get(0));
assertEquals(new HashSet<>(Arrays.asList(b1, b2)), new HashSet<>(plugins.subList(1, 3)));
assertEquals(new HashSet<>(Arrays.asList(c1, c2, c3, c4)), new HashSet<>(plugins.subList(3, 7)));
assertEquals(d1, plugins.get(7));
assertEquals(e1, plugins.get(8));
}
@Test
public void multiple_detached() {
// when graph has independent elements that are not connected with each other
final MarkwonPlugin a0 = new NamedPlugin("a0") {
};
final MarkwonPlugin a1 = new NamedPlugin("a1", a0) {
};
final MarkwonPlugin a2 = new NamedPlugin("a2", a1) {
};
final MarkwonPlugin b0 = new NamedPlugin("b0") {
};
final MarkwonPlugin b1 = new NamedPlugin("b1", b0) {
};
final MarkwonPlugin b2 = new NamedPlugin("b2", b1) {
};
final List<MarkwonPlugin> plugins = processor.process(Arrays.asList(
b2, a2, a0, b0, b1, a1));
assertEquals(6, plugins.size());
assertEquals(new HashSet<>(Arrays.asList(a0, b0)), new HashSet<>(plugins.subList(0, 2)));
assertEquals(new HashSet<>(Arrays.asList(a1, b1)), new HashSet<>(plugins.subList(2, 4)));
assertEquals(new HashSet<>(Arrays.asList(a2, b2)), new HashSet<>(plugins.subList(4, 6)));
}
private static abstract class NamedPlugin extends AbstractMarkwonPlugin {
private final String name;
private final Priority priority;
NamedPlugin(@NonNull String name) {
this(name, (Priority) null);
}
NamedPlugin(@NonNull String name, @Nullable MarkwonPlugin plugin) {
this(name, plugin != null ? Priority.after(plugin.getClass()) : null);
}
NamedPlugin(@NonNull String name, MarkwonPlugin... plugins) {
this(name, of(plugins));
}
NamedPlugin(@NonNull String name, @Nullable Class<? extends MarkwonPlugin> plugin) {
this(name, plugin != null ? Priority.after(plugin) : null);
}
NamedPlugin(@NonNull String name, @Nullable Priority priority) {
this.name = name;
this.priority = priority;
}
@NonNull
@Override
public Priority priority() {
return priority != null
? priority
: Priority.none();
}
@Override
public String toString() {
return "NamedPlugin{" +
"name='" + name + '\'' +
'}';
}
@NonNull
private static Priority of(@NonNull MarkwonPlugin... plugins) {
if (plugins.length == 0) return Priority.none();
final Priority.Builder builder = Priority.builder();
for (MarkwonPlugin plugin : plugins) {
builder.after(plugin.getClass());
}
return builder.build();
}
}
}

View File

@ -27,7 +27,6 @@ import ru.noties.markwon.SpannableBuilder;
import ru.noties.markwon.core.CorePluginBridge; import ru.noties.markwon.core.CorePluginBridge;
import ru.noties.markwon.core.MarkwonTheme; import ru.noties.markwon.core.MarkwonTheme;
import ru.noties.markwon.html.MarkwonHtmlRenderer; import ru.noties.markwon.html.MarkwonHtmlRenderer;
import ru.noties.markwon.image.AsyncDrawableLoader;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
@ -84,7 +83,7 @@ public class SyntaxHighlightTest {
final MarkwonConfiguration configuration = MarkwonConfiguration.builder() final MarkwonConfiguration configuration = MarkwonConfiguration.builder()
.syntaxHighlight(highlight) .syntaxHighlight(highlight)
.build(mock(MarkwonTheme.class), mock(AsyncDrawableLoader.class), mock(MarkwonHtmlRenderer.class), spansFactory); .build(mock(MarkwonTheme.class), mock(MarkwonHtmlRenderer.class), spansFactory);
final Map<Class<? extends Node>, MarkwonVisitor.NodeVisitor<? extends Node>> visitorMap = Collections.emptyMap(); final Map<Class<? extends Node>, MarkwonVisitor.NodeVisitor<? extends Node>> visitorMap = Collections.emptyMap();

View File

@ -22,6 +22,17 @@ dependencies {
compileOnly it['android-svg'] compileOnly it['android-svg']
compileOnly it['okhttp'] compileOnly it['okhttp']
} }
deps['test'].with {
testImplementation project(':markwon-test-span')
testImplementation it['junit']
testImplementation it['robolectric']
testImplementation it['mockito']
testImplementation it['commons-io']
}
} }
registerArtifact(this) registerArtifact(this)

View File

@ -14,9 +14,11 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Scanner; import java.util.Scanner;
import ru.noties.markwon.image.ImageItem;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@Config(manifest = Config.NONE) @Config(manifest = Config.NONE)
@ -31,17 +33,29 @@ public class DataUriSchemeHandlerTest {
@Test @Test
public void scheme_specific_part_is_empty() { public void scheme_specific_part_is_empty() {
assertNull(handler.handle("data:", Uri.parse("data:"))); try {
handler.handle("data:", Uri.parse("data:"));
} catch (Throwable t) {
assertTrue(t.getMessage(), t.getMessage().contains("Invalid data-uri"));
}
} }
@Test @Test
public void data_uri_is_empty() { public void data_uri_is_empty() {
assertNull(handler.handle("data://whatever", Uri.parse("data://whatever"))); try {
handler.handle("data:whatever", Uri.parse("data:whatever"));
} catch (Throwable t) {
assertTrue(t.getMessage(), t.getMessage().contains("Invalid data-uri"));
}
} }
@Test @Test
public void no_data() { public void no_data() {
assertNull(handler.handle("data://,", Uri.parse("data://,"))); try {
handler.handle("data:,", Uri.parse("data:,"));
} catch (Throwable t) {
assertTrue(t.getMessage(), t.getMessage().contains("Decoding data-uri failed"));
}
} }
@Test @Test
@ -58,33 +72,6 @@ public class DataUriSchemeHandlerTest {
} }
} }
final Map<String, Item> expected = new HashMap<String, Item>() {{
put("data://text/plain;,123", new Item("text/plain", "123"));
put("data://image/svg+xml;base64,MTIz", new Item("image/svg+xml", "123"));
}};
for (Map.Entry<String, Item> entry : expected.entrySet()) {
final ImageItem item = handler.handle(entry.getKey(), Uri.parse(entry.getKey()));
assertNotNull(entry.getKey(), item);
assertEquals(entry.getKey(), entry.getValue().contentType, item.contentType());
assertEquals(entry.getKey(), entry.getValue().data, readStream(item.inputStream()));
}
}
@Test
public void correct_real() {
final class Item {
final String contentType;
final String data;
Item(String contentType, String data) {
this.contentType = contentType;
this.data = data;
}
}
final Map<String, Item> expected = new HashMap<String, Item>() {{ final Map<String, Item> expected = new HashMap<String, Item>() {{
put("data:text/plain;,123", new Item("text/plain", "123")); put("data:text/plain;,123", new Item("text/plain", "123"));
put("data:image/svg+xml;base64,MTIz", new Item("image/svg+xml", "123")); put("data:image/svg+xml;base64,MTIz", new Item("image/svg+xml", "123"));
@ -93,8 +80,11 @@ public class DataUriSchemeHandlerTest {
for (Map.Entry<String, Item> entry : expected.entrySet()) { for (Map.Entry<String, Item> entry : expected.entrySet()) {
final ImageItem item = handler.handle(entry.getKey(), Uri.parse(entry.getKey())); final ImageItem item = handler.handle(entry.getKey(), Uri.parse(entry.getKey()));
assertNotNull(entry.getKey(), item); assertNotNull(entry.getKey(), item);
assertEquals(entry.getKey(), entry.getValue().contentType, item.contentType()); assertTrue(item.hasDecodingNeeded());
assertEquals(entry.getKey(), entry.getValue().data, readStream(item.inputStream()));
final ImageItem.WithDecodingNeeded withDecodingNeeded = item.getAsWithDecodingNeeded();
assertEquals(entry.getKey(), entry.getValue().contentType, withDecodingNeeded.contentType());
assertEquals(entry.getKey(), entry.getValue().data, readStream(withDecodingNeeded.inputStream()));
} }
} }