Skip to content

Commit e3b4cf2

Browse files
authored
test: Update e2e docker template (#1427)
While helping Ethan debug e2e flaky tests in CI, Don mentioned the npm script to run e2e in docker was ugly. I agreed and decided to clean it up some. This change makes the e2e tests in Docker also spin up the DHC server w/ anonymous auth so you don't have to. We could extend this to add a dev mode for e2e testing possibly, but I don't think you can get headed mode in Docker if you want it. You can also pass arguments directly now. `npm run e2e:ci -- --project=chromium tests/someTest.js` and it will run in Docker Also figured out a way to remove a COPY line for every package.json using multi-stage builds. It caches properly still if no package.json files change. Removed the volume mount for test-results because Docker creates the directories inside of it as root (I tried running the container as a regular user and it complains). This causes an issue if you run the snapshots in Docker w/ a failure and then try to run locally because the folder is owned by root and can't be cleared as a regular user. Still need to update the readme. And probably rename `e2e:ci` since it's not actually run in CI
1 parent 3445586 commit e3b4cf2

File tree

10 files changed

+169
-160
lines changed

10 files changed

+169
-160
lines changed

.dockerignore

+18-28
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,40 @@
1-
# Just copy the .gitignore file for files we don't want to copy to the docker image
2-
31
# dependencies
4-
/node_modules
2+
**/node_modules/
53

64
# testing
75
/coverage
6+
jest*
7+
__mocks__/
8+
.github/
89

910
# production
10-
/build
11-
/dist
11+
**/build/
12+
**/dist/
1213

1314
# misc
14-
.vscode/*
15-
!.vscode/settings.json
16-
!.vscode/tasks.json
17-
!.vscode/launch.json
18-
!.vscode/extensions.json
19-
!.vscode/*.code-snippets
15+
.git/
16+
.vscode/
2017
.DS_Store
21-
.env.local
22-
.env.development.local
23-
.env.test.local
24-
.env.production.local
18+
**/.env*.local
2519
.project
2620
.settings/
2721
.eslintcache
2822
.stylelintcache
2923
lerna-debug.log
3024
Lerna-Profile-*.json
3125

32-
/public/vs
33-
3426
npm-debug.log*
35-
yarn-debug.log*
36-
yarn-error.log*
37-
38-
src/**/*.css
3927

40-
tsconfig.tsbuildinfo
41-
packages/*/package-lock.json
42-
/test-results/
43-
/playwright-report/
44-
/playwright/.cache/
28+
**/tsconfig.tsbuildinfo
29+
test-results/
30+
playwright-report/
31+
playwright/.cache/
32+
**/CHANGELOG.md
4533

4634
# Ignore Dockerfile as well, since we don't need to copy that into the snapshot container
47-
Dockerfile
35+
**/Dockerfile
36+
.dockerignore
37+
**/.gitignore
4838

4939
# Tests are copied to the docker container, as it modifies them
50-
/tests
40+
tests/

.github/workflows/e2e.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ jobs:
5353
run: PLAYWRIGHT_BROWSERS_PATH=0 npx playwright install --with-deps
5454

5555
- name: Run Playwright tests
56-
run: PLAYWRIGHT_BROWSERS_PATH=0 npx playwright test
56+
run: PLAYWRIGHT_BROWSERS_PATH=0 npx playwright test --config=playwright-ci.config.ts
5757

5858
- name: Upload Playwright report
5959
uses: actions/upload-artifact@v3

README.md

+40-14
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,10 @@ We use Chrome for development with the React and Redux extensions.
4141

4242
- `npm install` : Install all dependencies and automatically bootstrap packages. Should be run before any of the other steps.
4343
- `npm start`: Start building all packages and watching them (when possible). Use when you're developing, and your changes will be picked up automatically.
44-
- `npm test`: Start running tests in all packages and watching (when possible). Use when you're developing, and any breaking changes will be printed out automatically.
45-
46-
Log messages from our log package are disabled by default in tests in [jest.setup.ts](./jest.setup.ts). To change the log level, set the `DH_LOG_LEVEL` env variable. For example, to enable all log messages run `DH_LOG_LEVEL=4 npm test`.
47-
48-
Note that log messages from other sources such as react prop types will still be printed since they do not go through our logger.
49-
50-
If you want to collect coverage locally, run `npm test -- --coverage`
51-
44+
- `npm test`: Start running tests in all packages and watching (when possible). Use when you're developing, and any breaking changes will be printed out automatically. See [Unit tests](#unit-tests) for more details.
5245
- `npm run build`: Create a production build of all packages. Mainly used by CI when packaging up a production version of the app.
5346
- `npm run preview`: Runs the Vite preview server for the built code-studio, embed-grid, and embed-chart. These will open on ports 4000, 4010, and 4020.
54-
- `npm run e2e`: Runs the Playwright end-to-end tests locally.
55-
- `npm run e2e:headed`: Runs end-to-end tests in headed mode debug mode. Useful if you need to debug why a particular test isn't work. For example, to debug the `table.spec.ts` test directly, you could run `npm run e2e:headed -- ./tests/table.spec.ts`.
47+
- `npm run e2e`: Runs the Playwright end-to-end tests locally. See [E2E Tests](#e2e-tests) for more details.
5648

5749
If your DHC address is different from the default `http://localhost:10000`, edit `.env.local` in each package to point to your local DHC. This is needed for the session websocket and for things like notebooks to be proxied correctly by Vite.
5850

@@ -88,13 +80,47 @@ A standalone application with it's own entry point. Recommend copying the [embed
8880

8981
A component/library package that can be imported into other packages. Recommend copying the [components](./packages/components/) package, removing any dependencies and files not required.
9082

91-
## Updating E2E Snapshots
83+
## Unit Tests
84+
85+
We use [Jest](https://jestjs.io/) for running unit tests. We use an eslint runner in Jest to lint files as tests. We also use [react-testing-library](https://testing-library.com/docs/react-testing-library/intro/) and [react-hooks-testing-library](https://react-hooks-testing-library.com/) for testing react components and hooks.
86+
87+
Run `npm test` to start Jest in watch mode. By default, this will only run tests that have changed relative to your git origin/main. Keeping your origin/main up to date will help keep the number of tests run to a minimum.
88+
89+
While the tests are running, you can press `p` to filter by filename or test name. You can also press `Shift+P` to see a list of projects and disable certain projects like the eslint or stylelint.
90+
91+
Log messages from our @deephaven/log package are disabled by default in tests in [jest.setup.ts](./jest.setup.ts). To change the log level, set the `DH_LOG_LEVEL` env variable. For example, to enable all log messages run `DH_LOG_LEVEL=4 npm test`.
92+
93+
Note that log messages from other sources such as react prop types will still be printed since they do not go through our logger.
94+
95+
If you want to collect coverage locally, run `npm test -- --coverage`
96+
97+
## E2E Tests
98+
99+
We use [Playwright](https://playwright.dev/) for end-to-end tests. We test against Chrome, Firefox, and Webkit (Safari). Snapshots from E2E tests are only run against Linux so they can be validated in CI.
100+
101+
You should be able to pass arguments to these commands as if you were running Playwright via CLI directly. For example, to test only `table.spec.ts` you could run `npm run e2e -- ./tests/table.spec.ts`, or to test only `table.spec.ts` in Firefox, you could run `npm run e2e -- --project firefox ./tests/table.spec.ts`. See [Playwright CLI](https://playwright.dev/docs/test-cli) for more details.
102+
103+
Snapshots are used by end-to-end tests to visually verify the output. Snapshots are both OS and broser specific. Sometimes changes are made requiring snapshots to be updated. Update snapshots locally by running `npm run e2e:update-snapshots`.
104+
105+
Once you are satisfied with the snapshots and everything is passing locally, you need to use the docker image to update snapshots for CI (unless you are running the same platform as CI (Ubuntu)). Run `npm run e2e:update-ci-snapshots` to update the CI snapshots. The snapshots will be written to your local directories. The Linux snapshots should be committed to git (non-Linux snapshots should be automatically ignored by git).
106+
107+
### Local
108+
109+
These scripts are recommended while developing your tests as they will be quicker to iterate and offer headed mode for debugging. You will need to run `npx playwright install` before using these scripts. You may also need to update the browsers with the same command any time the Playwright version is updated. See [Playwright Browsers](https://playwright.dev/docs/browsers) for more details.
110+
111+
You must have a web UI running on `localhost:4000/ide/` (dev mode and build preview are both fine), and `deephaven-core` running on port 10000 with anonymous authentication for E2E tests. See [this guide](https://deephaven.io/core/docs/how-to-guides/authentication/auth-anon/) for more details on anonymous authentication.
112+
113+
- `npm run e2e`: Run end-to-end tests in headless mode.
114+
- `npm run e2e:headed`: Runs end-to-end tests in headed debug mode. Also ignores snapshots since a test suite will stop once 1 snapshot comparison fails. Useful if you need to debug why a particular test isn't working. For example, to debug the `table.spec.ts` test directly, you could run `npm run e2e:headed -- ./tests/table.spec.ts`.
115+
- `npm run e2e:codegen`: Runs Playwright in codegen mode which can help with creating tests. See [Playwright Codegen](https://playwright.dev/docs/codegen/) for more details.
116+
- `npm run e2e:update-snapshots`: Updates the E2E snapshots for your local OS.
92117

93-
**Note:** You must have [Docker installed](https://docs.docker.com/get-docker/), and `deephaven-core` must already be running on port 10000 with anonymous authentication on your local machine for all e2e tests. To enable anonymous authentication, pass the flag through `START_OPTS`, e.g.: `docker run --detach --publish 10000:10000 --name dh-core-server --env "START_OPTS=-Xmx4g -DAuthHandlers=io.deephaven.auth.AnonymousAuthenticationHandler" ghcr.io/deephaven/server:edge` or `START_OPTS="-DAuthHandlers=io.deephaven.auth.AnonymousAuthenticationHandler" ./gradlew server-jetty-app:run`.
118+
### Docker
94119

95-
Snapshots are used by end-to-end tests to visually verify the output. Sometimes changes are made requiring snapshots to be updated. Before running snapshots locally, you must be running the development server with `npm start` or have run `npm run build` recently. Run snapshots locally by running `npm run e2e:update-snapshots`.
120+
These scripts will create a production build from your current code and run the tests in a Docker image. There is no need to install any other dependencies or have any other services running as they are all contained within Docker. Since any source code changes will require a new build, these scripts are only recommended if having issues with CI or if you need to update the snapshots for CI.
96121

97-
Once you are satisfied with the snapshots and everything is passing locally, you need to use a docker image to [update snapshots for CI](https://playwright.dev/docs/test-snapshots) (unless you are running the same platform as CI (Ubuntu)). Run `npm run e2e:update-ci-snapshots` which will mount the current directory into a docker image and re-run the tests from there. Test results will be written to your local directories.
122+
- `npm run e2e:docker`: Runs the E2E tests in a docker image. This is useful for testing how tests _should_ run in the CI environment locally.
123+
- `npm run e2e:update-ci-snapshots`: Updates the E2E snapshots for CI.
98124

99125
# Releases
100126

package.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,13 @@
4646
"test:unit": "jest --config jest.config.unit.cjs",
4747
"test:lint": "jest --config jest.config.lint.cjs",
4848
"test:golden-layout": "lerna run test:ci --scope=@deephaven/golden-layout --stream",
49+
"version-bump": "lerna version --conventional-commits --create-release github",
4950
"e2e": "playwright test",
5051
"e2e:codegen": "playwright codegen http://localhost:4000",
5152
"e2e:headed": "playwright test --project=chromium --debug --ignore-snapshots",
5253
"e2e:update-snapshots": "playwright test --update-snapshots",
53-
"version-bump": "lerna version --conventional-commits --create-release github",
54-
"e2e:update-ci-snapshots": "docker build --tag web-client-ui-ci-snapshots --file ./tests/update-ci-snapshots/Dockerfile . && docker run --rm --network host --volume $(pwd)/tests:/work/tests/ --volume $(pwd)/playwright-report:/work/playwright-report --volume $(pwd)/test-results:/work/test-results web-client-ui-ci-snapshots npm run e2e:update-snapshots -- --config=playwright-ci.config.ts"
54+
"e2e:docker": "./tests/docker-scripts/run.sh web-ui-tests",
55+
"e2e:update-ci-snapshots": "./tests/docker-scripts/run.sh web-ui-update-snapshots"
5556
},
5657
"repository": "https://github.com/deephaven/web-client-ui",
5758
"devDependencies": {

playwright-ci.config.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
1+
import type { PlaywrightTestConfig } from '@playwright/test';
12
import DefaultConfig from './playwright.config';
23

34
const config: PlaywrightTestConfig = {
45
...DefaultConfig,
5-
snapshotDir: './tests',
6+
webServer: {
7+
// Only start the main code-studio server right now
8+
// To test embed-grid and embed-chart, should have an array set for `webServer` and run them all separately as there's a port check
9+
command: 'BASE_URL=/ide/ npm run preview:app -- -- -- --no-open', // Passing flags through npm is fun
10+
port: 4000,
11+
timeout: 60 * 1000,
12+
reuseExistingServer: false,
13+
},
614
};
715

816
export default config;

playwright.config.ts

+2-42
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ const config: PlaywrightTestConfig = {
3232
/* Only have one worker since we don't want tests running in parallel, trampling over each other on the backend */
3333
workers: 1,
3434
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
35-
reporter: 'html',
35+
/* Use host 0.0.0.0 so it can be forwarded from within docker */
36+
reporter: [['html', { host: '0.0.0.0', port: 9323 }]],
3637
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
3738
use: {
3839
/* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
@@ -73,48 +74,7 @@ const config: PlaywrightTestConfig = {
7374
...devices['Desktop Safari'],
7475
},
7576
},
76-
77-
/* Test against mobile viewports. */
78-
// {
79-
// name: 'Mobile Chrome',
80-
// use: {
81-
// ...devices['Pixel 5'],
82-
// },
83-
// },
84-
// {
85-
// name: 'Mobile Safari',
86-
// use: {
87-
// ...devices['iPhone 12'],
88-
// },
89-
// },
90-
91-
/* Test against branded browsers. */
92-
// {
93-
// name: 'Microsoft Edge',
94-
// use: {
95-
// channel: 'msedge',
96-
// },
97-
// },
98-
// {
99-
// name: 'Google Chrome',
100-
// use: {
101-
// channel: 'chrome',
102-
// },
103-
// },
10477
],
105-
106-
/* Folder for test artifacts such as screenshots, videos, traces, etc. */
107-
// outputDir: 'test-results/',
108-
109-
/* Run your local dev server before starting the tests */
110-
webServer: {
111-
// Only start the main code-studio server right now
112-
// To test embed-grid and embed-chart, should have an array set for `webServer` and run them all separately as there's a port check
113-
command: 'BASE_URL=/ide/ npm run preview:app -- -- -- --no-open', // Passing flags through npm is fun
114-
port: 4000,
115-
timeout: 60 * 1000,
116-
reuseExistingServer: !process.env.CI,
117-
},
11878
};
11979

12080
export default config;

tests/docker-scripts/Dockerfile

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# syntax=docker/dockerfile:1
2+
# Dockerfile for updating the snapshots.
3+
# Expects to be run from the root of the web-client-ui repo
4+
FROM mcr.microsoft.com/playwright:v1.30.0-jammy AS playwright
5+
WORKDIR /work/
6+
7+
# Update packages list and install some build tools
8+
RUN set -eux; \
9+
apt-get update; \
10+
apt-get install build-essential --yes;
11+
12+
# Copy just the .nvmrc first and install nvm/node/npm first as these will change the least often
13+
# https://docs.docker.com/build/cache/
14+
COPY .nvmrc .
15+
16+
# Set the default shell so the correct node/npm is used after install
17+
# https://stackoverflow.com/a/60137919
18+
SHELL ["/bin/bash", "--login", "-i", "-c"]
19+
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
20+
RUN source /root/.bashrc && nvm install
21+
SHELL ["/bin/bash", "--login", "-c"]
22+
23+
# This is a workaround for copying all package.json files w/ directory structure
24+
# without needing to list every file as a COPY command
25+
# The copy --from=copy-packages command will be a cache hit if the package.json files didn't change
26+
FROM alpine AS copy-packages
27+
WORKDIR /work/
28+
COPY . /tmp/web-client-ui
29+
COPY package.json package-lock.json skip.js .
30+
# cd first so the cp doesn't include /tmp/web-client-ui in the paths
31+
RUN cd /tmp/web-client-ui && cp --parents ./packages/*/package.json /work/
32+
33+
FROM playwright AS build
34+
WORKDIR /work/
35+
COPY --from=copy-packages /work/ .
36+
37+
# Disable the postinstall script, or npm ci will try and build and the files won't be there
38+
# We don't need the postinstall since we're going to rebuild right after
39+
RUN SKIP_POSTINSTALL=1 npm ci
40+
41+
# Copy the web-client-ui src folder to the docker image
42+
# We do this last because the source files are the most likely to change
43+
# This requires the Dockerfile to be built in the context of the root of the web-client-ui repository
44+
# https://stackoverflow.com/a/34300129
45+
COPY . .
46+
47+
# Now build the app
48+
RUN npm run build
+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
version: '3.8'
2+
3+
services:
4+
dhc-server:
5+
image: ghcr.io/deephaven/server:${DHC_VERSION:-edge}
6+
expose:
7+
- 10000
8+
environment:
9+
- START_OPTS=-Xmx4g -DAuthHandlers=io.deephaven.auth.AnonymousAuthenticationHandler -Ddeephaven.console.type=python
10+
11+
web-ui-tests:
12+
build:
13+
context: ../../
14+
dockerfile: ./tests/docker-scripts/Dockerfile
15+
ipc: host
16+
environment:
17+
- VITE_PROXY_URL=http://dhc-server:10000
18+
ports:
19+
- 9323:9323
20+
volumes:
21+
- ../../tests:/work/tests
22+
- ../../test-results:/work/test-results
23+
- ../../playwright-report:/work/playwright-report
24+
entrypoint: 'npm run e2e -- --config=playwright-ci.config.ts'
25+
depends_on:
26+
dhc-server:
27+
condition: service_healthy
28+
29+
web-ui-update-snapshots:
30+
extends:
31+
service: web-ui-tests
32+
entrypoint: 'npm run e2e:update-snapshots -- --config=playwright-ci.config.ts'
33+
depends_on: # depends_on is not shared with extends
34+
dhc-server:
35+
condition: service_healthy

tests/docker-scripts/run.sh

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/bin/bash
2+
3+
# This script runs the docker-compose file with the given arguments
4+
# The argument should contain the container name to run as the first argument (e.g. web-ui-tests)
5+
# Once the container finishes its task, this script shuts down the docker containers
6+
# because docker compose run starts dependent containers, but does not stop them
7+
8+
pushd "$(dirname "$0")" # Set pwd to this directory
9+
docker compose run --service-ports --build --rm "$@" # Passes all arguments to the compose file
10+
exit_code=$?
11+
docker compose down
12+
popd # Reset pwd
13+
exit $exit_code

0 commit comments

Comments
 (0)