Commit f4947e29 authored by Michael Hamann's avatar Michael Hamann
Browse files

XRENDERING-631: The annotated HTML5 renderer should not render figcaption inside macros

* Refactor BlockStateChainingListenerTest to use parameterized tests.
parent c1a4522e
......@@ -27,8 +27,10 @@
import org.apache.commons.text.CaseUtils;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
import org.junit.jupiter.api.Named;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.stubbing.Stubber;
import org.xwiki.rendering.listener.Format;
import org.xwiki.rendering.listener.HeaderLevel;
......@@ -40,6 +42,7 @@
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.jupiter.params.provider.Arguments.arguments;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
......@@ -50,7 +53,7 @@
* @version $Id$
* @since 14.0RC1
*/
public class BlockStateChainingListenerTest
class BlockStateChainingListenerTest
{
private BlockStateChainingListener listener;
......@@ -67,52 +70,46 @@ void setUpChain()
}
/**
* Tests for all "begin/end"-methods if they do not modify the parent event (for the next in the chain) in the
* begin-method, correctly set it afterwards and if the previous event is correctly set, but only after the end
* event has been forwarded in the chain.
* @return A stream of {@link Arguments} consisting each all begin-methods of the {@link Listener} interface,
* each with the matching end method and suitable parameters.
*/
@TestFactory
Stream<DynamicTest> beginEndMethods()
static Stream<Arguments> beginEndMethodProvider()
{
return Arrays.stream(Listener.class.getMethods())
.filter(m -> m.getName().startsWith("begin"))
.map(beginMethod ->
DynamicTest.dynamicTest(getTestName(beginMethod),
() -> testBeginEndMethod(beginMethod)));
return Arrays.stream(Listener.class.getMethods()).filter(m -> m.getName().startsWith("begin")).map(m -> {
String endMethodName = m.getName().replace("begin", "end");
Method endMethod = null;
try {
endMethod = Listener.class.getMethod(endMethodName, m.getParameterTypes());
} catch (NoSuchMethodException e) {
fail("Expected end method " + endMethodName + " for " + m.getName() + " not found: " + e.getMessage());
}
return arguments(
Named.of(getTestName(m), m),
Named.of(getTestName(endMethod), endMethod),
getMockParameters(m)
);
});
}
/**
* Tests for all "on..." methods if they do not modify the parent event (for the next in the chain) and if the
* previous event is correctly set, but only after the event has been forwarded in the chain.
* Test all begin/end-methods.
*
* Tests for all "begin/end"-methods if they do not modify the parent event (for the next in the chain) in the
* begin-method, correctly set it afterwards and if the previous event is correctly set, but only after the end
* event has been forwarded in the chain.
*
* @param beginMethod The method to begin the container.
* @param endMethod The corresponding end method.
* @param parameters Suitable parameters for both methods.
*/
@TestFactory
Stream<DynamicTest> onMethods()
@ParameterizedTest(name = "{0} and {1} with {2}")
@MethodSource("beginEndMethodProvider")
void testBeginEndMethod(Method beginMethod, Method endMethod, Object[] parameters)
throws InvocationTargetException, IllegalAccessException
{
return Arrays.stream(Listener.class.getMethods())
.filter(m -> m.getName().startsWith("on"))
.map(beginMethod ->
DynamicTest.dynamicTest(getTestName(beginMethod),
() -> testOnMethod(beginMethod)));
}
private String getTestName(Method method)
{
return method.getName() + "(" + Arrays.stream(method.getParameterTypes()).map(Class::getName)
.collect(Collectors.joining(", ")) + ")";
}
private void testBeginEndMethod(Method beginMethod)
{
String endMethodName = beginMethod.getName().replace("begin", "end");
Class<?>[] parameterClasses = beginMethod.getParameterTypes();
try {
Method endMethod = Listener.class.getMethod(endMethodName, parameterClasses);
boolean isListItem = beginMethod.getName().equals("beginListItem");
boolean isDefinitionItem =
beginMethod.getName().equals("beginDefinitionTerm") || beginMethod.getName().equals(
"beginDefinitionDescription");
boolean isDefinitionItem = beginMethod.getName().equals("beginDefinitionTerm") || beginMethod.getName()
.equals("beginDefinitionDescription");
BlockStateChainingListener.Event expectedParentEvent;
......@@ -126,8 +123,6 @@ private void testBeginEndMethod(Method beginMethod)
expectedParentEvent = null;
}
Object[] parameters = Arrays.stream(parameterClasses).map(this::mockParameter).toArray();
this.listener.onId("MockID");
Stubber verifyPreviousAndParentEventStubber = doAnswer(invocation -> {
......@@ -171,17 +166,33 @@ private void testBeginEndMethod(Method beginMethod)
}
assertNull(this.listener.getParentEvent());
} catch (NoSuchMethodException e) {
fail("Expected end method " + endMethodName + " for " + beginMethod.getName() + " not found: "
+ e.getMessage());
} catch (InvocationTargetException e) {
fail("Listener method has thrown exception: " + e.getMessage());
} catch (IllegalAccessException e) {
fail("Listener method not callable: " + e.getMessage());
}
/**
* @return A stream of {@link Arguments} consisting each of all "on"-method of the {@link Listener} interface and
* suitable parameters.
*/
static Stream<Arguments> onMethodsProvider()
{
return Arrays.stream(Listener.class.getMethods())
.filter(m -> m.getName().startsWith("on")).map(m -> arguments(
Named.of(getTestName(m), m),
getMockParameters(m)
));
}
private void testOnMethod(Method method)
/**
* Test the "on"-methods of the {@link Listener} interface.
*
* Tests for all "on..." methods if they do not modify the parent event (for the next in the chain) and if the
* previous event is correctly set, but only after the event has been forwarded in the chain.
*
* @param method The "on"-method.
* @param parameters Suitable parameters for the method.
*/
@ParameterizedTest(name = "{0} with {1}")
@MethodSource("onMethodsProvider")
void testOnMethod(Method method, Object[] parameters) throws InvocationTargetException, IllegalAccessException
{
this.listener.beginDocument(MetaData.EMPTY);
......@@ -189,9 +200,6 @@ private void testOnMethod(Method method)
this.listener.beginParagraph(Listener.EMPTY_PARAMETERS);
this.listener.endParagraph(Listener.EMPTY_PARAMETERS);
Object[] parameters = Arrays.stream(method.getParameterTypes()).map(this::mockParameter).toArray();
try {
// Verify that the next in the chain still gets the old previous event and that the parent is not
// changed.
method.invoke(
......@@ -209,11 +217,6 @@ private void testOnMethod(Method method)
// Verify that the call has been correctly forwarded.
method.invoke(verify(this.mockListener), parameters);
} catch (InvocationTargetException e) {
fail("Listener method has thrown exception: " + e.getMessage());
} catch (IllegalAccessException e) {
fail("Listener method not callable: " + e.getMessage());
}
// Check if the previous event is the expected event.
String previousEventName = this.listener.getPreviousEvent().name();
......@@ -230,11 +233,30 @@ private void testOnMethod(Method method)
this.listener.endDocument(MetaData.EMPTY);
}
/**
* @param method The method to get a name for.
* @return The name of the method without class but with all parameter types.
*/
static private String getTestName(Method method)
{
return method.getName() + "(" + Arrays.stream(method.getParameterTypes()).map(Class::getName)
.collect(Collectors.joining(", ")) + ")";
}
/**
* @param method The method to get parameters for.
* @return A mock object or value for each expected parameter.
*/
static private Object getMockParameters(Method method)
{
return Arrays.stream(method.getParameterTypes()).map(BlockStateChainingListenerTest::mockParameter).toArray();
}
/**
* @param classToMock The class to return a mock object for.
* @return Either a mock object or in the case of an enum or primitive type a concrete value.
*/
private Object mockParameter(Class<?> classToMock)
static private Object mockParameter(Class<?> classToMock)
{
if (classToMock.equals(Format.class)) {
return Format.BOLD;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment