playwright
Advanced tools
Comparing version 1.50.0-alpha-2024-11-23 to 1.50.0-alpha-2024-11-24
@@ -93,2 +93,3 @@ "use strict"; | ||
updateSnapshots: takeFirst(configCLIOverrides.updateSnapshots, userConfig.updateSnapshots, 'missing'), | ||
updateSourceMethod: takeFirst(configCLIOverrides.updateSourceMethod, userConfig.updateSourceMethod, 'patch'), | ||
version: require('../../package.json').version, | ||
@@ -95,0 +96,0 @@ workers: 0, |
@@ -441,2 +441,3 @@ "use strict"; | ||
updateSnapshots: 'missing', | ||
updateSourceMethod: 'patch', | ||
version: '', | ||
@@ -443,0 +444,0 @@ workers: 0, |
@@ -50,3 +50,2 @@ "use strict"; | ||
const generateMissingBaseline = updateSnapshots === 'missing' && !expected; | ||
const generateNewBaseline = updateSnapshots === 'all' || generateMissingBaseline; | ||
if (generateMissingBaseline) { | ||
@@ -100,11 +99,12 @@ if (this.isNot) { | ||
}; | ||
if (!this.isNot && pass === this.isNot && generateNewBaseline) { | ||
// Only rebaseline failed snapshots. | ||
const suggestedRebaseline = `toMatchAriaSnapshot(\`\n${(0, _utils.escapeTemplateString)(indent(typedReceived.regex, '{indent} '))}\n{indent}\`)`; | ||
return { | ||
pass: this.isNot, | ||
message: () => '', | ||
name: 'toMatchAriaSnapshot', | ||
suggestedRebaseline | ||
}; | ||
if (!this.isNot) { | ||
if (updateSnapshots === 'all' || updateSnapshots === 'changed' && pass === this.isNot || generateMissingBaseline) { | ||
const suggestedRebaseline = `toMatchAriaSnapshot(\`\n${(0, _utils.escapeTemplateString)(indent(typedReceived.regex, '{indent} '))}\n{indent}\`)`; | ||
return { | ||
pass: this.isNot, | ||
message: () => '', | ||
name: 'toMatchAriaSnapshot', | ||
suggestedRebaseline | ||
}; | ||
} | ||
} | ||
@@ -111,0 +111,0 @@ return { |
@@ -147,3 +147,3 @@ "use strict"; | ||
handleMissingNegated() { | ||
const isWriteMissingMode = this.updateSnapshots === 'all' || this.updateSnapshots === 'missing'; | ||
const isWriteMissingMode = this.updateSnapshots !== 'none'; | ||
const message = `A snapshot doesn't exist at ${this.expectedPath}${isWriteMissingMode ? ', matchers using ".not" won\'t write them automatically.' : '.'}`; | ||
@@ -163,3 +163,3 @@ // NOTE: 'isNot' matcher implies inversed value. | ||
handleMissing(actual) { | ||
const isWriteMissingMode = this.updateSnapshots === 'all' || this.updateSnapshots === 'missing'; | ||
const isWriteMissingMode = this.updateSnapshots !== 'none'; | ||
if (isWriteMissingMode) writeFileSync(this.expectedPath, actual); | ||
@@ -178,3 +178,3 @@ this.testInfo.attachments.push({ | ||
const message = `A snapshot doesn't exist at ${this.expectedPath}${isWriteMissingMode ? ', writing actual.' : '.'}`; | ||
if (this.updateSnapshots === 'all') { | ||
if (this.updateSnapshots === 'all' || this.updateSnapshots === 'changed') { | ||
/* eslint-disable no-console */ | ||
@@ -258,10 +258,19 @@ console.log(message); | ||
const expected = _fs.default.readFileSync(helper.expectedPath); | ||
const result = helper.comparator(received, expected, helper.options); | ||
if (!result) return helper.handleMatching(); | ||
if (helper.updateSnapshots === 'all') { | ||
if (!(0, _utils.compareBuffersOrStrings)(received, expected)) return helper.handleMatching(); | ||
writeFileSync(helper.expectedPath, received); | ||
/* eslint-disable no-console */ | ||
console.log(helper.expectedPath + ' is not the same, writing actual.'); | ||
return helper.createMatcherResult(helper.expectedPath + ' running with --update-snapshots, writing actual.', true); | ||
} | ||
if (helper.updateSnapshots === 'changed') { | ||
const result = helper.comparator(received, expected, helper.options); | ||
if (!result) return helper.handleMatching(); | ||
writeFileSync(helper.expectedPath, received); | ||
/* eslint-disable no-console */ | ||
console.log(helper.expectedPath + ' does not match, writing actual.'); | ||
return helper.createMatcherResult(helper.expectedPath + ' running with --update-snapshots, writing actual.', true); | ||
} | ||
const result = helper.comparator(received, expected, helper.options); | ||
if (!result) return helper.handleMatching(); | ||
const receiver = (0, _utils.isString)(received) ? 'string' : 'Buffer'; | ||
@@ -351,4 +360,4 @@ const header = (0, _matcherHint.matcherHint)(this, undefined, 'toMatchSnapshot', receiver, undefined, undefined); | ||
// - regular matcher (i.e. not a `.not`) | ||
// - perhaps an 'all' flag to update non-matching screenshots | ||
expectScreenshotOptions.expected = await _fs.default.promises.readFile(helper.expectedPath); | ||
const expected = await _fs.default.promises.readFile(helper.expectedPath); | ||
expectScreenshotOptions.expected = helper.updateSnapshots === 'all' ? undefined : expected; | ||
const { | ||
@@ -362,4 +371,3 @@ actual, | ||
} = await page._expectScreenshot(expectScreenshotOptions); | ||
if (!errorMessage) return helper.handleMatching(); | ||
if (helper.updateSnapshots === 'all') { | ||
const writeFiles = () => { | ||
writeFileSync(helper.expectedPath, actual); | ||
@@ -370,3 +378,12 @@ writeFileSync(helper.actualPath, actual); | ||
return helper.createMatcherResult(helper.expectedPath + ' running with --update-snapshots, writing actual.', true); | ||
}; | ||
if (!errorMessage) { | ||
// Screenshot is matching, but is not necessarily the same as the expected. | ||
if (helper.updateSnapshots === 'all' && actual && (0, _utils.compareBuffersOrStrings)(actual, expected)) { | ||
console.log(helper.expectedPath + ' is re-generated, writing actual.'); | ||
return writeFiles(); | ||
} | ||
return helper.handleMatching(); | ||
} | ||
if (helper.updateSnapshots === 'changed' || helper.updateSnapshots === 'all') return writeFiles(); | ||
const header = (0, _matcherHint.matcherHint)(this, undefined, 'toHaveScreenshot', receiver, undefined, undefined, timedOut ? timeout : undefined); | ||
@@ -373,0 +390,0 @@ return helper.handleDifferent(actual, expectScreenshotOptions.expected, previous, diff, header, errorMessage, log); |
@@ -271,2 +271,4 @@ "use strict"; | ||
const shardPair = options.shard ? options.shard.split('/').map(t => parseInt(t, 10)) : undefined; | ||
let updateSnapshots; | ||
if (['all', 'changed', 'missing', 'none'].includes(options.updateSnapshots)) updateSnapshots = options.updateSnapshots;else updateSnapshots = 'updateSnapshots' in options ? 'changed' : 'missing'; | ||
const overrides = { | ||
@@ -289,3 +291,4 @@ forbidOnly: options.forbidOnly ? true : undefined, | ||
ignoreSnapshots: options.ignoreSnapshots ? !!options.ignoreSnapshots : undefined, | ||
updateSnapshots: options.updateSnapshots ? 'all' : undefined, | ||
updateSnapshots, | ||
updateSourceMethod: options.updateSourceMethod || 'patch', | ||
workers: options.workers | ||
@@ -333,3 +336,6 @@ }; | ||
const kTraceModes = ['on', 'off', 'on-first-retry', 'on-all-retries', 'retain-on-failure', 'retain-on-first-failure']; | ||
const testOptions = [['--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 "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`], ['--fail-on-flaky-tests', `Fail if any test is flagged as flaky (default: false)`], ['--forbid-only', `Fail if test.only is called (default: false)`], ['--fully-parallel', `Run all tests in parallel (default: false)`], ['--global-timeout <timeout>', `Maximum time this test suite can run in milliseconds (default: unlimited)`], ['-g, --grep <grep>', `Only run tests matching this regular expression (default: ".*")`], ['-gv, --grep-invert <grep>', `Only run tests that do not match this regular expression`], ['--headed', `Run tests in headed browsers (default: headless)`], ['--ignore-snapshots', `Ignore screenshot and snapshot expectations`], ['--last-failed', `Only re-run the failures`], ['--list', `Collect all the tests and report them, but do not run`], ['--max-failures <N>', `Stop after the first N failures`], ['--no-deps', 'Do not run project dependencies'], ['--output <dir>', `Folder for output artifacts (default: "test-results")`], ['--only-changed [ref]', `Only run test files that have been changed between 'HEAD' and 'ref'. Defaults to running all uncommitted changes. Only supports Git.`], ['--pass-with-no-tests', `Makes test run succeed even if no tests were found`], ['--project <project-name...>', `Only run tests from the specified list of projects, supports '*' wildcard (default: run all projects)`], ['--quiet', `Suppress stdio`], ['--repeat-each <N>', `Run each test N times (default: 1)`], ['--reporter <reporter>', `Reporter to use, comma-separated, can be ${_config.builtInReporters.map(name => `"${name}"`).join(', ')} (default: "${_config.defaultReporter}")`], ['--retries <retries>', `Maximum retry count for flaky tests, zero for no retries (default: no retries)`], ['--shard <shard>', `Shard tests and execute only the selected shard, specify in the form "current/all", 1-based, for example "3/5"`], ['--timeout <timeout>', `Specify test timeout threshold in milliseconds, zero for unlimited (default: ${_config.defaultTimeout})`], ['--trace <mode>', `Force tracing mode, can be ${kTraceModes.map(mode => `"${mode}"`).join(', ')}`], ['--tsconfig <path>', `Path to a single tsconfig applicable to all imported files (default: look up tsconfig for each imported file separately)`], ['--ui', `Run tests in interactive UI mode`], ['--ui-host <host>', 'Host to serve UI on; specifying this option opens UI in a browser tab'], ['--ui-port <port>', 'Port to serve UI on, 0 for any free port; specifying this option opens UI in a browser tab'], ['-u, --update-snapshots', `Update snapshots with actual results (default: only create missing snapshots)`], ['-j, --workers <workers>', `Number of concurrent workers or percentage of logical CPU cores, use 1 to run in a single worker (default: 50%)`], ['-x', `Stop after the first failure`]]; | ||
// Note: update docs/src/test-cli-js.md when you update this, program is the source of truth. | ||
const testOptions = [/* deprecated */['--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 "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`], ['--fail-on-flaky-tests', `Fail if any test is flagged as flaky (default: false)`], ['--forbid-only', `Fail if test.only is called (default: false)`], ['--fully-parallel', `Run all tests in parallel (default: false)`], ['--global-timeout <timeout>', `Maximum time this test suite can run in milliseconds (default: unlimited)`], ['-g, --grep <grep>', `Only run tests matching this regular expression (default: ".*")`], ['-gv, --grep-invert <grep>', `Only run tests that do not match this regular expression`], ['--headed', `Run tests in headed browsers (default: headless)`], ['--ignore-snapshots', `Ignore screenshot and snapshot expectations`], ['--last-failed', `Only re-run the failures`], ['--list', `Collect all the tests and report them, but do not run`], ['--max-failures <N>', `Stop after the first N failures`], ['--no-deps', 'Do not run project dependencies'], ['--output <dir>', `Folder for output artifacts (default: "test-results")`], ['--only-changed [ref]', `Only run test files that have been changed between 'HEAD' and 'ref'. Defaults to running all uncommitted changes. Only supports Git.`], ['--pass-with-no-tests', `Makes test run succeed even if no tests were found`], ['--project <project-name...>', `Only run tests from the specified list of projects, supports '*' wildcard (default: run all projects)`], ['--quiet', `Suppress stdio`], ['--repeat-each <N>', `Run each test N times (default: 1)`], ['--reporter <reporter>', `Reporter to use, comma-separated, can be ${_config.builtInReporters.map(name => `"${name}"`).join(', ')} (default: "${_config.defaultReporter}")`], ['--retries <retries>', `Maximum retry count for flaky tests, zero for no retries (default: no retries)`], ['--shard <shard>', `Shard tests and execute only the selected shard, specify in the form "current/all", 1-based, for example "3/5"`], ['--timeout <timeout>', `Specify test timeout threshold in milliseconds, zero for unlimited (default: ${_config.defaultTimeout})`], ['--trace <mode>', `Force tracing mode, can be ${kTraceModes.map(mode => `"${mode}"`).join(', ')}`], ['--tsconfig <path>', `Path to a single tsconfig applicable to all imported files (default: look up tsconfig for each imported file separately)`], ['--ui', `Run tests in interactive UI mode`], ['--ui-host <host>', 'Host to serve UI on; specifying this option opens UI in a browser tab'], ['--ui-port <port>', 'Port to serve UI on, 0 for any free port; specifying this option opens UI in a browser tab'], ['-u, --update-snapshots [mode]', `Update snapshots with actual results. Possible values are 'all', 'changed', 'missing' and 'none'. Not passing defaults to 'missing', passing without value defaults to 'changed'`], ['--update-source-method <method>', `Chooses the way source is updated. Possible values are 'overwrite', '3way' and 'patch'. Defaults to 'patch'`], ['-j, --workers <workers>', `Number of concurrent workers or percentage of logical CPU cores, use 1 to run in a single worker (default: 50%)`], ['-x', `Stop after the first failure`]]; | ||
addTestCommand(_program.program); | ||
@@ -336,0 +342,0 @@ addShowReportCommand(_program.program); |
@@ -40,3 +40,3 @@ "use strict"; | ||
async function applySuggestedRebaselines(config, reporter) { | ||
if (config.config.updateSnapshots !== 'all' && config.config.updateSnapshots !== 'missing') return; | ||
if (config.config.updateSnapshots === 'none') return; | ||
if (!suggestedRebaselines.size) return; | ||
@@ -48,2 +48,3 @@ const [project] = (0, _projectUtils.filterProjects)(config.projects, config.cliProjectFilter); | ||
const gitCache = new Map(); | ||
const patchFile = _path.default.join(project.project.outputDir, 'rebaselines.patch'); | ||
for (const fileName of [...suggestedRebaselines.keys()].sort()) { | ||
@@ -85,20 +86,23 @@ const source = await _fs.default.promises.readFile(fileName, 'utf8'); | ||
for (const range of ranges) result = result.substring(0, range.start) + range.newText + result.substring(range.end); | ||
if (process.env.PWTEST_UPDATE_SNAPSHOTS === 'overwrite') { | ||
const relativeName = _path.default.relative(process.cwd(), fileName); | ||
files.push(relativeName); | ||
if (config.config.updateSourceMethod === 'overwrite') { | ||
await _fs.default.promises.writeFile(fileName, result); | ||
} else if (process.env.PWTEST_UPDATE_SNAPSHOTS === 'manual') { | ||
} else if (config.config.updateSourceMethod === '3way') { | ||
await _fs.default.promises.writeFile(fileName, applyPatchWithConflictMarkers(source, result)); | ||
} else { | ||
const gitFolder = findGitRoot(_path.default.dirname(fileName), gitCache); | ||
const relativeName = _path.default.relative(gitFolder || process.cwd(), fileName); | ||
files.push(relativeName); | ||
patches.push(createPatch(relativeName, source, result)); | ||
const relativeToGit = _path.default.relative(gitFolder || process.cwd(), fileName); | ||
patches.push(createPatch(relativeToGit, source, result)); | ||
} | ||
} | ||
const patchFile = _path.default.join(project.project.outputDir, 'rebaselines.patch'); | ||
await _fs.default.promises.mkdir(_path.default.dirname(patchFile), { | ||
recursive: true | ||
}); | ||
await _fs.default.promises.writeFile(patchFile, patches.join('\n')); | ||
const fileList = files.map(file => ' ' + _utilsBundle.colors.dim(file)).join('\n'); | ||
reporter.onStdErr(`\nNew baselines created for:\n\n${fileList}\n\n ` + _utilsBundle.colors.cyan('git apply ' + _path.default.relative(process.cwd(), patchFile)) + '\n'); | ||
reporter.onStdErr(`\nNew baselines created for:\n\n${fileList}\n`); | ||
if (config.config.updateSourceMethod === 'patch') { | ||
await _fs.default.promises.mkdir(_path.default.dirname(patchFile), { | ||
recursive: true | ||
}); | ||
await _fs.default.promises.writeFile(patchFile, patches.join('\n')); | ||
reporter.onStdErr(`\n ` + _utilsBundle.colors.cyan('git apply ' + _path.default.relative(process.cwd(), patchFile)) + '\n'); | ||
} | ||
} | ||
@@ -105,0 +109,0 @@ function createPatch(fileName, before, after) { |
{ | ||
"name": "playwright", | ||
"version": "1.50.0-alpha-2024-11-23", | ||
"version": "1.50.0-alpha-2024-11-24", | ||
"description": "A high-level API to automate web browsers", | ||
@@ -59,3 +59,3 @@ "repository": { | ||
"dependencies": { | ||
"playwright-core": "1.50.0-alpha-2024-11-23" | ||
"playwright-core": "1.50.0-alpha-2024-11-24" | ||
}, | ||
@@ -62,0 +62,0 @@ "optionalDependencies": { |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
3154993
35778
176
+ Addedplaywright-core@1.50.0-alpha-2024-11-24(transitive)
- Removedplaywright-core@1.50.0-alpha-2024-11-23(transitive)