UNPKG

regressify

Version:
182 lines 7.66 kB
import fs from 'fs'; import { createScenario } from './scenarios.js'; import path from 'path'; import { getFlagArg, getStringArg, parseDataFromFile, getLibraryPath } from './helpers.js'; import chalk from 'chalk'; import { exit } from 'process'; import YAML from 'js-yaml'; import { getTestUrl } from './replacements.js'; import { getStatePath } from './state.js'; const libraryPath = getLibraryPath(); const engine = 'playwright'; function getArgConfig(args) { const testSuite = getStringArg(args, '--test-suite'); const isRef = getFlagArg(args, '--ref'); const globalRequiredLogin = getFlagArg(args, '--requiredLogin'); if (globalRequiredLogin) { console.log('force run all scenarios in login mode'); } if (!testSuite) { console.log(chalk.red('Argument `--test-suite` must be set.')); console.log(chalk.red('Sample command: regressify <command> --test-suite <test-suite>')); console.log(chalk.red('Command is either `ref`, `approve` or `test`.')); exit(1); } return { testSuite, isRef, globalRequiredLogin, }; } function getScriptPath(scriptPath, engine) { return path.join(libraryPath, '.engine_scripts', (engine == 'puppeteer' ? 'puppet' : 'playwright') + scriptPath); } function getData(testSuite) { let extensions = [ { ext: 'yaml', parse: YAML.load, }, { ext: 'yml', parse: YAML.load, }, { ext: 'json', parse: JSON.parse, }, ]; for (let i = 0; i < extensions.length; i++) { const dataPath = path.join(process.cwd(), 'visual_tests', `${testSuite}.tests.${extensions[i].ext}`); if (fs.existsSync(dataPath)) { console.log('Data path: ', dataPath); const content = fs.readFileSync(dataPath, 'utf-8'); return extensions[i].parse(content); } } throw `Data file not found for test suite: ${testSuite}`; } function expandScenarios(model, scenarios, level) { if (level > 100) { throw 'Level is too large'; } if (!model.needs) { return; } const neededActions = []; if (typeof model.needs === 'string') { neededActions.push(model.needs); } else { model.needs.forEach((n) => neededActions.push(n)); } neededActions.reverse().forEach((n) => { const targetScenarios = scenarios.filter((s) => !!s.id && s.id.toLowerCase() == n.toLowerCase()); if (targetScenarios.length !== 1) { throw `The test suite must contains exactly ONE scenario with id: ${n}`; } var targetScenario = targetScenarios[0]; expandScenarios(targetScenario, scenarios, level + 1); if (!!targetScenario.actions) { if (!model.actions) { model.actions = []; } model.actions = [...targetScenario.actions, ...model.actions]; } }); model.needs = undefined; } function getScenarios(args, testSuite, isRef, globalRequiredLogin) { const scenarios = []; const data = getData(testSuite); const viewports = parseDataFromFile(data?.viewportsPath ?? 'common/_viewports.yaml'); if (data) { [].forEach.call(data.scenarios, (s) => { expandScenarios(s, data.scenarios, 0); }); const getTestUrlLocal = (url) => getTestUrl(args, url, isRef); const pad = String(data?.scenarios.length).length; data.scenarios.forEach((s, index) => { const opts = { ...s, requiredLogin: globalRequiredLogin || s.requiredLogin, getTestUrl: getTestUrlLocal, url: isRef ? s.url : getTestUrl(args, s.url, isRef), index: String(index + 1).padStart(pad, ' '), total: data.scenarios.length, delay: s.delay ?? 1000, state: data.state, hideSelectors: s.hideSelectors ?? data.hideSelectors, removeSelectors: s.removeSelectors ?? data.removeSelectors, useCssOverride: s.useCssOverride ?? data.useCssOverride, jsOnReadyPath: s.jsOnReadyPath, viewports: !!s.viewportNames ? typeof s.viewportNames === 'string' ? viewports.filter((v) => v.label.toLowerCase() == s.viewportNames.trim().toLowerCase()) : viewports.filter((v) => s.viewportNames?.includes(v.label)) : !!data.viewportNames ? typeof data.viewportNames === 'string' ? viewports.filter((v) => v.label.toLowerCase() == data.viewportNames.trim().toLowerCase()) : viewports.filter((v) => data.viewportNames?.includes(v.label)) : undefined, referenceUrl: !isRef ? s.url : undefined, misMatchThreshold: s.misMatchThreshold ?? data.misMatchThreshold ?? 0.1, postInteractionWait: s.postInteractionWait ?? data.postInteractionWait ?? 1, }; if (opts.restore && Array.isArray(opts.restore)) { // Deduplicate restore array opts.restore = opts.restore.filter((value, index, self) => self.indexOf(value) === index); } if (opts.actions && Array.isArray(opts.actions)) { let persistActions = opts.actions.filter((a) => a.persist); for (const persistAction of persistActions) { persistAction.path = getStatePath(persistAction.persist); // console.log('Persist action: ', persistAction); } } const scenario = createScenario(opts); scenarios.push(scenario); }); } return { scenarios, data, viewports }; } export function getConfig(args) { const { testSuite, isRef, globalRequiredLogin } = getArgConfig(args); const { scenarios, data, viewports } = getScenarios(args, testSuite, isRef, globalRequiredLogin); const config = { id: testSuite, viewports, onBeforeScript: getScriptPath('/onBefore.js', engine), onReadyScript: getScriptPath('/onReady.js', engine), scenarios, paths: { bitmaps_reference: '.backstop/' + testSuite + '/bitmaps_reference', bitmaps_test: '.backstop/' + testSuite + '/bitmaps_test', engine_scripts: `${getLibraryPath()}/.engine_scripts`, html_report: '.backstop/' + testSuite + '/html_report', ci_report: '.backstop/' + testSuite + '/ci_report', }, report: [isRef ? 'CI' : 'browser'], engine, engineOptions: { args: [ '--disable-infobars', '--disable-setuid-sandbox', '--ignore-certifcate-errors', '--ignore-certifcate-errors-spki-list', '--no-sandbox', '--window-position=0,0', ], browser: data?.browser ?? 'chromium', ignoreHTTPSErrors: data && typeof data?.ignoreSslErrors === 'boolean' ? data.ignoreSslErrors : true, headless: data?.debug ? undefined : 'new', storageState: data?.state && fs.existsSync(getStatePath(data.state)) ? getStatePath(data.state) : undefined, }, asyncCaptureLimit: data?.asyncCaptureLimit ?? 5, asyncCompareLimit: data?.asyncCompareLimit ?? 50, debug: false, debugWindow: data?.debug, }; return config; } //# sourceMappingURL=config.js.map