@facet-coverage/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +422 -0
  3. package/bin/facet-coverage.js +3 -0
  4. package/dist/cli/commands/analyze.d.ts +13 -0
  5. package/dist/cli/commands/analyze.d.ts.map +1 -0
  6. package/dist/cli/commands/analyze.js +161 -0
  7. package/dist/cli/commands/analyze.js.map +1 -0
  8. package/dist/cli/commands/generate.d.ts +10 -0
  9. package/dist/cli/commands/generate.d.ts.map +1 -0
  10. package/dist/cli/commands/generate.js +67 -0
  11. package/dist/cli/commands/generate.js.map +1 -0
  12. package/dist/cli/commands/validate.d.ts +11 -0
  13. package/dist/cli/commands/validate.d.ts.map +1 -0
  14. package/dist/cli/commands/validate.js +120 -0
  15. package/dist/cli/commands/validate.js.map +1 -0
  16. package/dist/cli/commands/watch.d.ts +10 -0
  17. package/dist/cli/commands/watch.d.ts.map +1 -0
  18. package/dist/cli/commands/watch.js +151 -0
  19. package/dist/cli/commands/watch.js.map +1 -0
  20. package/dist/cli/index.d.ts +2 -0
  21. package/dist/cli/index.d.ts.map +1 -0
  22. package/dist/cli/index.js +47 -0
  23. package/dist/cli/index.js.map +1 -0
  24. package/dist/core/CoverageCalculator.d.ts +34 -0
  25. package/dist/core/CoverageCalculator.d.ts.map +1 -0
  26. package/dist/core/CoverageCalculator.js +167 -0
  27. package/dist/core/CoverageCalculator.js.map +1 -0
  28. package/dist/core/FacetParser.d.ts +39 -0
  29. package/dist/core/FacetParser.d.ts.map +1 -0
  30. package/dist/core/FacetParser.js +114 -0
  31. package/dist/core/FacetParser.js.map +1 -0
  32. package/dist/core/StructureReader.d.ts +37 -0
  33. package/dist/core/StructureReader.d.ts.map +1 -0
  34. package/dist/core/StructureReader.js +126 -0
  35. package/dist/core/StructureReader.js.map +1 -0
  36. package/dist/core/TestScanner.d.ts +36 -0
  37. package/dist/core/TestScanner.d.ts.map +1 -0
  38. package/dist/core/TestScanner.js +192 -0
  39. package/dist/core/TestScanner.js.map +1 -0
  40. package/dist/core/Validator.d.ts +33 -0
  41. package/dist/core/Validator.d.ts.map +1 -0
  42. package/dist/core/Validator.js +183 -0
  43. package/dist/core/Validator.js.map +1 -0
  44. package/dist/core/index.d.ts +6 -0
  45. package/dist/core/index.d.ts.map +1 -0
  46. package/dist/core/index.js +14 -0
  47. package/dist/core/index.js.map +1 -0
  48. package/dist/index.d.ts +6 -0
  49. package/dist/index.d.ts.map +1 -0
  50. package/dist/index.js +23 -0
  51. package/dist/index.js.map +1 -0
  52. package/dist/integrations/playwright.d.ts +95 -0
  53. package/dist/integrations/playwright.d.ts.map +1 -0
  54. package/dist/integrations/playwright.js +168 -0
  55. package/dist/integrations/playwright.js.map +1 -0
  56. package/dist/reporters/HtmlReporter.d.ts +53 -0
  57. package/dist/reporters/HtmlReporter.d.ts.map +1 -0
  58. package/dist/reporters/HtmlReporter.js +484 -0
  59. package/dist/reporters/HtmlReporter.js.map +1 -0
  60. package/dist/reporters/JsonReporter.d.ts +21 -0
  61. package/dist/reporters/JsonReporter.d.ts.map +1 -0
  62. package/dist/reporters/JsonReporter.js +58 -0
  63. package/dist/reporters/JsonReporter.js.map +1 -0
  64. package/dist/reporters/MarkdownReporter.d.ts +25 -0
  65. package/dist/reporters/MarkdownReporter.d.ts.map +1 -0
  66. package/dist/reporters/MarkdownReporter.js +141 -0
  67. package/dist/reporters/MarkdownReporter.js.map +1 -0
  68. package/dist/reporters/index.d.ts +4 -0
  69. package/dist/reporters/index.d.ts.map +1 -0
  70. package/dist/reporters/index.js +10 -0
  71. package/dist/reporters/index.js.map +1 -0
  72. package/dist/types.d.ts +205 -0
  73. package/dist/types.d.ts.map +1 -0
  74. package/dist/types.js +28 -0
  75. package/dist/types.js.map +1 -0
  76. package/package.json +88 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CoverageCalculator.js","sourceRoot":"","sources":["../../src/core/CoverageCalculator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import type { MarkdownSection, ParsedMarkdown } from '../types.js';
