soleprint init commit

This commit is contained in:
buenosairesam
2025-12-24 05:38:37 -03:00
commit 329c401ff5
96 changed files with 11564 additions and 0 deletions

View File

@@ -0,0 +1,153 @@
"""
Discover Playwright tests (.spec.ts files).
"""
import re
from pathlib import Path
from typing import Optional
from dataclasses import dataclass
@dataclass
class PlaywrightTestInfo:
"""Information about a discovered Playwright test."""
id: str
name: str
file_path: str
test_name: str
description: Optional[str] = None
gherkin_feature: Optional[str] = None
gherkin_scenario: Optional[str] = None
tags: list[str] = None
def __post_init__(self):
if self.tags is None:
self.tags = []
def discover_playwright_tests(tests_dir: Path) -> list[PlaywrightTestInfo]:
"""
Discover all Playwright tests in the frontend-tests directory.
Parses .spec.ts files to extract:
- test() calls
- describe() blocks
- Gherkin metadata from comments
- Tags from comments
"""
if not tests_dir.exists():
return []
tests = []
# Find all .spec.ts files
for spec_file in tests_dir.rglob("*.spec.ts"):
relative_path = spec_file.relative_to(tests_dir)
# Read file content
try:
content = spec_file.read_text()
except Exception:
continue
# Extract describe blocks and tests
tests_in_file = _parse_playwright_file(content, spec_file, relative_path)
tests.extend(tests_in_file)
return tests
def _parse_playwright_file(
content: str,
file_path: Path,
relative_path: Path
) -> list[PlaywrightTestInfo]:
"""Parse a Playwright test file to extract test information."""
tests = []
# Pattern to match test() calls
# test('test name', async ({ page }) => { ... })
# test.only('test name', ...)
test_pattern = re.compile(
r"test(?:\.\w+)?\s*\(\s*['\"]([^'\"]+)['\"]",
re.MULTILINE
)
# Pattern to match describe() blocks
describe_pattern = re.compile(
r"describe\s*\(\s*['\"]([^'\"]+)['\"]",
re.MULTILINE
)
# Extract metadata from comments above tests
# Looking for JSDoc-style comments with metadata
metadata_pattern = re.compile(
r"/\*\*\s*\n((?:\s*\*.*\n)+)\s*\*/\s*\n\s*test",
re.MULTILINE
)
# Find all describe blocks to use as context
describes = describe_pattern.findall(content)
describe_context = describes[0] if describes else None
# Find all tests
for match in test_pattern.finditer(content):
test_name = match.group(1)
# Look for metadata comment before this test
# Search backwards from the match position
before_test = content[:match.start()]
metadata_match = None
for m in metadata_pattern.finditer(before_test):
metadata_match = m
# Parse metadata if found
gherkin_feature = None
gherkin_scenario = None
tags = []
description = None
if metadata_match:
metadata_block = metadata_match.group(1)
# Extract Feature, Scenario, Tags from metadata
feature_match = re.search(r"\*\s*Feature:\s*(.+)", metadata_block)
scenario_match = re.search(r"\*\s*Scenario:\s*(.+)", metadata_block)
tags_match = re.search(r"\*\s*Tags:\s*(.+)", metadata_block)
desc_match = re.search(r"\*\s*@description\s+(.+)", metadata_block)
if feature_match:
gherkin_feature = feature_match.group(1).strip()
if scenario_match:
gherkin_scenario = scenario_match.group(1).strip()
if tags_match:
tags_str = tags_match.group(1).strip()
tags = [t.strip() for t in re.findall(r"@[\w-]+", tags_str)]
if desc_match:
description = desc_match.group(1).strip()
# Build test ID
module_name = str(relative_path).replace("/", ".").replace(".spec.ts", "")
test_id = f"frontend.{module_name}.{_sanitize_test_name(test_name)}"
tests.append(PlaywrightTestInfo(
id=test_id,
name=test_name,
file_path=str(relative_path),
test_name=test_name,
description=description or test_name,
gherkin_feature=gherkin_feature,
gherkin_scenario=gherkin_scenario,
tags=tags,
))
return tests
def _sanitize_test_name(name: str) -> str:
"""Convert test name to a valid identifier."""
# Replace spaces and special chars with underscores
sanitized = re.sub(r"[^\w]+", "_", name.lower())
# Remove leading/trailing underscores
sanitized = sanitized.strip("_")
return sanitized