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
+
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));
+ }
+}