add dev mode to playwright tests

This commit is contained in:
Rene Haas
2022-08-12 12:54:41 +02:00
parent 6f40de9291
commit 6e65ff9a90
15 changed files with 143 additions and 134 deletions
-1
View File
@@ -3,7 +3,6 @@ const { devices } = require('@playwright/test');
module.exports = { module.exports = {
testMatch: /.*\/tests\/playwright\/.*\.test\.[jt]sx?/, testMatch: /.*\/tests\/playwright\/.*\.test\.[jt]sx?/,
timeout: 10 * 60 * 1000, timeout: 10 * 60 * 1000,
actionTimeout: 300,
navigationTimeout: 1000, navigationTimeout: 1000,
retries: 0, retries: 0,
workers: 4, workers: 4,
@@ -2,7 +2,8 @@ const { expect } = require('@playwright/test');
const resultSelector = '#testResult'; const resultSelector = '#testResult';
module.exports = async (page) => { // default timeout = // 10mins
await page.locator(resultSelector).waitFor({ state: 'visible', timeout: 10 * 60 * 1000 }); // 10mins module.exports = async (page, timeout = 10 * 60 * 1000) => {
await expect(page.locator(resultSelector)).toHaveClass('passed', { timeout: 500 }); await page.locator(resultSelector).waitFor({ state: 'visible', timeout });
} await expect(page.locator(resultSelector)).toHaveClass('passed', { timeout: 1000 });
};
@@ -1,65 +1,73 @@
const { dirname } = require('path'); const { dirname } = require('path');
const { rollup, watch: rollupWatch } = require('rollup'); const { watch: rollupWatch } = require('rollup');
const { test } = require('@playwright/test'); const { test } = require('@playwright/test');
const createPlaywrightRollupConfig = require('@~local/rollup/playwright'); const createPlaywrightRollupConfig = require('@~local/rollup/playwright');
const collectCoverage = require('./collectCoverage'); const collectCoverage = require('./collectCoverage');
const createRollupBundle = async (testDir, watch = false) => { const createRollupBundle = async (testDir, useEsbuild, dev) => {
let server; const [config, getServer] = await createPlaywrightRollupConfig(testDir, useEsbuild, dev);
const onListening = (srv) => { const watcher = rollupWatch(config);
server = srv;
};
const config = await createPlaywrightRollupConfig(testDir, 'dev', onListening);
if (watch) { const outputPath = await new Promise((resolve) => {
const watcher = rollupWatch(config); let bundleOutput;
let outputPath = ''; if (dev) {
// eslint-disable-next-line no-await-in-loop console.log(`Using: ${useEsbuild ? 'esbuild' : 'rollup'}`); // eslint-disable-line
await new Promise((resolve) => { }
watcher.on('event', ({ code, error, result, output }) => { watcher.on('event', (event) => {
if (code === 'ERROR') { const { code, error, result, output } = event;
console.log('Error:', error); // eslint-disable-line if (code === 'ERROR') {
console.log('Error:', error); // eslint-disable-line
}
if (code === 'START') {
if (dev) {
// eslint-disable-next-line
console.log(`Building...`);
} }
if (code === 'BUNDLE_END') { }
outputPath = output[0]; if (code === 'BUNDLE_END') {
if (result && result.close) { bundleOutput = output;
result.close(); if (result) {
} result.close();
} }
if (code === 'END') { }
/* if (code === 'END') {
console.log('Watching for changes, press ENTER to continue.'); // eslint-disable-line if (dev) {
// eslint-disable-next-line
console.log(`Watching for changes...`);
console.log(''); // eslint-disable-line console.log(''); // eslint-disable-line
*/ } else {
resolve(); resolve(bundleOutput);
} }
}); }
}); });
});
const { address, port } = server.address(); const { address, port } = getServer().address();
return { return {
url: `${address}:${port}`, url: `${address}:${port}`,
output: outputPath, output: outputPath,
close: () => { close: () => {
server.close(); getServer().close();
watcher.close(); watcher.close();
}, },
}; };
}
const bundle = await rollup(config);
await bundle.write(config.output);
}; };
module.exports = () => { module.exports = (useEsbuild = true) => {
const originalCwd = process.cwd(); const originalCwd = process.cwd();
let url; let url;
let close; let close;
let output; let output;
// eslint-disable-next-line no-empty-pattern // eslint-disable-next-line no-empty-pattern
test.beforeAll(async ({}, { file, config }) => { test.beforeAll(async ({}, { file, config, timeout }) => {
({ close, url, output } = await createRollupBundle(dirname(file), true, config.quiet)); const isDev = config.globalTimeout === 0 && timeout === 0 && config.workers === 1;
if (isDev) {
test.setTimeout(0);
}
({ close, url, output } = await createRollupBundle(dirname(file), useEsbuild, isDev));
}); });
test.beforeEach(async ({ page, browserName }, { config }) => { test.beforeEach(async ({ page, browserName }, { config }) => {
@@ -8,7 +8,7 @@ const {
rollupAlias, rollupAlias,
rollupScss, rollupScss,
rollupLicense, rollupLicense,
} = require('./pipeline.common.plugins'); } = require('./plugins');
const moduleFormats = ['es', 'esm', 'module']; const moduleFormats = ['es', 'esm', 'module'];
const createMinifiedOutput = (baseOutput) => ({ const createMinifiedOutput = (baseOutput) => ({
@@ -53,6 +53,7 @@ module.exports = (resolve, options) => {
format, format,
generatedCode, generatedCode,
file: typeof filePathOverride === 'function' ? filePathOverride(filePath) : filePath, file: typeof filePathOverride === 'function' ? filePathOverride(filePath) : filePath,
plugins: (outputConfig.plugins || []).filter(Boolean),
}; };
const output = [baseOutput, minifiedVersion && createMinifiedOutput(baseOutput)].filter( const output = [baseOutput, minifiedVersion && createMinifiedOutput(baseOutput)].filter(
Boolean Boolean
@@ -5,7 +5,7 @@ const {
rollupResolve, rollupResolve,
rollupAlias, rollupAlias,
rollupScss, rollupScss,
} = require('./pipeline.common.plugins'); } = require('./plugins');
module.exports = (resolve, options) => { module.exports = (resolve, options) => {
const { rollup, paths, alias, extractStyles } = options; const { rollup, paths, alias, extractStyles } = options;
@@ -20,6 +20,7 @@ module.exports = (resolve, options) => {
format: 'esm', format: 'esm',
generatedCode: 'es2015', generatedCode: 'es2015',
file: path.resolve(distPath, `${file}.js`), file: path.resolve(distPath, `${file}.js`),
plugins: (outputConfig.plugins || []).filter(Boolean),
}; };
return { return {
@@ -1,10 +1,5 @@
const path = require('path'); const path = require('path');
const { const { rollupAlias, rollupResolve, rollupScss, rollupEsBuild } = require('./plugins');
rollupAlias,
rollupResolve,
rollupScss,
rollupEsBuild,
} = require('./pipeline.common.plugins');
module.exports = (resolve, options) => { module.exports = (resolve, options) => {
const { rollup, alias, paths, banner, extractStyles } = options; const { rollup, alias, paths, banner, extractStyles } = options;
@@ -2,7 +2,8 @@ const fs = require('fs');
const { basename } = require('path'); const { basename } = require('path');
const path = require('path'); const path = require('path');
const rollupDts = require('rollup-plugin-dts'); const rollupDts = require('rollup-plugin-dts');
const { rollupTs } = require('./pipeline.common.plugins');
const { rollupTs } = require('./plugins');
module.exports = (resolve, options) => { module.exports = (resolve, options) => {
const { rollup, paths } = options; const { rollup, paths } = options;
+9 -22
View File
@@ -6,10 +6,7 @@ const path = require('path');
const glob = require('glob'); const glob = require('glob');
const resolve = require('@~local/config/resolve'); const resolve = require('@~local/config/resolve');
const defaultOptions = require('./defaultOptions'); const defaultOptions = require('./defaultOptions');
const pipelineBuild = require('./pipeline.build'); const pipelineDefault = require('./pipeline.default');
const pipelineDev = require('./pipeline.dev');
const pipelineStyles = require('./pipeline.styles');
const pipelineTypes = require('./pipeline.types');
const workspaceRoot = path.dirname(execSync('npm root').toString()); const workspaceRoot = path.dirname(execSync('npm root').toString());
const pkg = require(`${workspaceRoot}/package.json`); const pkg = require(`${workspaceRoot}/package.json`);
@@ -33,7 +30,6 @@ const resolvePath = (basePath, pathToResolve, appendExt) => {
const mergeAndResolveOptions = (userOptions) => { const mergeAndResolveOptions = (userOptions) => {
const { const {
mode: defaultMode,
paths: defaultPaths, paths: defaultPaths,
versions: defaultVersions, versions: defaultVersions,
alias: defaultAlias, alias: defaultAlias,
@@ -42,10 +38,10 @@ const mergeAndResolveOptions = (userOptions) => {
extractTypes: defaultExtractTypes, extractTypes: defaultExtractTypes,
verbose: defaultVerbose, verbose: defaultVerbose,
banner: defaultBanner, banner: defaultBanner,
useEsbuild: defaultUseEsbuild,
} = defaultOptions; } = defaultOptions;
const { const {
project, project,
mode: rawMode,
paths: rawPaths = {}, paths: rawPaths = {},
alias: rawAlias = {}, alias: rawAlias = {},
rollup: rawRollup = {}, rollup: rawRollup = {},
@@ -54,6 +50,7 @@ const mergeAndResolveOptions = (userOptions) => {
extractTypes: rawExtractTypes, extractTypes: rawExtractTypes,
verbose: rawVerbose, verbose: rawVerbose,
banner: rawBanner, banner: rawBanner,
useEsbuild: rawUseEsbuild,
} = userOptions; } = userOptions;
const projectPath = process.cwd(); const projectPath = process.cwd();
const workspaces = pkg.workspaces const workspaces = pkg.workspaces
@@ -61,12 +58,12 @@ const mergeAndResolveOptions = (userOptions) => {
.flat(); .flat();
const mergedOptions = { const mergedOptions = {
project: project || path.basename(projectPath), project: project || path.basename(projectPath),
mode: rawMode || defaultMode,
extractStyles: rawExtractStyles ?? defaultExtractStyles, extractStyles: rawExtractStyles ?? defaultExtractStyles,
extractTypes: rawExtractTypes ?? defaultExtractTypes, extractTypes: rawExtractTypes ?? defaultExtractTypes,
verbose: rawVerbose ?? defaultVerbose, verbose: rawVerbose ?? defaultVerbose,
banner: rawBanner ?? defaultBanner, banner: rawBanner ?? defaultBanner,
versions: rawVersions ?? defaultVersions, versions: rawVersions ?? defaultVersions,
useEsbuild: rawUseEsbuild ?? defaultUseEsbuild,
paths: { paths: {
...defaultPaths, ...defaultPaths,
...rawPaths, ...rawPaths,
@@ -104,22 +101,12 @@ const mergeAndResolveOptions = (userOptions) => {
const createConfig = (userOptions = {}) => { const createConfig = (userOptions = {}) => {
const options = mergeAndResolveOptions(userOptions); const options = mergeAndResolveOptions(userOptions);
const { project, mode, extractTypes, extractStyles, verbose } = options; const { project, useEsbuild, verbose } = options;
const isBuild = mode === 'build'; const result = pipelineDefault(resolve, options, useEsbuild);
let result; const resultArr = Array.isArray(result) ? result : [result];
if (isBuild) {
const styles = extractStyles && pipelineStyles(resolve, options);
const types = extractTypes && pipelineTypes(resolve, options);
const js = pipelineBuild(resolve, options);
result = [styles, types, js].flat().filter((build) => !!build);
} else {
result = [pipelineDev(resolve, options)];
}
if (verbose) { if (verbose) {
result[0].plugins.push({ resultArr[0].plugins.push({
name: 'PROJECT', name: 'PROJECT',
buildStart() { buildStart() {
console.log(''); console.log('');
@@ -129,7 +116,7 @@ const createConfig = (userOptions = {}) => {
}); });
} }
return result; return resultArr;
}; };
module.exports = createConfig; module.exports = createConfig;
+1 -1
View File
@@ -1,8 +1,8 @@
module.exports = { module.exports = {
project: null, project: null,
mode: 'build',
verbose: false, verbose: false,
banner: null, banner: null,
useEsbuild: false,
paths: { paths: {
dist: './dist', dist: './dist',
types: './types', types: './types',
+15
View File
@@ -0,0 +1,15 @@
const bundleScriptDefault = require('./bundle/script.default');
const bundleScriptEsbuild = require('./bundle/script.esbuild');
const bundleStyles = require('./bundle/styles');
const bundleTypes = require('./bundle/types');
module.exports = (resolve, options, esbuild) => {
const { extractTypes, extractStyles } = options;
const bundleScript = esbuild ? bundleScriptEsbuild : bundleScriptDefault;
const styles = extractStyles && bundleStyles(resolve, options);
const types = extractTypes && bundleTypes(resolve, options);
const js = bundleScript(resolve, options);
return [styles, types, js].flat().filter((build) => !!build);
};
@@ -4,35 +4,53 @@ const fs = require('fs');
const path = require('path'); const path = require('path');
const rollupPluginStyles = require('rollup-plugin-styles'); const rollupPluginStyles = require('rollup-plugin-styles');
const rollupPluginServe = require('rollup-plugin-serve'); const rollupPluginServe = require('rollup-plugin-serve');
// const rollupPluginLivereload = require('rollup-plugin-livereload'); const rollupPluginLivereload = require('rollup-plugin-livereload');
const rollupPluginHtml = require('./rollup.pluginHtml'); const rollupPluginHtml = require('./rollup.pluginHtml');
const createRollupConfig = require('../createRollupConfig'); const createRollupConfig = require('../createRollupConfig');
// const rollupAdditionalWatchFiles = require('./rollup.pluginAdditionalWatchFiles'); const rollupAdditionalWatchFiles = require('./rollup.pluginAdditionalWatchFiles');
const portRange = { const portRange = {
min: 20000, min: 20000,
max: 60000, max: 60000,
}; };
const meta = { const paths = {
dist: './.build', dist: './.build',
html: './index.html',
input: './index.browser', input: './index.browser',
html: './index.html',
}; };
module.exports = (testDir, mode = 'dev', onListening = null) => { module.exports = (testDir, useEsbuild, dev) => {
const name = path.basename(testDir); const testPaths = Object.keys(paths).reduce((obj, key) => {
const htmlFilePath = path.resolve(testDir, meta.html); obj[key] = path.resolve(testDir, paths[key]);
const dist = path.resolve(testDir, meta.dist); return obj;
const htmlName = `${name}.html`; }, {});
const { min, max } = portRange;
const port = Math.floor(Math.random() * (max - min + 1) + min);
return createRollupConfig({ const { min, max } = portRange;
const { dist, input, html: htmlPath } = testPaths;
const name = path.basename(testDir);
const htmlName = `${name}.html`;
const port = Math.floor(Math.random() * (max - min + 1) + min);
const isDev = !!dev;
let server;
const config = createRollupConfig({
useEsbuild,
project: name, project: name,
mode, banner: testDir,
banner: `${testDir}`, extractStyle: false,
extractTypes: false,
paths: {
dist,
},
versions: [
{
format: 'iife',
generatedCode: 'es5',
minifiedVersion: false,
},
],
// if the import would be 'overlayscrollbars' and the package name is also 'overlayscrollbars' esbuild needs an alias to resolve it correctly // if the import would be 'overlayscrollbars' and the package name is also 'overlayscrollbars' esbuild needs an alias to resolve it correctly
alias: (workspaceRoot, workspaces, resolvePath) => alias: (workspaceRoot, workspaces, resolvePath) =>
workspaces.reduce((obj, resolvedPath) => { workspaces.reduce((obj, resolvedPath) => {
@@ -57,55 +75,38 @@ module.exports = (testDir, mode = 'dev', onListening = null) => {
} catch {} } catch {}
return obj; return obj;
}, {}), }, {}),
paths: {
dist,
},
versions: [
mode === 'dev'
? {
format: 'esm',
generatedCode: 'es2015',
minifiedVersion: false,
}
: {
format: 'iife',
generatedCode: 'es5',
minifiedVersion: false,
},
],
extractStyle: false,
rollup: { rollup: {
input: path.resolve(testDir, meta.input), input,
context: 'this', context: 'this',
moduleContext: () => 'this', moduleContext: () => 'this',
output: { output: {
sourcemap: true, sourcemap: isDev,
}, },
plugins: [ plugins: [
rollupPluginStyles(), rollupPluginStyles(),
rollupPluginHtml(`Playwright: ${name}`, htmlName, () => rollupPluginHtml(`Playwright: ${name}`, htmlName, () =>
fs.existsSync(htmlFilePath) ? fs.readFileSync(htmlFilePath, 'utf8') : null fs.existsSync(htmlPath) ? fs.readFileSync(htmlPath, 'utf8') : null
), ),
...(onListening rollupPluginServe({
? [ port,
// rollupAdditionalWatchFiles([htmlFilePath]), contentBase: dist,
rollupPluginServe({ historyApiFallback: `/${htmlName}`,
contentBase: dist, host: '127.0.0.1',
historyApiFallback: `/${htmlName}`, verbose: isDev,
host: '127.0.0.1', onListening: (srv) => {
port, server = srv;
onListening, },
}), }),
/* isDev && rollupAdditionalWatchFiles([htmlPath]),
rollupPluginLivereload({ isDev &&
watch: dist, rollupPluginLivereload({
port: port - 1, watch: dist,
verbose: false, port: port - 1,
}), verbose: false,
*/ }),
]
: []),
], ],
}, },
}); });
return [config, () => server];
}; };
+2 -2
View File
@@ -46,8 +46,8 @@
"postjest": "full-coverage", "postjest": "full-coverage",
"jest:node": "jest --runInBand --detectOpenHandles --selectProjects node --testPathPattern", "jest:node": "jest --runInBand --detectOpenHandles --selectProjects node --testPathPattern",
"jest:jsdom": "jest --runInBand --detectOpenHandles --selectProjects jsdom --testPathPattern", "jest:jsdom": "jest --runInBand --detectOpenHandles --selectProjects jsdom --testPathPattern",
"playwright": "playwright test --quiet", "playwright": "playwright test",
"postplaywright": "playwright-merge-coverage && full-coverage", "postplaywright": "playwright-merge-coverage && full-coverage",
"playwright:dev": "playwright test --workers 1" "playwright:dev": "playwright test --workers 1 --timeout 0 --global-timeout 0"
} }
} }