Skip to content

Commit

Permalink
[main] - Remove error checking on table headers since it does not app…
Browse files Browse the repository at this point in the history
…ear to be part of the spec and resolve all known issues around table header parsing - TT
  • Loading branch information
Tyler-Keith-Thompson committed Mar 26, 2023
1 parent fd0ca24 commit 822269f
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 38 deletions.
8 changes: 2 additions & 6 deletions Sources/CucumberSwift/Gherkin/Lexer/Lexer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,25 +55,21 @@ public class Lexer: StringReader {
}
if char == .tableHeaderOpen {
isTableHeader = true
advanceIndex()
continue
}
if char == .tableHeaderClose {
tableHeaderClosed = true
advanceIndex()
continue
}
if char.isTableCellDelimiter {
if isTableHeader && !tableHeaderClosed {
Gherkin.errors.append("File: \(url?.lastPathComponent ?? ""), table header not closed in table cell")
isTableHeader = false
}
break
}
str.append(char)
advanceIndex()
}
if isTableHeader {
return .tableHeader(position, str.trimmingCharacters(in: .whitespaces))
return .tableHeader(position, String(str.trimmingCharacters(in: .whitespaces).dropFirst().dropLast().trimmingCharacters(in: .whitespaces)))
} else {
return .match(position, str.trimmingCharacters(in: .whitespaces))
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/CucumberSwift/Gherkin/Parser/Step.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public class Step: CustomStringConvertible {
.map { token -> String in
if case Lexer.Token.tableCell(_, let cellToken) = token {
if case Lexer.Token.tableHeader = cellToken {
Gherkin.errors.append("File: \(cellToken.position.uri?.lastPathComponent ?? ""), table header <\(cellToken.valueDescription)> not found")
return "<\(cellToken.valueDescription)>"
}
return cellToken.valueDescription
}
Expand Down
6 changes: 2 additions & 4 deletions Tests/CucumberSwiftTests/CucumberTests/CucumberTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,8 @@ class CucumberTests: XCTestCase {
if let cells = row["cells"] as? [[String: Any]] {
XCTAssertEqual(dRow?.count, cells.count, "Row on DataTable doesn't have correct cells in: \(fileName)")
for (cellIndex, cell) in cells.enumerated() {
// slight hack to get around the fact we're comparing against parsed output
if let value = cell["value"] as? String,
let unwrappedValue = try? /^\<?(.*?)\>?$/.firstMatch(in: value) {
XCTAssertEqual(String(unwrappedValue.1), dRow?[safe: cellIndex], fileName)
if let value = cell["value"] as? String {
XCTAssertEqual(String(value), dRow?[safe: cellIndex], fileName)
}
}
}
Expand Down
27 changes: 0 additions & 27 deletions Tests/CucumberSwiftTests/Gherkin/ErrorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,33 +82,6 @@ class ErrorsTests: XCTestCase {
XCTAssert(Gherkin.errors.contains("File: single_parser_error.feature, expected: #EOF, #Language, #TagLine, #FeatureLine, #Comment, #Empty, got 'invalid line here'"))
}

func testTableHeaderNotClosedInCell() {
Cucumber.shared.parseIntoFeatures("""
Feature: Sample
Scenario Outline: Sample scenario
Then I have a sample step
| <paramA | <paramB> |
Examples:
| paramA | paramB |
| 0 | 1 |
""", uri: "table_header_not_closed_in_cell.feature")
XCTAssert(Gherkin.errors.contains("File: table_header_not_closed_in_cell.feature, table header not closed in table cell"))
}

func testTableHeaderNotFound() {
Cucumber.shared.parseIntoFeatures("""
Feature: Sample
Scenario: minimalistic
Given a simple data table
| <foo> | <bar> |
""", uri: "table_header_not_found.feature")
XCTAssert(Gherkin.errors.contains("File: table_header_not_found.feature, table header <foo> not found"))
XCTAssert(Gherkin.errors.contains("File: table_header_not_found.feature, table header <bar> not found"))
}

override func tearDown() {
Gherkin.errors.removeAll()
}
Expand Down
99 changes: 99 additions & 0 deletions Tests/CucumberSwiftTests/Gherkin/TableTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,36 @@ class TableTests: XCTestCase {
XCTAssertEqual(thenCalled, 2)
}

func testUnclosedTableHeader() {
Cucumber.shared.features.removeAll()
Cucumber.shared.parseIntoFeatures("""
Feature: Sample
Scenario: Scenario description
Given Something
When Something is done
Then the data looks like:
| speed | <9000 |
| size | >12000 |
""")

let scenario = Cucumber.shared.features.first?.scenarios.first
let step = scenario?.steps.last
let table = step?.dataTable
let firstRow = table?.rows.first
XCTAssertNotNil(step?.dataTable)
XCTAssertEqual(table?.rows.count, 2)
XCTAssertEqual(firstRow?.count, 2)
guard table?.rows.count == 2, firstRow?.count == 2 else { return }
XCTAssertEqual(firstRow?[0], "speed")
XCTAssertEqual(firstRow?[1], "<9000")

XCTAssertEqual(table?.rows[1][0], "size")
XCTAssertEqual(table?.rows[1][1], ">12000")

XCTAssert(Gherkin.errors.isEmpty)
Cucumber.shared.executeFeatures()
}

func testDataTableOnStepCanEscape() {
Cucumber.shared.features.removeAll()
Cucumber.shared.parseIntoFeatures(#"""
Expand Down Expand Up @@ -367,6 +397,75 @@ class TableTests: XCTestCase {
Cucumber.shared.executeFeatures()
}

func testComplexDataAttachedToStep() {
Cucumber.shared.features.removeAll()
Cucumber.shared.parseIntoFeatures("""
Feature: Some terse yet descriptive text of what is desired
Scenario: minimalistic
Given a simple data table
Then User should see log entries:
| TYPE | NAME | SUMMARY | LABEL | ACTIONS |
| missed | 01/06/2021 | Missed check | | <none> |
| missed | 01/05/2021 | Missed check | | <none> |
| checked | 01/04/2021 | Logged by Test user | | <none> |
| checked | 01/03/2021 | Logged by Test user | | <none> |
| ignored | 01/02/2021 | Ignored by Test user | (Ignored) | <none> |
| ignored | 01/01/2021 | Ignored by Test user | (Ignored) | <none> |
""")
let scenario = Cucumber.shared.features.first?.scenarios.first
let step = scenario?.steps.last
let table = step?.dataTable
let firstRow = table?.rows.first
XCTAssertNotNil(step?.dataTable)
XCTAssertEqual(table?.rows.count, 7)
XCTAssertEqual(firstRow?.count, 5)
guard table?.rows.count == 7, firstRow?.count == 5 else { return }
XCTAssertEqual(firstRow?[0], "TYPE")
XCTAssertEqual(firstRow?[1], "NAME")
XCTAssertEqual(firstRow?[2], "SUMMARY")
XCTAssertEqual(firstRow?[3], "LABEL")
XCTAssertEqual(firstRow?[4], "ACTIONS")

XCTAssertEqual(table?.rows[1][0], "missed")
XCTAssertEqual(table?.rows[1][1], "01/06/2021")
XCTAssertEqual(table?.rows[1][2], "Missed check")
XCTAssertEqual(table?.rows[1][3], "")
XCTAssertEqual(table?.rows[1][4], "<none>")

XCTAssertEqual(table?.rows[2][0], "missed")
XCTAssertEqual(table?.rows[2][1], "01/05/2021")
XCTAssertEqual(table?.rows[2][2], "Missed check")
XCTAssertEqual(table?.rows[2][3], "")
XCTAssertEqual(table?.rows[2][4], "<none>")

XCTAssertEqual(table?.rows[3][0], "checked")
XCTAssertEqual(table?.rows[3][1], "01/04/2021")
XCTAssertEqual(table?.rows[3][2], "Logged by Test user")
XCTAssertEqual(table?.rows[3][3], "")
XCTAssertEqual(table?.rows[3][4], "<none>")

XCTAssertEqual(table?.rows[4][0], "checked")
XCTAssertEqual(table?.rows[4][1], "01/03/2021")
XCTAssertEqual(table?.rows[4][2], "Logged by Test user")
XCTAssertEqual(table?.rows[4][3], "")
XCTAssertEqual(table?.rows[4][4], "<none>")

XCTAssertEqual(table?.rows[5][0], "ignored")
XCTAssertEqual(table?.rows[5][1], "01/02/2021")
XCTAssertEqual(table?.rows[5][2], "Ignored by Test user")
XCTAssertEqual(table?.rows[5][3], "(Ignored)")
XCTAssertEqual(table?.rows[5][4], "<none>")

XCTAssertEqual(table?.rows[6][0], "ignored")
XCTAssertEqual(table?.rows[6][1], "01/01/2021")
XCTAssertEqual(table?.rows[6][2], "Ignored by Test user")
XCTAssertEqual(table?.rows[6][3], "(Ignored)")
XCTAssertEqual(table?.rows[6][4], "<none>")

XCTAssert(Gherkin.errors.isEmpty)
Cucumber.shared.executeFeatures()
}

func testScenarioOutlineWithMultipleExamples() {
Cucumber.shared.features.removeAll()
Cucumber.shared.parseIntoFeatures("""
Expand Down

0 comments on commit 822269f

Please sign in to comment.