From 3a9c82c4d0edc6f2cdb08a0a54c940122f6bcb0e Mon Sep 17 00:00:00 2001 From: Andrei Kliuchnikau <58571912+draker94@users.noreply.github.com> Date: Tue, 5 Nov 2024 14:00:22 +0300 Subject: [PATCH] JBEHAVE-1603 Apply transformers from table file at its loading (#80) --- .../src/site/content/tabular-parameters.html | 17 ++++- .../org/jbehave/core/model/ExamplesTable.java | 24 +------ .../core/model/ExamplesTableFactory.java | 8 +++ .../core/model/TableTransformersExecutor.java | 31 +++++++++ .../core/model/ExamplesTableBehaviour.java | 32 ++------- .../model/ExamplesTableFactoryBehaviour.java | 30 +++++++-- .../TableTransformersExecutorBehaviour.java | 65 +++++++++++++++++++ 7 files changed, 149 insertions(+), 58 deletions(-) create mode 100644 jbehave-core/src/main/java/org/jbehave/core/model/TableTransformersExecutor.java create mode 100644 jbehave-core/src/test/java/org/jbehave/core/model/TableTransformersExecutorBehaviour.java diff --git a/distribution/src/site/content/tabular-parameters.html b/distribution/src/site/content/tabular-parameters.html index 50d26af3d..2a7c0d5af 100755 --- a/distribution/src/site/content/tabular-parameters.html +++ b/distribution/src/site/content/tabular-parameters.html @@ -310,7 +310,7 @@

Using values with line breaks

-

Using table transformers

+

Using table transformers

Table transformers allow the table to be transformed via an inlined property. E.g. to transform from a landscape table form we can to use the pre-registered transformer: @@ -382,6 +382,21 @@

Loading tabular parameter from an external resource

]]> +

If the external tabular parameters contains transformers, they will be applied immediately after the resource is loaded. Consequently, transformers from the current story/scenario will be applied subsequently.

+Scenario: +
+Then `https://www.url3.com` is equal to `<urls>`
+Examples:
+{transformer=REPLACING, replacing=url2, replacement=url3}
+/data/links.table
+
+links.table file: +
+{transformer=REPLACING, replacing=url1, replacement=url2}
+|urls                 |
+|https://www.url1.com |
+
+

We need to enable theExamplesTable parameter converter to find the resource with the appropriate resource loader configured via the ExamplesTableFactory

