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
	 Dimitry Ivanov
						Dimitry Ivanov