Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ static/
scripts/template/
.cache/
patternfly-docs/generated/
backstop_data/
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,6 @@ package-lock.json
/scripts/sizeReport/package-lock.json
/scripts/sizeReport/report.html
patternfly-docs/generated/**/*.js
backstop_data/bitmaps_test
backstop_data/html_report
backstop_data/reports
4 changes: 3 additions & 1 deletion .stylelintrc
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
],
"plugins": [
"stylelint-order",
"stylelint-scss"
"stylelint-scss",
"stylelint-use-logical-spec"
],
"ignoreFiles": [
"./src/patternfly/assets/fontawesome/*.scss",
Expand Down Expand Up @@ -45,6 +46,7 @@
"font-weight-notation": "numeric",
"import-notation": "string",
"keyframes-name-pattern": null,
"liberty/use-logical-spec": ["always", { "except": ["width", "max-width", "min-width", "height", "max-height", "min-height"] }],
"max-nesting-depth": 3,
"media-query-no-invalid": null,
"no-descending-specificity": null,
Expand Down
1,119 changes: 1,119 additions & 0 deletions backstop.config.js

Large diffs are not rendered by default.

52 changes: 52 additions & 0 deletions backstop.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
const config = require('./backstop.config');
const scenarios = [];
const viewports = [];

config.relativeUrls.map(relativeUrl => {
const url = (relativeUrl.url || relativeUrl);
const fullUrl = `${config.baseUrl}${url}`;
return scenarios.push({
label: url,
url: fullUrl,
delay: (relativeUrl.delay || 100), // a small timeout allows wiggle room for the page to fully render. increase as needed if you're getting rendering related false positives.
readySelector: '.ws-theme-switch-full-page',
removeSelectors: ['.ws-theme-switch-full-page'],
misMatchThreshold: 0.1
})
});

Object.keys(config.viewports).map(viewport => (
viewports.push({
name: viewport,
width: config.viewports[viewport].width,
height: config.viewports[viewport].height
})
));

module.exports = {
id: 'pf-core',
viewports,
scenarios,
onReadyScript: 'onReady.js',
report: ['browser'],
engine: 'puppeteer',
engineOptions: {
args: [
'--no-sandbox',
'--disable-setuid-sandbox'
]
},
paths: {
bitmaps_reference: 'backstop_data/bitmaps_reference',
bitmaps_test: 'backstop_data/bitmaps_test',
engine_scripts: 'backstop_data/engine_scripts',
html_report: 'backstop_data/html_report',
ci_report: 'backstop_data/ci_report'
},
asyncCaptureLimit: 5,
asyncCompareLimit: 50,
debug: false,
debugWindow: false,
archiveReport: false,
scenarioLogsInReports: false
};
14 changes: 14 additions & 0 deletions backstop_data/engine_scripts/cookies.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[
{
"domain": ".www.yourdomain.com",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this file supposed to be customized for PatternFly?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not this file, they provide a lot of example/templates for different configs/scripts you might want to use when testing. This would set a cookie with some value you might need for chromium to access a test URL

"path": "/",
"name": "yourCookieName",
"value": "yourCookieValue",
"expirationDate": 1798790400,
"hostOnly": false,
"httpOnly": false,
"secure": false,
"session": false,
"sameSite": "Lax"
}
]
Binary file added backstop_data/engine_scripts/imageStub.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions backstop_data/engine_scripts/onBefore.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
module.exports = async () => {
};
4 changes: 4 additions & 0 deletions backstop_data/engine_scripts/onReady.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = async (page) => {
// disable animations/transitions so they don't interfere with screenshot tool
await page.addStyleTag({content: "*, *::before, *::after {animation-delay:-1ms !important;animation-duration:1ms !important;animation-iteration-count:1 !important;transition-duration:0s !important;transition-delay:0s !important;}"});
};
43 changes: 43 additions & 0 deletions backstop_data/engine_scripts/playwright/clickAndHoverHelper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
module.exports = async (page, scenario) => {
const hoverSelector = scenario.hoverSelectors || scenario.hoverSelector;
const clickSelector = scenario.clickSelectors || scenario.clickSelector;
const keyPressSelector = scenario.keyPressSelectors || scenario.keyPressSelector;
const scrollToSelector = scenario.scrollToSelector;
const postInteractionWait = scenario.postInteractionWait; // selector [str] | ms [int]

if (keyPressSelector) {
for (const keyPressSelectorItem of [].concat(keyPressSelector)) {
await page.waitForSelector(keyPressSelectorItem.selector);
await page.type(keyPressSelectorItem.selector, keyPressSelectorItem.keyPress);
}
}

if (hoverSelector) {
for (const hoverSelectorIndex of [].concat(hoverSelector)) {
await page.waitForSelector(hoverSelectorIndex);
await page.hover(hoverSelectorIndex);
}
}

if (clickSelector) {
for (const clickSelectorIndex of [].concat(clickSelector)) {
await page.waitForSelector(clickSelectorIndex);
await page.click(clickSelectorIndex);
}
}

if (postInteractionWait) {
if (parseInt(postInteractionWait) > 0) {
await page.waitForTimeout(postInteractionWait);
} else {
await page.waitForSelector(postInteractionWait);
}
}

if (scrollToSelector) {
await page.waitForSelector(scrollToSelector);
await page.evaluate(scrollToSelector => {
document.querySelector(scrollToSelector).scrollIntoView();
}, scrollToSelector);
}
};
31 changes: 31 additions & 0 deletions backstop_data/engine_scripts/playwright/interceptImages.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* INTERCEPT IMAGES
* Listen to all requests. If a request matches IMAGE_URL_RE
* then stub the image with data from IMAGE_STUB_URL
*
* Use this in an onBefore script E.G.
```
module.exports = async function(page, scenario) {
require('./interceptImages')(page, scenario);
}
```
*
*/

const fs = require('fs');
const path = require('path');

const IMAGE_URL_RE = /\.gif|\.jpg|\.png/i;
const IMAGE_STUB_URL = path.resolve(__dirname, '../../imageStub.jpg');
const IMAGE_DATA_BUFFER = fs.readFileSync(IMAGE_STUB_URL);
const HEADERS_STUB = {};

module.exports = async function (page, scenario) {
page.route(IMAGE_URL_RE, route => {
route.fulfill({
body: IMAGE_DATA_BUFFER,
headers: HEADERS_STUB,
status: 200
});
});
};
16 changes: 16 additions & 0 deletions backstop_data/engine_scripts/playwright/loadCookies.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const fs = require('fs');

module.exports = async (browserContext, scenario) => {
let cookies = [];
const cookiePath = scenario.cookiePath;

// Read Cookies from File, if exists
if (fs.existsSync(cookiePath)) {
cookies = JSON.parse(fs.readFileSync(cookiePath));
}

// Add cookies to browser
browserContext.addCookies(cookies);

console.log('Cookie state restored with:', JSON.stringify(cookies, null, 2));
};
3 changes: 3 additions & 0 deletions backstop_data/engine_scripts/playwright/onBefore.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = async (page, scenario, viewport, isReference, browserContext) => {
await require('./loadCookies')(browserContext, scenario);
};
6 changes: 6 additions & 0 deletions backstop_data/engine_scripts/playwright/onReady.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = async (page, scenario, viewport, isReference, browserContext) => {
console.log('SCENARIO > ' + scenario.label);
await require('./clickAndHoverHelper')(page, scenario);

// add more ready handlers here...
};
27 changes: 27 additions & 0 deletions backstop_data/engine_scripts/playwright/overrideCSS.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* OVERRIDE CSS
* Apply this CSS to the loaded page, as a way to override styles.
*
* Use this in an onReady script E.G.
```
module.exports = async function(page, scenario) {
await require('./overrideCSS')(page, scenario);
}
```
*
*/

const BACKSTOP_TEST_CSS_OVERRIDE = `
html {
background-image: none;
}
`;

module.exports = async (page, scenario) => {
// inject arbitrary css to override styles
await page.addStyleTag({
content: BACKSTOP_TEST_CSS_OVERRIDE
});

console.log('BACKSTOP_TEST_CSS_OVERRIDE injected for: ' + scenario.label);
};
39 changes: 39 additions & 0 deletions backstop_data/engine_scripts/puppet/clickAndHoverHelper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
module.exports = async (page, scenario) => {
const hoverSelector = scenario.hoverSelectors || scenario.hoverSelector;
const clickSelector = scenario.clickSelectors || scenario.clickSelector;
const keyPressSelector = scenario.keyPressSelectors || scenario.keyPressSelector;
const scrollToSelector = scenario.scrollToSelector;
const postInteractionWait = scenario.postInteractionWait; // selector [str] | ms [int]

if (keyPressSelector) {
for (const keyPressSelectorItem of [].concat(keyPressSelector)) {
await page.waitForSelector(keyPressSelectorItem.selector);
await page.type(keyPressSelectorItem.selector, keyPressSelectorItem.keyPress);
}
}

if (hoverSelector) {
for (const hoverSelectorIndex of [].concat(hoverSelector)) {
await page.waitForSelector(hoverSelectorIndex);
await page.hover(hoverSelectorIndex);
}
}

if (clickSelector) {
for (const clickSelectorIndex of [].concat(clickSelector)) {
await page.waitForSelector(clickSelectorIndex);
await page.click(clickSelectorIndex);
}
}

if (postInteractionWait) {
await page.waitForTimeout(postInteractionWait);
}

if (scrollToSelector) {
await page.waitForSelector(scrollToSelector);
await page.evaluate(scrollToSelector => {
document.querySelector(scrollToSelector).scrollIntoView();
}, scrollToSelector);
}
};
65 changes: 65 additions & 0 deletions backstop_data/engine_scripts/puppet/ignoreCSP.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* IGNORE CSP HEADERS
* Listen to all requests. If a request matches scenario.url
* then fetch the request again manually, strip out CSP headers
* and respond to the original request without CSP headers.
* Allows `ignoreHTTPSErrors: true` BUT... requires `debugWindow: true`
*
* see https://github.com/GoogleChrome/puppeteer/issues/1229#issuecomment-380133332
* this is the workaround until Page.setBypassCSP lands... https://github.com/GoogleChrome/puppeteer/pull/2324
*
* @param {REQUEST} request
* @return {VOID}
*
* Use this in an onBefore script E.G.
```
module.exports = async function(page, scenario) {
require('./removeCSP')(page, scenario);
}
```
*
*/

const fetch = require('node-fetch');
const https = require('https');
const agent = new https.Agent({
rejectUnauthorized: false
});

module.exports = async function (page, scenario) {
const intercept = async (request, targetUrl) => {
const requestUrl = request.url();

// FIND TARGET URL REQUEST
if (requestUrl === targetUrl) {
const cookiesList = await page.cookies(requestUrl);
const cookies = cookiesList.map(cookie => `${cookie.name}=${cookie.value}`).join('; ');
const headers = Object.assign(request.headers(), { cookie: cookies });
const options = {
headers,
body: request.postData(),
method: request.method(),
follow: 20,
agent
};

const result = await fetch(requestUrl, options);

const buffer = await result.buffer();
const cleanedHeaders = result.headers._headers || {};
cleanedHeaders['content-security-policy'] = '';
await request.respond({
body: buffer,
headers: cleanedHeaders,
status: result.status
});
} else {
request.continue();
}
};

await page.setRequestInterception(true);
page.on('request', req => {
intercept(req, scenario.url);
});
};
37 changes: 37 additions & 0 deletions backstop_data/engine_scripts/puppet/interceptImages.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* INTERCEPT IMAGES
* Listen to all requests. If a request matches IMAGE_URL_RE
* then stub the image with data from IMAGE_STUB_URL
*
* Use this in an onBefore script E.G.
```
module.exports = async function(page, scenario) {
require('./interceptImages')(page, scenario);
}
```
*
*/

const fs = require('fs');
const path = require('path');

const IMAGE_URL_RE = /\.gif|\.jpg|\.png/i;
const IMAGE_STUB_URL = path.resolve(__dirname, '../imageStub.jpg');
const IMAGE_DATA_BUFFER = fs.readFileSync(IMAGE_STUB_URL);
const HEADERS_STUB = {};

module.exports = async function (page, scenario) {
const intercept = async (request, targetUrl) => {
if (IMAGE_URL_RE.test(request.url())) {
await request.respond({
body: IMAGE_DATA_BUFFER,
headers: HEADERS_STUB,
status: 200
});
} else {
request.continue();
}
};
await page.setRequestInterception(true);
page.on('request', intercept);
};
Loading