diff --git a/src/nl2gherkin/gherkin/parser.py b/src/nl2gherkin/gherkin/parser.py index e8b9585..41f25a9 100644 --- a/src/nl2gherkin/gherkin/parser.py +++ b/src/nl2gherkin/gherkin/parser.py @@ -1,7 +1,7 @@ - """Gherkin parser for validation.""" +"""Gherkin parser for validation.""" import re -from typing import List, Optional, Tuple +from typing import Optional class GherkinParser: @@ -13,10 +13,10 @@ class GherkinParser: def parse(self, content: str) -> dict: """Parse Gherkin content into an AST. - + Args: content: The Gherkin content to parse. - + Returns: Dictionary representing the Gherkin AST. """ @@ -26,7 +26,6 @@ class GherkinParser: "scenarios": [], } - current_section = None scenario: Optional[dict] = None for i, line in enumerate(lines): @@ -56,15 +55,21 @@ class GherkinParser: "steps": [], "line": i, } - elif stripped.startswith("Given ") or stripped.startswith("When ") or \ - stripped.startswith("Then ") or stripped.startswith("And ") or \ - stripped.startswith("But "): + elif ( + stripped.startswith("Given ") + or stripped.startswith("When ") + or stripped.startswith("Then ") + or stripped.startswith("And ") + or stripped.startswith("But ") + ): if scenario: - scenario["steps"].append({ - "keyword": stripped.split()[0], - "text": " ".join(stripped.split()[1:]), - "line": i, - }) + scenario["steps"].append( + { + "keyword": stripped.split()[0], + "text": " ".join(stripped.split()[1:]), + "line": i, + } + ) elif stripped.startswith("Examples:"): if scenario: scenario["has_examples"] = True @@ -74,16 +79,16 @@ class GherkinParser: return ast - def validate(self, content: str) -> Tuple[bool, List[str]]: + def validate(self, content: str) -> tuple[bool, list[str]]: """Validate Gherkin syntax. - + Args: content: The Gherkin content to validate. - + Returns: Tuple of (is_valid, list_of_errors). """ - errors: List[str] = [] + errors: list[str] = [] if not content.strip(): return False, ["Empty content"] @@ -94,8 +99,7 @@ class GherkinParser: return False, ["Gherkin must start with 'Feature:'"] has_scenario = any( - line.strip().startswith("Scenario:") or - line.strip().startswith("Scenario Outline:") + line.strip().startswith("Scenario:") or line.strip().startswith("Scenario Outline:") for line in lines ) @@ -117,16 +121,32 @@ class GherkinParser: stripped = line.strip() if stripped.startswith("Examples:") and not any( - "Scenario Outline" in l for l in lines[:i] + "Scenario Outline" in line for line in lines[:i] ): - errors.append(f"Line {i + 1}: Examples table can only be used with Scenario Outline") + errors.append( + f"Line {i + 1}: Examples table can only be used with Scenario Outline" + ) for i, line in enumerate(lines): stripped = line.strip() - if stripped and not stripped.startswith(("Feature:", "Scenario", "Given ", "When ", - "Then ", "And ", "But ", "Background:", "Examples:", "|", "@", " ")): + if stripped and not stripped.startswith( + ( + "Feature:", + "Scenario", + "Given ", + "When ", + "Then ", + "And ", + "But ", + "Background:", + "Examples:", + "|", + "@", + " ", + ) + ): if not stripped.startswith("#"): - if i > 0 and lines[i-1].strip().endswith(":"): + if i > 0 and lines[i - 1].strip().endswith(":"): continue pass @@ -135,12 +155,12 @@ class GherkinParser: return True, [] - def validate_feature(self, feature_content: str) -> Tuple[bool, List[str]]: + def validate_feature(self, feature_content: str) -> tuple[bool, list[str]]: """Validate a single feature. - + Args: feature_content: The feature content to validate. - + Returns: Tuple of (is_valid, list_of_errors). """