Skip to content

Commit c292057

Browse files
authored
Implement basics for E2E tests driven by playwright (#6038)
* [PoC] Implement basics for E2E tests driven by playwright (JS) * Update tracker test run instructions in README * Update package config on e2e tests * Set playwright reporter format to list * Add mix task for running e2e tests in UI mode * Add e2e test run job to CI config * Add missing PG and CH services to e2e CI config * Increase timeouts for e2e CI tasks * Temporarily remove tzdata updater * Revert "Temporarily remove tzdata updater" This reverts commit 6105473. * Add step downloading geo data * Setup E2E seeds before running CI * Run e2e tests via mix task to ensure setup env variables * Set `BASE_URL` env var explicitly in CI config instead * Reduce shards to 1 * Change how cwd is set for playwright server * Show server log output in e2e tests * Install asset dependencies during e2e setup * Build assets as well * Hide server output in e2e tests again * Parallelize e2e tests again * Reduce test sharding from 4 to 2 * Cache more fetched and compiled assets * Remove redundant tests * Clean up playwright config slightly * Try reducing the time spent fetching system deps * Output screenshots on failure * Upload screenshots from failed tests to GH artifacts * Make one test fail on purpose * Revert "Make one test fail on purpose" This reverts commit 3372a82. * Update gitignore inside e2e to ignore outputDir * Add notes about how to run e2e tests locally * Add preferred envs for E2E mix tasks * Don't dump screenshots and don't upload them as GH artifacts * Rely on cached `tracker/node_modules` and not install tracker conditionally * Remove no longer relevant comments from mix.exs * Fix invalid playwright install option that surfaced with pruned cache
1 parent 2a9e0a3 commit c292057

22 files changed

Lines changed: 682 additions & 30 deletions

File tree

.github/workflows/elixir.yml

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,147 @@ jobs:
113113
env:
114114
MIX_TEST_PARTITION: ${{ matrix.mix_test_partition }}
115115

116+
e2e:
117+
name: End-to-end tests
118+
runs-on: ubuntu-latest
119+
timeout-minutes: 15
120+
env:
121+
MIX_ENV: e2e_test
122+
BASE_URL: "http://localhost:8000"
123+
services:
124+
postgres:
125+
image: "postgres:18"
126+
ports:
127+
- 5432:5432
128+
env:
129+
POSTGRES_PASSWORD: postgres
130+
options: >-
131+
--health-cmd pg_isready
132+
--health-interval 10s
133+
--health-timeout 5s
134+
--health-retries 5
135+
clickhouse:
136+
image: clickhouse/clickhouse-server:25.11.5.8-alpine
137+
ports:
138+
- 8123:8123
139+
env:
140+
CLICKHOUSE_SKIP_USER_SETUP: 1
141+
options: >-
142+
--health-cmd nc -zw3 localhost 8124
143+
--health-interval 10s
144+
--health-timeout 5s
145+
--health-retries 5
146+
strategy:
147+
fail-fast: false
148+
matrix:
149+
shardIndex: [1, 2]
150+
shardTotal: [2]
151+
steps:
152+
- uses: actions/checkout@v6
153+
with:
154+
fetch-depth: 0
155+
156+
- uses: marocchino/tool-versions-action@v1
157+
id: versions
158+
159+
- uses: erlef/setup-beam@v1
160+
with:
161+
elixir-version: ${{ steps.versions.outputs.elixir }}
162+
otp-version: ${{ steps.versions.outputs.erlang }}
163+
164+
- uses: actions/cache@v5
165+
with:
166+
path: |
167+
deps
168+
_build
169+
assets/node_modules
170+
tracker/node_modules
171+
priv/tracker/js
172+
priv/tracker/installation_support
173+
${{ env.PERSISTENT_CACHE_DIR }}
174+
key: e2e-${{ env.MIX_ENV }}-${{ env.CACHE_VERSION }}-${{ github.head_ref || github.ref }}-${{ hashFiles('**/mix.lock') }}
175+
restore-keys: |
176+
e2e-${{ env.MIX_ENV }}-${{ env.CACHE_VERSION }}-${{ github.head_ref || github.ref }}-
177+
e2e-${{ env.MIX_ENV }}-${{ env.CACHE_VERSION }}-refs/heads/master-
178+
179+
- name: Cache E2E dependencies and Playwright browsers
180+
uses: actions/cache@v5
181+
id: playwright-cache
182+
with:
183+
path: |
184+
e2e/node_modules
185+
~/.cache/ms-playwright
186+
~/.cache/ms-playwright-github
187+
key: playwright-${{ runner.os }}-${{ hashFiles('e2e/package-lock.json') }}
188+
restore-keys: |
189+
playwright-${{ runner.os }}-
190+
191+
- name: Check for changes in tracker/**
192+
uses: dorny/paths-filter@v3
193+
id: changes
194+
with:
195+
filters: |
196+
tracker:
197+
- 'tracker/**'
198+
199+
- run: npm install --prefix ./tracker
200+
- run: npm run deploy --prefix ./tracker
201+
- run: mix deps.get --only $MIX_ENV
202+
- run: mix compile --warnings-as-errors --all-warnings
203+
- run: npm install --prefix ./assets
204+
- run: mix assets.deploy
205+
- run: mix do ecto.create, ecto.migrate
206+
- run: mix download_country_database
207+
- run: mix run -e "Tzdata.ReleaseUpdater.poll_for_update"
208+
209+
- name: Setup E2E seeds
210+
run: mix run priv/repo/e2e_seeds.exs
211+
212+
- name: Install E2E dependencies
213+
run: npm --prefix ./e2e ci
214+
215+
- name: Install E2E Playwright Browsers
216+
if: steps.playwright-cache.outputs.cache-hit != 'true'
217+
working-directory: ./e2e
218+
run: npx playwright install --with-deps chromium
219+
220+
- name: Run E2E Playwright tests
221+
run: npm --prefix ./e2e test -- --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} --reporter=blob
222+
223+
- name: Upload E2E blob report to GitHub Actions Artifacts
224+
if: ${{ !cancelled() }}
225+
uses: actions/upload-artifact@v6
226+
with:
227+
name: e2e-blob-report-${{ matrix.shardIndex }}
228+
path: e2e/blob-report
229+
retention-days: 1
230+
231+
merge-sharded-e2e-test-report:
232+
if: ${{ !cancelled() }}
233+
needs: [e2e]
234+
timeout-minutes: 15
235+
runs-on: ubuntu-latest
236+
steps:
237+
- uses: actions/checkout@v6
238+
- uses: actions/setup-node@v6
239+
with:
240+
node-version: 23.2.0
241+
cache: 'npm'
242+
cache-dependency-path: e2e/package-lock.json
243+
- name: Install dependencies
244+
run: npm --prefix ./e2e ci
245+
246+
- name: Download blob reports from GitHub Actions Artifacts
247+
uses: actions/download-artifact@v7
248+
with:
249+
path: all-e2e-blob-reports
250+
pattern: e2e-blob-report-*
251+
merge-multiple: true
252+
253+
- name: Merge into list report
254+
working-directory: ./e2e
255+
run: npx playwright merge-reports --reporter list ../all-e2e-blob-reports
256+
116257
static:
117258
name: Static checks (format, credo, dialyzer)
118259
env:
@@ -125,6 +266,7 @@ jobs:
125266

126267
- uses: marocchino/tool-versions-action@v1
127268
id: versions
269+
128270
- uses: erlef/setup-beam@v1
129271
with:
130272
elixir-version: ${{ steps.versions.outputs.elixir }}

config/.env.e2e_test

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
BASE_URL=http://localhost:8000
2+
SECURE_COOKIE=false
3+
DATABASE_URL=postgres://postgres:postgres@127.0.0.1:5432/plausible_e2e
4+
CLICKHOUSE_DATABASE_URL=http://127.0.0.1:8123/plausible_e2e
5+
CLICKHOUSE_MAX_BUFFER_SIZE_BYTES=1000000
6+
SECRET_KEY_BASE=/njrhntbycvastyvtk1zycwfm981vpo/0xrvwjjvemdakc/vsvbrevlwsc6u8rcg
7+
TOTP_VAULT_KEY=Q3BD4nddbkVJIPXgHuo5NthGKSIH0yesRfG05J88HIo=
8+
ENVIRONMENT=dev
9+
MAILER_ADAPTER=Bamboo.LocalAdapter
10+
LOG_LEVEL=warning
11+
SELFHOST=false
12+
DISABLE_CRON=true
13+
ADMIN_USER_IDS=1
14+
SHOW_CITIES=true
15+
PADDLE_VENDOR_AUTH_CODE=895e20d4efaec0575bb857f44b183217b332d9592e76e69b8a
16+
PADDLE_VENDOR_ID=3942
17+
SSO_VERIFICATION_NAMESERVERS=0.0.0.0:5354
18+
19+
GOOGLE_CLIENT_ID=875387135161-l8tp53dpt7fdhdg9m1pc3vl42si95rh0.apps.googleusercontent.com
20+
GOOGLE_CLIENT_SECRET=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
21+
22+
PROMEX_DISABLED=false
23+
SITE_DEFAULT_INGEST_THRESHOLD=1000000
24+
25+
S3_DISABLED=false
26+
S3_ACCESS_KEY_ID=minioadmin
27+
S3_SECRET_ACCESS_KEY=minioadmin
28+
S3_REGION=us-east-1
29+
S3_ENDPOINT=http://localhost:10000
30+
S3_EXPORTS_BUCKET=dev-exports
31+
S3_IMPORTS_BUCKET=dev-imports
32+
33+
HELP_SCOUT_APP_ID=fake_app_id
34+
HELP_SCOUT_APP_SECRET=fake_app_secret
35+
HELP_SCOUT_SIGNATURE_KEY=fake_signature_key
36+
HELP_SCOUT_VAULT_KEY=ym9ZQg0KPNGCH3C2eD5y6KpL0tFzUqAhwxQO6uEv/ZM=
37+
38+
VERIFICATION_ENABLED=true

config/e2e_test.exs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import Config
2+
3+
config :plausible, PlausibleWeb.Endpoint,
4+
server: true,
5+
check_origin: false
6+
7+
config :plausible, paddle_api: Plausible.Billing.DevPaddleApiMock
8+
9+
config :phoenix, :stacktrace_depth, 20
10+
config :phoenix, :plug_init_mode, :runtime
11+
12+
config :bcrypt_elixir, :log_rounds, 4
13+
14+
config :plausible, Plausible.Ingestion.Counters, enabled: false
15+
16+
config :plausible, Oban, testing: :manual
17+
18+
config :plausible, Plausible.Session.Salts, interval: :timer.hours(1)

config/runtime.exs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ if config_env() == :ce_test do
1414
Envy.load(["config/.env.test"])
1515
end
1616

17+
if config_env() == :e2e_test do
18+
Envy.load(["config/.env.e2e_test"])
19+
end
20+
1721
config_dir = System.get_env("CONFIG_DIR", "/run/secrets")
1822

1923
log_format =

e2e/.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
# Playwright
3+
node_modules/
4+
/test-results/
5+
/playwright-report/
6+
/blob-report/
7+
/output/
8+
/playwright/.cache/
9+
/playwright/.auth/

e2e/package-lock.json

Lines changed: 97 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

e2e/package.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"name": "e2e",
3+
"scripts": {
4+
"test": "npx playwright test",
5+
"test:ui": "npx playwright test --ui"
6+
},
7+
"license": "MIT",
8+
"devDependencies": {
9+
"@playwright/test": "^1.58.0",
10+
"@types/node": "^25.1.0"
11+
}
12+
}

0 commit comments

Comments
 (0)