import { execa } from 'execa'; import * as fs from 'fs'; import { resolve } from 'path'; import chalk from 'chalk'; const removeNewline = (string) => { return string.replace(/(\r\n|\n|\r)/gm, ""); } const readConfigFile = (file) => { if (fs.existsSync(file)) { return fs.readFileSync(file, { encoding: 'utf-8' }); } return ''; } // These files are optional, so we don't want to error if they don't exist const display = removeNewline(readConfigFile('docker-display.txt')); const displayVolume = removeNewline(readConfigFile('docker-display-volume.txt')); // Using --mount requires an absolute path which is what this gives us. const pwd = resolve('./'); /** * -it will let the user gracefully kill the process using Ctrl+C (or equivalent) * -e DISPLAY and -v handle configuration for headed mode * --ipc=host is recommended when using Chromium to avoid out of memory crashes: https://playwright.dev/docs/ci#docker * --init is recommended to avoid zombie processes: https://playwright.dev/docs/ci#docker * --mount allow us to mount the local Ionic project inside of the Docker container so devs do not need to re-build the project in Docker. */ const args = ['run', '--rm', '--init', `-e DISPLAY=${display}`, `-v ${displayVolume}`, '--ipc=host', `--mount=type=bind,source=${pwd},target=/ionic`, 'ionic-playwright', 'npm run test.e2e --', ...process.argv.slice(2)]; // Set the CI env variable so Playwright uses the CI config if (process.env.CI) { args.splice(1, 0, '-e CI=true'); /** * Otherwise, we should let the session be interactive locally. This will * not work on CI which is why we do not apply it there. */ } else { args.splice(1, 0, '-it'); } /** * While these config files are optional to run the tests, they are required to run * the tests in headed mode. Add a warning if dev tries to run headed tests without * the correct config files. */ const requestHeaded = process.argv.find(arg => arg.includes('headed')); const hasHeadedConfigFiles = display && displayVolume; if (requestHeaded && !hasHeadedConfigFiles) { console.warn(chalk.yellow.bold('\n⚠️ You are running tests in headed mode, but one or more of your headed config files was not found.\nPlease ensure that both docker-display.txt and docker-display-volume.txt have been created in the correct location.\n')); } const res = await execa('docker', args, { shell: true, stdio: 'inherit' }); // If underlying scripts failed this whole process should fail too process.exit(res.exitCode);