: diff --git a/jbehave-core/src/main/java/org/jbehave/core/model/ExamplesTable.java b/jbehave-core/src/main/java/org/jbehave/core/model/ExamplesTable.java index 954bc4486..809240d8f 100755 --- a/jbehave-core/src/main/java/org/jbehave/core/model/ExamplesTable.java +++ b/jbehave-core/src/main/java/org/jbehave/core/model/ExamplesTable.java @@ -166,7 +166,6 @@ public class ExamplesTable { private Map namedParameters = Collections.emptyMap(); private ParameterControls parameterControls; - private TableTransformerMonitor tableTransformerMonitor; public ExamplesTable(String tableAsString) { this(tableAsString, new TableTransformers()); @@ -195,8 +194,8 @@ private ExamplesTable(String tableAsString, ParameterConverters parameterConvert this.parameterControls = parameterControls; this.defaults = new ConvertedParameters(EMPTY_MAP, parameterConverters); this.tablePropertiesQueue.addAll(tablePropertiesQueue.getProperties()); - this.tableTransformerMonitor = tableTransformerMonitor; - String transformedTable = applyTransformers(tableTransformers, tablePropertiesQueue.getTable(), tableParsers); + String transformedTable = TableTransformersExecutor.applyTransformers(tableTransformers, + tablePropertiesQueue.getTable(), tableParsers, this.tablePropertiesQueue, tableTransformerMonitor); this.tableRows = tableParsers.parseRows(transformedTable, lastTableProperties()); } @@ -212,25 +211,6 @@ private ExamplesTable(ExamplesTable other, Row defaults) { this.defaults = defaults; } - private String applyTransformers(TableTransformers tableTransformers, String tableAsString, - TableParsers tableParsers) { - String transformedTable = tableAsString; - TableProperties previousProperties = null; - for (TableProperties properties : tablePropertiesQueue) { - String transformer = properties.getTransformer(); - if (transformer != null) { - if (previousProperties != null) { - properties.overrideSeparatorsFrom(previousProperties); - } - tableTransformerMonitor.beforeTransformerApplying(transformer, properties, tableAsString); - transformedTable = tableTransformers.transform(transformer, transformedTable, tableParsers, properties); - tableTransformerMonitor.afterTransformerApplying(transformer, properties, transformedTable); - } - previousProperties = properties; - } - return transformedTable; - } - public ExamplesTable withDefaults(Parameters defaults) { return new ExamplesTable(this, new ChainedRow(defaults, this.defaults)); } diff --git a/jbehave-core/src/main/java/org/jbehave/core/model/ExamplesTableFactory.java b/jbehave-core/src/main/java/org/jbehave/core/model/ExamplesTableFactory.java index c4e24cfbb..e163b452b 100755 --- a/jbehave-core/src/main/java/org/jbehave/core/model/ExamplesTableFactory.java +++ b/jbehave-core/src/main/java/org/jbehave/core/model/ExamplesTableFactory.java @@ -95,6 +95,14 @@ public ExamplesTable createExamplesTable(String input) { String loadedTable = resourceLoader.loadResourceAsText(tableAsString.trim()); tablePropertiesQueue = tableParsers.parseProperties(loadedTable); Deque target = tablePropertiesQueue.getProperties(); + + boolean hasTransformers = target.getFirst().getTransformer() != null; + if (hasTransformers) { + loadedTable = TableTransformersExecutor.applyTransformers(tableTransformers, + tablePropertiesQueue.getTable(), tableParsers, target, tableTransformerMonitor); + tablePropertiesQueue = tableParsers.parseProperties(loadedTable); + target = tablePropertiesQueue.getProperties(); + } properties.descendingIterator().forEachRemaining(target::addFirst); } diff --git a/jbehave-core/src/main/java/org/jbehave/core/model/TableTransformersExecutor.java b/jbehave-core/src/main/java/org/jbehave/core/model/TableTransformersExecutor.java new file mode 100644 index 000000000..2f546d45f --- /dev/null +++ b/jbehave-core/src/main/java/org/jbehave/core/model/TableTransformersExecutor.java @@ -0,0 +1,31 @@ +package org.jbehave.core.model; + +import static org.jbehave.core.model.ExamplesTable.TableProperties; + +import java.util.Deque; + +public final class TableTransformersExecutor { + + private TableTransformersExecutor() { + } + + public static String applyTransformers(TableTransformers tableTransformers, String tableAsString, + TableParsers tableParsers, Deque tablePropertiesQueue, + TableTransformerMonitor tableTransformerMonitor) { + String transformedTable = tableAsString; + TableProperties previousProperties = null; + for (TableProperties properties : tablePropertiesQueue) { + String transformer = properties.getTransformer(); + if (transformer != null) { + if (previousProperties != null) { + properties.overrideSeparatorsFrom(previousProperties); + } + tableTransformerMonitor.beforeTransformerApplying(transformer, properties, transformedTable); + transformedTable = tableTransformers.transform(transformer, transformedTable, tableParsers, properties); + tableTransformerMonitor.afterTransformerApplying(transformer, properties, transformedTable); + } + previousProperties = properties; + } + return transformedTable; + } +} diff --git a/jbehave-core/src/test/java/org/jbehave/core/model/ExamplesTableBehaviour.java b/jbehave-core/src/test/java/org/jbehave/core/model/ExamplesTableBehaviour.java index c034130d1..87d848b13 100755 --- a/jbehave-core/src/test/java/org/jbehave/core/model/ExamplesTableBehaviour.java +++ b/jbehave-core/src/test/java/org/jbehave/core/model/ExamplesTableBehaviour.java @@ -12,10 +12,6 @@ import static org.junit.jupiter.api.Assertions.assertNotSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.params.provider.Arguments.arguments; -import static org.mockito.ArgumentMatchers.argThat; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; import java.beans.BeanInfo; import java.beans.IntrospectionException; @@ -329,7 +325,7 @@ void shouldParseTableWithSequenceOfTransformers() { properties.getProperties().setProperty("valueSeparator", "!"); return tableAsString.replace('|', '!'); }); - ExamplesTableFactory factory = createFactory(tableTransformers, new NullTableTransformerMonitor()); + ExamplesTableFactory factory = createFactory(tableTransformers); ExamplesTable table = factory.createExamplesTable(tableWithProperties); Properties properties = table.getProperties(); assertThat(properties.getProperty("transformer"), equalTo("FROM_LANDSCAPE")); @@ -705,32 +701,12 @@ void shouldReturnNamedRowFromJaggedTable() { assertEquals(expected, table.getRow(1)); } - @Test - void shouldUseCustomTableTransformerMonitor() { - String table = "|key|\n|value|"; - String transformerName = "ANY_TRANSFORMER"; - String propertiesAsString = String.format("transformer=%s, property=any_property", transformerName); - - TableTransformers transformers = new TableTransformers(); - transformers.useTransformer(transformerName, (input, parser, props) -> input); - TableTransformerMonitor tableTransformerMonitor = mock(TableTransformerMonitor.class); - ExamplesTableFactory factory = createFactory(transformers, tableTransformerMonitor); - factory.createExamplesTable(String.format("{%s}\n%s", propertiesAsString, table)); - - verify(tableTransformerMonitor).beforeTransformerApplying(eq(transformerName), argThat( - p -> p.getPropertiesAsString().equals(propertiesAsString)), eq(table)); - verify(tableTransformerMonitor).afterTransformerApplying(eq(transformerName), argThat( - p -> p.getPropertiesAsString().equals(propertiesAsString)), eq(table)); - } - private ExamplesTableFactory createFactory(ParameterConverter... converters) { TableTransformers tableTransformers = new TableTransformers(); - return createFactory(tableTransformers, new NullTableTransformerMonitor(), converters); + return createFactory(tableTransformers, converters); } - private ExamplesTableFactory createFactory(TableTransformers tableTransformers, - TableTransformerMonitor transformerMonitor, - ParameterConverter... converters) { + private ExamplesTableFactory createFactory(TableTransformers tableTransformers, ParameterConverter... converters) { LoadFromClasspath resourceLoader = new LoadFromClasspath(); ParameterControls parameterControls = new ParameterControls(); ParameterConverters parameterConverters = new ParameterConverters(resourceLoader, parameterControls, @@ -739,7 +715,7 @@ private ExamplesTableFactory createFactory(TableTransformers tableTransformers, TableParsers tableParsers = new TableParsers(keywords, parameterConverters); parameterConverters.addConverters(converters); return new ExamplesTableFactory(keywords, resourceLoader, parameterConverters, parameterControls, tableParsers, - tableTransformers, transformerMonitor); + tableTransformers, new NullTableTransformerMonitor()); } private void assertTableAsString(String tableAsString, String expectedTableAsString) { diff --git a/jbehave-core/src/test/java/org/jbehave/core/model/ExamplesTableFactoryBehaviour.java b/jbehave-core/src/test/java/org/jbehave/core/model/ExamplesTableFactoryBehaviour.java index 2d21fe82b..36cc06ab6 100755 --- a/jbehave-core/src/test/java/org/jbehave/core/model/ExamplesTableFactoryBehaviour.java +++ b/jbehave-core/src/test/java/org/jbehave/core/model/ExamplesTableFactoryBehaviour.java @@ -110,20 +110,36 @@ void shouldCreateExamplesTableFromTableInputWithInlinedSeparatorsHavingSpacesAtS } @Test - void shouldTestTransformersOrderForExamplesTableFromResourceInput() { + void shouldLoadAndProperlyApplyTransformersForExamplesTableFromResourceInput() { // Given ResourceLoader resourceLoader = mock(ResourceLoader.class); + String lineFromFirstOuterTransformer = "|one|two|"; + String lineFromSecondOuterTransformer = "\n|11|12|"; + String lineFromFirstInnerTransformer = "\n|13|14|"; + String lineFromSecondInnerTransformer = "\n|15|16|\n"; TableTransformers tableTransformers = new TableTransformers(); - tableTransformers.useTransformer("CUSTOM_TRANSFORMER1", (input, parser, props) -> input); - tableTransformers.useTransformer("CUSTOM_TRANSFORMER2", (input, parser, props) -> input); + tableTransformers.useTransformer("CUSTOM_TRANSFORMER1", (input, parser, props) -> + input + lineFromFirstOuterTransformer); + tableTransformers.useTransformer("CUSTOM_TRANSFORMER2", (input, parser, props) -> + input + lineFromSecondOuterTransformer); + tableTransformers.useTransformer("CUSTOM_TRANSFORMER3", (input, parser, props) -> + input + lineFromFirstInnerTransformer); + tableTransformers.useTransformer("CUSTOM_TRANSFORMER4", (input, parser, props) -> + input + lineFromSecondInnerTransformer); ExamplesTableFactory factory = new ExamplesTableFactory(resourceLoader, tableTransformers); - String transformers = "{transformer=CUSTOM_TRANSFORMER1}\n{transformer=CUSTOM_TRANSFORMER2}\n"; + String outerTransformers = "{transformer=CUSTOM_TRANSFORMER1}\n{transformer=CUSTOM_TRANSFORMER2}\n"; + String innerTransformers = "{transformer=CUSTOM_TRANSFORMER3}\n{transformer=CUSTOM_TRANSFORMER4}\n"; // When - when(resourceLoader.loadResourceAsText(RESOURCE_PATH)).thenReturn(TABLE_AS_STRING); - ExamplesTable examplesTable = factory.createExamplesTable(transformers + RESOURCE_PATH); + when(resourceLoader.loadResourceAsText(RESOURCE_PATH)).thenReturn(outerTransformers); + ExamplesTable examplesTable = factory.createExamplesTable(innerTransformers + RESOURCE_PATH); // Then - assertThat(examplesTable.asString(), equalTo(transformers + TABLE_AS_STRING)); + assertThat(examplesTable.asString(), equalTo( + innerTransformers + + lineFromFirstOuterTransformer + + lineFromSecondOuterTransformer + + lineFromFirstInnerTransformer + + lineFromSecondInnerTransformer)); } } diff --git a/jbehave-core/src/test/java/org/jbehave/core/model/TableTransformersExecutorBehaviour.java b/jbehave-core/src/test/java/org/jbehave/core/model/TableTransformersExecutorBehaviour.java new file mode 100644 index 000000000..39493615b --- /dev/null +++ b/jbehave-core/src/test/java/org/jbehave/core/model/TableTransformersExecutorBehaviour.java @@ -0,0 +1,65 @@ +package org.jbehave.core.model; + +import static org.jbehave.core.model.ExamplesTable.TableProperties; +import static org.jbehave.core.model.ExamplesTable.TablePropertiesQueue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import java.util.Deque; + +import org.jbehave.core.i18n.LocalizedKeywords; +import org.jbehave.core.io.LoadFromClasspath; +import org.jbehave.core.steps.ParameterControls; +import org.jbehave.core.steps.ParameterConverters; +import org.junit.jupiter.api.Test; + +class TableTransformersExecutorBehaviour { + + private static final TableTransformers TRANSFORMERS = new TableTransformers(); + private static final ParameterConverters PARAMETER_CONVERTERS = new ParameterConverters( + new LoadFromClasspath(), new ParameterControls(), TRANSFORMERS, true); + private static final TableParsers TABLE_PARSERS = new TableParsers(new LocalizedKeywords(), PARAMETER_CONVERTERS); + + @Test + void shouldApplyTransformers() { + String table = "|key|\n!value0!"; + String lineFromFirstTransformer = "\n!value1!"; + String lineFromSecondTransformer = "\n!value2!"; + String tableTransformed = table + lineFromFirstTransformer + lineFromSecondTransformer; + String firstTransformerName = "FIRST_TRANSFORMER"; + String firstPropertiesAsString = String.format("transformer=%s, property=any_property1, valueSeparator=!", + firstTransformerName); + String secondTransformerName = "SECOND_TRANSFORMER"; + String secondPropertiesAsString = String.format( + "transformer=%s, property=any_property2", secondTransformerName); + TablePropertiesQueue tablePropertiesQueue = TABLE_PARSERS.parseProperties( + "{" + firstPropertiesAsString + "}" + + "{" + secondPropertiesAsString + "}" + + "\n" + + table); + Deque tableProperties = tablePropertiesQueue.getProperties(); + + + TRANSFORMERS.useTransformer(firstTransformerName, (tableAsString, tableParsers, properties) -> + tableAsString + lineFromFirstTransformer); + TRANSFORMERS.useTransformer(secondTransformerName, (tableAsString, tableParsers, properties) -> + tableAsString + lineFromSecondTransformer); + TableTransformerMonitor tableTransformerMonitor = mock(TableTransformerMonitor.class); + String output = TableTransformersExecutor.applyTransformers( + TRANSFORMERS, table, TABLE_PARSERS, tableProperties, tableTransformerMonitor); + + assertEquals(tableTransformed, output); + verify(tableTransformerMonitor).beforeTransformerApplying(eq(firstTransformerName), argThat( + p -> p.getPropertiesAsString().equals(firstPropertiesAsString)), eq(table)); + verify(tableTransformerMonitor).afterTransformerApplying(eq(firstTransformerName), argThat(p -> + p.getPropertiesAsString().equals(firstPropertiesAsString)), eq(table + lineFromFirstTransformer)); + verify(tableTransformerMonitor).beforeTransformerApplying(eq(secondTransformerName), argThat(p -> + p.getPropertiesAsString().equals(secondPropertiesAsString)), eq(table + lineFromFirstTransformer)); + verify(tableTransformerMonitor).afterTransformerApplying(eq(secondTransformerName), argThat( + p -> p.getPropertiesAsString().equals(secondPropertiesAsString)), + eq(table + lineFromFirstTransformer + lineFromSecondTransformer)); + } +}