MarkwonImpl tests
This commit is contained in:
parent
4c18115b57
commit
9958f34574
232
markwon/src/test/java/ru/noties/markwon/MarkwonImplTest.java
Normal file
232
markwon/src/test/java/ru/noties/markwon/MarkwonImplTest.java
Normal file
@ -0,0 +1,232 @@
|
||||
package ru.noties.markwon;
|
||||
|
||||
import android.text.Spanned;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.commonmark.node.Node;
|
||||
import org.commonmark.node.Visitor;
|
||||
import org.commonmark.parser.Parser;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.RETURNS_MOCKS;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(manifest = Config.NONE)
|
||||
public class MarkwonImplTest {
|
||||
|
||||
@Test
|
||||
public void parse_calls_plugin_process_markdown() {
|
||||
|
||||
final MarkwonPlugin plugin = mock(MarkwonPlugin.class);
|
||||
final MarkwonImpl impl = new MarkwonImpl(
|
||||
TextView.BufferType.SPANNABLE,
|
||||
mock(Parser.class),
|
||||
mock(MarkwonVisitor.class),
|
||||
Collections.singletonList(plugin));
|
||||
|
||||
impl.parse("whatever");
|
||||
|
||||
verify(plugin, times(1)).processMarkdown(eq("whatever"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parse_markwon_processed() {
|
||||
|
||||
final Parser parser = mock(Parser.class);
|
||||
|
||||
final MarkwonPlugin first = mock(MarkwonPlugin.class);
|
||||
final MarkwonPlugin second = mock(MarkwonPlugin.class);
|
||||
|
||||
when(first.processMarkdown(anyString())).thenReturn("first");
|
||||
when(second.processMarkdown(anyString())).thenReturn("second");
|
||||
|
||||
final MarkwonImpl impl = new MarkwonImpl(
|
||||
TextView.BufferType.SPANNABLE,
|
||||
parser,
|
||||
mock(MarkwonVisitor.class),
|
||||
Arrays.asList(first, second));
|
||||
|
||||
impl.parse("zero");
|
||||
|
||||
verify(first, times(1)).processMarkdown(eq("zero"));
|
||||
verify(second, times(1)).processMarkdown(eq("first"));
|
||||
|
||||
// verify parser has `second` as input
|
||||
verify(parser, times(1)).parse(eq("second"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void render_calls_plugins() {
|
||||
// before parsing each plugin is called `configureRenderProps` and `beforeRender`
|
||||
// after parsing each plugin is called `afterRender`
|
||||
|
||||
final MarkwonPlugin plugin = mock(MarkwonPlugin.class);
|
||||
|
||||
final MarkwonVisitor visitor = mock(MarkwonVisitor.class);
|
||||
final SpannableBuilder builder = mock(SpannableBuilder.class);
|
||||
|
||||
final MarkwonImpl impl = new MarkwonImpl(
|
||||
TextView.BufferType.SPANNABLE,
|
||||
mock(Parser.class),
|
||||
visitor,
|
||||
Collections.singletonList(plugin));
|
||||
|
||||
when(visitor.builder()).thenReturn(builder);
|
||||
|
||||
final Node node = mock(Node.class);
|
||||
|
||||
final AtomicBoolean flag = new AtomicBoolean(false);
|
||||
|
||||
// we will validate _before_ part here
|
||||
doAnswer(new Answer() {
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) {
|
||||
|
||||
// mark this flag (we must ensure that this method body is executed)
|
||||
flag.set(true);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
verify(plugin, times(1)).configureRenderProps(null);
|
||||
verify(plugin, times(1)).beforeRender(eq(node));
|
||||
verify(plugin, times(0)).afterRender(any(Node.class), any(MarkwonVisitor.class));
|
||||
|
||||
return null;
|
||||
}
|
||||
}).when(node).accept(any(Visitor.class));
|
||||
|
||||
impl.render(node);
|
||||
|
||||
// validate that Answer was called (it has assertions about _before_ part
|
||||
assertTrue(flag.get());
|
||||
|
||||
verify(plugin, times(1)).afterRender(eq(node), eq(visitor));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void render_clears_visitor() {
|
||||
// each render call should have empty-state visitor (no previous rendering info)
|
||||
|
||||
final MarkwonVisitor visitor = mock(MarkwonVisitor.class, RETURNS_MOCKS);
|
||||
|
||||
final MarkwonImpl impl = new MarkwonImpl(
|
||||
TextView.BufferType.SPANNABLE,
|
||||
mock(Parser.class),
|
||||
visitor,
|
||||
Collections.<MarkwonPlugin>emptyList());
|
||||
|
||||
impl.render(mock(Node.class));
|
||||
|
||||
verify(visitor, times(1)).clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void render_props() {
|
||||
// render props are configured properly and cleared after render function
|
||||
|
||||
final MarkwonVisitor visitor = mock(MarkwonVisitor.class, RETURNS_MOCKS);
|
||||
|
||||
final RenderProps renderProps = mock(RenderProps.class);
|
||||
doAnswer(new Answer() {
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) {
|
||||
renderProps.clearAll();
|
||||
return null;
|
||||
}
|
||||
}).when(visitor).clear();
|
||||
|
||||
when(visitor.renderProps()).thenReturn(renderProps);
|
||||
|
||||
final MarkwonPlugin plugin = mock(MarkwonPlugin.class);
|
||||
|
||||
final MarkwonImpl impl = new MarkwonImpl(
|
||||
TextView.BufferType.SPANNABLE,
|
||||
mock(Parser.class),
|
||||
visitor,
|
||||
Collections.singletonList(plugin));
|
||||
|
||||
final AtomicBoolean flag = new AtomicBoolean(false);
|
||||
final Node node = mock(Node.class);
|
||||
|
||||
doAnswer(new Answer() {
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) {
|
||||
|
||||
flag.set(true);
|
||||
|
||||
verify(visitor, times(1)).renderProps();
|
||||
verify(plugin, times(1)).configureRenderProps(eq(renderProps));
|
||||
verify(renderProps, times(0)).clearAll();
|
||||
|
||||
return null;
|
||||
}
|
||||
}).when(node).accept(any(Visitor.class));
|
||||
|
||||
impl.render(node);
|
||||
|
||||
assertTrue(flag.get());
|
||||
|
||||
verify(renderProps, times(1)).clearAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void set_parsed_markdown() {
|
||||
// calls `beforeSetText` on plugins
|
||||
// calls `TextView#setText(text, BUFFER_TYPE)`
|
||||
// calls `afterSetText` on plugins
|
||||
|
||||
final MarkwonPlugin plugin = mock(MarkwonPlugin.class);
|
||||
final MarkwonImpl impl = new MarkwonImpl(
|
||||
TextView.BufferType.EDITABLE,
|
||||
mock(Parser.class),
|
||||
mock(MarkwonVisitor.class, RETURNS_MOCKS),
|
||||
Collections.singletonList(plugin));
|
||||
|
||||
final TextView textView = mock(TextView.class);
|
||||
final AtomicBoolean flag = new AtomicBoolean(false);
|
||||
|
||||
doAnswer(new Answer() {
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) {
|
||||
|
||||
flag.set(true);
|
||||
|
||||
verify(plugin, times(1)).beforeSetText(eq(textView), any(Spanned.class));
|
||||
verify(plugin, times(0)).afterSetText(any(TextView.class));
|
||||
|
||||
final ArgumentCaptor<TextView.BufferType> captor =
|
||||
ArgumentCaptor.forClass(TextView.BufferType.class);
|
||||
|
||||
verify(textView).setText(any(CharSequence.class), captor.capture());
|
||||
assertEquals(TextView.BufferType.EDITABLE, captor.getValue());
|
||||
|
||||
return null;
|
||||
}
|
||||
}).when(textView).setText(any(CharSequence.class), any(TextView.BufferType.class));
|
||||
|
||||
impl.setParsedMarkdown(textView, mock(Spanned.class));
|
||||
|
||||
assertTrue(flag.get());
|
||||
|
||||
verify(plugin, times(1)).afterSetText(eq(textView));
|
||||
}
|
||||
}
|
@ -22,7 +22,6 @@ import ru.noties.markwon.MarkwonConfiguration;
|
||||
import ru.noties.markwon.MarkwonSpansFactory;
|
||||
import ru.noties.markwon.MarkwonVisitor;
|
||||
import ru.noties.markwon.RenderProps;
|
||||
import ru.noties.markwon.RenderPropsImpl;
|
||||
import ru.noties.markwon.SpanFactory;
|
||||
import ru.noties.markwon.SpannableBuilder;
|
||||
import ru.noties.markwon.core.CorePluginBridge;
|
||||
@ -90,7 +89,7 @@ public class SyntaxHighlightTest {
|
||||
|
||||
final MarkwonVisitor visitor = new AbstractMarkwonVisitorImpl(
|
||||
configuration,
|
||||
new RenderPropsImpl(),
|
||||
mock(RenderProps.class),
|
||||
visitorMap);
|
||||
|
||||
final SpannableBuilder builder = visitor.builder();
|
||||
|
Loading…
x
Reference in New Issue
Block a user