mirror of
				https://github.com/microsoft/playwright.git
				synced 2025-06-26 21:40:17 +00:00 
			
		
		
		
	
							parent
							
								
									d7f5f1f5fe
								
							
						
					
					
						commit
						44a934c160
					
				| @ -492,7 +492,7 @@ export default defineConfig({ | |||||||
| 
 | 
 | ||||||
| Only the files matching one of these patterns are executed as test files. Matching is performed against the absolute file path. Strings are treated as glob patterns. | Only the files matching one of these patterns are executed as test files. Matching is performed against the absolute file path. Strings are treated as glob patterns. | ||||||
| 
 | 
 | ||||||
| By default, Playwright looks for files matching the following glob pattern: `**/*.@(spec|test).?(m)[jt]s?(x)`. This means JavaScript or TypeScript files with `".test"` or `".spec"` suffix, for example `login-screen.wrong-credentials.spec.ts`. | By default, Playwright looks for files matching the following glob pattern: `**/*.@(spec|test).?(c|m)[jt]s?(x)`. This means JavaScript or TypeScript files with `".test"` or `".spec"` suffix, for example `login-screen.wrong-credentials.spec.ts`. | ||||||
| 
 | 
 | ||||||
| **Usage** | **Usage** | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -305,7 +305,7 @@ Use [`property: TestConfig.testIgnore`] to change this option for all projects. | |||||||
| 
 | 
 | ||||||
| Only the files matching one of these patterns are executed as test files. Matching is performed against the absolute file path. Strings are treated as glob patterns. | Only the files matching one of these patterns are executed as test files. Matching is performed against the absolute file path. Strings are treated as glob patterns. | ||||||
| 
 | 
 | ||||||
| By default, Playwright looks for files matching the following glob pattern: `**/*.@(spec|test).?(m)[jt]s?(x)`. This means JavaScript or TypeScript files with `".test"` or `".spec"` suffix, for example `login-screen.wrong-credentials.spec.ts`. | By default, Playwright looks for files matching the following glob pattern: `**/*.@(spec|test).?(c|m)[jt]s?(x)`. This means JavaScript or TypeScript files with `".test"` or `".spec"` suffix, for example `login-screen.wrong-credentials.spec.ts`. | ||||||
| 
 | 
 | ||||||
| Use [`property: TestConfig.testMatch`] to change this option for all projects. | Use [`property: TestConfig.testMatch`] to change this option for all projects. | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -24,7 +24,7 @@ import { stopProfiling, startProfiling } from 'playwright-core/lib/utils'; | |||||||
| import { experimentalLoaderOption, fileIsModule, serializeError } from './util'; | import { experimentalLoaderOption, fileIsModule, serializeError } from './util'; | ||||||
| import { showHTMLReport } from './reporters/html'; | import { showHTMLReport } from './reporters/html'; | ||||||
| import { createMergedReport } from './reporters/merge'; | import { createMergedReport } from './reporters/merge'; | ||||||
| import { ConfigLoader, kDefaultConfigFiles, resolveConfigFile } from './common/configLoader'; | import { ConfigLoader, resolveConfigFile } from './common/configLoader'; | ||||||
| import type { ConfigCLIOverrides } from './common/ipc'; | import type { ConfigCLIOverrides } from './common/ipc'; | ||||||
| import type { FullResult, TestError } from '../reporter'; | import type { FullResult, TestError } from '../reporter'; | ||||||
| import type { TraceMode } from '../types/test'; | import type { TraceMode } from '../types/test'; | ||||||
| @ -61,7 +61,7 @@ Examples: | |||||||
| function addListFilesCommand(program: Command) { | function addListFilesCommand(program: Command) { | ||||||
|   const command = program.command('list-files [file-filter...]', { hidden: true }); |   const command = program.command('list-files [file-filter...]', { hidden: true }); | ||||||
|   command.description('List files with Playwright Test tests'); |   command.description('List files with Playwright Test tests'); | ||||||
|   command.option('-c, --config <file>', `Configuration file, or a test directory with optional ${kDefaultConfigFiles.map(file => `"${file}"`).join('/')}`); |   command.option('-c, --config <file>', `Configuration file, or a test directory with optional "playwright.config.{m,c}?{js,ts}"`); | ||||||
|   command.option('--project <project-name...>', `Only run tests from the specified list of projects (default: list all projects)`); |   command.option('--project <project-name...>', `Only run tests from the specified list of projects (default: list all projects)`); | ||||||
|   command.action(async (args, opts) => { |   command.action(async (args, opts) => { | ||||||
|     try { |     try { | ||||||
| @ -297,7 +297,7 @@ const kTraceModes: TraceMode[] = ['on', 'off', 'on-first-retry', 'on-all-retries | |||||||
| 
 | 
 | ||||||
| const testOptions: [string, string][] = [ | const testOptions: [string, string][] = [ | ||||||
|   ['--browser <browser>', `Browser to use for tests, one of "all", "chromium", "firefox" or "webkit" (default: "chromium")`], |   ['--browser <browser>', `Browser to use for tests, one of "all", "chromium", "firefox" or "webkit" (default: "chromium")`], | ||||||
|   ['-c, --config <file>', `Configuration file, or a test directory with optional ${kDefaultConfigFiles.map(file => `"${file}"`).join('/')}`], |   ['-c, --config <file>', `Configuration file, or a test directory with optional "playwright.config.{m,c}?{js,ts}"`], | ||||||
|   ['--debug', `Run tests with Playwright Inspector. Shortcut for "PWDEBUG=1" environment variable and "--timeout=0 --max-failures=1 --headed --workers=1" options`], |   ['--debug', `Run tests with Playwright Inspector. Shortcut for "PWDEBUG=1" environment variable and "--timeout=0 --max-failures=1 --headed --workers=1" options`], | ||||||
|   ['--forbid-only', `Fail if test.only is called (default: false)`], |   ['--forbid-only', `Fail if test.only is called (default: false)`], | ||||||
|   ['--fully-parallel', `Run all tests in parallel (default: false)`], |   ['--fully-parallel', `Run all tests in parallel (default: false)`], | ||||||
|  | |||||||
| @ -173,7 +173,7 @@ export class FullProjectInternal { | |||||||
|       testDir, |       testDir, | ||||||
|       snapshotDir: takeFirst(pathResolve(configDir, projectConfig.snapshotDir), pathResolve(configDir, config.snapshotDir), testDir), |       snapshotDir: takeFirst(pathResolve(configDir, projectConfig.snapshotDir), pathResolve(configDir, config.snapshotDir), testDir), | ||||||
|       testIgnore: takeFirst(projectConfig.testIgnore, config.testIgnore, []), |       testIgnore: takeFirst(projectConfig.testIgnore, config.testIgnore, []), | ||||||
|       testMatch: takeFirst(projectConfig.testMatch, config.testMatch, '**/*.@(spec|test).?(m)[jt]s?(x)'), |       testMatch: takeFirst(projectConfig.testMatch, config.testMatch, '**/*.@(spec|test).?(c|m)[jt]s?(x)'), | ||||||
|       timeout: takeFirst(configCLIOverrides.timeout, projectConfig.timeout, config.timeout, defaultTimeout), |       timeout: takeFirst(configCLIOverrides.timeout, projectConfig.timeout, config.timeout, defaultTimeout), | ||||||
|       use: mergeObjects(config.use, projectConfig.use, configCLIOverrides.use), |       use: mergeObjects(config.use, projectConfig.use, configCLIOverrides.use), | ||||||
|       dependencies: projectConfig.dependencies || [], |       dependencies: projectConfig.dependencies || [], | ||||||
|  | |||||||
| @ -258,8 +258,6 @@ function validateProject(file: string, project: Project, title: string) { | |||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export const kDefaultConfigFiles = ['playwright.config.ts', 'playwright.config.js', 'playwright.config.mjs']; |  | ||||||
| 
 |  | ||||||
| export function resolveConfigFile(configFileOrDirectory: string): string | null { | export function resolveConfigFile(configFileOrDirectory: string): string | null { | ||||||
|   const resolveConfig = (configFile: string) => { |   const resolveConfig = (configFile: string) => { | ||||||
|     if (fs.existsSync(configFile)) |     if (fs.existsSync(configFile)) | ||||||
| @ -267,8 +265,8 @@ export function resolveConfigFile(configFileOrDirectory: string): string | null | |||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   const resolveConfigFileFromDirectory = (directory: string) => { |   const resolveConfigFileFromDirectory = (directory: string) => { | ||||||
|     for (const configName of kDefaultConfigFiles) { |     for (const ext of ['.ts', '.js', '.mts', '.mjs', '.cts', '.cjs']) { | ||||||
|       const configFile = resolveConfig(path.resolve(directory, configName)); |       const configFile = resolveConfig(path.resolve(directory, 'playwright.config' + ext)); | ||||||
|       if (configFile) |       if (configFile) | ||||||
|         return configFile; |         return configFile; | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -102,8 +102,8 @@ export function buildDependentProjects(forProject: FullProjectInternal, projects | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function collectFilesForProject(project: FullProjectInternal, fsCache = new Map<string, string[]>()): Promise<string[]> { | export async function collectFilesForProject(project: FullProjectInternal, fsCache = new Map<string, string[]>()): Promise<string[]> { | ||||||
|   const extensions = ['.js', '.ts', '.mjs', '.tsx', '.jsx']; |   const extensions = new Set(['.js', '.ts', '.mjs', '.mts', '.cjs', '.cts', '.jsx', '.tsx', '.mjsx', '.mtsx', '.cjsx', '.ctsx']); | ||||||
|   const testFileExtension = (file: string) => extensions.includes(path.extname(file)); |   const testFileExtension = (file: string) => extensions.has(path.extname(file)); | ||||||
|   const allFiles = await cachedCollectFiles(project.project.testDir, project.respectGitIgnore, fsCache); |   const allFiles = await cachedCollectFiles(project.project.testDir, project.respectGitIgnore, fsCache); | ||||||
|   const testMatch = createFileMatcher(project.project.testMatch); |   const testMatch = createFileMatcher(project.project.testMatch); | ||||||
|   const testIgnore = createFileMatcher(project.project.testIgnore); |   const testIgnore = createFileMatcher(project.project.testIgnore); | ||||||
|  | |||||||
| @ -280,9 +280,10 @@ export async function normalizeAndSaveAttachment(outputPath: string, name: strin | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export function fileIsModule(file: string): boolean { | export function fileIsModule(file: string): boolean { | ||||||
|   if (file.endsWith('.mjs')) |   if (file.endsWith('.mjs') || file.endsWith('.mts')) | ||||||
|     return true; |     return true; | ||||||
| 
 |   if (file.endsWith('.cjs') || file.endsWith('.cts')) | ||||||
|  |     return false; | ||||||
|   const folder = path.dirname(file); |   const folder = path.dirname(file); | ||||||
|   return folderIsModule(folder); |   return folderIsModule(folder); | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										12
									
								
								packages/playwright-test/types/test.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								packages/playwright-test/types/test.d.ts
									
									
									
									
										vendored
									
									
								
							| @ -395,8 +395,8 @@ export interface FullProject<TestArgs = {}, WorkerArgs = {}> { | |||||||
|    * Only the files matching one of these patterns are executed as test files. Matching is performed against the |    * Only the files matching one of these patterns are executed as test files. Matching is performed against the | ||||||
|    * absolute file path. Strings are treated as glob patterns. |    * absolute file path. Strings are treated as glob patterns. | ||||||
|    * |    * | ||||||
|    * By default, Playwright looks for files matching the following glob pattern: `**\/*.@(spec|test).?(m)[jt]s?(x)`. This |    * By default, Playwright looks for files matching the following glob pattern: `**\/*.@(spec|test).?(c|m)[jt]s?(x)`. | ||||||
|    * means JavaScript or TypeScript files with `".test"` or `".spec"` suffix, for example |    * This means JavaScript or TypeScript files with `".test"` or `".spec"` suffix, for example | ||||||
|    * `login-screen.wrong-credentials.spec.ts`. |    * `login-screen.wrong-credentials.spec.ts`. | ||||||
|    * |    * | ||||||
|    * Use [testConfig.testMatch](https://playwright.dev/docs/api/class-testconfig#test-config-test-match) to change this
 |    * Use [testConfig.testMatch](https://playwright.dev/docs/api/class-testconfig#test-config-test-match) to change this
 | ||||||
| @ -1240,8 +1240,8 @@ interface TestConfig { | |||||||
|    * Only the files matching one of these patterns are executed as test files. Matching is performed against the |    * Only the files matching one of these patterns are executed as test files. Matching is performed against the | ||||||
|    * absolute file path. Strings are treated as glob patterns. |    * absolute file path. Strings are treated as glob patterns. | ||||||
|    * |    * | ||||||
|    * By default, Playwright looks for files matching the following glob pattern: `**\/*.@(spec|test).?(m)[jt]s?(x)`. This |    * By default, Playwright looks for files matching the following glob pattern: `**\/*.@(spec|test).?(c|m)[jt]s?(x)`. | ||||||
|    * means JavaScript or TypeScript files with `".test"` or `".spec"` suffix, for example |    * This means JavaScript or TypeScript files with `".test"` or `".spec"` suffix, for example | ||||||
|    * `login-screen.wrong-credentials.spec.ts`. |    * `login-screen.wrong-credentials.spec.ts`. | ||||||
|    * |    * | ||||||
|    * **Usage** |    * **Usage** | ||||||
| @ -6439,8 +6439,8 @@ interface TestProject { | |||||||
|    * Only the files matching one of these patterns are executed as test files. Matching is performed against the |    * Only the files matching one of these patterns are executed as test files. Matching is performed against the | ||||||
|    * absolute file path. Strings are treated as glob patterns. |    * absolute file path. Strings are treated as glob patterns. | ||||||
|    * |    * | ||||||
|    * By default, Playwright looks for files matching the following glob pattern: `**\/*.@(spec|test).?(m)[jt]s?(x)`. This |    * By default, Playwright looks for files matching the following glob pattern: `**\/*.@(spec|test).?(c|m)[jt]s?(x)`. | ||||||
|    * means JavaScript or TypeScript files with `".test"` or `".spec"` suffix, for example |    * This means JavaScript or TypeScript files with `".test"` or `".spec"` suffix, for example | ||||||
|    * `login-screen.wrong-credentials.spec.ts`. |    * `login-screen.wrong-credentials.spec.ts`. | ||||||
|    * |    * | ||||||
|    * Use [testConfig.testMatch](https://playwright.dev/docs/api/class-testconfig#test-config-test-match) to change this
 |    * Use [testConfig.testMatch](https://playwright.dev/docs/api/class-testconfig#test-config-test-match) to change this
 | ||||||
|  | |||||||
| @ -392,3 +392,47 @@ test('should resolve .js import to .tsx file in ESM mode for components', async | |||||||
|   expect(result.passed).toBe(1); |   expect(result.passed).toBe(1); | ||||||
|   expect(result.exitCode).toBe(0); |   expect(result.exitCode).toBe(0); | ||||||
| }); | }); | ||||||
|  | 
 | ||||||
|  | test('should load cjs config and test in non-ESM mode', async ({ runInlineTest }) => { | ||||||
|  |   const result = await runInlineTest({ | ||||||
|  |     'package.json': `{ "type": "module" }`, | ||||||
|  |     'playwright.config.cjs': ` | ||||||
|  |       const fs = require('fs'); | ||||||
|  |       module.exports = { projects: [{name: 'foo'}] }; | ||||||
|  |     `,
 | ||||||
|  |     'a.test.js': ` | ||||||
|  |       import { test, expect } from '@playwright/test'; | ||||||
|  |       test('check project name', ({}, testInfo) => { | ||||||
|  |         expect(testInfo.project.name).toBe('foo'); | ||||||
|  |       }); | ||||||
|  |     `,
 | ||||||
|  |     'b.spec.cjs': ` | ||||||
|  |       const { test, expect } = require('@playwright/test'); | ||||||
|  |       test('check project name', ({}, testInfo) => { | ||||||
|  |         expect(testInfo.project.name).toBe('foo'); | ||||||
|  |       }); | ||||||
|  |     `,
 | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   expect(result.exitCode).toBe(0); | ||||||
|  |   expect(result.passed).toBe(2); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | test('should disallow ESM when config is cjs', async ({ runInlineTest }) => { | ||||||
|  |   const result = await runInlineTest({ | ||||||
|  |     'package.json': `{ "type": "module" }`, | ||||||
|  |     'playwright.config.cjs': ` | ||||||
|  |       const fs = require('fs'); | ||||||
|  |       module.exports = { projects: [{name: 'foo'}] }; | ||||||
|  |     `,
 | ||||||
|  |     'a.test.ts': ` | ||||||
|  |       import { test, expect } from '@playwright/test'; | ||||||
|  |       test('check project name', ({}, testInfo) => { | ||||||
|  |         expect(testInfo.project.name).toBe('foo'); | ||||||
|  |       }); | ||||||
|  |     `,
 | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   expect(result.exitCode).toBe(1); | ||||||
|  |   expect(result.output).toContain('Unknown file extension ".ts"'); | ||||||
|  | }); | ||||||
|  | |||||||
| @ -224,7 +224,7 @@ test('should load esm when package.json has type module', async ({ runInlineTest | |||||||
|   expect(result.passed).toBe(1); |   expect(result.passed).toBe(1); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| test('should load esm config files', async ({ runInlineTest }) => { | test('should load mjs config file', async ({ runInlineTest }) => { | ||||||
|   const result = await runInlineTest({ |   const result = await runInlineTest({ | ||||||
|     'playwright.config.mjs': ` |     'playwright.config.mjs': ` | ||||||
|       import * as fs from 'fs'; |       import * as fs from 'fs'; | ||||||
| @ -242,6 +242,24 @@ test('should load esm config files', async ({ runInlineTest }) => { | |||||||
|   expect(result.passed).toBe(1); |   expect(result.passed).toBe(1); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
|  | test('should load mts config file', async ({ runInlineTest }) => { | ||||||
|  |   const result = await runInlineTest({ | ||||||
|  |     'playwright.config.mts': ` | ||||||
|  |       import * as fs from 'fs'; | ||||||
|  |       export default { projects: [{name: 'foo'}] }; | ||||||
|  |     `,
 | ||||||
|  |     'a.test.ts': ` | ||||||
|  |       import { test, expect } from '@playwright/test'; | ||||||
|  |       test('check project name', ({}, testInfo) => { | ||||||
|  |         expect(testInfo.project.name).toBe('foo'); | ||||||
|  |       }); | ||||||
|  |     ` | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   expect(result.exitCode).toBe(0); | ||||||
|  |   expect(result.passed).toBe(1); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
| test('should load ts from esm when package.json has type module', async ({ runInlineTest, nodeVersion }) => { | test('should load ts from esm when package.json has type module', async ({ runInlineTest, nodeVersion }) => { | ||||||
|   // We only support experimental esm mode on Node 16+
 |   // We only support experimental esm mode on Node 16+
 | ||||||
|   test.skip(nodeVersion.major < 16); |   test.skip(nodeVersion.major < 16); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Dmitry Gozman
						Dmitry Gozman