diff --git a/README.md b/README.md index 53b51cd6..819c54f3 100644 --- a/README.md +++ b/README.md @@ -158,6 +158,8 @@ Add the configuration below to your `cypress.json` file to make changes to the d "serverPort": 2121, // Port number for "update snapshot server" "updateSnapshots": false, // Automatically update snapshots, useful if you have lots of changes "backgroundBlend": "difference" // background-blend-mode for diff image, useful to switch to "overlay" + "retryCount": 0 // Amount of retries if snapshot comparison fails + "retryDelay": 200 // Delay time between snapshot retries } } ``` diff --git a/src/commands/toMatchImageSnapshot.js b/src/commands/toMatchImageSnapshot.js index d053632d..6a95ae04 100644 --- a/src/commands/toMatchImageSnapshot.js +++ b/src/commands/toMatchImageSnapshot.js @@ -19,7 +19,7 @@ function afterScreenshot(taskData) { }; } -async function toMatchImageSnapshot(subject, commandOptions) { +async function toMatchImageSnapshot(subject, commandOptions, isRetry = false) { const options = getImageConfig(commandOptions); const customName = getCustomName(commandOptions); const customSeparator = getCustomSeparator(commandOptions); @@ -30,6 +30,7 @@ async function toMatchImageSnapshot(subject, commandOptions) { customName, customSeparator, subject, + isRetry, }); const screenShotConfig = getScreenshotConfig(commandOptions); @@ -50,7 +51,18 @@ async function toMatchImageSnapshot(subject, commandOptions) { MATCH_IMAGE, taskData, NO_LOG - ).then(logMessage) + ).then((result) => { + if (!result.passed && commandOptions.retryCount > 0) { + return cy.wait(commandOptions.retryDelay).then(() => { + const newCommandOptions = { + ...commandOptions, + retryCount: commandOptions.retryCount - 1, + }; + return toMatchImageSnapshot(subject, newCommandOptions, true); + }); + } + return logMessage(result); + }) ); } diff --git a/src/commands/toMatchSnapshot.js b/src/commands/toMatchSnapshot.js index 9c2b82ea..cf0429f6 100644 --- a/src/commands/toMatchSnapshot.js +++ b/src/commands/toMatchSnapshot.js @@ -6,16 +6,28 @@ const logMessage = require('../utils/commands/logMessage'); const { NO_LOG } = require('../constants'); const { COMMAND_MATCH_SNAPSHOT: commandName } = require('./commandNames'); -function toMatchSnapshot(subject, options) { +function toMatchSnapshot(subject, options, isRetry = false) { return getTaskData({ commandName, options, subject, + isRetry, }).then(taskData => cy.task( MATCH_TEXT, taskData, NO_LOG - ).then(logMessage) + ).then((result) => { + if (!result.passed && options.retryCount > 0) { + return cy.wait(options.retryDelay).then(() => { + const newOptions = { + ...options, + retryCount: options.retryCount - 1, + }; + return toMatchSnapshot(subject, newOptions, true); + }); + } + return logMessage(result); + }) ); } diff --git a/src/config.js b/src/config.js index 65f6a1e3..d54ba5a5 100644 --- a/src/config.js +++ b/src/config.js @@ -50,6 +50,8 @@ const DEFAULT_CONFIG = Object.freeze({ updateSnapshots: false, backgroundBlend: 'difference', name: '', + retryCount: 0, + retryDelay: 200, }); const CONFIG_KEY = 'cypress-plugin-snapshots'; diff --git a/src/utils/commands/getTaskData.js b/src/utils/commands/getTaskData.js index 87f841fe..0cdf7e8d 100644 --- a/src/utils/commands/getTaskData.js +++ b/src/utils/commands/getTaskData.js @@ -26,14 +26,15 @@ async function getTaskData({ options, customName, customSeparator, - subject: testSubject + subject: testSubject, + isRetry, } = {}) { const subjectIsImage = isImage(commandName); const test = getTestForTask(); const testTitle = getTestTitle(test); const spec = await getSpec(); const testFile = spec.absolute; - const snapshotTitle = getSnapshotTitle(test, customName, customSeparator, subjectIsImage); + const snapshotTitle = getSnapshotTitle(test, customName, customSeparator, subjectIsImage, isRetry); const subject = subjectIsImage ? testSubject : getSubject(testSubject); const dataType = getDataType({commandName, subject: testSubject}); diff --git a/src/utils/snapshotTitles.js b/src/utils/snapshotTitles.js index c0995f8a..fa9526e8 100644 --- a/src/utils/snapshotTitles.js +++ b/src/utils/snapshotTitles.js @@ -10,15 +10,17 @@ function snapshotTitleIsUsed(snapshotTitle, isImage = false) { return (isImage ? SNAPSHOT_TITLES_IMAGE : SNAPSHOT_TITLES_TEXT).indexOf(snapshotTitle) !== -1; } -function getSnapshotTitle(test, customName, customSeparator, isImage = false) { +function getSnapshotTitle(test, customName, customSeparator, isImage = false, isRetry = false) { const name = customName || getTestTitle(test); const separator = customSeparator || ' #'; const snapshots = isImage ? SNAPSHOTS_IMAGE : SNAPSHOTS_TEXT; - if (snapshots[name] !== undefined) { - snapshots[name] += 1; - } else { - snapshots[name] = 0; + if (!isRetry) { + if (snapshots[name] !== undefined) { + snapshots[name] += 1; + } else { + snapshots[name] = 0; + } } const snapshotTitle = `${name}${separator}${snapshots[name]}`;