diff --git a/CucumberSwift/Extensions/CharacterExtensions.swift b/CucumberSwift/Extensions/CharacterExtensions.swift index 81816631..f259ce5b 100644 --- a/CucumberSwift/Extensions/CharacterExtensions.swift +++ b/CucumberSwift/Extensions/CharacterExtensions.swift @@ -41,8 +41,7 @@ extension Character { isNewline || isTagMarker || isQuote || -// isNumeric || -// isDecimal || + isNumeric || isTableCellDelimiter || isHeaderToken } diff --git a/CucumberSwift/Gherkin/Lexer.swift b/CucumberSwift/Gherkin/Lexer.swift index ea400315..63c36a08 100644 --- a/CucumberSwift/Gherkin/Lexer.swift +++ b/CucumberSwift/Gherkin/Lexer.swift @@ -122,6 +122,8 @@ class Lexer { let str = readLineUntil{ $0.isQuote } advanceIndex() return .string(str) + } else if char.isNumeric { + return .integer(readLineUntil{ !$0.isNumeric }) } else if let _ = lastKeyword { return .match(readLineUntil{ $0.isSymbol }) } else { diff --git a/CucumberSwift/Gherkin/Parser/Step.swift b/CucumberSwift/Gherkin/Parser/Step.swift index f37af533..66c02206 100644 --- a/CucumberSwift/Gherkin/Parser/Step.swift +++ b/CucumberSwift/Gherkin/Parser/Step.swift @@ -33,6 +33,8 @@ public class Step : NSObject { match += m } else if case Token.string(let s) = token { match += "\"\(s)\"" + } else if case Token.integer(let n) = token { + match += n } } let tableLines = node.tokens diff --git a/CucumberSwift/Gherkin/Token.swift b/CucumberSwift/Gherkin/Token.swift index 8bf1f234..3e0ed4bf 100644 --- a/CucumberSwift/Gherkin/Token.swift +++ b/CucumberSwift/Gherkin/Token.swift @@ -29,8 +29,7 @@ extension Sequence where Element == Token { enum Token: Equatable { case newLine -// case integer(Int) -// case double(Double) + case integer(String) case string(String) case match(String) case title(String) @@ -53,10 +52,8 @@ enum Token: Equatable { return description1 == description2 case let (.tag(tag1), .tag(tag2)): return tag1 == tag2 -// case let (.integer(int1), .integer(int2)): -// return int1 == int2 -// case let (.double(double1), .double(double2)): -// return double1 == double2 + case let (.integer(num1), .integer(num2)): + return num1 == num2 case let (.string(string1), .string(string2)): return string1 == string2 case let (.tableHeader(tableHeader1), .tableHeader(tableHeader2)): @@ -92,4 +89,10 @@ enum Token: Equatable { } return false } + func isInteger() -> Bool { + if case .integer(_) = self { + return true + } + return false + } } diff --git a/CucumberSwift/StubGeneration/StubGenerator.swift b/CucumberSwift/StubGeneration/StubGenerator.swift index cd9d1b7c..d1b26733 100644 --- a/CucumberSwift/StubGeneration/StubGenerator.swift +++ b/CucumberSwift/StubGeneration/StubGenerator.swift @@ -33,6 +33,8 @@ class StubGenerator { .replacingOccurrences(of: "\"", with: "\\\"", options: [], range: nil) } else if case Token.string(_) = token { regex += "\\\"(.*?)\\\"" + } else if case Token.integer(_) = token { + regex += "(\\\\d+)" } } return regex.trimmingCharacters(in: .whitespaces) @@ -46,8 +48,11 @@ class StubGenerator { executableSteps.filter{ $0.execute == nil }.forEach { let regex = regexForTokens($0.tokens) let stringCount = $0.tokens.filter { $0.isString() }.count - let matchesParameter = (stringCount > 0) ? "matches" : "_" - var method = Method(keyword: $0.keyword, regex: regex, matchesParameter: matchesParameter, variables: [(type: "string", count: stringCount)]) + let integerCount = $0.tokens.filter { $0.isInteger() }.count + let matchesParameter = (stringCount > 0 || integerCount > 0) ? "matches" : "_" + let variables = [(type: "string", count: stringCount), + (type: "integer", count: integerCount)] + var method = Method(keyword: $0.keyword, regex: regex, matchesParameter: matchesParameter, variables: variables) if let m = lookup[regex] { method = m if (!method.keyword.contains($0.keyword)) { diff --git a/CucumberSwiftTests/Gherkin/ParserTests.swift b/CucumberSwiftTests/Gherkin/ParserTests.swift index 3ac3c506..6b9693b4 100644 --- a/CucumberSwiftTests/Gherkin/ParserTests.swift +++ b/CucumberSwiftTests/Gherkin/ParserTests.swift @@ -185,5 +185,6 @@ class ParserTests: XCTestCase { XCTAssertEqual(scenario?.steps[3].keyword, .then) XCTAssertEqual(scenario?.steps[3].match, "it works") } + cucumber.executeFeatures() } } diff --git a/CucumberSwiftTests/StepGenerationTests.swift b/CucumberSwiftTests/StepGenerationTests.swift index ee4b61e2..ce9d7b9d 100644 --- a/CucumberSwiftTests/StepGenerationTests.swift +++ b/CucumberSwiftTests/StepGenerationTests.swift @@ -175,4 +175,35 @@ class StepGenerationTests:XCTestCase { """ XCTAssertEqual(actual, expected) } + + func testGeneratedRegexWithIntegerLiteral() { + let cucumber = Cucumber(withString: """ + Feature: Some terse yet descriptive text of what is desired + Scenario: Some determinable business situation + Given I login 1 time + """) + let actual = cucumber.generateUnimplementedStepDefinitions() + let expected = """ + cucumber.Given("^I login (\\\\d+) time$") { matches, _ in + let integerOne = matches[1] + } + """ + XCTAssert(actual.contains(expected), "\"\(actual)\" does not contain \"\(expected)\"") + } + + func testGeneratedRegexWithMultipleIntegerLiterals() { + let cucumber = Cucumber(withString: """ + Feature: Some terse yet descriptive text of what is desired + Scenario: Some determinable business situation + Given I enter 1234 then 4321 + """) + let actual = cucumber.generateUnimplementedStepDefinitions() + let expected = """ + cucumber.Given("^I enter (\\\\d+) then (\\\\d+)$") { matches, _ in + let integerOne = matches[1] + let integerTwo = matches[2] + } + """ + XCTAssert(actual.contains(expected), "\"\(actual)\" does not contain \"\(expected)\"") + } }