2
+ /**
3
+ * Parses markdown files and extracts sections
4
+ */
5
+ export declare class FacetParser {
6
+ /**
7
+ * Convert a title to a URL-friendly slug
8
+ */
9
+ static slugify(title: string): string;
10
+ /**
11
+ * Parse a markdown file and extract all sections
12
+ */
13
+ parseFile(filePath: string): ParsedMarkdown;
14
+ /**
15
+ * Parse markdown content and extract sections
16
+ */
17
+ parseContent(content: string, filePath?: string): ParsedMarkdown;
18
+ /**
19
+ * Find a section by its slug
20
+ */
21
+ findSection(parsed: ParsedMarkdown, slug: string): MarkdownSection | undefined;
22
+ /**
23
+ * Check if a section exists in a file
24
+ */
25
+ sectionExists(filePath: string, sectionSlug: string): boolean;
26
+ /**
27
+ * Get all section slugs from a file
28
+ */
29
+ getSectionSlugs(filePath: string): string[];
30
+ /**
31
+ * Extract the filename without extension as a prefix
32
+ */
33
+ static getFilePrefix(filePath: string): string;
34
+ /**
35
+ * Generate facet ID from file and section
36
+ */
37
+ static generateFacetId(filePath: string, sectionSlug: string): string;
38
+ }
39
+ //# sourceMappingURL=FacetParser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FacetParser.d.ts","sourceRoot":"","sources":["../../src/core/FacetParser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEnE;;GAEG;AACH,qBAAa,WAAW;IACtB;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAUrC;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc;IAS3C;;OAEG;IACH,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAW,GAAG,cAAc;IAgDpE;;OAEG;IACH,WAAW,CAAC,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAI9E;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO;IAS7D;;OAEG;IACH,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE;IAK3C;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAK9C;;OAEG;IACH,MAAM,CAAC,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM;CAItE"}
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FacetParser = void 0;
4
+ const fs_1 = require("fs");
5
+ /**
6
+ * Parses markdown files and extracts sections
7
+ */
8
+ class FacetParser {
9
+ /**
10
+ * Convert a title to a URL-friendly slug
11
+ */
12
+ static slugify(title) {
13
+ return title
14
+ .toLowerCase()
15
+ .trim()
16
+ .replace(/[^\w\s-]/g, '') // Remove special characters
17
+ .replace(/\s+/g, '-') // Replace spaces with hyphens
18
+ .replace(/-+/g, '-') // Replace multiple hyphens with single
19
+ .replace(/^-|-$/g, ''); // Remove leading/trailing hyphens
20
+ }
21
+ /**
22
+ * Parse a markdown file and extract all sections
23
+ */
24
+ parseFile(filePath) {
25
+ if (!(0, fs_1.existsSync)(filePath)) {
26
+ throw new Error(`Markdown file not found: ${filePath}`);
27
+ }
28
+ const content = (0, fs_1.readFileSync)(filePath, 'utf-8');
29
+ return this.parseContent(content, filePath);
30
+ }
31
+ /**
32
+ * Parse markdown content and extract sections
33
+ */
34
+ parseContent(content, filePath = '') {
35
+ const lines = content.split('\n');
36
+ const sections = [];
37
+ // First pass: find all headings
38
+ const headings = [];
39
+ for (let i = 0; i < lines.length; i++) {
40
+ const line = lines[i];
41
+ const match = line.match(/^(#{1,6})\s+(.+)$/);
42
+ if (match) {
43
+ headings.push({
44
+ level: match[1].length,
45
+ title: match[2].trim(),
46
+ line: i + 1, // 1-indexed
47
+ });
48
+ }
49
+ }
50
+ // Second pass: create sections with content
51
+ for (let i = 0; i < headings.length; i++) {
52
+ const heading = headings[i];
53
+ const nextHeading = headings[i + 1];
54
+ const startLine = heading.line;
55
+ const endLine = nextHeading ? nextHeading.line - 1 : lines.length;
56
+ // Extract content between headings
57
+ const contentLines = lines.slice(startLine, endLine - 1);
58
+ const sectionContent = contentLines.join('\n').trim();
59
+ sections.push({
60
+ title: heading.title,
61
+ slug: FacetParser.slugify(heading.title),
62
+ level: heading.level,
63
+ startLine,
64
+ endLine,
65
+ content: sectionContent,
66
+ });
67
+ }
68
+ return {
69
+ file: filePath,
70
+ sections,
71
+ };
72
+ }
73
+ /**
74
+ * Find a section by its slug
75
+ */
76
+ findSection(parsed, slug) {
77
+ return parsed.sections.find(s => s.slug === slug);
78
+ }
79
+ /**
80
+ * Check if a section exists in a file
81
+ */
82
+ sectionExists(filePath, sectionSlug) {
83
+ try {
84
+ const parsed = this.parseFile(filePath);
85
+ return this.findSection(parsed, sectionSlug) !== undefined;
86
+ }
87
+ catch {
88
+ return false;
89
+ }
90
+ }
91
+ /**
92
+ * Get all section slugs from a file
93
+ */
94
+ getSectionSlugs(filePath) {
95
+ const parsed = this.parseFile(filePath);
96
+ return parsed.sections.map(s => s.slug);
97
+ }
98
+ /**
99
+ * Extract the filename without extension as a prefix
100
+ */
101
+ static getFilePrefix(filePath) {
102
+ const basename = filePath.split('/').pop() || '';
103
+ return basename.replace(/\.md$/i, '').toLowerCase();
104
+ }
105
+ /**
106
+ * Generate facet ID from file and section
107
+ */
108
+ static generateFacetId(filePath, sectionSlug) {
109
+ const prefix = FacetParser.getFilePrefix(filePath);
110
+ return `${prefix}:${sectionSlug}`;
111
+ }
112
+ }
113
+ exports.FacetParser = FacetParser;
114
+ //# sourceMappingURL=FacetParser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FacetParser.js","sourceRoot":"","sources":["../../src/core/FacetParser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import type { FacetStructure, Facet, FacetConfig } from '../types.js';
2
+ /**
3
+ * Reads and parses facet structure files
4
+ */
5
+ export declare class StructureReader {
6
+ private config;
7
+ constructor(config?: Partial<FacetConfig>);
8
+ /**
9
+ * Find all structure files matching the configured patterns
10
+ */
11
+ findStructureFiles(cwd?: string): Promise<string[]>;
12
+ /**
13
+ * Read and parse a single structure file
14
+ */
15
+ readStructure(filePath: string): FacetStructure;
16
+ /**
17
+ * Read all structure files and return combined facets
18
+ */
19
+ readAllStructures(cwd?: string): Promise<Map<string, FacetStructure>>;
20
+ /**
21
+ * Get all facets from all structure files
22
+ */
23
+ getAllFacets(cwd?: string): Promise<Facet[]>;
24
+ /**
25
+ * Get facet by ID
26
+ */
27
+ getFacetById(id: string, cwd?: string): Promise<Facet | undefined>;
28
+ /**
29
+ * Resolve the absolute path to a facet's source file
30
+ */
31
+ resolveSourcePath(facet: Facet, structureFilePath: string): string;
32
+ /**
33
+ * Validate structure object
34
+ */
35
+ private validateStructure;
36
+ }
37
+ //# sourceMappingURL=StructureReader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StructureReader.d.ts","sourceRoot":"","sources":["../../src/core/StructureReader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,WAAW,EAAiB,MAAM,aAAa,CAAC;AAErF;;GAEG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAc;gBAEhB,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM;IAK7C;;OAEG;IACG,kBAAkB,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAWxE;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc;IA8B/C;;OAEG;IACG,iBAAiB,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAY1F;;OAEG;IACG,YAAY,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAWjE;;OAEG;IACG,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC;IAKvF;;OAEG;IACH,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,GAAG,MAAM;IAOlE;;OAEG;IACH,OAAO,CAAC,iBAAiB;CAkC1B"}
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StructureReader = void 0;
4
+ const fs_1 = require("fs");
5
+ const path_1 = require("path");
6
+ const glob_1 = require("glob");
7
+ /**
8
+ * Reads and parses facet structure files
9
+ */
10
+ class StructureReader {
11
+ config;
12
+ constructor(config = {}) {
13
+ const { defaultConfig } = require('../types.js');
14
+ this.config = { ...defaultConfig, ...config };
15
+ }
16
+ /**
17
+ * Find all structure files matching the configured patterns
18
+ */
19
+ async findStructureFiles(cwd = process.cwd()) {
20
+ const files = [];
21
+ for (const pattern of this.config.structureFiles) {
22
+ const matches = await (0, glob_1.glob)(pattern, { cwd, absolute: true });
23
+ files.push(...matches);
24
+ }
25
+ return [...new Set(files)]; // Remove duplicates
26
+ }
27
+ /**
28
+ * Read and parse a single structure file
29
+ */
30
+ readStructure(filePath) {
31
+ if (!(0, fs_1.existsSync)(filePath)) {
32
+ throw new Error(`Structure file not found: ${filePath}`);
33
+ }
34
+ const content = (0, fs_1.readFileSync)(filePath, 'utf-8');
35
+ let structure;
36
+ try {
37
+ structure = JSON.parse(content);
38
+ }
39
+ catch (error) {
40
+ throw new Error(`Invalid JSON in structure file: ${filePath}`);
41
+ }
42
+ // Validate structure
43
+ this.validateStructure(structure, filePath);
44
+ // Resolve relative paths in facets
45
+ const structureDir = (0, path_1.dirname)(filePath);
46
+ structure.facets = structure.facets.map(facet => ({
47
+ ...facet,
48
+ source: {
49
+ ...facet.source,
50
+ file: facet.source.file, // Keep relative for portability
51
+ },
52
+ }));
53
+ return structure;
54
+ }
55
+ /**
56
+ * Read all structure files and return combined facets
57
+ */
58
+ async readAllStructures(cwd = process.cwd()) {
59
+ const files = await this.findStructureFiles(cwd);
60
+ const structures = new Map();
61
+ for (const file of files) {
62
+ const structure = this.readStructure(file);
63
+ structures.set(file, structure);
64
+ }
65
+ return structures;
66
+ }
67
+ /**
68
+ * Get all facets from all structure files
69
+ */
70
+ async getAllFacets(cwd = process.cwd()) {
71
+ const structures = await this.readAllStructures(cwd);
72
+ const facets = [];
73
+ for (const structure of structures.values()) {
74
+ facets.push(...structure.facets);
75
+ }
76
+ return facets;
77
+ }
78
+ /**
79
+ * Get facet by ID
80
+ */
81
+ async getFacetById(id, cwd = process.cwd()) {
82
+ const facets = await this.getAllFacets(cwd);
83
+ return facets.find(f => f.id === id);
84
+ }
85
+ /**
86
+ * Resolve the absolute path to a facet's source file
87
+ */
88
+ resolveSourcePath(facet, structureFilePath) {
89
+ const structureDir = (0, path_1.dirname)(structureFilePath);
90
+ // Go up one level from .facet directory to get feature directory
91
+ const featureDir = (0, path_1.dirname)(structureDir);
92
+ return (0, path_1.resolve)(featureDir, facet.source.file);
93
+ }
94
+ /**
95
+ * Validate structure object
96
+ */
97
+ validateStructure(structure, filePath) {
98
+ if (!structure.feature) {
99
+ throw new Error(`Missing 'feature' field in structure file: ${filePath}`);
100
+ }
101
+ if (!Array.isArray(structure.facets)) {
102
+ throw new Error(`Missing or invalid 'facets' array in structure file: ${filePath}`);
103
+ }
104
+ const seenIds = new Set();
105
+ for (const facet of structure.facets) {
106
+ if (!facet.id) {
107
+ throw new Error(`Facet missing 'id' field in structure file: ${filePath}`);
108
+ }
109
+ if (seenIds.has(facet.id)) {
110
+ throw new Error(`Duplicate facet ID '${facet.id}' in structure file: ${filePath}`);
111
+ }
112
+ seenIds.add(facet.id);
113
+ if (!facet.source?.file) {
114
+ throw new Error(`Facet '${facet.id}' missing 'source.file' in structure file: ${filePath}`);
115
+ }
116
+ if (!facet.source?.section) {
117
+ throw new Error(`Facet '${facet.id}' missing 'source.section' in structure file: ${filePath}`);
118
+ }
119
+ if (!facet.type) {
120
+ throw new Error(`Facet '${facet.id}' missing 'type' in structure file: ${filePath}`);
121
+ }
122
+ }
123
+ }
124
+ }
125
+ exports.StructureReader = StructureReader;
126
+ //# sourceMappingURL=StructureReader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StructureReader.js","sourceRoot":"","sources":["../../src/core/StructureReader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import type { TestLink, FacetConfig } from '../types.js';
2
+ /**
3
+ * Scans test files for facet annotations
4
+ */
5
+ export declare class TestScanner {
6
+ private config;
7
+ constructor(config?: Partial<FacetConfig>);
8
+ /**
9
+ * Find all test files matching configured patterns
10
+ */
11
+ findTestFiles(cwd?: string): Promise<string[]>;
12
+ /**
13
+ * Scan a single test file for facet annotations
14
+ */
15
+ scanFile(filePath: string, cwd?: string): TestLink[];
16
+ /**
17
+ * Scan test content for facet annotations
18
+ * Supports both Playwright-style annotations and comment-based annotations:
19
+ * - Playwright: test('name', { annotation: facet('id1', 'id2') }, ...)
20
+ * - Comment: // @facet id1, id2 \n test('name', ...)
21
+ */
22
+ scanContent(content: string, filePath: string, cwd?: string): TestLink[];
23
+ /**
24
+ * Scan all test files for facet annotations
25
+ */
26
+ scanAllTests(cwd?: string): Promise<TestLink[]>;
27
+ /**
28
+ * Get all facet IDs referenced in tests
29
+ */
30
+ getAllReferencedFacetIds(cwd?: string): Promise<Set<string>>;
31
+ /**
32
+ * Get tests that cover a specific facet ID
33
+ */
34
+ getTestsForFacet(facetId: string, cwd?: string): Promise<TestLink[]>;
35
+ }
36
+ //# sourceMappingURL=TestScanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TestScanner.d.ts","sourceRoot":"","sources":["../../src/core/TestScanner.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAGzD;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAc;gBAEhB,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM;IAI7C;;OAEG;IACG,aAAa,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAwBnE;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,GAAE,MAAsB,GAAG,QAAQ,EAAE;IASnE;;;;;OAKG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,GAAE,MAAsB,GAAG,QAAQ,EAAE;IAwHvF;;OAEG;IACG,YAAY,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAgBpE;;OAEG;IACG,wBAAwB,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAajF;;OAEG;IACG,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;CAI1F"}
@@ -0,0 +1,192 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TestScanner = void 0;
4
+ const fs_1 = require("fs");
5
+ const glob_1 = require("glob");
6
+ const path_1 = require("path");
7
+ const types_js_1 = require("../types.js");
8
+ /**
9
+ * Scans test files for facet annotations
10
+ */
11
+ class TestScanner {
12
+ config;
13
+ constructor(config = {}) {
14
+ this.config = { ...types_js_1.defaultConfig, ...config };
15
+ }
16
+ /**
17
+ * Find all test files matching configured patterns
18
+ */
19
+ async findTestFiles(cwd = process.cwd()) {
20
+ const patterns = this.config.testPatterns || ['**/*.spec.ts', '**/*.test.ts'];
21
+ const files = [];
22
+ // Expand testDir pattern
23
+ const testDirs = await (0, glob_1.glob)(this.config.testDir, { cwd, absolute: true });
24
+ for (const testDir of testDirs) {
25
+ for (const pattern of patterns) {
26
+ const matches = await (0, glob_1.glob)(pattern, { cwd: testDir, absolute: true });
27
+ files.push(...matches);
28
+ }
29
+ }
30
+ // Also search in the testDir pattern directly if it includes globs
31
+ for (const pattern of patterns) {
32
+ const fullPattern = `${this.config.testDir}/${pattern}`;
33
+ const matches = await (0, glob_1.glob)(fullPattern, { cwd, absolute: true });
34
+ files.push(...matches);
35
+ }
36
+ return [...new Set(files)]; // Remove duplicates
37
+ }
38
+ /**
39
+ * Scan a single test file for facet annotations
40
+ */
41
+ scanFile(filePath, cwd = process.cwd()) {
42
+ if (!(0, fs_1.existsSync)(filePath)) {
43
+ throw new Error(`Test file not found: ${filePath}`);
44
+ }
45
+ const content = (0, fs_1.readFileSync)(filePath, 'utf-8');
46
+ return this.scanContent(content, filePath, cwd);
47
+ }
48
+ /**
49
+ * Scan test content for facet annotations
50
+ * Supports both Playwright-style annotations and comment-based annotations:
51
+ * - Playwright: test('name', { annotation: facet('id1', 'id2') }, ...)
52
+ * - Comment: // @facet id1, id2 \n test('name', ...)
53
+ */
54
+ scanContent(content, filePath, cwd = process.cwd()) {
55
+ const testLinks = [];
56
+ const lines = content.split('\n');
57
+ // Track describe blocks for full title
58
+ const describeStack = [];
59
+ // Patterns for test definitions
60
+ const testPattern = /(?:test|it)\s*\(\s*(['"`])(.+?)\1\s*,\s*\{/g;
61
+ const testSimplePattern = /(?:test|it)\s*\(\s*(['"`])(.+?)\1\s*,/g;
62
+ const describePattern = /describe\s*\(\s*(['"`])(.+?)\1/g;
63
+ // Pattern for Playwright-style facet annotations
64
+ const facetPattern = /annotation\s*:\s*facet\s*\(\s*([^)]+)\s*\)/g;
65
+ const facetIdsPattern = /(['"`])([^'"`]+)\1/g;
66
+ // Pattern for comment-based facet annotations: // @facet id1, id2
67
+ const commentFacetPattern = /^\s*\/\/\s*@facet\s+(.+)$/;
68
+ // Track brace depth for describe blocks
69
+ let braceDepth = 0;
70
+ const describeDepths = [];
71
+ // Track pending comment-based facet IDs
72
+ let pendingFacetIds = [];
73
+ let pendingFacetLine = -1;
74
+ for (let i = 0; i < lines.length; i++) {
75
+ const line = lines[i];
76
+ const lineNumber = i + 1;
77
+ // Check for comment-based facet annotation
78
+ const commentMatch = commentFacetPattern.exec(line);
79
+ if (commentMatch) {
80
+ const facetString = commentMatch[1];
81
+ // Parse comma-separated facet IDs, trimming whitespace
82
+ pendingFacetIds = facetString.split(',').map(id => id.trim()).filter(id => id.length > 0);
83
+ pendingFacetLine = lineNumber;
84
+ continue;
85
+ }
86
+ // Track describe blocks
87
+ const describeMatch = describePattern.exec(line);
88
+ if (describeMatch) {
89
+ describeStack.push(describeMatch[2]);
90
+ describeDepths.push(braceDepth);
91
+ describePattern.lastIndex = 0;
92
+ }
93
+ // Count braces for scope tracking
94
+ const openBraces = (line.match(/\{/g) || []).length;
95
+ const closeBraces = (line.match(/\}/g) || []).length;
96
+ braceDepth += openBraces - closeBraces;
97
+ // Pop describe blocks when we exit their scope
98
+ while (describeDepths.length > 0 && braceDepth <= describeDepths[describeDepths.length - 1]) {
99
+ describeStack.pop();
100
+ describeDepths.pop();
101
+ }
102
+ // Look for test definitions
103
+ // First try with annotation block pattern
104
+ let testMatch = testPattern.exec(line);
105
+ testPattern.lastIndex = 0;
106
+ // Also try simple test pattern for comment-based annotations
107
+ if (!testMatch) {
108
+ testMatch = testSimplePattern.exec(line);
109
+ testSimplePattern.lastIndex = 0;
110
+ }
111
+ if (testMatch) {
112
+ const testTitle = testMatch[2];
113
+ let facetIds = [];
114
+ // Check for pending comment-based facet IDs (within 3 lines)
115
+ if (pendingFacetIds.length > 0 && lineNumber - pendingFacetLine <= 3) {
116
+ facetIds = [...pendingFacetIds];
117
+ pendingFacetIds = [];
118
+ pendingFacetLine = -1;
119
+ }
120
+ else {
121
+ // Look for Playwright-style facet annotation in the next few lines
122
+ const annotationBlock = lines.slice(i, Math.min(i + 10, lines.length)).join('\n');
123
+ const facetMatch = facetPattern.exec(annotationBlock);
124
+ facetPattern.lastIndex = 0;
125
+ if (facetMatch) {
126
+ const facetArgs = facetMatch[1];
127
+ let idMatch;
128
+ while ((idMatch = facetIdsPattern.exec(facetArgs)) !== null) {
129
+ facetIds.push(idMatch[2]);
130
+ }
131
+ facetIdsPattern.lastIndex = 0;
132
+ }
133
+ }
134
+ if (facetIds.length > 0) {
135
+ const fullTitle = [...describeStack, testTitle].join(' > ');
136
+ testLinks.push({
137
+ file: (0, path_1.relative)(cwd, filePath),
138
+ title: testTitle,
139
+ fullTitle,
140
+ facetIds,
141
+ line: lineNumber,
142
+ });
143
+ }
144
+ }
145
+ // Clear pending facet IDs if we've moved too far past them
146
+ if (pendingFacetIds.length > 0 && lineNumber - pendingFacetLine > 3) {
147
+ pendingFacetIds = [];
148
+ pendingFacetLine = -1;
149
+ }
150
+ }
151
+ return testLinks;
152
+ }
153
+ /**
154
+ * Scan all test files for facet annotations
155
+ */
156
+ async scanAllTests(cwd = process.cwd()) {
157
+ const files = await this.findTestFiles(cwd);
158
+ const allLinks = [];
159
+ for (const file of files) {
160
+ try {
161
+ const links = this.scanFile(file, cwd);
162
+ allLinks.push(...links);
163
+ }
164
+ catch (error) {
165
+ console.warn(`Warning: Could not scan test file ${file}: ${error}`);
166
+ }
167
+ }
168
+ return allLinks;
169
+ }
170
+ /**
171
+ * Get all facet IDs referenced in tests
172
+ */
173
+ async getAllReferencedFacetIds(cwd = process.cwd()) {
174
+ const links = await this.scanAllTests(cwd);
175
+ const ids = new Set();
176
+ for (const link of links) {
177
+ for (const id of link.facetIds) {
178
+ ids.add(id);
179
+ }
180
+ }
181
+ return ids;
182
+ }
183
+ /**
184
+ * Get tests that cover a specific facet ID
185
+ */
186
+ async getTestsForFacet(facetId, cwd = process.cwd()) {
187
+ const links = await this.scanAllTests(cwd);
188
+ return links.filter(link => link.facetIds.includes(facetId));
189
+ }
190
+ }
191
+ exports.TestScanner = TestScanner;
192
+ //# sourceMappingURL=TestScanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TestScanner.js","sourceRoot":"","sources":["../../src/core/TestScanner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import type { FacetConfig, FacetStructure, ValidationResult } from '../types.js';
2
+ /**
3
+ * Validates facet structures, source files, and test links
4
+ */
5
+ export declare class Validator {
6
+ private config;
7
+ private structureReader;
8
+ private facetParser;
9
+ private testScanner;
10
+ constructor(config?: Partial<FacetConfig>);
11
+ /**
12
+ * Run full validation
13
+ */
14
+ validate(cwd?: string): Promise<ValidationResult>;
15
+ /**
16
+ * Validate a single structure
17
+ */
18
+ validateStructure(structure: FacetStructure, structureFile: string, cwd: string): ValidationResult;
19
+ /**
20
+ * Check if a facet ID is valid
21
+ */
22
+ private isValidFacetId;
23
+ /**
24
+ * Check if a reference is a valid path-style reference
25
+ * e.g., 'facets/business.md#guest-purchase-flow'
26
+ */
27
+ private isValidPathReference;
28
+ /**
29
+ * Quick validation check - returns boolean
30
+ */
31
+ isValid(cwd?: string): Promise<boolean>;
32
+ }
33
+ //# sourceMappingURL=Validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Validator.d.ts","sourceRoot":"","sources":["../../src/core/Validator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EAGd,gBAAgB,EAEjB,MAAM,aAAa,CAAC;AAMrB;;GAEG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,WAAW,CAAc;gBAErB,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM;IAO7C;;OAEG;IACG,QAAQ,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA+EtE;;OAEG;IACH,iBAAiB,CACf,SAAS,EAAE,cAAc,EACzB,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,GACV,gBAAgB;IAuDnB;;OAEG;IACH,OAAO,CAAC,cAAc;IAKtB;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IA2B5B;;OAEG;IACG,OAAO,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,OAAO,CAAC;CAI7D"}