Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added pathPattern parameter to takeScreenshot method #8093

Merged
merged 10 commits into from
Dec 22, 2023
1 change: 1 addition & 0 deletions src/notifications/warning-message.ts
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ export default {
screenshotMarkNotFound: 'Unable to locate the page area in the browser window screenshot at {screenshotPath}, because the page area mark with ID {markId} is not found in the screenshot.',
screenshotsFullPageNotSupported: 'TestCafe does not support full-page screenshots in {browserAlias}.',
screenshotRewritingError: 'The file at "{screenshotPath}" already exists. It has just been rewritten with a recent screenshot. This situation can possibly cause issues. To avoid them, make sure that each screenshot has a unique path. If a test runs in multiple browsers, consider including the user agent in the screenshot path or generate a unique identifier in another way.',
screenshotPathOverridesPathPattern: 'The screenshot path "{customPath}" overrides the "{customPathPattern}" pathPattern parameter. Choose only one of the parameters to specify the screenshot path.',
browserManipulationsOnRemoteBrowser: 'The screenshot and window resize functionalities are not supported in a remote browser. They can function only if the browser is running on the same machine and in the same environment as the TestCafe server.',
screenshotNotSupportedByBrowserProvider: 'The screenshot functionality is not supported by the "{providerName}" browser provider.',
videoNotSupportedByBrowser: 'Video recording is not supported by the "{browserAlias}" browser.',
12 changes: 8 additions & 4 deletions src/screenshots/capturer.js
Original file line number Diff line number Diff line change
@@ -103,8 +103,8 @@ export default class Capturer {
return this._joinWithBaseScreenshotPath(correctedCustomPath);
}

_getScreenshotPath (forError) {
const path = this.pathPattern.getPath(forError);
_getScreenshotPath (forError, customPathPattern) {
const path = this.pathPattern.getPath(forError, customPathPattern);

this._incrementFileIndexes(forError);

@@ -122,15 +122,19 @@ export default class Capturer {
await this.provider.takeScreenshot(this.browserId, filePath, pageWidth, pageHeight, fullPage);
}

async _capture (forError, { actionId, failedActionId, pageDimensions, cropDimensions, markSeed, customPath, fullPage, thumbnails } = {}) {
async _capture (forError, { actionId, failedActionId, pageDimensions, cropDimensions, markSeed, customPath, customPathPattern, fullPage, thumbnails } = {}) {
if (!this.enabled)
return null;

thumbnails = thumbnails === void 0 ? this.thumbnails : thumbnails;

const screenshotPath = customPath ? this._getCustomScreenshotPath(customPath) : this._getScreenshotPath(forError);
const screenshotPath = customPath ? this._getCustomScreenshotPath(customPath) : this._getScreenshotPath(forError, customPathPattern);

const thumbnailPath = this._getThumbnailPath(screenshotPath);

if (customPath && customPathPattern)
this.warningLog.addWarning(WARNING_MESSAGE.screenshotPathOverridesPathPattern, customPath, customPathPattern);

if (isInQueue(screenshotPath))
this.warningLog.addWarning(WARNING_MESSAGE.screenshotRewritingError, screenshotPath);

15 changes: 8 additions & 7 deletions src/test-run/browser-manipulation-queue.js
Original file line number Diff line number Diff line change
@@ -59,13 +59,14 @@ export default class BrowserManipulationQueue {
case COMMAND_TYPE.takeElementScreenshot:
case COMMAND_TYPE.takeScreenshot:
return await this._takeScreenshot(() => this.screenshotCapturer.captureAction({
actionId: command.actionId,
customPath: command.path,
pageDimensions: driverMsg.pageDimensions,
cropDimensions: driverMsg.cropDimensions,
markSeed: command.markSeed,
fullPage: command.fullPage,
thumbnails: command.thumbnails,
actionId: command.actionId,
customPath: command.path,
customPathPattern: command.pathPattern,
pageDimensions: driverMsg.pageDimensions,
cropDimensions: driverMsg.cropDimensions,
markSeed: command.markSeed,
fullPage: command.fullPage,
thumbnails: command.thumbnails,
}));

case COMMAND_TYPE.takeScreenshotOnFail:
1 change: 1 addition & 0 deletions src/test-run/commands/browser-manipulation.js
Original file line number Diff line number Diff line change
@@ -47,6 +47,7 @@ export class TakeScreenshotCommand extends TakeScreenshotBaseCommand {
getAssignableProperties () {
return [
{ name: 'path', type: screenshotPathArgument, defaultValue: '' },
{ name: 'pathPattern', type: stringArgument, defaultValue: '' },
{ name: 'fullPage', type: booleanArgument, defaultValue: void 0 },
{ name: 'thumbnails', type: booleanArgument, defaultValue: void 0 },
];
5 changes: 3 additions & 2 deletions src/utils/path-pattern.js
Original file line number Diff line number Diff line change
@@ -124,8 +124,9 @@ export default class PathPattern extends EventEmitter {
return resultFilePath;
}

getPath (forError) {
const path = this._buildPath(this.pattern, this.placeholderToDataMap, forError);
getPath (forError, customPathPattern) {
const pathPattern = customPathPattern || this.pattern;
const path = this._buildPath(pathPattern, this.placeholderToDataMap, forError);

return correctFilePath(path, this.fileExtension);
}
26 changes: 26 additions & 0 deletions test/functional/fixtures/api/es-next/take-screenshot/test.js
Original file line number Diff line number Diff line change
@@ -114,6 +114,32 @@ describe('[API] t.takeScreenshot()', function () {
});
});

it('Should take a screenshot with a custom pathPattern', function () {
return runTests('./testcafe-fixtures/take-screenshot.js', 'Take a screenshot with a pathPattern')
.then(function () {
const screenshotPath = path.join('screenshots', 'Take a screenshot with a pathPattern');
const screenshotsCheckingOptions = { baseDir: 'screenshots', forError: false, screenshotsCount: 2, customPath: screenshotPath };

expect(assertionHelper.checkScreenshotsCreated(screenshotsCheckingOptions)).eql(true);
return assertionHelper.removeScreenshotDir('screenshots');
});
});

it('Should create a warning if pathPattern is used with path parameter', function () {
const { reporter, assertReporterWarnings, warningResult } = createWarningReporter();

return runTests('./testcafe-fixtures/take-screenshot.js', 'Should create a warning and use path parameter', { reporter })
.then(function () {
const screenshotPath = path.join('screenshots', 'screenshot-path');
const screenshotsCheckingOptions = { baseDir: 'screenshots', forError: false, screenshotsCount: 2, customPath: screenshotPath };

expect(assertionHelper.checkScreenshotsCreated(screenshotsCheckingOptions)).eql(true);
expect(warningResult.warnings[0].message).eql('The screenshot path "screenshot-path/custom" overrides the "${TEST}/custom" pathPattern parameter. Choose only one of the parameters to specify the screenshot path.');
assertReporterWarnings('takeScreenshot');
return assertionHelper.removeScreenshotDir('screenshots');
});
});

it('Should save screenshots to default dir if screenshotPath is not specified', function () {
return runTests('./testcafe-fixtures/take-screenshot.js', 'Take a screenshot')
.then(function () {
Original file line number Diff line number Diff line change
@@ -137,3 +137,11 @@ test('Rewrite a screenshot with warning', async t => {
await t.takeScreenshot('custom/duplicate.png');
await t.takeScreenshot('custom/duplicate.png');
});

test('Take a screenshot with a pathPattern', async t => {
await t.takeScreenshot({ pathPattern: '${TEST}/custom' });
});

test('Should create a warning and use path parameter', async t => {
await t.takeScreenshot({ path: 'screenshot-path/custom', pathPattern: '${TEST}/custom' });
});
11 changes: 6 additions & 5 deletions test/server/data/test-controller-reporter-expected/index.js
Original file line number Diff line number Diff line change
@@ -433,11 +433,12 @@ module.exports = {
testRunId: 'test-run-id',
name: 'takeScreenshot',
command: {
path: 'screenshotPath',
fullPage: true,
thumbnails: undefined,
type: 'take-screenshot',
actionId: 'TakeScreenshotCommand',
path: 'screenshotPath',
pathPattern: '',
fullPage: true,
thumbnails: undefined,
type: 'take-screenshot',
actionId: 'TakeScreenshotCommand',
},
test: {
id: 'test-id',
42 changes: 31 additions & 11 deletions test/server/test-run-commands-test.js
Original file line number Diff line number Diff line change
@@ -853,12 +853,13 @@ describe('Test run commands', () => {
let command = createCommand(commandObj);

expect(JSON.parse(JSON.stringify(command))).eql({
type: TYPE.takeScreenshot,
actionId: TYPE.takeScreenshot,
markData: '',
markSeed: null,
path: 'custom',
fullPage: true,
type: TYPE.takeScreenshot,
actionId: TYPE.takeScreenshot,
markData: '',
markSeed: null,
path: 'custom',
fullPage: true,
pathPattern: '',
});

commandObj = {
@@ -869,11 +870,30 @@ describe('Test run commands', () => {
command = createCommand(commandObj);

expect(JSON.parse(JSON.stringify(command))).eql({
type: TYPE.takeScreenshot,
actionId: TYPE.takeScreenshot,
markData: '',
markSeed: null,
path: '',
type: TYPE.takeScreenshot,
actionId: TYPE.takeScreenshot,
markData: '',
markSeed: null,
path: '',
pathPattern: '',
});

commandObj = {
type: TYPE.takeScreenshot,
fullPage: true,
pathPattern: 'custom',
};

command = createCommand(commandObj);

expect(JSON.parse(JSON.stringify(command))).eql({
type: TYPE.takeScreenshot,
actionId: TYPE.takeScreenshot,
fullPage: true,
markData: '',
markSeed: null,
path: '',
pathPattern: 'custom',
});
});