Skip to content

Commit 801e455

Browse files
committed
fix(jstest): support include/exclude pattern parsing in Jest/Vitest configs
In monorepos using both Jest and Vitest, testMatch, testPathIgnorePatterns, include, and exclude settings were ignored, causing files to be detected under wrong frameworks. Example: In prisma packages/cli, vitest.config.ts's include: ['**/*.vitest.ts'] was ignored, causing .test.ts files to be incorrectly classified as vitest. Jest: Added parsing for testMatch, testPathIgnorePatterns, modulePathIgnorePatterns Vitest: Added parsing for test.include, test.exclude (with coverage block exclusion) fix #83
1 parent afbe437 commit 801e455

File tree

7 files changed

+137
-42
lines changed

7 files changed

+137
-42
lines changed

pkg/parser/strategies/jest/definition.go

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,23 @@ func (p *JestConfigParser) Parse(ctx context.Context, configPath string, content
9595
scope.Roots = roots
9696
}
9797

98+
// Parse test match patterns as include patterns
99+
if testMatch := parseTestMatch(content); len(testMatch) > 0 {
100+
scope.Include = testMatch
101+
}
102+
103+
// Parse ignore patterns as exclude patterns
104+
var excludePatterns []string
105+
if testPathIgnore := parseTestPathIgnorePatterns(content); len(testPathIgnore) > 0 {
106+
excludePatterns = append(excludePatterns, testPathIgnore...)
107+
}
108+
if modulePathIgnore := parseModulePathIgnorePatterns(content); len(modulePathIgnore) > 0 {
109+
excludePatterns = append(excludePatterns, modulePathIgnore...)
110+
}
111+
if len(excludePatterns) > 0 {
112+
scope.Exclude = excludePatterns
113+
}
114+
98115
return scope, nil
99116
}
100117

@@ -105,10 +122,13 @@ func (p *JestParser) Parse(ctx context.Context, source []byte, filename string)
105122
}
106123

107124
var (
108-
configRootDirPattern = regexp.MustCompile(`rootDir\s*:\s*['"]([^'"]+)['"]`)
109-
configRootsPattern = regexp.MustCompile(`roots\s*:\s*\[([^\]]+)\]`)
110-
configRootItemPattern = regexp.MustCompile(`['"]([^'"]+)['"]`)
111-
injectGlobalsFalsePattern = regexp.MustCompile(`injectGlobals\s*:\s*false`)
125+
configRootDirPattern = regexp.MustCompile(`rootDir\s*:\s*['"]([^'"]+)['"]`)
126+
configRootsPattern = regexp.MustCompile(`roots\s*:\s*\[([^\]]+)\]`)
127+
configRootItemPattern = regexp.MustCompile(`['"]([^'"]+)['"]`)
128+
injectGlobalsFalsePattern = regexp.MustCompile(`injectGlobals\s*:\s*false`)
129+
configTestMatchPattern = regexp.MustCompile(`testMatch\s*:\s*\[([^\]]+)\]`)
130+
configTestPathIgnorePattern = regexp.MustCompile(`testPathIgnorePatterns\s*:\s*\[([^\]]+)\]`)
131+
configModulePathIgnorePattern = regexp.MustCompile(`modulePathIgnorePatterns\s*:\s*\[([^\]]+)\]`)
112132
)
113133

114134
func parseRootDir(content []byte) string {
@@ -155,3 +175,39 @@ func parseRoots(content []byte, configDir string, rootDir string) []string {
155175
func parseInjectGlobalsFalse(content []byte) bool {
156176
return injectGlobalsFalsePattern.Match(content)
157177
}
178+
179+
func parseTestMatch(content []byte) []string {
180+
match := configTestMatchPattern.FindSubmatch(content)
181+
if match == nil {
182+
return nil
183+
}
184+
return extractJestPatterns(match[1])
185+
}
186+
187+
func parseTestPathIgnorePatterns(content []byte) []string {
188+
match := configTestPathIgnorePattern.FindSubmatch(content)
189+
if match == nil {
190+
return nil
191+
}
192+
return extractJestPatterns(match[1])
193+
}
194+
195+
func parseModulePathIgnorePatterns(content []byte) []string {
196+
match := configModulePathIgnorePattern.FindSubmatch(content)
197+
if match == nil {
198+
return nil
199+
}
200+
return extractJestPatterns(match[1])
201+
}
202+
203+
func extractJestPatterns(content []byte) []string {
204+
items := configRootItemPattern.FindAllSubmatch(content, -1)
205+
if len(items) == 0 {
206+
return nil
207+
}
208+
var patterns []string
209+
for _, item := range items {
210+
patterns = append(patterns, string(item[1]))
211+
}
212+
return patterns
213+
}

pkg/parser/strategies/vitest/definition.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ func (p *VitestConfigParser) Parse(ctx context.Context, configPath string, conte
4444
scope := framework.NewConfigScope(configPath, root)
4545
scope.Framework = frameworkName
4646
scope.GlobalsMode = parseGlobals(ctx, content)
47+
scope.Include = parseInclude(content)
48+
scope.Exclude = parseExclude(content)
4749
return scope, nil
4850
}
4951

@@ -56,6 +58,11 @@ func (p *VitestParser) Parse(ctx context.Context, source []byte, filename string
5658
var (
5759
configRootPattern = regexp.MustCompile(`root\s*:\s*['"]([^'"]+)['"]`)
5860
configGlobalsPattern = regexp.MustCompile(`globals\s*:\s*true`)
61+
// Pattern to remove coverage block (which has its own include/exclude)
62+
configCoveragePattern = regexp.MustCompile(`(?s)coverage\s*:\s*\{[^}]*(?:\{[^}]*\}[^}]*)*\}`)
63+
configIncludePattern = regexp.MustCompile(`(?:^|[,\s])include\s*:\s*\[([^\]]+)\]`)
64+
configExcludePattern = regexp.MustCompile(`(?:^|[,\s])exclude\s*:\s*\[([^\]]+)\]`)
65+
configItemPattern = regexp.MustCompile(`['"]([^'"]+)['"]`)
5966
)
6067

6168
func parseRoot(content []byte) string {
@@ -69,6 +76,38 @@ func parseGlobals(ctx context.Context, content []byte) bool {
6976
return extraction.MatchPatternExcludingComments(ctx, content, configGlobalsPattern)
7077
}
7178

79+
func parseInclude(content []byte) []string {
80+
// Remove coverage block first to avoid matching coverage.include
81+
cleaned := configCoveragePattern.ReplaceAll(content, []byte{})
82+
match := configIncludePattern.FindSubmatch(cleaned)
83+
if match == nil {
84+
return nil
85+
}
86+
return extractPatterns(match[1])
87+
}
88+
89+
func parseExclude(content []byte) []string {
90+
// Remove coverage block first to avoid matching coverage.exclude
91+
cleaned := configCoveragePattern.ReplaceAll(content, []byte{})
92+
match := configExcludePattern.FindSubmatch(cleaned)
93+
if match == nil {
94+
return nil
95+
}
96+
return extractPatterns(match[1])
97+
}
98+
99+
func extractPatterns(content []byte) []string {
100+
items := configItemPattern.FindAllSubmatch(content, -1)
101+
if len(items) == 0 {
102+
return nil
103+
}
104+
var patterns []string
105+
for _, item := range items {
106+
patterns = append(patterns, string(item[1]))
107+
}
108+
return patterns
109+
}
110+
72111
// VitestContentMatcher matches vitest-specific patterns (vi.fn, vi.mock, etc.).
73112
type VitestContentMatcher struct{}
74113

tests/integration/testdata/golden/cypress-v15.8.1.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
"repository": "cypress",
33
"ref": "v15.8.1",
44
"expectedFrameworks": ["cypress", "jest", "mocha", "vitest"],
5-
"fileCount": 1560,
6-
"testCount": 10873,
5+
"fileCount": 1475,
6+
"testCount": 10780,
77
"frameworkCounts": {
8-
"cypress": 1233,
9-
"jest": 34,
10-
"mocha": 8,
11-
"vitest": 285
8+
"cypress": 1273,
9+
"jest": 31,
10+
"mocha": 14,
11+
"vitest": 157
1212
},
1313
"sampleFiles": [
1414
{
@@ -133,7 +133,7 @@
133133
}
134134
],
135135
"stats": {
136-
"filesMatched": 1560,
136+
"filesMatched": 1475,
137137
"filesScanned": 1560
138138
}
139139
}

tests/integration/testdata/golden/next.js-v15.0.3.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
"repository": "next.js",
33
"ref": "v15.0.3",
44
"expectedFrameworks": ["cargo-test", "cypress", "jest", "mocha", "playwright", "vitest"],
5-
"fileCount": 1349,
6-
"testCount": 7805,
5+
"fileCount": 1348,
6+
"testCount": 7802,
77
"frameworkCounts": {
88
"cargo-test": 54,
99
"cypress": 3,
10-
"jest": 1282,
10+
"jest": 1281,
1111
"mocha": 2,
1212
"playwright": 3,
1313
"vitest": 5
@@ -135,7 +135,7 @@
135135
}
136136
],
137137
"stats": {
138-
"filesMatched": 1349,
138+
"filesMatched": 1348,
139139
"filesScanned": 2155
140140
}
141141
}

tests/integration/testdata/golden/prisma-6.9.0.json

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
"fileCount": 449,
66
"testCount": 1904,
77
"frameworkCounts": {
8-
"jest": 370,
9-
"vitest": 79
8+
"jest": 404,
9+
"vitest": 45
1010
},
1111
"sampleFiles": [
1212
{
@@ -17,49 +17,49 @@
1717
},
1818
{
1919
"path": "packages/cli/src/__tests__/artificial-panic.test.ts",
20-
"framework": "vitest",
20+
"framework": "jest",
2121
"suiteCount": 5,
2222
"testCount": 6
2323
},
2424
{
2525
"path": "packages/cli/src/__tests__/checkpoint.test.ts",
26-
"framework": "vitest",
26+
"framework": "jest",
2727
"suiteCount": 0,
2828
"testCount": 12
2929
},
3030
{
3131
"path": "packages/cli/src/__tests__/commandState.test.ts",
32-
"framework": "vitest",
32+
"framework": "jest",
3333
"suiteCount": 1,
3434
"testCount": 3
3535
},
3636
{
3737
"path": "packages/cli/src/__tests__/commands/CLI.test.ts",
38-
"framework": "vitest",
38+
"framework": "jest",
3939
"suiteCount": 1,
4040
"testCount": 11
4141
},
4242
{
4343
"path": "packages/cli/src/__tests__/commands/DebugInfo.test.ts",
44-
"framework": "vitest",
44+
"framework": "jest",
4545
"suiteCount": 1,
4646
"testCount": 6
4747
},
4848
{
4949
"path": "packages/cli/src/__tests__/commands/Format.test.ts",
50-
"framework": "vitest",
50+
"framework": "jest",
5151
"suiteCount": 1,
5252
"testCount": 12
5353
},
5454
{
5555
"path": "packages/cli/src/__tests__/commands/Generate.test.ts",
56-
"framework": "vitest",
56+
"framework": "jest",
5757
"suiteCount": 5,
5858
"testCount": 38
5959
},
6060
{
6161
"path": "packages/cli/src/__tests__/commands/Studio.test.ts",
62-
"framework": "vitest",
62+
"framework": "jest",
6363
"suiteCount": 2,
6464
"testCount": 10
6565
},
@@ -71,61 +71,61 @@
7171
},
7272
{
7373
"path": "packages/cli/src/__tests__/commands/Validate.test.ts",
74-
"framework": "vitest",
74+
"framework": "jest",
7575
"suiteCount": 1,
7676
"testCount": 14
7777
},
7878
{
7979
"path": "packages/cli/src/__tests__/commands/Version.test.ts",
80-
"framework": "vitest",
80+
"framework": "jest",
8181
"suiteCount": 1,
8282
"testCount": 0
8383
},
8484
{
8585
"path": "packages/cli/src/__tests__/config.test.ts",
86-
"framework": "vitest",
86+
"framework": "jest",
8787
"suiteCount": 0,
8888
"testCount": 2
8989
},
9090
{
9191
"path": "packages/cli/src/__tests__/dependent-generator.test.ts",
92-
"framework": "vitest",
92+
"framework": "jest",
9393
"suiteCount": 0,
9494
"testCount": 1
9595
},
9696
{
9797
"path": "packages/cli/src/__tests__/dotenv-1-custom-schema-path.test.ts",
98-
"framework": "vitest",
98+
"framework": "jest",
9999
"suiteCount": 0,
100100
"testCount": 1
101101
},
102102
{
103103
"path": "packages/cli/src/__tests__/dotenv-2-prisma-folder.test.ts",
104-
"framework": "vitest",
104+
"framework": "jest",
105105
"suiteCount": 0,
106106
"testCount": 1
107107
},
108108
{
109109
"path": "packages/cli/src/__tests__/dotenv-3-conflict.test.ts",
110-
"framework": "vitest",
110+
"framework": "jest",
111111
"suiteCount": 0,
112112
"testCount": 1
113113
},
114114
{
115115
"path": "packages/cli/src/__tests__/dotenv-4-prisma-when-no-schema.test.ts",
116-
"framework": "vitest",
116+
"framework": "jest",
117117
"suiteCount": 0,
118118
"testCount": 1
119119
},
120120
{
121121
"path": "packages/cli/src/__tests__/dotenv-5-only-root.test.ts",
122-
"framework": "vitest",
122+
"framework": "jest",
123123
"suiteCount": 0,
124124
"testCount": 1
125125
},
126126
{
127127
"path": "packages/cli/src/__tests__/dotenv-6-expand.test.ts",
128-
"framework": "vitest",
128+
"framework": "jest",
129129
"suiteCount": 0,
130130
"testCount": 1
131131
}

tests/integration/testdata/golden/specvital-web-v1.1.2.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
"repository": "specvital-web",
33
"ref": "v1.1.2",
44
"expectedFrameworks": ["go-testing", "vitest"],
5-
"fileCount": 22,
5+
"fileCount": 21,
66
"testCount": 146,
77
"frameworkCounts": {
88
"go-testing": 16,
9-
"vitest": 6
9+
"vitest": 5
1010
},
1111
"sampleFiles": [
1212
{
@@ -131,7 +131,7 @@
131131
}
132132
],
133133
"stats": {
134-
"filesMatched": 22,
134+
"filesMatched": 21,
135135
"filesScanned": 22
136136
}
137137
}

tests/integration/testdata/golden/trpc-v10.45.2.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
"repository": "trpc",
33
"ref": "v10.45.2",
44
"expectedFrameworks": ["playwright", "vitest"],
5-
"fileCount": 172,
6-
"testCount": 793,
5+
"fileCount": 171,
6+
"testCount": 792,
77
"frameworkCounts": {
88
"playwright": 9,
9-
"vitest": 163
9+
"vitest": 162
1010
},
1111
"sampleFiles": [
1212
{
@@ -131,7 +131,7 @@
131131
}
132132
],
133133
"stats": {
134-
"filesMatched": 172,
134+
"filesMatched": 171,
135135
"filesScanned": 172
136136
}
137137
}

0 commit comments

Comments
 (0)