MarkwonBuilderImpl test
This commit is contained in:
parent
581265a22a
commit
c16cdff871
@ -8,6 +8,7 @@ import android.support.annotation.NonNull;
|
|||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
|
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
@ -71,9 +72,17 @@ public class MarkdownRenderer {
|
|||||||
cancel();
|
cancel();
|
||||||
|
|
||||||
task = service.submit(new Runnable() {
|
task = service.submit(new Runnable() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
try {
|
||||||
|
execute();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
Debug.e(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void execute() {
|
||||||
final UrlProcessor urlProcessor;
|
final UrlProcessor urlProcessor;
|
||||||
if (uri == null) {
|
if (uri == null) {
|
||||||
urlProcessor = new UrlProcessorInitialReadme();
|
urlProcessor = new UrlProcessorInitialReadme();
|
||||||
|
@ -80,8 +80,6 @@ ext {
|
|||||||
'junit' : 'junit:junit:4.12',
|
'junit' : 'junit:junit:4.12',
|
||||||
'robolectric': 'org.robolectric:robolectric:3.8',
|
'robolectric': 'org.robolectric:robolectric:3.8',
|
||||||
'ix-java' : 'com.github.akarnokd:ixjava:1.0.0',
|
'ix-java' : 'com.github.akarnokd:ixjava:1.0.0',
|
||||||
'jackson-yaml' : 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.9.0',
|
|
||||||
'jackson-databind': 'com.fasterxml.jackson.core:jackson-databind:2.9.6',
|
|
||||||
'gson' : 'com.google.code.gson:gson:2.8.5',
|
'gson' : 'com.google.code.gson:gson:2.8.5',
|
||||||
'commons-io' : 'commons-io:commons-io:2.6',
|
'commons-io' : 'commons-io:commons-io:2.6',
|
||||||
'mockito' : 'org.mockito:mockito-core:2.21.0'
|
'mockito' : 'org.mockito:mockito-core:2.21.0'
|
||||||
|
@ -2,7 +2,7 @@ package ru.noties.markwon;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.util.Log;
|
import android.support.annotation.VisibleForTesting;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.commonmark.parser.Parser;
|
import org.commonmark.parser.Parser;
|
||||||
@ -12,6 +12,7 @@ import java.util.Collections;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
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.image.AsyncDrawableLoader;
|
import ru.noties.markwon.image.AsyncDrawableLoader;
|
||||||
import ru.noties.markwon.priority.PriorityProcessor;
|
import ru.noties.markwon.priority.PriorityProcessor;
|
||||||
@ -19,6 +20,7 @@ import ru.noties.markwon.priority.PriorityProcessor;
|
|||||||
/**
|
/**
|
||||||
* @since 3.0.0
|
* @since 3.0.0
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("WeakerAccess")
|
||||||
class MarkwonBuilderImpl implements Markwon.Builder {
|
class MarkwonBuilderImpl implements Markwon.Builder {
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
@ -66,6 +68,7 @@ class MarkwonBuilderImpl implements Markwon.Builder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("UnusedReturnValue")
|
||||||
@NonNull
|
@NonNull
|
||||||
public MarkwonBuilderImpl priorityProcessor(@NonNull PriorityProcessor priorityProcessor) {
|
public MarkwonBuilderImpl priorityProcessor(@NonNull PriorityProcessor priorityProcessor) {
|
||||||
this.priorityProcessor = priorityProcessor;
|
this.priorityProcessor = priorityProcessor;
|
||||||
@ -76,6 +79,23 @@ class MarkwonBuilderImpl implements Markwon.Builder {
|
|||||||
@Override
|
@Override
|
||||||
public Markwon build() {
|
public Markwon build() {
|
||||||
|
|
||||||
|
if (plugins.isEmpty()) {
|
||||||
|
throw new IllegalStateException("No plugins were added to this builder. Use #usePlugin " +
|
||||||
|
"method to add them");
|
||||||
|
}
|
||||||
|
|
||||||
|
// this class will sort plugins to match a priority/dependency graph that we have
|
||||||
|
PriorityProcessor priorityProcessor = this.priorityProcessor;
|
||||||
|
if (priorityProcessor == null) {
|
||||||
|
// strictly speaking we do not need updating this field
|
||||||
|
// as we are not building this class to be reused between multiple `build` calls
|
||||||
|
priorityProcessor = this.priorityProcessor = PriorityProcessor.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
// please note that this method must not modify supplied collection
|
||||||
|
// if nothing should be done -> the same collection can be returned
|
||||||
|
final List<MarkwonPlugin> plugins = preparePlugins(priorityProcessor, this.plugins);
|
||||||
|
|
||||||
final Parser.Builder parserBuilder = new Parser.Builder();
|
final Parser.Builder parserBuilder = new Parser.Builder();
|
||||||
final MarkwonTheme.Builder themeBuilder = MarkwonTheme.builderWithDefaults(context);
|
final MarkwonTheme.Builder themeBuilder = MarkwonTheme.builderWithDefaults(context);
|
||||||
final AsyncDrawableLoader.Builder asyncDrawableLoaderBuilder = new AsyncDrawableLoader.Builder();
|
final AsyncDrawableLoader.Builder asyncDrawableLoaderBuilder = new AsyncDrawableLoader.Builder();
|
||||||
@ -84,18 +104,7 @@ class MarkwonBuilderImpl implements Markwon.Builder {
|
|||||||
final MarkwonSpansFactory.Builder spanFactoryBuilder = new MarkwonSpansFactoryImpl.BuilderImpl();
|
final MarkwonSpansFactory.Builder spanFactoryBuilder = new MarkwonSpansFactoryImpl.BuilderImpl();
|
||||||
final RenderProps renderProps = new RenderPropsImpl();
|
final RenderProps renderProps = new RenderPropsImpl();
|
||||||
|
|
||||||
PriorityProcessor priorityProcessor = this.priorityProcessor;
|
|
||||||
if (priorityProcessor == null) {
|
|
||||||
// strictly speaking we do not need updating this field
|
|
||||||
// as we are not building this class to be reused between multiple `build` calls
|
|
||||||
priorityProcessor = this.priorityProcessor = PriorityProcessor.create();
|
|
||||||
}
|
|
||||||
final List<MarkwonPlugin> plugins = priorityProcessor.process(this.plugins);
|
|
||||||
|
|
||||||
for (MarkwonPlugin plugin : plugins) {
|
for (MarkwonPlugin plugin : plugins) {
|
||||||
if (true) {
|
|
||||||
Log.e("PLUGIN", plugin.getClass().getName());
|
|
||||||
}
|
|
||||||
plugin.configureParser(parserBuilder);
|
plugin.configureParser(parserBuilder);
|
||||||
plugin.configureTheme(themeBuilder);
|
plugin.configureTheme(themeBuilder);
|
||||||
plugin.configureImages(asyncDrawableLoaderBuilder);
|
plugin.configureImages(asyncDrawableLoaderBuilder);
|
||||||
@ -116,4 +125,59 @@ class MarkwonBuilderImpl implements Markwon.Builder {
|
|||||||
Collections.unmodifiableList(plugins)
|
Collections.unmodifiableList(plugins)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
@NonNull
|
||||||
|
static List<MarkwonPlugin> preparePlugins(
|
||||||
|
@NonNull PriorityProcessor priorityProcessor,
|
||||||
|
@NonNull List<MarkwonPlugin> plugins) {
|
||||||
|
|
||||||
|
// with this method we will ensure that CorePlugin is added IF and ONLY IF
|
||||||
|
// there are plugins that depend on it. If CorePlugin is added, or there are
|
||||||
|
// no plugins that require it, CorePlugin won't be added
|
||||||
|
final List<MarkwonPlugin> out = ensureImplicitCoreIfHasDependents(plugins);
|
||||||
|
|
||||||
|
return priorityProcessor.process(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
// this method will _implicitly_ add CorePlugin if there is at least one plugin
|
||||||
|
// that depends on CorePlugin
|
||||||
|
@VisibleForTesting
|
||||||
|
@NonNull
|
||||||
|
static List<MarkwonPlugin> ensureImplicitCoreIfHasDependents(@NonNull List<MarkwonPlugin> plugins) {
|
||||||
|
// loop over plugins -> if CorePlugin is found -> break;
|
||||||
|
// iterate over all plugins and check if CorePlugin is requested
|
||||||
|
|
||||||
|
boolean hasCore = false;
|
||||||
|
boolean hasCoreDependents = false;
|
||||||
|
|
||||||
|
for (MarkwonPlugin plugin : plugins) {
|
||||||
|
|
||||||
|
// here we do not check for exact match (a user could've subclasses CorePlugin
|
||||||
|
// and supplied it. In this case we DO NOT implicitly add CorePlugin
|
||||||
|
if (CorePlugin.class.isAssignableFrom(plugin.getClass())) {
|
||||||
|
hasCore = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if plugin has CorePlugin in dependencies -> mark for addition
|
||||||
|
if (!hasCoreDependents) {
|
||||||
|
// here we check for direct CorePlugin, if it's not CorePlugin (exact, not a subclass
|
||||||
|
// or something -> ignore)
|
||||||
|
if (plugin.priority().after().contains(CorePlugin.class)) {
|
||||||
|
hasCoreDependents = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasCoreDependents && !hasCore) {
|
||||||
|
final List<MarkwonPlugin> out = new ArrayList<>(plugins.size() + 1);
|
||||||
|
// add default instance of CorePlugin
|
||||||
|
out.add(CorePlugin.create());
|
||||||
|
out.addAll(plugins);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
return plugins;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,9 @@ import ru.noties.markwon.image.data.DataUriSchemeHandler;
|
|||||||
import ru.noties.markwon.image.file.FileSchemeHandler;
|
import ru.noties.markwon.image.file.FileSchemeHandler;
|
||||||
import ru.noties.markwon.image.network.NetworkSchemeHandler;
|
import ru.noties.markwon.image.network.NetworkSchemeHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 3.0.0
|
||||||
|
*/
|
||||||
public class ImagesPlugin extends AbstractMarkwonPlugin {
|
public class ImagesPlugin extends AbstractMarkwonPlugin {
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
|
@ -2,6 +2,7 @@ package ru.noties.markwon.priority;
|
|||||||
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -18,7 +19,10 @@ class PriorityProcessorImpl extends PriorityProcessor {
|
|||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public List<MarkwonPlugin> process(@NonNull List<MarkwonPlugin> plugins) {
|
public List<MarkwonPlugin> process(@NonNull List<MarkwonPlugin> in) {
|
||||||
|
|
||||||
|
// create new collection based on supplied argument
|
||||||
|
final List<MarkwonPlugin> plugins = new ArrayList<>(in);
|
||||||
|
|
||||||
final int size = plugins.size();
|
final int size = plugins.size();
|
||||||
|
|
||||||
@ -32,7 +36,6 @@ class PriorityProcessorImpl extends PriorityProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// change to Map<Plugin,Int>
|
|
||||||
final Map<MarkwonPlugin, Integer> cache = new HashMap<>(size);
|
final Map<MarkwonPlugin, Integer> cache = new HashMap<>(size);
|
||||||
for (MarkwonPlugin plugin : plugins) {
|
for (MarkwonPlugin plugin : plugins) {
|
||||||
cache.put(plugin, eval(plugin, map));
|
cache.put(plugin, eval(plugin, map));
|
||||||
@ -126,8 +129,4 @@ class PriorityProcessorImpl extends PriorityProcessor {
|
|||||||
return map.get(o1).compareTo(map.get(o2));
|
return map.get(o1).compareTo(map.get(o2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class NoCorePluginAddedException extends Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,231 @@
|
|||||||
|
package ru.noties.markwon;
|
||||||
|
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.text.Spanned;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import org.commonmark.node.Node;
|
||||||
|
import org.commonmark.parser.Parser;
|
||||||
|
import org.junit.Test;
|
||||||
|
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.RuntimeEnvironment;
|
||||||
|
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.image.AsyncDrawableLoader;
|
||||||
|
import ru.noties.markwon.priority.Priority;
|
||||||
|
import ru.noties.markwon.priority.PriorityProcessor;
|
||||||
|
|
||||||
|
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.fail;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.Mockito.atLeast;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
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)
|
||||||
|
@Config(manifest = Config.NONE)
|
||||||
|
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(false) {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
final List<MarkwonPlugin> plugins = ensureImplicitCoreIfHasDependents(Arrays.asList(plugin, corePlugin));
|
||||||
|
assertThat(plugins, hasSize(2));
|
||||||
|
assertThat(plugins, hasItem(plugin));
|
||||||
|
assertThat(plugins, hasItem(corePlugin));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void prepare_plugins() {
|
||||||
|
// validate that prepare plugins is calling `ensureImplicitCoreIfHasDependents` and
|
||||||
|
// priority processor
|
||||||
|
|
||||||
|
final PriorityProcessor priorityProcessor = mock(PriorityProcessor.class);
|
||||||
|
when(priorityProcessor.process(ArgumentMatchers.<MarkwonPlugin>anyList()))
|
||||||
|
.thenAnswer(new Answer<Object>() {
|
||||||
|
@Override
|
||||||
|
public Object answer(InvocationOnMock invocation) {
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
@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
|
||||||
|
public void no_plugins_added_throws() {
|
||||||
|
// there is no sense in having an instance with no plugins registered
|
||||||
|
|
||||||
|
try {
|
||||||
|
new MarkwonBuilderImpl(RuntimeEnvironment.application).build();
|
||||||
|
fail();
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
assertThat(e.getMessage(), e.getMessage(), containsString("No plugins were added"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void plugin_configured() {
|
||||||
|
// verify that all configuration methods (applicable) are called
|
||||||
|
|
||||||
|
final MarkwonPlugin plugin = mock(MarkwonPlugin.class);
|
||||||
|
when(plugin.priority()).thenReturn(Priority.none());
|
||||||
|
|
||||||
|
final MarkwonBuilderImpl impl = new MarkwonBuilderImpl(RuntimeEnvironment.application);
|
||||||
|
impl.usePlugin(plugin).build();
|
||||||
|
|
||||||
|
verify(plugin, times(1)).configureParser(any(Parser.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)).configureVisitor(any(MarkwonVisitor.Builder.class));
|
||||||
|
verify(plugin, times(1)).configureSpansFactory(any(MarkwonSpansFactory.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
|
||||||
|
verify(plugin, times(0)).configureRenderProps(any(RenderProps.class));
|
||||||
|
verify(plugin, times(0)).processMarkdown(anyString());
|
||||||
|
verify(plugin, times(0)).beforeRender(any(Node.class));
|
||||||
|
verify(plugin, times(0)).afterRender(any(Node.class), any(MarkwonVisitor.class));
|
||||||
|
verify(plugin, times(0)).beforeSetText(any(TextView.class), any(Spanned.class));
|
||||||
|
verify(plugin, times(0)).afterSetText(any(TextView.class));
|
||||||
|
}
|
||||||
|
}
|
@ -159,6 +159,33 @@ public class PriorityProcessorTest {
|
|||||||
assertEquals(third, plugins.get(2));
|
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
|
@Test
|
||||||
public void plugin_duplicate() {
|
public void plugin_duplicate() {
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user