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

Feature/reload page on error #1179

Open
wants to merge 32 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
e998459
Reload single URL if responded with invalid status
Apr 24, 2020
4bc7eb2
Update README.md
sapcik Apr 24, 2020
08a6440
- Reload page after error X times
Apr 28, 2020
0866918
Merge branch 'feature/reload-page-on-error' of github.com:sapcik/Back…
Apr 28, 2020
954fd8c
Added label for errors
Apr 28, 2020
ffc292b
Fixed problem with timeout
Apr 30, 2020
8a04bf1
Bypass cache by adding random param to the URL
May 21, 2020
26a44fa
Bypass cache by adding random param to the URL (for reference & test)
May 21, 2020
693ba11
Added additional delay
May 21, 2020
f89146b
Wait for networkidle2
May 21, 2020
4b71d92
Reload page
May 27, 2020
3af4c65
Added logs
May 27, 2020
37362b1
Added reload instead of goto
May 27, 2020
01fa0ea
Refresh page, hard reload from the JS
Jun 2, 2020
f3955d6
Updated puppeteer version
Jun 2, 2020
1acde5d
Do not reload
Jul 6, 2020
5ff769f
Reload single URL if responded with invalid status
Apr 24, 2020
20ddf6e
- Reload page after error X times
Apr 28, 2020
13b3e78
Update README.md
sapcik Apr 24, 2020
9dfb409
Added label for errors
Apr 28, 2020
54f6f23
Fixed problem with timeout
Apr 30, 2020
0bba28a
Bypass cache by adding random param to the URL
May 21, 2020
d59272a
Bypass cache by adding random param to the URL (for reference & test)
May 21, 2020
4df09f0
Added additional delay
May 21, 2020
4a974c1
Wait for networkidle2
May 21, 2020
cdf9f56
Reload page
May 27, 2020
fadc13d
Added logs
May 27, 2020
c1bd09f
Added reload instead of goto
May 27, 2020
5b53953
Refresh page, hard reload from the JS
Jun 2, 2020
f99b47b
Updated puppeteer version
Jun 2, 2020
1cd3dcc
Do not reload
Jul 6, 2020
81426a2
Merge branch 'feature/reload-page-on-error' of github.com:sapcik/Back…
Apr 22, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,19 @@ module.exports = async (page, scenario, vp) => {
};
```

### Reload scenario on specific error (puppeteer)

By default puppeteer will take a screenshot even if the URL returned http status different than 200. If you want to reload website on failure (only once), add the following code to `backstop.json`.

```json
"reloadOnError": {
"enable": true, // Whether website should be reloaded on error
"waitBeforeReload": 1500, // Wait 1500ms before reload
"onStatus": [504, 503, 500] // Reload website if responded with one of the following statuses
},
```
Keep in mind that it works fine only with puppeteer `"engine": "puppeteer"`.

#### Setting the base path for custom onBefore and onReady scripts

By default the base path is a folder called `engine_scripts` inside your BackstopJS installation directory. You can override this by setting the `paths.scripts` property in your `backstop.json` file to point to somewhere in your project directory (recommended).
Expand Down
20 changes: 19 additions & 1 deletion core/util/createBitmaps.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,18 @@ function delegateScenarios (config) {
function writeCompareConfigFile (comparePairsFileName, compareConfig) {
var compareConfigJSON = JSON.stringify(compareConfig, null, 2);
ensureDirectoryPath(comparePairsFileName);

return fs.writeFile(comparePairsFileName, compareConfigJSON);
}

function flatMapFailuresUrls (rawTestPairs) {
return rawTestPairs.reduce((acc, result) => {
var failureUrls = result.failureUrls;

return acc.concat(failureUrls);
}, []);
}

function flatMapTestPairs (rawTestPairs) {
return rawTestPairs.reduce((acc, result) => {
var testPairs = result.testPairs;
Expand Down Expand Up @@ -176,8 +185,17 @@ module.exports = function (config, isReference) {
const result = {
compareConfig: {
testPairs: flatMapTestPairs(rawTestPairs)
}
},
};

const failuresUrls = flatMapFailuresUrls(rawTestPairs);

if (failuresUrls.length > 0) {
var failedUrlsPath = config.bitmaps_reference + '/' + (isReference ? 'reference-' : 'test-') + config.reloadOnError.outputFile;
ensureDirectoryPath(failedUrlsPath);
fs.writeFile(failedUrlsPath, JSON.stringify(failuresUrls, null, '\t'))
}

return writeCompareConfigFile(config.tempCompareConfigFileName, result);
});

Expand Down
7 changes: 7 additions & 0 deletions core/util/extendConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ function extendConfig (config, userConfig) {
config.asyncCompareLimit = userConfig.asyncCompareLimit;
config.backstopVersion = version;
config.dockerCommandTemplate = userConfig.dockerCommandTemplate;
config.reloadOnError = userConfig.reloadOnError || {
"enabled": false,
"retryCount": 3,
"waitBeforeReload": 1500,
"onStatus": [504, 503, 500],
"outputFile": "retry_urls.json"
}
return config;
}

Expand Down
64 changes: 61 additions & 3 deletions core/util/runPuppet.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const injectBackstopTools = require('../../capture/backstopTools.js');
const engineTools = require('./engineTools');

const MIN_CHROME_VERSION = 62;
const TEST_TIMEOUT = 60000;
const TEST_TIMEOUT = 120000;
const DEFAULT_FILENAME_TEMPLATE = '{configId}_{scenarioLabel}_{selectorIndex}_{selectorLabel}_{viewportIndex}_{viewportLabel}';
const DEFAULT_BITMAPS_TEST_DIR = 'bitmaps_test';
const DEFAULT_BITMAPS_REFERENCE_DIR = 'bitmaps_reference';
Expand Down Expand Up @@ -40,7 +40,6 @@ async function processScenarioView (scenario, variantOrScenarioLabelSafe, scenar
if (!config.paths) {
config.paths = {};
}

if (typeof viewport.label !== 'string') {
viewport.label = viewport.name || '';
}
Expand All @@ -63,7 +62,10 @@ async function processScenarioView (scenario, variantOrScenarioLabelSafe, scenar
const browser = await puppeteer.launch(puppeteerArgs);
const page = await browser.newPage();

let urlWrongStatus = [];

await page.setViewport({ width: VP_W, height: VP_H });

page.setDefaultNavigationTimeout(engineTools.getEngineOption(config, 'waitTimeout', TEST_TIMEOUT));

if (isReference) {
Expand Down Expand Up @@ -116,7 +118,58 @@ async function processScenarioView (scenario, variantOrScenarioLabelSafe, scenar
if (isReference && scenario.referenceUrl) {
url = scenario.referenceUrl;
}
await page.goto(translateUrl(url));

// Open the URL for a first time
await page.goto(translateUrl(url), {waitUntil: 'networkidle0'});

// Add random string to the URL
// It will allow to bypass cache
var bypass = "";

if (url.indexOf('?') !== -1) {
bypass = '&bypassCache=' + Date.now()
} else {
bypass = '?bypassCache=' + Date.now()
}

// Open the URL for a first time
await page.evaluate(`location.reload(true);`);

console.log(chalk.green('Opening URL:', translateUrl(url) + bypass));

var request = await page.reload(translateUrl(url) + bypass, {waitUntil: 'networkidle0'});

if (config.reloadOnError.enabled) {
// Check the status of the request
if (config.reloadOnError.onStatus.indexOf(request.status()) !== -1) {
let reloadArray = Array.from(Array(config.reloadOnError.retryCount).keys());

for(const iteration of reloadArray) {
const reloadRequest = await page.goto(translateUrl(url) + bypass, {waitUntil: 'networkidle0'});

if (config.reloadOnError.onStatus.indexOf(reloadRequest.status()) === -1) {
break;
}

await ((milis) => {
return new Promise(function (resolve, reject) {
setTimeout(function () { resolve(); }, milis);
});
})(config.reloadOnError.waitBeforeReload);
urlWrongStatus.push({
iteration: iteration+1,
url: translateUrl(url),
status: reloadRequest.status(),
date: new Date().toISOString(),
timestamp: Date.now(),
viewportLabel: viewport.label,
reloadStatus: (iteration === reloadArray.length - 1) ? 'failed' : 'reload'
});
}
}
}

// await page.waitFor(2000);

await injectBackstopTools(page);

Expand Down Expand Up @@ -259,6 +312,11 @@ async function processScenarioView (scenario, variantOrScenarioLabelSafe, scenar
fs.copy(config.env.backstop + ERROR_SELECTOR_PATH, filePath);
}

compareConfig = { failureUrls: urlWrongStatus, ...compareConfig }

// console.log(compareConfig);
// console.log(urlWrongStatus);

return Promise.resolve(compareConfig);
}

Expand Down
Loading