Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Run Playwright server for component tests in docker #31440

Closed
denselmann opened this issue Jun 25, 2024 · 8 comments
Closed

Run Playwright server for component tests in docker #31440

denselmann opened this issue Jun 25, 2024 · 8 comments

Comments

@denselmann
Copy link

denselmann commented Jun 25, 2024

I would like to run Playwright component tests on a Playwright server in Docker while keeping the tests running on the host system.
Like explained in #26482 I've followed these steps:

Run Playwright Server in Docker

docker run \
-p 9009:9009 \
--add-host=hostmachine:host-gateway \
--rm --init -it \
mcr.microsoft.com/playwright:v1.44.1-jammy \
/bin/bash -c "cd /home/pwuser && npx -y playwright@1.44.1 run-server --port 9009"

Connect client to running server

PW_TEST_CONNECT_WS_ENDPOINT=ws://127.0.0.1:9009/ playwright test -c playwright-ct.config.ts

No I get the following error

Error: net::ERR_CONNECTION_REFUSED at http://localhost:3100/
Call log: - navigating to "http://localhost:3100/", waiting until "load" at Object.page (/Users/myuser/Development/project/node_modules/@playwright/experimental-ct-core/lib/mount.js:38:16)

I think, this is because of the fact, that Playwright uses Vite under the hood and Vite tries to start a new webserver on the hostmachine which doesn't know about the Server running in the docker container.

This is my playwright-ct.config.ts:

import { defineConfig } from '@playwright/experimental-ct-react';
import { ScreenshotMode, TraceMode, VideoMode } from 'playwright/types/test';

/**
 * See https://playwright.dev/docs/test-configuration.
 */
export default defineConfig({
  testDir: 'tests',
  /* The base directory, relative to the config file, for snapshot files created with toMatchSnapshot and toHaveScreenshot. */
  snapshotDir: './__snapshots__',
  /* Maximum time one test can run for. */
  timeout: 10 * 1000,
  /* Run tests in files in parallel */
  fullyParallel: true,
  /* Fail the build on CI if you accidentally left test.only in the source code. */
  forbidOnly: !!process.env.CI,
  /* Retry on CI only */
  retries: process.env.CI ? 1 : 0,
  /* Opt out of parallel tests on CI. */
  workers: 1,
  /* Reporter to use. See https://playwright.dev/docs/test-reporters */
  reporter: 'list',
  /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
  use: {
    /* Port to use for Playwright component endpoint. */
    ctPort: 3100,
    headless: process.env.PLAYWRIGHT_HEADED !== 'on',
    screenshot: (process.env.PLAYWRIGHT_SCREENSHOT || 'on') as ScreenshotMode,
    /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
    trace: (process.env.PLAYWRIGHT_TRACE || 'off') as TraceMode,
    video: (process.env.PLAYWRIGHT_VIDEO || 'off') as VideoMode,
  },
  outputDir: 'test-results/',
});

It would be really nice to get this kind of setup running.

@pavelfeldman
Copy link
Member

I think, this is because of the fact, that Playwright uses Vite under the hood and Vite tries to start a new webserver on the hostmachine which doesn't know about the Server running in the docker container.

I would think this is the reason, yes. You need to make sure that the host port is accessible from within the container. Follow docker docks to either create a tunnel or configure docker to see the ports.

@oskar-martensson
Copy link

I think the issue is that right now we cannot decouple the preview server host and the base URL when running the tests:
In https://github.com/microsoft/playwright/blob/main/packages/playwright-ct-core/src/vitePlugin.ts:

      if (isAddressInfo(address)) {
        const protocol = viteConfig.preview.https ? 'https:' : 'http:';
        process.env.PLAYWRIGHT_TEST_BASE_URL = `${protocol}//${viteConfig.preview.host}:${address.port}`;
      }

In my case I set use.baseURL to "host.docker.internal:3100", and my ctViteConfig.preview.host to "localhost". Even so, the test still tries to navigate to "localhost" instead of "host.docker.internal".
Maybe something along the lines of:

      if (use.baseURL) {
        process.env.PLAYWRIGHT_TEST_BASE_URL = use.baseUrl;
      } else if (isAddressInfo(address)) {
        const protocol = finalConfig.preview.https ? 'https:' : 'http:';
        process.env.PLAYWRIGHT_TEST_BASE_URL = `${protocol}//${finalConfig.preview.host}:${address.port}`;
      }

oskar-martensson pushed a commit to oskar-martensson/playwright that referenced this issue Jun 27, 2024
@pavelfeldman
Copy link
Member

I think the issue is that right now we cannot decouple the preview server host and the base URL when running the tests

I see what you are saying. We page.goto(process.env.PLAYWRIGHT_TEST_BASE_URL) when you mount and we assume that the target url is accessible from where the browser is running. So you pretty much need to export port with the same number to docker -p 4173:4173 or whatever preview port you configure. Does that not work for you?

@oskar-martensson
Copy link

Hm, I'm unsure if I misinterpreted the original question.
My problem is that Chromium which is running in the container is unable to navigate to the preview server that is running on the host machine. This is because Chromium attempts to navigate to the preview server using localhost - which refers to the container itself, not the host.

Setup:
Host machine - Running playwright tests as well as preview server
Docker container - Running the playwright server

Running docker -p 4173:4173 would enable the host machine to reach the container, but it won't enable the container to reach the host. As far as I know the common way to enable a container to reach the host is by using host.docker.internal.

Thanks for the quick response!

@pavelfeldman
Copy link
Member

Running docker -p 4173:4173 would enable the host machine to reach the container, but it won't enable the container to reach the host. As far as I know the common way to enable a container to reach the host is by using host.docker.internal.

Ah, yes, you are right. I assume you are non-Linux, so sharing network interface is not an option to you. Would SSH tunnel work for you?

@pavelfeldman
Copy link
Member

pavelfeldman commented Jun 27, 2024

Another approach would be to set PW_TEST_CONNECT_EXPOSE_NETWORK - it would enable tethering (reverse proxy) to the host. The value is fed into https://playwright.dev/docs/api/class-browsertype#browser-type-connect's exposeNetwork. Tell me if that works for you and I can update the #26482.

@oskar-martensson
Copy link

I got it working by setting ctViteConfig.preview.host to my host's local IP which worked both for the preview server and also allowed the container to reach it!
Thank you for all the help!

@pavelfeldman
Copy link
Member

Closing as per above, please feel free to open a new issue if this does not cover your use case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants