Description
The following is a valid gherkin document with two empty tables according to the gherkin/java 18.1.1 parser. However at a glance the tables do not look empty.
Feature: Empty tables?
Scenario: This is valid Gherkin
Given a non-empty list
| hello
Feature: Empty tables?
Scenario Outline: This is also valid Gherkin
Given a step <hello>
Examples:
| hello
For more complex tables this will confuse users about what their tables actually contain. This can be especially insidious when tables are automatically transformed into POJO's and used as DTOs. It also has knock on effects on other parts of Cucumber. For example in this SO question, the user is confused about incorrect step definitions generated by ignoring the unfinished table cell.
It is essential that a users are not mislead about the contents of a table. So when encountering an unfinished table cell, i.e. any non-whitespace characters after the last |
on a table row line I would expect the parser to throw an exception and explain the problem.
import io.cucumber.gherkin.Gherkin;
import io.cucumber.messages.Messages;
import org.junit.jupiter.api.Test;
import java.util.UUID;
import static io.cucumber.gherkin.Gherkin.makeSourceEnvelope;
import static java.util.Collections.singletonList;
import static org.junit.jupiter.api.Assertions.assertEquals;
class FeatureParserTest {
@Test
void non_empty_table() {
String source = "" +
"Feature: Empty table?\n" +
" Scenario: This is valid Gherkin\n" +
" Given a non-empty list\n" +
" | hello \n";
Messages.PickleStepArgument.PickleTable pickleTable = Gherkin.fromSources(
singletonList(makeSourceEnvelope(source, "table.feature")),
false,
false,
true,
() -> UUID.randomUUID().toString()
)
.map(Messages.Envelope::getPickle)
.map(pickle -> pickle.getSteps(0))
.map(Messages.Pickle.PickleStep::getArgument)
.map(Messages.PickleStepArgument::getDataTable)
.findFirst()
.get();
assertEquals(1, pickleTable.getRowsList().size());
assertEquals(1, pickleTable.getRows(0).getCellsCount()); // fails, table is empty
}
@Test
void one_example() {
String source = "" +
"Feature: Single example?\n" +
" Scenario Outline: This is valid Gherkin\n" +
" Given a step <hello>\n" +
" Examples: \n" +
" | hello \n";
Messages.GherkinDocument.Feature.TableRow row = Gherkin.fromSources(
singletonList(makeSourceEnvelope(source, "table.feature")),
false,
true,
false,
() -> UUID.randomUUID().toString()
)
.filter(Messages.Envelope::hasGherkinDocument)
.map(Messages.Envelope::getGherkinDocument)
.map(Messages.GherkinDocument::getFeature)
.map(feature -> feature.getChildren(0))
.map(Messages.GherkinDocument.Feature.FeatureChild::getScenario)
.map(Messages.GherkinDocument.Feature.Scenario::getExamplesList)
.map(examples -> examples.get(0))
.map(Messages.GherkinDocument.Feature.Scenario.Examples::getTableHeader)
.findFirst()
.get();
assertEquals(1, row.getCellsCount()); // fails, table is empty
}
}
Activity