chore: port installation tests to @playwright/test (#13644)
This commit is contained in:
Родитель
2e6ef8f622
Коммит
e69e836c40
|
@ -134,7 +134,7 @@ jobs:
|
|||
- run: npm run build
|
||||
- run: npx playwright install-deps
|
||||
- name: INSTALLATION TESTS
|
||||
run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- bash installation-tests/run_all_tests.sh
|
||||
run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- npm run itest
|
||||
|
||||
headful_linux:
|
||||
name: "Headful Linux"
|
||||
|
|
|
@ -25,3 +25,5 @@ playwright-report
|
|||
/packages/playwright/README.md
|
||||
/packages/playwright-core/api.json
|
||||
.env
|
||||
/tests/installation/output/
|
||||
/tests/installation/.registry.json
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
output
|
|
@ -1,24 +0,0 @@
|
|||
# Installation Tests
|
||||
|
||||
These tests check end-to-end installation and operation of Playwright.
|
||||
Each test is set with a separate folder that contains all scripts from
|
||||
`fixture-scripts` folder and dummy package.json.
|
||||
|
||||
To create a new test, create a new file that starts with `test_*.sh`
|
||||
with the following header:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
source ./initialize_test.sh && initialize_test "$@" # initialize test
|
||||
```
|
||||
|
||||
To run all tests:
|
||||
|
||||
```bash
|
||||
./run_all_tests.sh
|
||||
```
|
||||
|
||||
To install local builds of `playwright` packages in tests, do `npm_i playwright`.
|
||||
|
||||
Each test run will get its own npm state. You can use `local-playwright-registry <package>` to
|
||||
ensure it was installed as part of the test run, and that it was a local copy.
|
|
@ -1,274 +0,0 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
/*
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// ============================================
|
||||
// See `./local-playwright-registry help` for
|
||||
// usage and help.
|
||||
// ============================================
|
||||
|
||||
const crypto = require('crypto');
|
||||
const { spawn } = require('child_process');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const http = require('http');
|
||||
const https = require('https');
|
||||
|
||||
// WORK_DIR should be a local directory the Registry can work in through its lifetime. It will not be removed automatically.
|
||||
const WORK_DIR = path.join(process.cwd(), '.playwright-registry');
|
||||
// ACCESS_LOGS records which packages have been served locally vs. proxied to the official npm registry.
|
||||
const ACCESS_LOGS = path.join(WORK_DIR, 'access.log');
|
||||
// REGISTRY_URL_FILE is the URL to us to connect to the registy. It is allocated dynamically and shows up on disk only once the packages are actually available for download.
|
||||
const REGISTRY_URL_FILE = path.join(WORK_DIR, 'registry.url.txt');
|
||||
|
||||
const kPublicNpmRegistry = 'https://registry.npmjs.org';
|
||||
const kContentTypeAbbreviatedMetadata = 'application/vnd.npm.install-v1+json';
|
||||
|
||||
class Registry {
|
||||
constructor() {
|
||||
this._objectsDir = path.join(WORK_DIR, 'objects');
|
||||
this._packageMeta = new Map();
|
||||
this._address = '';
|
||||
this._log = () => { };
|
||||
}
|
||||
|
||||
async init() {
|
||||
await fs.promises.mkdir(this._objectsDir, { recursive: true });
|
||||
await fs.promises.writeFile(ACCESS_LOGS, '');
|
||||
this._log = msg => fs.appendFileSync(ACCESS_LOGS, `${msg}\n`);
|
||||
|
||||
await Promise.all([
|
||||
this._addPackage('playwright', getEnvOrDie('PLAYWRIGHT_TGZ')),
|
||||
this._addPackage('playwright-core', getEnvOrDie('PLAYWRIGHT_CORE_TGZ')),
|
||||
this._addPackage('playwright-chromium', getEnvOrDie('PLAYWRIGHT_CHROMIUM_TGZ')),
|
||||
this._addPackage('playwright-firefox',getEnvOrDie('PLAYWRIGHT_FIREFOX_TGZ')),
|
||||
this._addPackage('playwright-webkit',getEnvOrDie('PLAYWRIGHT_WEBKIT_TGZ')),
|
||||
this._addPackage('@playwright/test',getEnvOrDie('PLAYWRIGHT_TEST_TGZ')),
|
||||
]);
|
||||
|
||||
// Minimal Server that implements essential endpoints from the NPM Registry API.
|
||||
// See https://github.com/npm/registry/blob/master/docs/REGISTRY-API.md.
|
||||
this._server = http.createServer(async (req, res) => {
|
||||
this._log(`REQUEST: ${req.method} ${req.url}`);
|
||||
// 1. Only support GET requests
|
||||
if (req.method !== 'GET') {
|
||||
res.writeHead(405).end();
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. Determine what package is being asked for.
|
||||
// The paths we can handle look like:
|
||||
// - /<userSuppliedPackageName>/*/<userSuppliedTarName i.e. some *.tgz>
|
||||
// - /<userSuppliedPackageName>/*
|
||||
// - /<userSuppliedPackageName>
|
||||
const url = new URL(req.url, kPublicNpmRegistry);
|
||||
let [, userSuppliedPackageName, , userSuppliedTarName] = url.pathname.split('/');
|
||||
if (userSuppliedPackageName)
|
||||
userSuppliedPackageName = decodeURIComponent(userSuppliedPackageName);
|
||||
if (userSuppliedTarName)
|
||||
userSuppliedTarName = decodeURIComponent(userSuppliedTarName);
|
||||
|
||||
// 3. If we have local metadata, serve directly (otherwise, proxy to upstream).
|
||||
if (this._packageMeta.has(userSuppliedPackageName)) {
|
||||
const [metadata, objectPath] = this._packageMeta.get(userSuppliedPackageName);
|
||||
if (userSuppliedTarName) { // Tar ball request.
|
||||
if (path.basename(objectPath) !== userSuppliedTarName) {
|
||||
res.writeHead(404).end();
|
||||
return;
|
||||
}
|
||||
this._log(`LOCAL ${userSuppliedPackageName} tar`);
|
||||
const fileStream = fs.createReadStream(objectPath);
|
||||
fileStream.pipe(res, { end: true });
|
||||
fileStream.on('error', console.error);
|
||||
res.on('error', console.error);
|
||||
return;
|
||||
} else { // Metadata request.
|
||||
this._log(`LOCAL ${userSuppliedPackageName} metadata`);
|
||||
res.setHeader('content-type', kContentTypeAbbreviatedMetadata);
|
||||
res.write(JSON.stringify(metadata));
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
} else { // Fall through to official registry.
|
||||
this._log(`PROXIED ${userSuppliedPackageName}`);
|
||||
const client = { req, res };
|
||||
const toNpm = https.request({
|
||||
host: url.host,
|
||||
headers: { ...req.headers, 'host': url.host },
|
||||
method: req.method,
|
||||
path: url.pathname,
|
||||
searchParams: url.searchParams,
|
||||
protocol: 'https:',
|
||||
}, fromNpm => {
|
||||
client.res.writeHead(fromNpm.statusCode, fromNpm.statusMessage, fromNpm.headers);
|
||||
fromNpm.on('error', console.error);
|
||||
fromNpm.pipe(client.res, { end: true });
|
||||
});
|
||||
client.req.pipe(toNpm);
|
||||
client.req.on('error', console.error);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
this._server.listen(undefined, 'localhost', () => {
|
||||
this._address = new URL(`http://localhost:${this._server.address().port}`).toString();
|
||||
// We now have an address to make tarball paths fully qualified.
|
||||
for (const [,[metadata]] of this._packageMeta.entries()) {
|
||||
for (const [,version] of Object.entries(metadata.versions))
|
||||
version.dist.tarball = this._address + version.dist.tarball;
|
||||
}
|
||||
fs.writeFileSync(REGISTRY_URL_FILE, this._address.toString());
|
||||
});
|
||||
process.on('exit', () => {
|
||||
console.log('closing server');
|
||||
this._server.close(console.error);
|
||||
});
|
||||
}
|
||||
|
||||
async _addPackage(pkg, tarPath) {
|
||||
const tmpDir = await fs.promises.mkdtemp(path.join(WORK_DIR, '.staging-package-'));
|
||||
const { stderr, code } = await spawnAsync('tar', ['-xvzf', tarPath, '-C', tmpDir]);
|
||||
if (!!code)
|
||||
throw new Error(`Failed to untar ${pkg}: ${stderr}`);
|
||||
|
||||
const packageJson = JSON.parse((await fs.promises.readFile(path.join(tmpDir, 'package', 'package.json'), 'utf8')));
|
||||
if (pkg !== packageJson.name)
|
||||
throw new Error(`Package name mismatch: ${pkg} is called ${packageJson.name} in its package.json`);
|
||||
|
||||
const shasum = crypto.createHash('sha1').update(await fs.promises.readFile(tarPath)).digest().toString('hex');
|
||||
const metadata = {
|
||||
'dist-tags': {
|
||||
latest: packageJson.version,
|
||||
[packageJson.version]: packageJson.version,
|
||||
},
|
||||
'modified': new Date().toISOString(),
|
||||
'name': pkg,
|
||||
'versions': {
|
||||
[packageJson.version]: {
|
||||
_hasShrinkwrap: false,
|
||||
name: pkg,
|
||||
version: packageJson.version,
|
||||
dependencies: packageJson.dependencies || {},
|
||||
optionalDependencies: packageJson.optionalDependencies || {},
|
||||
devDependencies: packageJson.devDependencies || {},
|
||||
bundleDependencies: packageJson.bundleDependencies || {},
|
||||
peerDependencies: packageJson.peerDependencies || {},
|
||||
bin: packageJson.bin || {},
|
||||
directories: packageJson.directories || [],
|
||||
dist: {
|
||||
// This needs to be updated later with a full address.
|
||||
tarball: `${encodeURIComponent(pkg)}/-/${shasum}.tgz`,
|
||||
shasum,
|
||||
},
|
||||
engines: packageJson.engines || {},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const object = path.join(this._objectsDir, `${shasum}.tgz`);
|
||||
await fs.promises.copyFile(tarPath, object);
|
||||
|
||||
this._packageMeta.set(pkg, [metadata, object]);
|
||||
}
|
||||
|
||||
static async registryFactory() {
|
||||
const registry = new Registry();
|
||||
await registry.init();
|
||||
return registry;
|
||||
}
|
||||
|
||||
static async waitForReady() {
|
||||
const OVERALL_TIMEOUT_MS = 60000;
|
||||
const registryUrl = await new Promise(async (res, rej) => {
|
||||
setTimeout(rej.bind(null, new Error('Timeout: Registry failed to become ready.')), OVERALL_TIMEOUT_MS);
|
||||
while (true) {
|
||||
const registryUrl = await fs.promises.readFile(REGISTRY_URL_FILE, 'utf8').catch(() => null);
|
||||
if (registryUrl)
|
||||
return res(registryUrl);
|
||||
await new Promise(r => setTimeout(r, 500));
|
||||
}
|
||||
});
|
||||
console.log(registryUrl);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
static async assertLocalPkg(pkg) {
|
||||
const logs = await fs.promises.readFile(ACCESS_LOGS, 'utf8');
|
||||
const lines = logs.split(`\n`);
|
||||
if (lines.includes(`LOCAL ${pkg} metadata`) && lines.includes(`LOCAL ${pkg} tar`) && !lines.includes(`PROXIED ${pkg} metadata`))
|
||||
return;
|
||||
console.log('Expected LOCAL metadata and tar, and no PROXIED logs for:', pkg);
|
||||
console.log('Logs:');
|
||||
console.log(lines.join(`\n`));
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
const getEnvOrDie = varName => {
|
||||
const v = process.env[varName];
|
||||
if (!v)
|
||||
throw new Error(`${varName} environment variable MUST be set.`);
|
||||
|
||||
return v;
|
||||
};
|
||||
|
||||
const spawnAsync = (cmd, args, options) => {
|
||||
const process = spawn(cmd, args, Object.assign({ windowsHide: true }, options));
|
||||
|
||||
return new Promise(resolve => {
|
||||
let stdout = '';
|
||||
let stderr = '';
|
||||
if (process.stdout)
|
||||
process.stdout.on('data', data => stdout += data);
|
||||
if (process.stderr)
|
||||
process.stderr.on('data', data => stderr += data);
|
||||
process.on('close', code => resolve({ stdout, stderr, code }));
|
||||
process.on('error', error => resolve({ stdout, stderr, code: 0, error }));
|
||||
});
|
||||
};
|
||||
|
||||
const commands = {
|
||||
'help': async () => {
|
||||
console.log(`
|
||||
A minimal, inefficent npm registry to serve local npm packages, or fall through
|
||||
to the offical npm registry. This is useful for testing npm and npx utilities,
|
||||
but should NOT, be used for anything more.
|
||||
|
||||
Commands:
|
||||
- help.......................: prints this help message
|
||||
- start......................: starts the registry server
|
||||
- wait-for-ready.............: blocks waiting for the server to print
|
||||
that it's actually ready and serving the
|
||||
packages you published!
|
||||
- assert-downloaded <package>: confirms that <package> was served locally,
|
||||
AND never proxied to the official registry.`);
|
||||
},
|
||||
'start': Registry.registryFactory,
|
||||
'wait-for-ready': Registry.waitForReady,
|
||||
'assert-served-from-local-tgz': ([pkg]) => Registry.assertLocalPkg(pkg),
|
||||
};
|
||||
|
||||
(async () => {
|
||||
const command = commands[process.argv[2]];
|
||||
if (!command) {
|
||||
console.log(`${process.argv[2]} not a valid command:`);
|
||||
await commands['help']();
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
await command(process.argv.slice(3));
|
||||
})();
|
|
@ -1,57 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
args=""
|
||||
pkgs=""
|
||||
for i in "$@"; do
|
||||
if [[ "$i" == "playwright" ]]; then
|
||||
args="${args} ${PLAYWRIGHT_TGZ}"
|
||||
pkgs="${pkgs} playwright"
|
||||
elif [[ $i == "playwright-core" ]]; then
|
||||
args="${args} ${PLAYWRIGHT_CORE_TGZ}"
|
||||
pkgs="${pkgs} playwright-core"
|
||||
elif [[ $i == "playwright-firefox" ]]; then
|
||||
args="${args} ${PLAYWRIGHT_FIREFOX_TGZ}"
|
||||
pkgs="${pkgs} playwright-firefox"
|
||||
elif [[ $i == "playwright-chromium" ]]; then
|
||||
args="${args} ${PLAYWRIGHT_CHROMIUM_TGZ}"
|
||||
pkgs="${pkgs} playwright-chromium"
|
||||
elif [[ $i == "playwright-webkit" ]]; then
|
||||
args="${args} ${PLAYWRIGHT_WEBKIT_TGZ}"
|
||||
pkgs="${pkgs} playwright-webkit"
|
||||
elif [[ $i == "@playwright/test" ]]; then
|
||||
args="${args} ${PLAYWRIGHT_TEST_TGZ}"
|
||||
pkgs="${pkgs} @playwright/test"
|
||||
elif [[ $i == "-"* ]]; then
|
||||
args="${args} $i"
|
||||
else
|
||||
echo "ERROR: cannot install package $i using npm_i. Use regular npm instead"
|
||||
fi
|
||||
done
|
||||
npm install $args 2>&1
|
||||
|
||||
SCRIPT=$(cat <<EOF
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
const packages = process.argv.slice(1);
|
||||
console.log('Verifying local installation of:', packages.join(', '));
|
||||
|
||||
for (const package of packages) {
|
||||
const expectedDir = process.env.EXPECTED_NODE_MODULES_PARENT;
|
||||
const packageJsonPath = path.join(path.dirname(require.resolve(package)), 'package.json');
|
||||
if (!packageJsonPath.startsWith(expectedDir)) {
|
||||
console.error('Local resolution of package failed. Package:', package, 'Expected:', expectedDir, 'Got:', path.dirname(packageJsonPath));
|
||||
process.exit(1);
|
||||
}
|
||||
const expectedVersion = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')).version;
|
||||
if (expectedVersion !== process.env.PLAYWRIGHT_VERSION_UNDER_TEST) {
|
||||
console.error('Version of local package did not match expectation. Package:', package, 'Expected:', expectedVersion, 'Got:', process.env.PLAYWRIGHT_VERSION_UNDER_TEST);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Confirmed local installation of:', packages.join(', '));
|
||||
EOF
|
||||
)
|
||||
|
||||
node -e "${SCRIPT}" $pkgs
|
|
@ -1,3 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
npx --yes playwright $@ 2>&1
|
|
@ -1,130 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# break script execution if some command returns non-zero exit code
|
||||
set -e
|
||||
|
||||
TEST_FRAMEWORK_RUN_ROOT="/tmp/playwright-installation-tests"
|
||||
|
||||
function build_packages() {
|
||||
local PACKAGE_BUILDER="../../utils/pack_package.js"
|
||||
rm -rf ./output
|
||||
mkdir ./output
|
||||
pushd ./output >/dev/null
|
||||
|
||||
node ${PACKAGE_BUILDER} playwright-core "${PLAYWRIGHT_CORE_TGZ}" 2>&1 1>/dev/null
|
||||
node ${PACKAGE_BUILDER} playwright-test "${PLAYWRIGHT_TEST_TGZ}" 2>&1 1>/dev/null
|
||||
node ${PACKAGE_BUILDER} playwright "${PLAYWRIGHT_TGZ}" 2>&1 1>/dev/null
|
||||
node ${PACKAGE_BUILDER} playwright-chromium "${PLAYWRIGHT_CHROMIUM_TGZ}" 2>&1 1>/dev/null
|
||||
node ${PACKAGE_BUILDER} playwright-webkit "${PLAYWRIGHT_WEBKIT_TGZ}" 2>&1 1>/dev/null
|
||||
node ${PACKAGE_BUILDER} playwright-firefox "${PLAYWRIGHT_FIREFOX_TGZ}" 2>&1 1>/dev/null
|
||||
popd >/dev/null
|
||||
}
|
||||
|
||||
function cecho(){
|
||||
local RED="\033[0;31m"
|
||||
local GREEN="\033[0;32m"
|
||||
local YELLOW="\033[1;33m"
|
||||
local NC="\033[0m" # No Color
|
||||
printf "${!1}${2} ${NC}\n"
|
||||
}
|
||||
|
||||
function report_test_result {
|
||||
RV=$?
|
||||
set +x
|
||||
if [[ $RV == 0 ]]; then
|
||||
echo
|
||||
cecho "GREEN" "<<<<<<<<<<<<"
|
||||
cecho "GREEN" " Test '${TEST_FILE}' PASSED"
|
||||
cecho "GREEN" "<<<<<<<<<<<<"
|
||||
else
|
||||
cecho "RED" "<<<<<<<<<<<<"
|
||||
cecho "RED" " Test '${TEST_FILE}' FAILED"
|
||||
cecho "RED" " To debug locally, run:"
|
||||
cecho "RED" " bash ${TEST_FILE}"
|
||||
cecho "RED" "<<<<<<<<<<<<"
|
||||
echo
|
||||
fi
|
||||
echo
|
||||
}
|
||||
|
||||
function setup_env_variables() {
|
||||
# Package paths.
|
||||
NODE_VERSION=$(node -e "console.log(process.version.slice(1).split('.')[0])")
|
||||
|
||||
export PLAYWRIGHT_CORE_TGZ="${PWD}/output/playwright-core.tgz"
|
||||
export PLAYWRIGHT_TGZ="${PWD}/output/playwright.tgz"
|
||||
export PLAYWRIGHT_CHROMIUM_TGZ="${PWD}/output/playwright-chromium.tgz"
|
||||
export PLAYWRIGHT_WEBKIT_TGZ="${PWD}/output/playwright-webkit.tgz"
|
||||
export PLAYWRIGHT_FIREFOX_TGZ="${PWD}/output/playwright-firefox.tgz"
|
||||
export PLAYWRIGHT_TEST_TGZ="${PWD}/output/playwright-test.tgz"
|
||||
PLAYWRIGHT_CHECKOUT="${PWD}/.."
|
||||
export PLAYWRIGHT_VERSION_UNDER_TEST="$(node ${PLAYWRIGHT_CHECKOUT}/utils/workspace.js --get-version)"
|
||||
}
|
||||
|
||||
function clean_test_root() {
|
||||
rm -rf "${TEST_FRAMEWORK_RUN_ROOT}"
|
||||
mkdir -p "${TEST_FRAMEWORK_RUN_ROOT}"
|
||||
}
|
||||
|
||||
function initialize_test {
|
||||
trap "report_test_result; kill %1; cd $(pwd -P);" EXIT
|
||||
cd "$(dirname $0)"
|
||||
|
||||
# cleanup environment
|
||||
unset PLAYWRIGHT_DOWNLOAD_HOST
|
||||
unset PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD
|
||||
export PLAYWRIGHT_BROWSERS_PATH=0
|
||||
|
||||
local SCRIPTS_PATH="$(pwd -P)"
|
||||
setup_env_variables
|
||||
TEST_FILE=$(basename $0)
|
||||
TEST_NAME=$(basename ${0%%.sh})
|
||||
|
||||
# Check if test tries to install using npm directly
|
||||
if grep 'npm i.*playwright' "$0" 2>&1 >/dev/null; then
|
||||
# If it does, this is an error: you will miss output
|
||||
cecho "RED" "ERROR: test tries to install playwright-family package from NPM registry!"
|
||||
cecho "RED" " Do not use NPM to install playwright packages!"
|
||||
cecho "RED" " Instead, use 'npm_i' command to install local package"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$1" != "--no-build" && "$2" != "--no-build" ]]; then
|
||||
echo 'Building packages... NOTE: run with `--no-build` to reuse previous builds'
|
||||
build_packages
|
||||
else
|
||||
if [[ ! -f "${PLAYWRIGHT_TGZ}" || \
|
||||
! -f "${PLAYWRIGHT_CORE_TGZ}" || \
|
||||
! -f "${PLAYWRIGHT_CHROMIUM_TGZ}" || \
|
||||
! -f "${PLAYWRIGHT_WEBKIT_TGZ}" || \
|
||||
! -f "${PLAYWRIGHT_FIREFOX_TGZ}" || \
|
||||
! -f "${PLAYWRIGHT_TEST_TGZ}" ]]; then
|
||||
echo 'ERROR: cannot run test with `--no-build` flag! One of the packages is missing!'
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
if [[ "$1" != "--do-not-clean-test-root" && "$2" != "--do-not-clean-test-root" ]]; then
|
||||
clean_test_root
|
||||
fi
|
||||
cd ${TEST_FRAMEWORK_RUN_ROOT}
|
||||
|
||||
cecho "YELLOW" ">>>>>>>>>>>>"
|
||||
cecho "YELLOW" " Running test - '${TEST_FILE}'"
|
||||
cecho "YELLOW" " Workdir - ${PWD}/${TEST_NAME}"
|
||||
cecho "YELLOW" ">>>>>>>>>>>>"
|
||||
mkdir ${TEST_NAME} && cd ${TEST_NAME} && npm init -y 1>/dev/null 2>/dev/null
|
||||
|
||||
cp "${SCRIPTS_PATH}/fixture-scripts/"* .
|
||||
export PATH="${SCRIPTS_PATH}/bin:${PATH}"
|
||||
|
||||
# Start up our local registry and configure npm to use it
|
||||
local-playwright-registry start &
|
||||
TEST_TMP_NPM_SCRATCH_SPACE="${TEST_FRAMEWORK_RUN_ROOT}/${TEST_NAME}--npm-scratch-space"
|
||||
export npm_config_prefix="$TEST_TMP_NPM_SCRATCH_SPACE/npm_prefix"
|
||||
export npm_config_cache="$TEST_TMP_NPM_SCRATCH_SPACE/npm_cache"
|
||||
export npm_config_registry="$(local-playwright-registry wait-for-ready)"
|
||||
export EXPECTED_NODE_MODULES_PARENT="$(pwd -P)"
|
||||
|
||||
# Enable bash lines logging.
|
||||
set -x
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
set +x
|
||||
|
||||
function report_results() {
|
||||
echo
|
||||
if [[ -n "${FAILED_TESTS}" ]]; then
|
||||
cecho "RED" "SOME TESTS FAILED! To debug:"
|
||||
cecho "RED" "${FAILED_TESTS}"
|
||||
exit 1
|
||||
else
|
||||
cecho "GREEN" "All tests passed!"
|
||||
exit 0
|
||||
fi
|
||||
}
|
||||
|
||||
trap "report_results; cd $(pwd -P)" EXIT
|
||||
cd "$(dirname $0)"
|
||||
|
||||
source ./initialize_test.sh
|
||||
|
||||
setup_env_variables
|
||||
echo "Building packages..."
|
||||
build_packages
|
||||
clean_test_root
|
||||
|
||||
function gh_echo {
|
||||
if [[ -z "${GITHUB_ACTIONS}" ]]; then
|
||||
return
|
||||
fi
|
||||
echo "$@"
|
||||
}
|
||||
|
||||
FAILED_TESTS=""
|
||||
|
||||
TOTAL=$(ls -1 test_*.sh | wc -l | tr -d ' ')
|
||||
COUNTER=1
|
||||
for i in test_*.sh
|
||||
do
|
||||
set +e
|
||||
cecho "YELLOW" "Running ${COUNTER}/${TOTAL} - $i..."
|
||||
COUNTER=$(( COUNTER + 1 ))
|
||||
OUTPUT=$(bash $i --multitest --no-build 2>&1)
|
||||
RV=$?
|
||||
set -e
|
||||
if [[ "${RV}" != 0 ]]; then
|
||||
FAILED_TESTS="${FAILED_TESTS}- ${i}\n"
|
||||
|
||||
gh_echo "::group::FAILED - $i"
|
||||
cecho "RED" "FAILED - $i"
|
||||
echo "${OUTPUT}"
|
||||
gh_echo "::endgroup::"
|
||||
else
|
||||
gh_echo "::group::PASSED - $i"
|
||||
cecho "GREEN" "PASSED - $i"
|
||||
gh_echo "${OUTPUT}"
|
||||
gh_echo "::endgroup::"
|
||||
fi
|
||||
done
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
#!/bin/bash
|
||||
source ./initialize_test.sh && initialize_test "$@"
|
||||
|
||||
npm_i playwright-core
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm_i playwright
|
||||
npm i -D typescript@3.8
|
||||
npm i -D @types/node@14
|
||||
echo "import { AndroidDevice, _android, AndroidWebView, Page } from 'playwright';" > "test.ts"
|
||||
|
||||
echo "Running tsc"
|
||||
npx --yes -p typescript@3.7.5 tsc "test.ts"
|
|
@ -1,8 +0,0 @@
|
|||
#!/bin/bash
|
||||
source ./initialize_test.sh && initialize_test "$@"
|
||||
|
||||
npm_i playwright-core
|
||||
node "./download-chromedriver.js" "${PWD}"
|
||||
export PWTEST_CHROMEDRIVER="${PWD}/chromedriver"
|
||||
cd "${PLAYWRIGHT_CHECKOUT}"
|
||||
npm run test -- --reporter=list selenium.spec
|
|
@ -1,12 +0,0 @@
|
|||
#!/bin/bash
|
||||
source ./initialize_test.sh && initialize_test "$@"
|
||||
|
||||
npm_i playwright-core
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm_i playwright
|
||||
npm i electron@12
|
||||
npm i -D typescript@3.8
|
||||
npm i -D @types/node@14
|
||||
echo "import { Page, _electron, ElectronApplication, Electron } from 'playwright';" > "test.ts"
|
||||
|
||||
echo "Running tsc"
|
||||
npx --yes -p typescript@3.7.5 tsc "test.ts"
|
|
@ -1,20 +0,0 @@
|
|||
#!/bin/bash
|
||||
source ./initialize_test.sh && initialize_test "$@"
|
||||
|
||||
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm_i playwright{,-core,-webkit,-firefox,-chromium}
|
||||
# test subshell installation
|
||||
OUTPUT=$(npm_i --foreground-script @playwright/test)
|
||||
|
||||
SCRIPT=$(cat <<EOF
|
||||
const packageJSON = require('./package.json');
|
||||
for (const [entry, value] of Object.entries(packageJSON.dependencies)) {
|
||||
if (!value.startsWith('file:')) {
|
||||
console.log('ERROR: entry ' + entry + ' installed from NPM registry!');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
EOF
|
||||
)
|
||||
# make sure all dependencies are locally installed.
|
||||
node -e "${SCRIPT}"
|
|
@ -1,22 +0,0 @@
|
|||
#!/bin/bash
|
||||
source ./initialize_test.sh && initialize_test "$@"
|
||||
|
||||
echo "Running codegen command without installing"
|
||||
OUTPUT="$(npx_playwright codegen || true)"
|
||||
local-playwright-registry assert-served-from-local-tgz playwright
|
||||
if [[ "${OUTPUT}" != *'Please run the following command to download new browsers'* ]]; then
|
||||
echo "ERROR: should instruct user to download browsers"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${OUTPUT}" == *"chromium"*"downloaded"* ]]; then
|
||||
echo "ERROR: should not download chromium"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${OUTPUT}" == *"webkit"*"downloaded"* ]]; then
|
||||
echo "ERROR: should not download webkit"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${OUTPUT}" == *"firefox"*"downloaded"* ]]; then
|
||||
echo "ERROR: should not download firefox"
|
||||
exit 1
|
||||
fi
|
|
@ -1,22 +0,0 @@
|
|||
#!/bin/bash
|
||||
source ./initialize_test.sh && initialize_test "$@"
|
||||
|
||||
echo "Running global help command without first installing project"
|
||||
OUTPUT="$(npx_playwright --help)"
|
||||
local-playwright-registry assert-served-from-local-tgz playwright
|
||||
if [[ "${OUTPUT}" == *'To avoid unexpected behavior, please install your dependencies first'* ]]; then
|
||||
echo "ERROR: should not warn user about global installation"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${OUTPUT}" == *"chromium"*"downloaded"* ]]; then
|
||||
echo "ERROR: should not download chromium"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${OUTPUT}" == *"webkit"*"downloaded"* ]]; then
|
||||
echo "ERROR: should not download webkit"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${OUTPUT}" == *"firefox"*"downloaded"* ]]; then
|
||||
echo "ERROR: should not download firefox"
|
||||
exit 1
|
||||
fi
|
|
@ -1,26 +0,0 @@
|
|||
#!/bin/bash
|
||||
source ./initialize_test.sh && initialize_test "$@"
|
||||
|
||||
echo "Running install explcitly"
|
||||
OUTPUT="$(npx_playwright install || true)"
|
||||
local-playwright-registry assert-served-from-local-tgz playwright
|
||||
if [[ "${OUTPUT}" == *'Please run the following command to download new browsers'* ]]; then
|
||||
echo "ERROR: should not tell the user to run install"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${OUTPUT}" != *'To avoid unexpected behavior, please install your dependencies first'* ]]; then
|
||||
echo "ERROR: should warn user about global installation"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${OUTPUT}" != *"chromium"*"downloaded"* ]]; then
|
||||
echo "ERROR: should download chromium"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${OUTPUT}" != *"firefox"*"downloaded"* ]]; then
|
||||
echo "ERROR: should download firefox"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${OUTPUT}" != *"webkit"*"downloaded"* ]]; then
|
||||
echo "ERROR: should download webkit"
|
||||
exit 1
|
||||
fi
|
|
@ -1,28 +0,0 @@
|
|||
#!/bin/bash
|
||||
source ./initialize_test.sh && initialize_test "$@"
|
||||
|
||||
npm_i playwright-core
|
||||
OUTPUT=$(npm_i --foreground-script playwright-chromium)
|
||||
if [[ "${OUTPUT}" == *'To avoid unexpected behavior, please install your dependencies first'* ]]; then
|
||||
echo "ERROR: should not warn user about global installation"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${OUTPUT}" != *"chromium"* ]]; then
|
||||
echo "ERROR: should download chromium"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${OUTPUT}" == *"firefox"* ]]; then
|
||||
echo "ERROR: should not download firefox"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${OUTPUT}" == *"webkit"* ]]; then
|
||||
echo "ERROR: should not download webkit"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Running sanity.js"
|
||||
node sanity.js playwright-chromium
|
||||
if [[ ${NODE_VERSION} -ge 14 ]]; then
|
||||
echo "Running esm.js"
|
||||
node esm-playwright-chromium.mjs
|
||||
fi
|
|
@ -1,38 +0,0 @@
|
|||
#!/bin/bash
|
||||
source ./initialize_test.sh && initialize_test "$@"
|
||||
|
||||
npm_i playwright-core
|
||||
npm_i playwright
|
||||
|
||||
echo "Running playwright codegen"
|
||||
OUTPUT=$(PWTEST_CLI_EXIT=1 npx playwright codegen)
|
||||
if [[ "${OUTPUT}" != *"@playwright/test"* ]]; then
|
||||
echo "ERROR: missing @playwright/test in the output"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${OUTPUT}" != *"{ page }"* ]]; then
|
||||
echo "ERROR: missing { page } in the output"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Running playwright codegen --target=javascript"
|
||||
OUTPUT=$(PWTEST_CLI_EXIT=1 npx playwright codegen --target=javascript)
|
||||
if [[ "${OUTPUT}" != *"playwright"* ]]; then
|
||||
echo "ERROR: missing playwright in the output"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${OUTPUT}" != *"page.close"* ]]; then
|
||||
echo "ERROR: missing page.close in the output"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Running playwright codegen --target=python"
|
||||
OUTPUT=$(PWTEST_CLI_EXIT=1 npx playwright codegen --target=python)
|
||||
if [[ "${OUTPUT}" != *"chromium.launch"* ]]; then
|
||||
echo "ERROR: missing chromium.launch in the output"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${OUTPUT}" != *"browser.close"* ]]; then
|
||||
echo "ERROR: missing browser.close in the output"
|
||||
exit 1
|
||||
fi
|
|
@ -1,50 +0,0 @@
|
|||
#!/bin/bash
|
||||
source ./initialize_test.sh && initialize_test "$@"
|
||||
|
||||
npm_i playwright-core
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm_i playwright
|
||||
|
||||
BROWSERS="$(pwd -P)/browsers"
|
||||
|
||||
echo "Running playwright install chromium"
|
||||
OUTPUT=$(PLAYWRIGHT_BROWSERS_PATH=${BROWSERS} npx playwright install chromium)
|
||||
if [[ "${OUTPUT}" != *"chromium"* ]]; then
|
||||
echo "ERROR: should download chromium"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${OUTPUT}" != *"ffmpeg"* ]]; then
|
||||
echo "ERROR: should download ffmpeg"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${OUTPUT}" == *"webkit"* ]]; then
|
||||
echo "ERROR: should not download webkit"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${OUTPUT}" == *"firefox"* ]]; then
|
||||
echo "ERROR: should not download firefox"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Running playwright install"
|
||||
OUTPUT=$(PLAYWRIGHT_BROWSERS_PATH=${BROWSERS} npx playwright install)
|
||||
if [[ "${OUTPUT}" == *"chromium"* ]]; then
|
||||
echo "ERROR: should not download chromium"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${OUTPUT}" == *"ffmpeg"* ]]; then
|
||||
echo "ERROR: should not download ffmpeg"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${OUTPUT}" != *"webkit"* ]]; then
|
||||
echo "ERROR: should download webkit"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${OUTPUT}" != *"firefox"* ]]; then
|
||||
echo "ERROR: should download firefox"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Running sanity.js"
|
||||
node sanity.js playwright none
|
||||
PLAYWRIGHT_BROWSERS_PATH="${BROWSERS}" node sanity.js playwright
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
#!/bin/bash
|
||||
source ./initialize_test.sh && initialize_test "$@"
|
||||
|
||||
npm_i playwright-core
|
||||
npm_i playwright
|
||||
|
||||
echo "Running playwright screenshot"
|
||||
|
||||
node_modules/.bin/playwright screenshot about:blank one.png
|
||||
if [[ ! -f one.png ]]; then
|
||||
echo 'node_modules/.bin/playwright does not work'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
npx playwright screenshot about:blank two.png
|
||||
if [[ ! -f two.png ]]; then
|
||||
echo 'npx playwright does not work'
|
||||
exit 1
|
||||
fi
|
|
@ -1,12 +0,0 @@
|
|||
#!/bin/bash
|
||||
source ./initialize_test.sh && initialize_test "$@"
|
||||
|
||||
npm_i playwright-core
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm_i playwright
|
||||
|
||||
echo "Running playwright install"
|
||||
PLAYWRIGHT_BROWSERS_PATH="0" npx playwright install
|
||||
|
||||
echo "Running driver-client.js"
|
||||
PLAYWRIGHT_BROWSERS_PATH="0" node driver-client.js
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
#!/bin/bash
|
||||
source ./initialize_test.sh && initialize_test "$@"
|
||||
|
||||
npm_i playwright-core
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm_i playwright
|
||||
npm i electron@9.0
|
||||
|
||||
echo "Running sanity-electron.js"
|
||||
node sanity-electron.js
|
|
@ -1,28 +0,0 @@
|
|||
#!/bin/bash
|
||||
source ./initialize_test.sh && initialize_test "$@"
|
||||
|
||||
npm_i playwright-core
|
||||
OUTPUT=$(npm_i --foreground-script playwright-firefox)
|
||||
if [[ "${OUTPUT}" == *'To avoid unexpected behavior, please install your dependencies first'* ]]; then
|
||||
echo "ERROR: should not warn user about global installation"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${OUTPUT}" == *"chromium"* ]]; then
|
||||
echo "ERROR: should not download chromium"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${OUTPUT}" != *"firefox"* ]]; then
|
||||
echo "ERROR: should download firefox"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${OUTPUT}" == *"webkit"* ]]; then
|
||||
echo "ERROR: should not download webkit"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Running sanity.js"
|
||||
node sanity.js playwright-firefox
|
||||
if [[ ${NODE_VERSION} -ge 14 ]]; then
|
||||
echo "Running esm.js"
|
||||
node esm-playwright-firefox.mjs
|
||||
fi
|
|
@ -1,14 +0,0 @@
|
|||
#!/bin/bash
|
||||
source ./initialize_test.sh && initialize_test "$@"
|
||||
|
||||
BROWSERS="$(pwd -P)/browsers"
|
||||
npm_i playwright-core
|
||||
PLAYWRIGHT_BROWSERS_PATH="${BROWSERS}" npm_i playwright
|
||||
if [[ ! -d "${BROWSERS}" ]]; then
|
||||
echo "Directory for shared browsers was not created!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Running sanity.js"
|
||||
node sanity.js playwright none
|
||||
PLAYWRIGHT_BROWSERS_PATH="${BROWSERS}" node sanity.js playwright
|
|
@ -1,20 +0,0 @@
|
|||
#!/bin/bash
|
||||
source ./initialize_test.sh && initialize_test "$@"
|
||||
|
||||
npm_i playwright-core
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm_i playwright-firefox
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm_i playwright-webkit
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm_i playwright-chromium
|
||||
|
||||
BROWSERS="$(pwd -P)/browsers"
|
||||
PLAYWRIGHT_BROWSERS_PATH="${BROWSERS}" npm_i playwright
|
||||
if [[ ! -d "${BROWSERS}" ]]; then
|
||||
echo "Directory for shared browsers was not created!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Running sanity.js"
|
||||
# Every package should be able to launch.
|
||||
PLAYWRIGHT_BROWSERS_PATH="${BROWSERS}" node sanity.js playwright-chromium all
|
||||
PLAYWRIGHT_BROWSERS_PATH="${BROWSERS}" node sanity.js playwright-firefox all
|
||||
PLAYWRIGHT_BROWSERS_PATH="${BROWSERS}" node sanity.js playwright-webkit all
|
|
@ -1,16 +0,0 @@
|
|||
#!/bin/bash
|
||||
source ./initialize_test.sh && initialize_test "$@"
|
||||
|
||||
# @see https://github.com/microsoft/playwright/issues/1651
|
||||
|
||||
BROWSERS="$(pwd -P)/browsers"
|
||||
|
||||
mkdir install-1 && pushd install-1 && npm init -y
|
||||
npm_i playwright-core
|
||||
PLAYWRIGHT_BROWSERS_PATH="${BROWSERS}" npm_i playwright
|
||||
# Note: the `npm install` would not actually crash, the error
|
||||
# is merely logged to the console. To reproduce the error, we should make
|
||||
# sure that script's install.js can be run subsequently without unhandled promise rejections.
|
||||
# Note: the flag `--unahdnled-rejections=strict` will force node to terminate in case
|
||||
# of UnhandledPromiseRejection.
|
||||
PLAYWRIGHT_BROWSERS_PATH="${BROWSERS}" node --unhandled-rejections=strict node_modules/playwright/install.js
|
|
@ -1,31 +0,0 @@
|
|||
#!/bin/bash
|
||||
source ./initialize_test.sh && initialize_test "$@"
|
||||
|
||||
npm_i playwright-core
|
||||
OUTPUT=$(npm_i --foreground-script playwright)
|
||||
if [[ "${OUTPUT}" != *"chromium"* ]]; then
|
||||
echo "ERROR: should download chromium"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${OUTPUT}" != *"firefox"* ]]; then
|
||||
echo "ERROR: should download firefox"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${OUTPUT}" != *"webkit"* ]]; then
|
||||
echo "ERROR: should download webkit"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Running sanity.js"
|
||||
node sanity.js playwright
|
||||
if [[ ${NODE_VERSION} -ge 14 ]]; then
|
||||
echo "Running esm.js"
|
||||
node esm-playwright.mjs
|
||||
fi
|
||||
|
||||
echo "Running playwright test"
|
||||
if npx playwright test -c .; then
|
||||
echo "ERROR: should not be able to run tests with just playwright package"
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
#!/bin/bash
|
||||
source ./initialize_test.sh && initialize_test "$@"
|
||||
|
||||
# Make sure that browsers path is resolved relative to the `npm install` call location.
|
||||
mkdir foo
|
||||
cd foo
|
||||
npm_i playwright-core
|
||||
PLAYWRIGHT_BROWSERS_PATH="../relative" npm_i playwright
|
||||
cd ..
|
||||
|
||||
echo "Running sanity.js"
|
||||
PLAYWRIGHT_BROWSERS_PATH="./relative" node sanity.js playwright
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
#!/bin/bash
|
||||
source ./initialize_test.sh && initialize_test "$@"
|
||||
|
||||
npm_i playwright-core
|
||||
PLAYWRIGHT_BROWSERS_PATH="" HOME=. npm_i playwright
|
||||
echo "Running sanity.js"
|
||||
# Firefox does not work with relative HOME.
|
||||
PLAYWRIGHT_BROWSERS_PATH="" HOME=. node sanity.js playwright chromium webkit
|
|
@ -1,12 +0,0 @@
|
|||
#!/bin/bash
|
||||
source ./initialize_test.sh && initialize_test "$@"
|
||||
|
||||
npm_i playwright-core
|
||||
npm_i playwright
|
||||
|
||||
OUTPUT="$(node validate-dependencies.js)"
|
||||
if [[ "${OUTPUT}" != *"PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS"* ]]; then
|
||||
echo "ERROR: validateDependencies was not called"
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
#!/bin/bash
|
||||
source ./initialize_test.sh && initialize_test "$@"
|
||||
|
||||
npm_i playwright-core
|
||||
npm_i playwright
|
||||
|
||||
OUTPUT="$(node validate-dependencies-skip-executable-path.js)"
|
||||
if [[ "${OUTPUT}" == *"PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS"* ]]; then
|
||||
echo "ERROR: validateDependencies was called"
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
#!/bin/bash
|
||||
source ./initialize_test.sh && initialize_test "$@"
|
||||
|
||||
npm_i playwright-core
|
||||
OUTPUT=$(npm_i --foreground-script playwright-webkit)
|
||||
if [[ "${OUTPUT}" == *'To avoid unexpected behavior, please install your dependencies first'* ]]; then
|
||||
echo "ERROR: should not warn user about global installation"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${OUTPUT}" == *"chromium"* ]]; then
|
||||
echo "ERROR: should not download chromium"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${OUTPUT}" == *"firefox"* ]]; then
|
||||
echo "ERROR: should not download firefox"
|
||||
exit 1
|
||||
fi
|
||||
if [[ "${OUTPUT}" != *"webkit"* ]]; then
|
||||
echo "ERROR: should download webkit"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Running sanity.js"
|
||||
node sanity.js playwright-webkit
|
||||
if [[ ${NODE_VERSION} -ge 14 ]]; then
|
||||
echo "Running esm.js"
|
||||
node esm-playwright-webkit.mjs
|
||||
fi
|
|
@ -1,16 +0,0 @@
|
|||
#!/bin/bash
|
||||
source ./initialize_test.sh && initialize_test "$@"
|
||||
|
||||
BROWSERS="$(pwd -P)/browsers"
|
||||
npm_i playwright-core
|
||||
PLAYWRIGHT_BROWSERS_PATH="${BROWSERS}" npm_i playwright
|
||||
PLAYWRIGHT_BROWSERS_PATH="${BROWSERS}" npm_i playwright-firefox
|
||||
PLAYWRIGHT_BROWSERS_PATH="${BROWSERS}" npm_i playwright-webkit
|
||||
PLAYWRIGHT_BROWSERS_PATH="${BROWSERS}" npm_i playwright-chromium
|
||||
|
||||
echo "Running screencast.js"
|
||||
PLAYWRIGHT_BROWSERS_PATH="${BROWSERS}" node screencast.js playwright
|
||||
PLAYWRIGHT_BROWSERS_PATH="${BROWSERS}" node screencast.js playwright-chromium
|
||||
PLAYWRIGHT_BROWSERS_PATH="${BROWSERS}" node screencast.js playwright-webkit
|
||||
PLAYWRIGHT_BROWSERS_PATH="${BROWSERS}" node screencast.js playwright-firefox
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
#!/bin/bash
|
||||
source ./initialize_test.sh && initialize_test "$@"
|
||||
|
||||
npm_i playwright-core
|
||||
OUTPUT=$(PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm_i --foreground-script playwright)
|
||||
if [[ "${OUTPUT}" != *"Skipping browsers download because"* ]]; then
|
||||
echo "missing log message that browsers download is skipped"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -d ./node_modules/playwright/.local-browsers ]]; then
|
||||
echo "local browsers folder should be empty"
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
#!/bin/bash
|
||||
source ./initialize_test.sh && initialize_test "$@"
|
||||
|
||||
npm_i playwright-core
|
||||
OUTPUT=$(PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm_i --foreground-script playwright)
|
||||
if [[ "${OUTPUT}" != *"Skipping browsers download because"* ]]; then
|
||||
echo "missing log message that browsers download is skipped"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$(uname)" != "Linux" ]]; then
|
||||
echo
|
||||
echo "Skipping test on non-Linux platform"
|
||||
echo
|
||||
return
|
||||
fi
|
||||
|
||||
OUTPUT=$(PWDEBUG=1 node inspector-custom-executable.js)
|
||||
if [[ "${OUTPUT}" != *"SUCCESS"* ]]; then
|
||||
echo "missing log message that launch succeeded: ${OUTPUT}"
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
#!/bin/bash
|
||||
source ./initialize_test.sh && initialize_test "$@"
|
||||
|
||||
# @types/node@14.18.9 is the last version which is compatibel with typescript@3.7.5.
|
||||
# After @types/node@14.18.9 URLSearchParams from @types/node conflicts with typescript's
|
||||
# shipped types and it results in a type error / build failure.
|
||||
npm i -D @types/node@14.18.9
|
||||
|
||||
# install all packages.
|
||||
npm_i playwright-core
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm_i playwright
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm_i playwright-firefox
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm_i playwright-webkit
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm_i playwright-chromium
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm_i @playwright/test
|
||||
|
||||
# typecheck all packages.
|
||||
for PKG_NAME in "playwright" \
|
||||
"playwright-core" \
|
||||
"playwright-firefox" \
|
||||
"playwright-chromium" \
|
||||
"playwright-webkit"
|
||||
do
|
||||
echo "Checking types of ${PKG_NAME}"
|
||||
echo "import { Page } from '${PKG_NAME}';" > "${PKG_NAME}.ts" && npx --yes -p typescript@3.7.5 tsc "${PKG_NAME}.ts"
|
||||
done;
|
||||
|
||||
echo "Checking types of @playwright/test"
|
||||
echo npx --yes -p typescript@3.7.5 tsc "playwright-test-types.ts"
|
|
@ -18,6 +18,7 @@
|
|||
"wtest": "playwright test --config=tests/library/playwright.config.ts --project=webkit",
|
||||
"atest": "playwright test --config=tests/android/playwright.config.ts",
|
||||
"etest": "playwright test --config=tests/electron/playwright.config.ts",
|
||||
"itest": "playwright test --config=tests/installation/playwright.config.ts",
|
||||
"test-html-reporter": "playwright test --config=packages/html-reporter",
|
||||
"test-web": "playwright test --config=packages/web",
|
||||
"ttest": "node ./tests/playwright-test/stable-test-runner/node_modules/@playwright/test/cli test --config=tests/playwright-test/playwright.config.ts",
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { test } from './npmTest';
|
||||
|
||||
test('android types', async ({ exec, tsc, writeFiles }) => {
|
||||
await exec('npm i --foreground-scripts playwright', { env: { PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1' } });
|
||||
await writeFiles({
|
||||
'test.ts':
|
||||
`import { AndroidDevice, _android, AndroidWebView, Page } from 'playwright';`,
|
||||
});
|
||||
await tsc('test.ts');
|
||||
});
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import path from 'path';
|
||||
import { test } from './npmTest';
|
||||
|
||||
test('connect to selenium', async ({ exec, tmpWorkspace }, testInfo) => {
|
||||
await exec('npm i --foreground-scripts playwright-core');
|
||||
await exec(`node ./download-chromedriver.js ${path.join(tmpWorkspace)}`);
|
||||
await exec(`npm run test -- --reporter=list selenium.spec --output=${testInfo.outputPath('tmp-test-results')}`, { cwd: path.join(__dirname, '..', '..'), env: { PWTEST_CHROMEDRIVER: path.join(tmpWorkspace, 'chromedriver') } });
|
||||
});
|
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { test } from './npmTest';
|
||||
|
||||
test('driver should work', async ({ exec }) => {
|
||||
await exec('npm i --foreground-scripts playwright', { env: { PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1' } });
|
||||
await exec('npx playwright install');
|
||||
await exec('node driver-client.js');
|
||||
});
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { test } from './npmTest';
|
||||
|
||||
test('electron types', async ({ exec, tsc, writeFiles }) => {
|
||||
await exec('npm i --foreground-scripts playwright electron@12', { env: { PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1' } });
|
||||
await writeFiles({
|
||||
'test.ts':
|
||||
`import { Page, _electron, ElectronApplication, Electron } from 'playwright';`
|
||||
});
|
||||
await tsc('test.ts');
|
||||
});
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export {}
|
||||
|
||||
declare global {
|
||||
namespace PlaywrightTest {
|
||||
interface Matchers<R, T> {
|
||||
toHaveLoggedSoftwareDownload(browsers: ("chromium" | "firefox" | "webkit" | "ffmpeg")[]): R;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import path from 'path';
|
||||
import { spawnAsync } from 'playwright-core/lib/utils/spawnAsync';
|
||||
import { rimraf } from 'playwright-core/lib/utilsBundle';
|
||||
import { promisify } from 'util';
|
||||
import fs from 'fs';
|
||||
|
||||
const PACKAGE_BUILDER_SCRIPT = path.join(__dirname, '..', '..', 'utils', 'pack_package.js');
|
||||
const TMP_WORKSPACE = '/tmp/pwt/workspaces';
|
||||
|
||||
async function globalSetup() {
|
||||
await promisify(rimraf)(TMP_WORKSPACE);
|
||||
console.log(`Temporary workspaces will be created in ${TMP_WORKSPACE}. They will not be removed at the end. Set DEBUG=itest to determine which sub-dir a specific test is using.`);
|
||||
await fs.promises.mkdir(TMP_WORKSPACE, { recursive: true });
|
||||
if (process.env.PWTEST_INSTALLATION_TEST_SKIP_PACKAGE_BUILDS) {
|
||||
console.log('Skipped building packages. Unset PWTEST_INSTALLATION_TEST_SKIP_PACKAGE_BUILDS to build packages.');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Building packages. Set PWTEST_INSTALLATION_TEST_SKIP_PACKAGE_BUILDS to skip.');
|
||||
const outputDir = path.join(__dirname, 'output');
|
||||
await promisify(rimraf)(outputDir);
|
||||
await fs.promises.mkdir(outputDir, { recursive: true });
|
||||
|
||||
const build = async (buildTarget: string, pkgNameOverride?: string) => {
|
||||
const outPath = path.resolve(path.join(outputDir, `${buildTarget}.tgz`));
|
||||
const { code, stderr, stdout } = await spawnAsync('node', [PACKAGE_BUILDER_SCRIPT, buildTarget, outPath]);
|
||||
if (!!code)
|
||||
throw new Error(`Failed to build: ${buildTarget}:\n${stderr}\n${stdout}`);
|
||||
console.log('Built:', pkgNameOverride || buildTarget);
|
||||
return [pkgNameOverride || buildTarget, outPath];
|
||||
};
|
||||
|
||||
const builds = await Promise.all([
|
||||
build('playwright-core'),
|
||||
build('playwright-test', '@playwright/test'),
|
||||
build('playwright'),
|
||||
build('playwright-chromium'),
|
||||
build('playwright-firefox'),
|
||||
build('playwright-webkit'),
|
||||
]);
|
||||
|
||||
await fs.promises.writeFile(path.join(__dirname, './.registry.json'), JSON.stringify(Object.fromEntries(builds)));
|
||||
}
|
||||
|
||||
export default globalSetup;
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import path from 'path';
|
||||
import { test, expect } from './npmTest';
|
||||
import fs from 'fs';
|
||||
|
||||
test('installs local packages', async ({ registry, exec, tmpWorkspace }) => {
|
||||
const packages = ['playwright', 'playwright-core', 'playwright-chromium', 'playwright-firefox', 'playwright-webkit', '@playwright/test'];
|
||||
await exec('npm i --foreground-scripts', ...packages, { env: { PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1' } });
|
||||
|
||||
const output = await exec('node', path.join(__dirname, '..', '..', 'utils', 'workspace.js'), '--get-version');
|
||||
const expectedPlaywrightVersion = output.trim();
|
||||
for (const pkg of packages) {
|
||||
await test.step(`check version and installation location of ${pkg}`, async () => {
|
||||
registry.assertLocalPackage(pkg);
|
||||
const result = await exec('node', `--eval='console.log(JSON.stringify(require.resolve("${pkg}")))'`);
|
||||
const pkgJsonPath = path.join(path.dirname(JSON.parse(result)), 'package.json');
|
||||
expect(pkgJsonPath.startsWith(path.join(tmpWorkspace, 'node_modules'))).toBeTruthy();
|
||||
const installedVersion = JSON.parse(await fs.promises.readFile(pkgJsonPath, 'utf8')).version;
|
||||
expect(installedVersion).toBe(expectedPlaywrightVersion);
|
||||
});
|
||||
}
|
||||
});
|
|
@ -0,0 +1,172 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line spaced-comment
|
||||
/// <reference path="./expect.d.ts" />
|
||||
|
||||
import { test as _test, expect as _expect } from '@playwright/test';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import debugLogger from 'debug';
|
||||
import { Registry } from './registry';
|
||||
import { spawnAsync } from './spawnAsync';
|
||||
|
||||
const debug = debugLogger('itest');
|
||||
|
||||
/**
|
||||
* A minimal NPM Registry Server that can serve local packages, or proxy to the upstream registry.
|
||||
* This is useful in test installation behavior of packages that aren't yet published. It's particularly helpful
|
||||
* when your installation requires transitive dependencies that are also not yet published.
|
||||
*
|
||||
* See https://github.com/npm/registry/blob/master/docs/REGISTRY-API.md for information on the offical APIs.
|
||||
*/
|
||||
|
||||
_expect.extend({
|
||||
toHaveLoggedSoftwareDownload(received: any, browsers: ('chromium' | 'firefox' | 'webkit' | 'ffmpeg')[]) {
|
||||
if (typeof received !== 'string')
|
||||
throw new Error(`Expected argument to be a string.`);
|
||||
|
||||
const downloaded = new Set();
|
||||
for (const [, browser] of received.matchAll(/^.*(chromium|firefox|webkit|ffmpeg) v\d+ downloaded.*$/img))
|
||||
downloaded.add(browser);
|
||||
|
||||
const expected = browsers;
|
||||
if (expected.length === downloaded.size && expected.every(browser => downloaded.has(browser)))
|
||||
return { pass: true };
|
||||
return {
|
||||
pass: false,
|
||||
message: () => [
|
||||
`Browser download expectation failed!`,
|
||||
` expected: ${[...expected].sort().join(', ')}`,
|
||||
` actual: ${[...downloaded].sort().join(', ')}`,
|
||||
].join('\n'),
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
const expect = _expect;
|
||||
|
||||
export type ExecOptions = { cwd?: string, env?: Record<string, string>, message?: string, expectToExitWithError?: boolean };
|
||||
export type ArgsOrOptions = [] | [...string[]] | [...string[], ExecOptions] | [ExecOptions];
|
||||
export const test = _test.extend<{
|
||||
_autoCopyScripts: void,
|
||||
tmpWorkspace: string,
|
||||
nodeMajorVersion: number,
|
||||
installedSoftwareOnDisk: (registryPath?: string) => Promise<string[]>;
|
||||
writeFiles: (nameToContents: Record<string, string>) => Promise<void>,
|
||||
exec: (cmd: string, ...argsAndOrOptions: ArgsOrOptions) => Promise<string>
|
||||
tsc: (...argsAndOrOptions: ArgsOrOptions) => Promise<string>,
|
||||
registry: Registry,
|
||||
}>({
|
||||
_autoCopyScripts: [async ({ tmpWorkspace }, use) => {
|
||||
const dstDir = path.join(tmpWorkspace);
|
||||
const sourceDir = path.join(__dirname, 'fixture-scripts');
|
||||
const contents = await fs.promises.readdir(sourceDir);
|
||||
await Promise.all(contents.map(f => fs.promises.copyFile(path.join(sourceDir, f), path.join(dstDir, f))));
|
||||
await use();
|
||||
}, {
|
||||
auto: true,
|
||||
}],
|
||||
nodeMajorVersion: async ({}, use) => {
|
||||
await use(+process.versions.node.split('.')[0]);
|
||||
},
|
||||
writeFiles: async ({ tmpWorkspace }, use) => {
|
||||
await use(async (nameToContents: Record<string, string>) => {
|
||||
for (const [name, contents] of Object.entries(nameToContents))
|
||||
await fs.promises.writeFile(path.join(tmpWorkspace, name), contents);
|
||||
});
|
||||
},
|
||||
tmpWorkspace: async ({}, use) => {
|
||||
// We want a location that won't have a node_modules dir anywhere along its path
|
||||
const tmpWorkspace = path.join('/tmp/pwt/workspaces', path.basename(test.info().outputDir));
|
||||
await fs.promises.mkdir(tmpWorkspace);
|
||||
debug(`Workspace Folder: ${tmpWorkspace}`);
|
||||
await spawnAsync('npm', ['init', '-y'], {
|
||||
cwd: tmpWorkspace,
|
||||
});
|
||||
|
||||
await use(tmpWorkspace);
|
||||
},
|
||||
registry: async ({}, use, testInfo) => {
|
||||
const port = testInfo.workerIndex + 16123;
|
||||
const url = `http://127.0.0.1:${port}`;
|
||||
const registry = new Registry(testInfo.outputPath('registry'), url);
|
||||
await registry.start(JSON.parse((await fs.promises.readFile(path.join(__dirname, './.registry.json'), 'utf8'))));
|
||||
await use(registry);
|
||||
await registry.shutdown();
|
||||
},
|
||||
installedSoftwareOnDisk: async ({ tmpWorkspace }, use) => {
|
||||
await use(async (registryPath?: string) => fs.promises.readdir(registryPath || path.join(tmpWorkspace, 'browsers')).catch(() => []).then(files => files.map(f => f.split('-')[0]).filter(f => !f.startsWith('.'))));
|
||||
},
|
||||
exec: async ({ registry, tmpWorkspace }, use, testInfo) => {
|
||||
await use(async (cmd: string, ...argsAndOrOptions: [] | [...string[]] | [...string[], ExecOptions] | [ExecOptions]) => {
|
||||
let args: string[] = [];
|
||||
let options: ExecOptions = {};
|
||||
if (typeof argsAndOrOptions[argsAndOrOptions.length - 1] === 'object')
|
||||
options = argsAndOrOptions.pop() as ExecOptions;
|
||||
|
||||
args = argsAndOrOptions as string[];
|
||||
|
||||
let result!: Awaited<ReturnType<typeof spawnAsync>>;
|
||||
await test.step(`exec: ${[cmd, ...args].join(' ')}`, async () => {
|
||||
result = await spawnAsync(cmd, args, {
|
||||
shell: true,
|
||||
cwd: options.cwd ?? tmpWorkspace,
|
||||
// NB: We end up running npm-in-npm, so it's important that we do NOT forward process.env and instead cherry-pick environment variables.
|
||||
env: {
|
||||
'PATH': process.env.PATH,
|
||||
'DISPLAY': process.env.DISPLAY,
|
||||
'XAUTHORITY': process.env.XAUTHORITY,
|
||||
'PLAYWRIGHT_BROWSERS_PATH': path.join(tmpWorkspace, 'browsers'),
|
||||
'npm_config_cache': testInfo.outputPath('npm_cache'),
|
||||
'npm_config_registry': registry.url(),
|
||||
'npm_config_prefix': testInfo.outputPath('npm_global'),
|
||||
...options.env,
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const stdio = `${result.stdout}\n${result.stderr}`;
|
||||
|
||||
await testInfo.attach(`${[cmd, ...args].join(' ')}`, { body: `COMMAND: ${[cmd, ...args].join(' ')}\n\nEXIT CODE: ${result.code}\n\n====== STDIO + STDERR ======\n\n${stdio}` });
|
||||
|
||||
// This means something is really off with spawn
|
||||
if (result.error)
|
||||
throw result.error;
|
||||
|
||||
// User expects command to fail
|
||||
if (options.expectToExitWithError) {
|
||||
if (result.code === 0) {
|
||||
const message = options.message ? ` Message: ${options.message}` : '';
|
||||
throw new Error(`Expected the command to exit with an error, but exited cleanly.${message}`);
|
||||
}
|
||||
} else if (result.code !== 0) {
|
||||
const message = options.message ? ` Message: ${options.message}` : '';
|
||||
throw new Error(`Expected the command to exit cleanly (0 status code), but exited with ${result.code}.${message}`);
|
||||
}
|
||||
|
||||
return stdio;
|
||||
|
||||
});
|
||||
},
|
||||
tsc: async ({ exec }, use) => {
|
||||
await exec('npm i --foreground-scripts typescript@3.8 @types/node@14');
|
||||
await use((...args: ArgsOrOptions) => exec('npx', '-p', 'typescript@3.8', 'tsc', ...args));
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
export { expect };
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { test, expect } from './npmTest';
|
||||
|
||||
test('npx playwright --help should not download browsers', async ({ exec, installedSoftwareOnDisk }) => {
|
||||
const result = await exec('npx playwright --help');
|
||||
expect(result).toHaveLoggedSoftwareDownload([]);
|
||||
expect(await installedSoftwareOnDisk()).toEqual([]);
|
||||
expect(result).not.toContain(`To avoid unexpected behavior, please install your dependencies first`);
|
||||
});
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { test, expect } from './npmTest';
|
||||
|
||||
test('npx playwright install global', async ({ exec, installedSoftwareOnDisk }) => {
|
||||
const result = await exec('npx playwright install');
|
||||
expect(result).toHaveLoggedSoftwareDownload(['chromium', 'ffmpeg', 'firefox', 'webkit']);
|
||||
expect(await installedSoftwareOnDisk()).toEqual(['chromium', 'ffmpeg', 'firefox', 'webkit']);
|
||||
expect(result).not.toContain(`Please run the following command to download new browsers`);
|
||||
expect(result).toContain(`To avoid unexpected behavior, please install your dependencies first`);
|
||||
});
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { test, expect } from './npmTest';
|
||||
|
||||
test('npx playwright codegen', async ({ exec, installedSoftwareOnDisk }) => {
|
||||
const stdio = await exec('npx playwright codegen', { expectToExitWithError: true });
|
||||
expect(stdio).toHaveLoggedSoftwareDownload([]);
|
||||
expect(await installedSoftwareOnDisk()).toEqual([]);
|
||||
expect(stdio).toContain(`Please run the following command to download new browsers`);
|
||||
});
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { test, expect } from './npmTest';
|
||||
|
||||
test('codegen should work', async ({ exec }) => {
|
||||
await exec('npm i --foreground-scripts playwright');
|
||||
|
||||
await test.step('codegen without arguments', async () => {
|
||||
const result = await exec('npx playwright codegen', { env: { PWTEST_CLI_EXIT: '1' } });
|
||||
expect(result).toContain(`@playwright/test`);
|
||||
expect(result).toContain(`{ page }`);
|
||||
});
|
||||
|
||||
await test.step('codegen --target=javascript', async () => {
|
||||
const result = await exec('npx playwright codegen --target=javascript', { env: { PWTEST_CLI_EXIT: '1' } });
|
||||
expect(result).toContain(`playwright`);
|
||||
expect(result).toContain(`page.close`);
|
||||
});
|
||||
|
||||
await test.step('codegen --target=python', async () => {
|
||||
const result = await exec('npx playwright codegen --target=python', { env: { PWTEST_CLI_EXIT: '1' } });
|
||||
expect(result).toContain(`chromium.launch`);
|
||||
expect(result).toContain(`browser.close`);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { test, expect } from './npmTest';
|
||||
|
||||
test('codegen should work', async ({ exec, installedSoftwareOnDisk }) => {
|
||||
await exec('npm i --foreground-scripts playwright', { env: { PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1' } });
|
||||
|
||||
await test.step('playwright install chromium', async () => {
|
||||
const result = await exec('npx playwright install chromium');
|
||||
expect(result).toHaveLoggedSoftwareDownload(['chromium', 'ffmpeg']);
|
||||
expect(await installedSoftwareOnDisk()).toEqual(['chromium', 'ffmpeg']);
|
||||
});
|
||||
|
||||
await test.step('playwright install', async () => {
|
||||
const result = await exec('npx playwright install');
|
||||
expect(result).toHaveLoggedSoftwareDownload(['firefox', 'webkit']);
|
||||
expect(await installedSoftwareOnDisk()).toEqual(['chromium', 'ffmpeg', 'firefox', 'webkit']);
|
||||
});
|
||||
|
||||
await exec('node sanity.js playwright none', { env: { PLAYWRIGHT_BROWSERS_PATH: undefined } });
|
||||
await exec('node sanity.js playwright');
|
||||
});
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { test } from './npmTest';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
test('playwright cli screenshot should work', async ({ exec, tmpWorkspace }) => {
|
||||
await exec('npm i --foreground-scripts playwright');
|
||||
await exec('./node_modules/.bin/playwright screenshot about:blank one.png');
|
||||
await fs.promises.stat(path.join(tmpWorkspace, 'one.png'));
|
||||
|
||||
await exec('npx playwright screenshot about:blank two.png');
|
||||
await fs.promises.stat(path.join(tmpWorkspace, 'two.png'));
|
||||
});
|
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { test } from './npmTest';
|
||||
|
||||
test('electron should work', async ({ exec }) => {
|
||||
await exec('npm i --foreground-scripts playwright electron@9.0', { env: { PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1' } });
|
||||
await exec('node sanity-electron.js');
|
||||
});
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { test, expect } from './npmTest';
|
||||
|
||||
test('global installation cross package', async ({ exec, installedSoftwareOnDisk }) => {
|
||||
const packages = ['playwright-chromium', 'playwright-firefox', 'playwright-webkit'];
|
||||
for (const pkg of packages)
|
||||
await exec('npm i --foreground-scripts', pkg, { env: { PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1' } });
|
||||
const result = await exec('npm i --foreground-scripts playwright');
|
||||
expect(result).toHaveLoggedSoftwareDownload(['chromium', 'ffmpeg', 'firefox', 'webkit']);
|
||||
expect(await installedSoftwareOnDisk()).toEqual(['chromium', 'ffmpeg', 'firefox', 'webkit']);
|
||||
|
||||
for (const pkg of packages)
|
||||
await test.step(pkg, () => exec('node ./sanity.js', pkg, 'all'));
|
||||
});
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { test, expect } from './npmTest';
|
||||
|
||||
test('global installation', async ({ exec, installedSoftwareOnDisk }) => {
|
||||
const result = await exec('npm i --foreground-scripts playwright');
|
||||
expect(result).toHaveLoggedSoftwareDownload(['chromium', 'ffmpeg', 'firefox', 'webkit']);
|
||||
expect(await installedSoftwareOnDisk()).toEqual(['chromium', 'ffmpeg', 'firefox', 'webkit']);
|
||||
await exec('node sanity.js playwright none', { env: { PLAYWRIGHT_BROWSERS_PATH: undefined } });
|
||||
await exec('node ./sanity.js playwright');
|
||||
});
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { test } from './npmTest';
|
||||
import path from 'path';
|
||||
|
||||
test('subsequent installs works', async ({ exec }) => {
|
||||
test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/1651' });
|
||||
await exec('npm i --foreground-scripts playwright');
|
||||
// Note: the `npm install` would not actually crash, the error
|
||||
// is merely logged to the console. To reproduce the error, we should make
|
||||
// sure that script's install.js can be run subsequently without unhandled promise rejections.
|
||||
// Note: the flag `--unhandled-rejections=strict` will force node to terminate in case
|
||||
// of UnhandledPromiseRejection.
|
||||
await exec('node --unhandled-rejections=strict', path.join('./node_modules', 'playwright', 'install.js'));
|
||||
});
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { test } from './npmTest';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
test('playwright should work with relative home path', async ({ exec, tmpWorkspace }) => {
|
||||
await fs.promises.mkdir(path.join(tmpWorkspace, 'foo'));
|
||||
// Make sure that browsers path is resolved relative to the `npm install` call location.
|
||||
await exec('npm i --foreground-scripts playwright', { cwd: path.join(tmpWorkspace, 'foo'), env: { PLAYWRIGHT_BROWSERS_PATH: '../relative' } });
|
||||
await exec('node sanity.js playwright', { env: { PLAYWRIGHT_BROWSERS_PATH: './relative' } });
|
||||
});
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { test } from './npmTest';
|
||||
|
||||
test('playwright should work with relative home path', async ({ exec }) => {
|
||||
const env = { PLAYWRIGHT_BROWSERS_PATH: '0', HOME: '.' };
|
||||
await exec('npm i --foreground-scripts playwright', { env });
|
||||
// Firefox does not work with relative HOME.
|
||||
await exec('node sanity.js playwright chromium webkit', { env });
|
||||
});
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { test, expect } from './npmTest';
|
||||
|
||||
test(`playwright should work`, async ({ exec, nodeMajorVersion, installedSoftwareOnDisk }) => {
|
||||
const result = await exec('npm i --foreground-scripts playwright');
|
||||
expect(result).toHaveLoggedSoftwareDownload(['chromium', 'ffmpeg', 'firefox', 'webkit']);
|
||||
expect(await installedSoftwareOnDisk()).toEqual(['chromium', 'ffmpeg', 'firefox', 'webkit']);
|
||||
await exec('node ./sanity.js playwright');
|
||||
if (nodeMajorVersion >= 14)
|
||||
await exec('node esm-playwright.mjs');
|
||||
const stdio = await exec('npx playwright', 'test', '-c', '.', { expectToExitWithError: true });
|
||||
expect(stdio).toContain(`Please install @playwright/test package to use Playwright Test.`);
|
||||
});
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { test } from './npmTest';
|
||||
|
||||
test('@playwright/test should work', async ({ exec, nodeMajorVersion }) => {
|
||||
await exec('npm i --foreground-scripts @playwright/test');
|
||||
await exec('npx playwright test -c .', { expectToExitWithError: true, message: 'should not be able to run tests without installing browsers' });
|
||||
|
||||
await exec('npx playwright install');
|
||||
await exec('npx playwright test -c . --browser=all --reporter=list,json sample.spec.js', { env: { PLAYWRIGHT_JSON_OUTPUT_NAME: 'report.json' } });
|
||||
await exec('node ./read-json-report.js ./report.json');
|
||||
await exec('node sanity.js @playwright/test');
|
||||
if (nodeMajorVersion >= 14)
|
||||
await exec('node', 'esm-playwright-test.mjs');
|
||||
});
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { test, expect } from './npmTest';
|
||||
|
||||
test('@playwright/test stacks should work', async ({ exec }) => {
|
||||
await exec('npm i --foreground-scripts @playwright/test');
|
||||
await exec('npx playwright install chromium');
|
||||
const output = await exec('npx playwright test -c . failing.spec.js', { expectToExitWithError: true, env: { DEBUG: 'pw:api' } });
|
||||
expect(output).toContain('expect.toHaveText started');
|
||||
expect(output).toContain('failing.spec.js:5:38');
|
||||
});
|
|
@ -0,0 +1,33 @@
|
|||
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { test, expect } from './npmTest';
|
||||
|
||||
for (const pkg of ['playwright-chromium', 'playwright-firefox', 'playwright-webkit']) {
|
||||
test(`${pkg} should work`, async ({ exec, nodeMajorVersion, installedSoftwareOnDisk }) => {
|
||||
const result = await exec('npm i --foreground-scripts', pkg);
|
||||
const browserName = pkg.split('-')[1];
|
||||
const expectedSoftware = [browserName];
|
||||
if (browserName === 'chromium')
|
||||
expectedSoftware.push('ffmpeg');
|
||||
expect(result).toHaveLoggedSoftwareDownload(expectedSoftware as any);
|
||||
expect(await installedSoftwareOnDisk()).toEqual(expectedSoftware);
|
||||
expect(result).not.toContain(`To avoid unexpected behavior, please install your dependencies first`);
|
||||
await exec('node ./sanity.js', pkg);
|
||||
if (nodeMajorVersion >= 14)
|
||||
await exec('node', `esm-${pkg}.mjs`);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import path from 'path';
|
||||
import type { PlaywrightTestConfig } from '@playwright/test';
|
||||
import { config as loadEnv } from 'dotenv';
|
||||
loadEnv({ path: path.join(__dirname, '..', '..', '.env') });
|
||||
|
||||
const config: PlaywrightTestConfig = {
|
||||
testIgnore: '**\/fixture-scripts/**',
|
||||
globalSetup: path.join(__dirname, 'globalSetup'),
|
||||
timeout: 5 * 60 * 1000,
|
||||
retries: 0,
|
||||
reporter: process.env.CI ? 'dot' : [['list'], ['html', { open: 'on-failure' }]],
|
||||
forbidOnly: !!process.env.CI,
|
||||
workers: 1,
|
||||
};
|
||||
|
||||
export default config;
|
|
@ -0,0 +1,184 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import crypto from 'crypto';
|
||||
import fs from 'fs';
|
||||
import type { Server } from 'http';
|
||||
import http from 'http';
|
||||
import https from 'https';
|
||||
import path from 'path';
|
||||
import { spawnAsync } from './spawnAsync';
|
||||
|
||||
const kPublicNpmRegistry = 'https://registry.npmjs.org';
|
||||
const kContentTypeAbbreviatedMetadata = 'application/vnd.npm.install-v1+json';
|
||||
|
||||
export class Registry {
|
||||
private _workDir: string;
|
||||
private _url: string;
|
||||
private _objectsDir: string;
|
||||
private _packageMeta: Map<string, [any, string]> = new Map();
|
||||
private _log: { pkg: string, status: 'PROXIED' | 'LOCAL', type?: 'tar' | 'metadata' }[] = [];
|
||||
private _server: Server;
|
||||
|
||||
constructor(workDir: string, url: string) {
|
||||
this._workDir = workDir;
|
||||
this._objectsDir = path.join(this._workDir);
|
||||
this._url = url;
|
||||
}
|
||||
|
||||
url() { return this._url; }
|
||||
|
||||
async shutdown() {
|
||||
return new Promise<void>((res, rej) => this._server.close(err => err ? rej(err) : res()));
|
||||
}
|
||||
|
||||
async start(packages: { [pkg: string]: string }) {
|
||||
await fs.promises.mkdir(this._workDir, { recursive: true });
|
||||
await fs.promises.mkdir(this._objectsDir, { recursive: true });
|
||||
|
||||
await Promise.all(Object.entries(packages).map(([pkg, tar]) => this._addPackage(pkg, tar)));
|
||||
|
||||
this._server = http.createServer(async (req, res) => {
|
||||
// 1. Only support GET requests
|
||||
if (req.method !== 'GET')
|
||||
return res.writeHead(405).end();
|
||||
|
||||
// 2. Determine what package is being asked for.
|
||||
// The paths we can handle look like:
|
||||
// - /<userSuppliedPackageName>/*/<userSuppliedTarName i.e. some *.tgz>
|
||||
// - /<userSuppliedPackageName>/*
|
||||
// - /<userSuppliedPackageName>
|
||||
const url = new URL(req.url, kPublicNpmRegistry);
|
||||
let [/* empty */, userSuppliedPackageName, /* empty */, userSuppliedTarName] = url.pathname.split('/');
|
||||
if (userSuppliedPackageName)
|
||||
userSuppliedPackageName = decodeURIComponent(userSuppliedPackageName);
|
||||
if (userSuppliedTarName)
|
||||
userSuppliedTarName = decodeURIComponent(userSuppliedTarName);
|
||||
|
||||
// 3. If we have local metadata, serve directly (otherwise, proxy to upstream).
|
||||
if (this._packageMeta.has(userSuppliedPackageName)) {
|
||||
const [metadata, objectPath] = this._packageMeta.get(userSuppliedPackageName);
|
||||
if (userSuppliedTarName) { // Tarball request.
|
||||
if (path.basename(objectPath) !== userSuppliedTarName) {
|
||||
res.writeHead(404).end();
|
||||
return;
|
||||
}
|
||||
this._logAccess({ status: 'LOCAL', type: 'tar', pkg: userSuppliedPackageName });
|
||||
const fileStream = fs.createReadStream(objectPath);
|
||||
fileStream.pipe(res, { end: true });
|
||||
fileStream.on('error', console.log);
|
||||
res.on('error', console.log);
|
||||
return;
|
||||
} else { // Metadata request.
|
||||
this._logAccess({ status: 'LOCAL', type: 'metadata', pkg: userSuppliedPackageName });
|
||||
res.setHeader('content-type', kContentTypeAbbreviatedMetadata);
|
||||
res.write(JSON.stringify(metadata, null, ' '));
|
||||
res.end();
|
||||
}
|
||||
} else { // Fall through to official registry
|
||||
this._logAccess({ status: 'PROXIED', pkg: userSuppliedPackageName });
|
||||
const client = { req, res };
|
||||
const toNpm = https.request({
|
||||
host: url.host,
|
||||
headers: { ...req.headers, 'host': url.host },
|
||||
method: req.method,
|
||||
path: url.pathname,
|
||||
searchParams: url.searchParams,
|
||||
protocol: 'https:',
|
||||
}, fromNpm => {
|
||||
client.res.writeHead(fromNpm.statusCode, fromNpm.statusMessage, fromNpm.headers);
|
||||
fromNpm.on('error', err => console.log(`error: `, err));
|
||||
fromNpm.pipe(client.res, { end: true });
|
||||
});
|
||||
client.req.pipe(toNpm);
|
||||
client.req.on('error', err => console.log(`error: `, err));
|
||||
}
|
||||
});
|
||||
|
||||
this._server.listen(Number.parseInt(new URL(this._url).port, 10), 'localhost');
|
||||
await new Promise<void>((res, rej) => {
|
||||
this._server.on('listening', () => res());
|
||||
this._server.on('error', rej);
|
||||
});
|
||||
}
|
||||
|
||||
public assertLocalPackage(pkg) {
|
||||
const summary = this._log.reduce((acc, f) => {
|
||||
if (f.pkg === pkg) {
|
||||
acc.local = f.status === 'LOCAL' || acc.local;
|
||||
acc.proxied = f.status === 'PROXIED' || acc.proxied;
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, { local: false, proxied: false });
|
||||
|
||||
if (summary.local && !summary.proxied)
|
||||
return;
|
||||
|
||||
throw new Error(`${pkg} was not accessed strictly locally: local: ${summary.local}, proxied: ${summary.proxied}`);
|
||||
}
|
||||
|
||||
private async _addPackage(pkg: string, tarPath: string) {
|
||||
const tmpDir = await fs.promises.mkdtemp(path.join(this._workDir, '.staging-package-'));
|
||||
const { stderr, code } = await spawnAsync('tar', ['-xvzf', tarPath, '-C', tmpDir]);
|
||||
if (!!code)
|
||||
throw new Error(`Failed to untar ${pkg}: ${stderr}`);
|
||||
|
||||
const packageJson = JSON.parse((await fs.promises.readFile(path.join(tmpDir, 'package', 'package.json'), 'utf8')));
|
||||
if (pkg !== packageJson.name)
|
||||
throw new Error(`Package name mismatch: ${pkg} is called ${packageJson.name} in its package.json`);
|
||||
|
||||
const now = new Date().toISOString();
|
||||
const shasum = crypto.createHash('sha1').update(await fs.promises.readFile(tarPath)).digest().toString('hex');
|
||||
const tarball = new URL(this._url);
|
||||
tarball.pathname = `${tarball.pathname}${tarball.pathname.endsWith('/') ? '' : '/'}${encodeURIComponent(pkg)}/-/${shasum}.tgz`;
|
||||
const metadata = {
|
||||
'dist-tags': {
|
||||
latest: packageJson.version,
|
||||
[packageJson.version]: packageJson.version,
|
||||
},
|
||||
'modified': now,
|
||||
'name': pkg,
|
||||
'versions': {
|
||||
[packageJson.version]: {
|
||||
_hasShrinkwrap: false,
|
||||
name: pkg,
|
||||
version: packageJson.version,
|
||||
dependencies: packageJson.dependencies || {},
|
||||
optionalDependencies: packageJson.optionalDependencies || {},
|
||||
devDependencies: packageJson.devDependencies || {},
|
||||
bundleDependencies: packageJson.bundleDependencies || {},
|
||||
peerDependencies: packageJson.peerDependencies || {},
|
||||
bin: packageJson.bin || {},
|
||||
directories: packageJson.directories || [],
|
||||
scripts: packageJson.scripts || {},
|
||||
dist: {
|
||||
tarball: tarball.toString(),
|
||||
shasum,
|
||||
},
|
||||
engines: packageJson.engines || {},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const object = path.join(this._objectsDir, `${shasum}.tgz`);
|
||||
await fs.promises.copyFile(tarPath, object);
|
||||
this._packageMeta.set(pkg, [metadata, object]);
|
||||
}
|
||||
|
||||
private _logAccess(info: {status: 'PROXIED' | 'LOCAL', pkg: string, type?: 'tar' | 'metadata'}) {
|
||||
this._log.push(info);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { test } from './npmTest';
|
||||
|
||||
test('screencast works', async ({ exec }) => {
|
||||
const packages = ['playwright', 'playwright-chromium', 'playwright-firefox', 'playwright-webkit'];
|
||||
await exec('npm i --foreground-scripts', ...packages);
|
||||
for (const pkg of packages)
|
||||
await test.step(pkg, () => exec('node ./screencast.js', pkg));
|
||||
});
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { test, expect } from './npmTest';
|
||||
|
||||
test('should skip download', async ({ exec }) => {
|
||||
const installOutput = await exec('npm i --foreground-scripts playwright', { env: { PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1' } });
|
||||
expect(installOutput).toContain('Skipping browsers download because');
|
||||
if (process.platform === 'linux') {
|
||||
const output = await exec('node inspector-custom-executable.js', { env: { PWDEBUG: '1' } });
|
||||
expect(output).toContain('SUCCESS');
|
||||
}
|
||||
});
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { test, expect } from './npmTest';
|
||||
|
||||
test('PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD should skip browser installs', async ({ exec, installedSoftwareOnDisk }) => {
|
||||
const result = await exec('npm i --foreground-scripts playwright', { env: { PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1' } });
|
||||
expect(result).toHaveLoggedSoftwareDownload([]);
|
||||
expect(await installedSoftwareOnDisk()).toEqual([]);
|
||||
expect(result).toContain(`Skipping browsers download because`);
|
||||
});
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import type { SpawnOptions } from 'child_process';
|
||||
import { spawn } from 'child_process';
|
||||
import debugLogger from 'debug';
|
||||
|
||||
const debugExec = debugLogger('itest:exec');
|
||||
const debugExecStdout = debugLogger('itest:exec:stdout');
|
||||
const debugExecStderr = debugLogger('itest:exec:stderr');
|
||||
|
||||
export function spawnAsync(cmd: string, args: string[], options: SpawnOptions = {}): Promise<{stdout: string, stderr: string, code: number | null, error?: Error}> {
|
||||
// debugExec(`CWD: ${options.cwd || process.cwd()}`);
|
||||
// debugExec(`ENV: ${Object.entries(options.env || {}).map(([key, value]) => `${key}=${value}`).join(' ')}`);
|
||||
debugExec([cmd, ...args].join(' '));
|
||||
const p = spawn(cmd, args, Object.assign({ windowsHide: true }, options));
|
||||
|
||||
return new Promise(resolve => {
|
||||
let stdout = '';
|
||||
let stderr = '';
|
||||
if (p.stdout) {
|
||||
p.stdout.on('data', data => {
|
||||
debugExecStdout(data.toString());
|
||||
stdout += data;
|
||||
});
|
||||
}
|
||||
if (p.stderr) {
|
||||
p.stderr.on('data', data => {
|
||||
debugExecStderr(data.toString());
|
||||
stderr += data;
|
||||
});
|
||||
}
|
||||
p.on('close', code => resolve({ stdout, stderr, code }));
|
||||
p.on('error', error => resolve({ stdout, stderr, code: 0, error }));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { test } from './npmTest';
|
||||
|
||||
test('typescript types should work', async ({ exec, tsc, writeFiles }) => {
|
||||
const libraryPackages = [
|
||||
'playwright',
|
||||
'playwright-core',
|
||||
'playwright-firefox',
|
||||
'playwright-webkit',
|
||||
'playwright-chromium',
|
||||
];
|
||||
await exec('npm i @playwright/test', ...libraryPackages, { env: { PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1' } });
|
||||
|
||||
for (const libraryPackage of libraryPackages) {
|
||||
const filename = libraryPackage + '.ts';
|
||||
await writeFiles({
|
||||
[filename]: `import { Page } from '${libraryPackage}';`,
|
||||
});
|
||||
await tsc(filename);
|
||||
}
|
||||
|
||||
await tsc('playwright-test-types.ts');
|
||||
});
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { test, expect } from './npmTest';
|
||||
|
||||
test.describe('validate dependencies', () => {
|
||||
test('default (on)', async ({ exec }) => {
|
||||
await exec('npm i --foreground-scripts playwright');
|
||||
const result = await exec('node ./validate-dependencies.js');
|
||||
expect(result).toContain(`PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS`);
|
||||
});
|
||||
|
||||
test('disabled (off)', async ({ exec }) => {
|
||||
await exec('npm i --foreground-scripts playwright');
|
||||
const result = await exec('node ./validate-dependencies-skip-executable-path.js');
|
||||
expect(result).not.toContain(`PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS`);
|
||||
});
|
||||
});
|
Загрузка…
Ссылка в новой задаче