Skip to content

Commit 94c7bfb

Browse files
authored
fix: support IgnoreDirectoriesMatch (#1175)
* fix: ingoreDirectoriesMatch correctly populated * fix: add tests * fix: skip ignore if explicitly included * fix: add files for testing * fix: ignoring .git for testing
1 parent b9a2d62 commit 94c7bfb

File tree

11 files changed

+220
-3
lines changed

11 files changed

+220
-3
lines changed

packages/cli/src/constructs/project.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ export class Session {
243243
static privateLocations: PrivateLocationApi[]
244244
static parsers = new Map<string, Parser>()
245245
static constructExports: ConstructExport[] = []
246+
static ignoreDirectoriesMatch: string[] = []
246247

247248
static async loadFile<T = unknown> (filePath: string): Promise<T> {
248249
const loader = this.loader
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Allow node_modules in test fixtures
2+
!node_modules
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"mockUser": {
3+
"id": 1,
4+
"name": "Test User"
5+
}
6+
}

packages/cli/src/services/__tests__/fixtures/playwright-bundle-test/node_modules/@internal/test-helpers/helper.js

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/cli/src/services/__tests__/fixtures/playwright-bundle-test/package-lock.json

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"name": "playwright-bundle-test",
3+
"version": "1.0.0",
4+
"dependencies": {
5+
"@playwright/test": "^1.40.0"
6+
}
7+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { defineConfig } from '@playwright/test'
2+
3+
export default defineConfig({
4+
testDir: './tests',
5+
timeout: 30000,
6+
})
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { test, expect } from '@playwright/test'
2+
3+
test('basic test', async ({ page }) => {
4+
await page.goto('https://playwright.dev/')
5+
expect(await page.title()).toContain('Playwright')
6+
})

packages/cli/src/services/__tests__/util.spec.ts

Lines changed: 157 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
import path from 'node:path'
2-
import { describe, it, expect } from 'vitest'
2+
import fs from 'node:fs/promises'
3+
import { describe, it, expect, beforeEach, afterEach } from 'vitest'
4+
import { extract } from 'tar'
35

46
import {
57
pathToPosix,
68
isFileSync,
79
getPlaywrightVersionFromPackage,
10+
bundlePlayWrightProject,
811
} from '../util'
12+
import { Session } from '../../constructs/project'
913

1014
describe('util', () => {
1115
describe('pathToPosix()', () => {
@@ -46,4 +50,156 @@ describe('util', () => {
4650
expect(version).toMatch(/^\d+\.\d+\.\d+/)
4751
})
4852
})
53+
54+
describe('bundlePlayWrightProject()', () => {
55+
let originalBasePath: string | undefined
56+
let extractDir: string
57+
58+
beforeEach(async () => {
59+
// Save original Session state
60+
originalBasePath = Session.basePath
61+
62+
// Set up Session for bundling
63+
const fixtureDir = path.join(__dirname, 'fixtures', 'playwright-bundle-test')
64+
Session.basePath = fixtureDir
65+
66+
// Create temp directory for extraction
67+
extractDir = await fs.mkdtemp(path.join(__dirname, 'temp-extract-'))
68+
})
69+
70+
afterEach(async () => {
71+
// Restore Session state
72+
Session.basePath = originalBasePath
73+
Session.ignoreDirectoriesMatch = []
74+
75+
// Clean up extraction directory
76+
try {
77+
await fs.rm(extractDir, { recursive: true, force: true })
78+
} catch {
79+
// Ignore cleanup errors
80+
}
81+
})
82+
83+
it('should exclude directories matching ignoreDirectoriesMatch pattern', async () => {
84+
const fixtureDir = path.join(__dirname, 'fixtures', 'playwright-bundle-test')
85+
const playwrightConfigPath = path.join(fixtureDir, 'playwright.config.ts')
86+
87+
// Set ignoreDirectoriesMatch to exclude fixtures directory
88+
Session.ignoreDirectoriesMatch = ['**/fixtures/**']
89+
90+
// Bundle the project
91+
const result = await bundlePlayWrightProject(playwrightConfigPath, [])
92+
93+
// Extract the bundle
94+
await extract({
95+
file: result.outputFile,
96+
cwd: extractDir,
97+
})
98+
99+
// Check that test files are included
100+
const testsDir = path.join(extractDir, 'tests')
101+
const testFiles = await fs.readdir(testsDir)
102+
expect(testFiles).toContain('example.spec.ts')
103+
104+
// Check that fixtures directory is NOT included
105+
const fixturesPath = path.join(extractDir, 'fixtures')
106+
await expect(fs.access(fixturesPath)).rejects.toThrow()
107+
}, 30000)
108+
109+
it('should include all directories when ignoreDirectoriesMatch is empty', async () => {
110+
const fixtureDir = path.join(__dirname, 'fixtures', 'playwright-bundle-test')
111+
const playwrightConfigPath = path.join(fixtureDir, 'playwright.config.ts')
112+
113+
// Set empty ignoreDirectoriesMatch
114+
Session.ignoreDirectoriesMatch = []
115+
116+
// Bundle the project with include pattern that matches fixtures
117+
const result = await bundlePlayWrightProject(playwrightConfigPath, ['fixtures/**/*'])
118+
119+
// Extract the bundle
120+
await extract({
121+
file: result.outputFile,
122+
cwd: extractDir,
123+
})
124+
125+
// Check that fixtures directory IS included when explicitly in include
126+
const fixturesPath = path.join(extractDir, 'fixtures')
127+
const fixturesExists = await fs.access(fixturesPath).then(() => true).catch(() => false)
128+
expect(fixturesExists).toBe(true)
129+
130+
if (fixturesExists) {
131+
const fixtureFiles = await fs.readdir(fixturesPath)
132+
expect(fixtureFiles).toContain('mock-data.json')
133+
}
134+
}, 30000)
135+
136+
it('should include explicit node_modules patterns bypassing default ignores', async () => {
137+
const fixtureDir = path.join(__dirname, 'fixtures', 'playwright-bundle-test')
138+
const playwrightConfigPath = path.join(fixtureDir, 'playwright.config.ts')
139+
140+
// Set empty ignoreDirectoriesMatch
141+
Session.ignoreDirectoriesMatch = []
142+
143+
// Bundle the project with explicit node_modules pattern
144+
const result = await bundlePlayWrightProject(playwrightConfigPath, ['node_modules/@internal/test-helpers/**'])
145+
146+
// Extract the bundle
147+
await extract({
148+
file: result.outputFile,
149+
cwd: extractDir,
150+
})
151+
152+
// Check that node_modules directory IS included when explicitly specified
153+
const nodeModulesPath = path.join(extractDir, 'node_modules', '@internal', 'test-helpers')
154+
const nodeModulesExists = await fs.access(nodeModulesPath).then(() => true).catch(() => false)
155+
expect(nodeModulesExists).toBe(true)
156+
157+
if (nodeModulesExists) {
158+
const helperFiles = await fs.readdir(nodeModulesPath)
159+
expect(helperFiles).toContain('helper.js')
160+
}
161+
}, 30000)
162+
163+
it('should still respect custom ignoreDirectoriesMatch for explicit patterns', async () => {
164+
const fixtureDir = path.join(__dirname, 'fixtures', 'playwright-bundle-test')
165+
const playwrightConfigPath = path.join(fixtureDir, 'playwright.config.ts')
166+
167+
// Set custom ignoreDirectoriesMatch to exclude @internal
168+
Session.ignoreDirectoriesMatch = ['**/@internal/**']
169+
170+
// Bundle the project with explicit node_modules pattern
171+
const result = await bundlePlayWrightProject(playwrightConfigPath, ['node_modules/@internal/test-helpers/**'])
172+
173+
// Extract the bundle
174+
await extract({
175+
file: result.outputFile,
176+
cwd: extractDir,
177+
})
178+
179+
// Check that @internal is NOT included (custom ignore still applies)
180+
const nodeModulesPath = path.join(extractDir, 'node_modules', '@internal')
181+
await expect(fs.access(nodeModulesPath)).rejects.toThrow()
182+
}, 30000)
183+
184+
it('should exclude node_modules with broad patterns despite include', async () => {
185+
const fixtureDir = path.join(__dirname, 'fixtures', 'playwright-bundle-test')
186+
const playwrightConfigPath = path.join(fixtureDir, 'playwright.config.ts')
187+
188+
// Set empty ignoreDirectoriesMatch
189+
Session.ignoreDirectoriesMatch = []
190+
191+
// Bundle with a broad pattern that would match node_modules but doesn't explicitly target it
192+
const result = await bundlePlayWrightProject(playwrightConfigPath, ['**/*.js'])
193+
194+
// Extract the bundle
195+
await extract({
196+
file: result.outputFile,
197+
cwd: extractDir,
198+
})
199+
200+
// Check that node_modules is NOT included (default ignore still applies for broad patterns)
201+
const nodeModulesPath = path.join(extractDir, 'node_modules')
202+
await expect(fs.access(nodeModulesPath)).rejects.toThrow()
203+
}, 30000)
204+
})
49205
})

packages/cli/src/services/project-parser.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ export async function parseProject (opts: ProjectParseOpts): Promise<Project> {
8181
Session.availableRuntimes = availableRuntimes
8282
Session.defaultRuntimeId = defaultRuntimeId
8383
Session.verifyRuntimeDependencies = verifyRuntimeDependencies ?? true
84+
Session.ignoreDirectoriesMatch = ignoreDirectoriesMatch
8485

8586
// TODO: Do we really need all of the ** globs, or could we just put node_modules?
8687
const ignoreDirectories = ['**/node_modules/**', '**/.git/**', ...ignoreDirectoriesMatch]

0 commit comments

Comments
 (0)