Skip to content

Commit

Permalink
auto-launch container
Browse files Browse the repository at this point in the history
  • Loading branch information
aslushnikov committed Sep 6, 2022
1 parent d75700c commit add84ca
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 40 deletions.
56 changes: 22 additions & 34 deletions packages/playwright-core/src/cli/docker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,22 +171,6 @@ export async function installImage() {
console.log(`Done!`);
}

export async function wsEndpoint(): Promise<string> {
await ensureDockerIsRunning();
const result = await wsEndpointInternal();
if (!result) {
throw new Error(`\n` + utils.wrapInASCIIBox([
`Docker container is not running!`,
`Please run docker container first:`,
``,
` npx playwright docker start`,
``,
`<3 Playwright Team`,
].join('\n'), 1));
}
return result;
}

async function wsEndpointInternal(): Promise<string|undefined> {
const containerId = await findRunningDockerContainerId();
if (!containerId)
Expand All @@ -207,7 +191,20 @@ async function wsEndpointInternal(): Promise<string|undefined> {
return webSocketLine ? 'ws://' + webSocketLine.substring(LINE_PREFIX.length) : undefined;
}

export async function startContainer() {
export async function containerInfo(): Promise<{wsEndpoint: string, vncSession: string}|undefined> {
await ensureDockerIsRunning();
const wsEndpoint = await wsEndpointInternal();
return wsEndpoint ? containerInfoInternal(wsEndpoint) : undefined;
}

function containerInfoInternal(wsEndpoint: string): { wsEndpoint: string, vncSession: string } {
return {
wsEndpoint,
vncSession: `http://127.0.0.1:7900?path=${utils.createGuid()}&resize=scale`,
};
}

export async function ensureContainer(): Promise<{ wsEndpoint: string, vncSession: string }> {
await ensureDockerIsRunning();
const pwImage = await findDockerImage(VRT_IMAGE_NAME);
if (!pwImage) {
Expand All @@ -220,10 +217,10 @@ export async function startContainer() {
`<3 Playwright Team`,
].join('\n'), 1));
}
if (await wsEndpointInternal()) {
console.log(`Container is already running.`);
return;
}

let wsEndpoint = await wsEndpointInternal();
if (wsEndpoint)
return containerInfoInternal(wsEndpoint);

await launchContainer({
image: pwImage,
Expand All @@ -234,24 +231,15 @@ export async function startContainer() {

// Wait for the service to become available.
const startTime = Date.now();
let endpoint = undefined;
const timeouts = [0, 100, 100, 200, 500, 1000];
do {
await new Promise(x => setTimeout(x, timeouts.shift() ?? 1000));
endpoint = await wsEndpointInternal();
} while (!endpoint && Date.now() < startTime + 60000);
wsEndpoint = await wsEndpointInternal();
} while (!wsEndpoint && Date.now() < startTime + 60000);

if (!endpoint)
if (!wsEndpoint)
throw new Error('Failed to launch docker container!');

/* eslint-disable no-console */
console.log(`✨ Launched Playwright ${getPlaywrightVersion()} Docker Container ✨`);
console.log(``);
console.log(`- VNC session: http://127.0.0.1:7900?path=${utils.createGuid()}&resize=scale`);
console.log(`- WS endpoint: ${endpoint}`);
console.log(``);
console.log(`You can now run tests with browsers inside this container:`);
console.log(` npx playwright docker test`);
return containerInfoInternal(wsEndpoint);
}

export async function stopContainer() {
Expand Down
39 changes: 33 additions & 6 deletions packages/playwright-test/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import type { Command } from 'playwright-core/lib/utilsBundle';
import * as docker from 'playwright-core/lib/cli/docker';
import * as utils from 'playwright-core/lib/utils';
import fs from 'fs';
import url from 'url';
import path from 'path';
Expand All @@ -36,6 +37,17 @@ export function addTestCommands(program: Command) {
addDockerCommand(program);
}

const dockerStartupMessage = (vncSession: string, wsEndpoint: string) => ([
`Playwright launched docker container to run browsers.`,
`- VNC session: ${vncSession}`,
`- WS endpoint: ${wsEndpoint}`,
``,
`Please stop container manually when it is no longer needed:`,
``,
` npx playwright docker stop`,
``,
].join('\n'));

function addDockerCommand(program: Command) {
const dockerCommand = program.command('docker', { hidden: true });

Expand All @@ -47,8 +59,14 @@ function addDockerCommand(program: Command) {

dockerCommand.command('start')
.description('Start container')
.action(function(options) {
docker.startContainer();
.action(async function(options) {
if (await docker.containerInfo()) {
console.log('Container is already running.');
return;
}
const info = await docker.ensureContainer();
/* eslint-disable no-console */
console.log(dockerStartupMessage(info.vncSession, info.wsEndpoint));
});

dockerCommand.command('stop')
Expand Down Expand Up @@ -91,10 +109,19 @@ function addTestCommand(program: Command, isDocker: boolean) {
command.action(async (args, opts) => {
try {
if (isDocker) {
const wsEndpoint = await docker.wsEndpoint();
if (!wsEndpoint)
throw new Error(`Playwright docker container is not running; run "npx playwright docker start" first`);
process.env.PW_TEST_CONNECT_WS_ENDPOINT = await docker.wsEndpoint();
let info = await docker.containerInfo();
if (info) {
/* eslint-disable no-console */
console.log(utils.wrapInASCIIBox([
`Running browsers in a pre-launched docker container.`,
`- VNC session: ${info.vncSession}`,
].join('\n'), 1));
} else {
info = await docker.ensureContainer();
/* eslint-disable no-console */
console.log(utils.wrapInASCIIBox(dockerStartupMessage(info.vncSession, info.wsEndpoint), 1));
}
process.env.PW_TEST_CONNECT_WS_ENDPOINT = info.wsEndpoint;
process.env.PW_TEST_CONNECT_HEADERS = JSON.stringify({
'x-playwright-proxy': '*',
});
Expand Down

0 comments on commit add84ca

Please sign in to comment.