Skip to content

Commit 05789df

Browse files
(PC-39004)[PRO] test: finalize desk e2e tests suite using Playwright
1 parent 6b79585 commit 05789df

File tree

14 files changed

+782
-45
lines changed

14 files changed

+782
-45
lines changed

.github/workflows/dev_on_pull_request_workflow.yml

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,9 +210,25 @@ jobs:
210210
GCP_EHP_WORKLOAD_IDENTITY_PROVIDER: ${{ secrets.GCP_EHP_WORKLOAD_IDENTITY_PROVIDER }}
211211
GCP_EHP_SERVICE_ACCOUNT: ${{ secrets.GCP_EHP_SERVICE_ACCOUNT }}
212212

213+
test-pro-e2e-playwright:
214+
name: "Pro E2E Tests (Playwright)"
215+
needs: [pcapi-init-job, build-pcapi-tests]
216+
uses: ./.github/workflows/dev_on_workflow_tests_pro_e2e_playwright.yml
217+
if: always() &&
218+
!cancelled() &&
219+
needs.pcapi-init-job.outputs.api-changed == 'true' ||
220+
needs.pcapi-init-job.outputs.pro-changed == 'true'
221+
with:
222+
ENV: "development"
223+
tag: ${{ needs.build-pcapi-tests.result == 'skipped' && 'latest' || github.sha }}
224+
CACHE_BUCKET_NAME: "passculture-infra-prod-github-runner-cache"
225+
secrets:
226+
GCP_EHP_WORKLOAD_IDENTITY_PROVIDER: ${{ secrets.GCP_EHP_WORKLOAD_IDENTITY_PROVIDER }}
227+
GCP_EHP_SERVICE_ACCOUNT: ${{ secrets.GCP_EHP_SERVICE_ACCOUNT }}
228+
213229
dependabot-auto-merge:
214230
name: "Dependabot"
215-
needs: [test-pro, test-pro-e2e]
231+
needs: [test-pro, test-pro-e2e, test-pro-e2e-playwright]
216232
if: github.event.pull_request.user.login == 'dependabot[bot]'
217233
uses: ./.github/workflows/dev_on_workflow_dependabot_auto_merge.yml
218234
secrets:
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
name: "3 [on_workflow] Tests E2E Playwright"
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
ENV:
7+
type: string
8+
required: true
9+
image:
10+
type: string
11+
required: false
12+
default: pcapi-tests
13+
tag:
14+
type: string
15+
required: true
16+
CACHE_BUCKET_NAME:
17+
type: string
18+
required: true
19+
secrets:
20+
GCP_EHP_WORKLOAD_IDENTITY_PROVIDER:
21+
required: true
22+
GCP_EHP_SERVICE_ACCOUNT:
23+
required: true
24+
25+
defaults:
26+
run:
27+
working-directory: pro
28+
29+
jobs:
30+
install:
31+
name: "Install Playwright E2E 🔧"
32+
runs-on: ubuntu-latest
33+
steps:
34+
- name: Checkout
35+
uses: actions/checkout@v6
36+
37+
- uses: technote-space/workflow-conclusion-action@v3
38+
39+
- uses: actions/setup-node@v6
40+
with:
41+
node-version-file: "pro/package.json"
42+
43+
- name: "Cache the node_modules"
44+
id: "yarn-modules-cache"
45+
uses: pass-culture-github-actions/[email protected]
46+
with:
47+
compression-method: "gzip"
48+
bucket: ${{ inputs.CACHE_BUCKET_NAME }}
49+
path: |
50+
**/node_modules
51+
key: v1-yarn-pro-playwright-dependency-cache-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
52+
restore-keys: |
53+
v1-yarn-pro-playwright-dependency-cache-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
54+
55+
- name: "Install dependencies (3 attempts)"
56+
uses: nick-fields/retry@v3
57+
with:
58+
timeout_minutes: 2
59+
max_attempts: 3
60+
command: |
61+
cd pro
62+
yarn install --immutable
63+
64+
- name: "Install Playwright browsers"
65+
run: npx playwright install chromium --with-deps
66+
67+
- name: "Build vite application"
68+
run: yarn build:${{ inputs.ENV }}
69+
70+
- name: Save build folder
71+
uses: actions/upload-artifact@v5
72+
with:
73+
name: build-playwright
74+
if-no-files-found: error
75+
path: pro/build
76+
77+
- name: Cache Docker layers
78+
uses: actions/cache@v4
79+
with:
80+
path: /tmp/.buildx-cache
81+
key: ${{ runner.os }}-buildx-${{ github.sha }}
82+
restore-keys: ${{ runner.os }}-buildx-
83+
84+
- name: Cache Poetry
85+
uses: actions/cache@v4
86+
with:
87+
path: ~/.cache/pypoetry
88+
key: poetry-${{ hashFiles('**/poetry.lock') }}
89+
90+
playwright-run:
91+
name: "Run Playwright E2E"
92+
runs-on: ubuntu-24.04
93+
needs: [install]
94+
strategy:
95+
fail-fast: false
96+
matrix:
97+
project: [chromium, mobile-chrome]
98+
99+
steps:
100+
- name: Checkout
101+
uses: actions/checkout@v6
102+
103+
- name: "Authentification to Google"
104+
uses: "google-github-actions/auth@v3"
105+
with:
106+
workload_identity_provider: ${{ secrets.GCP_EHP_WORKLOAD_IDENTITY_PROVIDER }}
107+
service_account: ${{ secrets.GCP_EHP_SERVICE_ACCOUNT }}
108+
109+
- name: "Get Secret"
110+
id: secrets
111+
uses: "google-github-actions/get-secretmanager-secrets@v3"
112+
with:
113+
secrets: |-
114+
ARTIFACT_REGISTRY_WORKLOAD_IDENTITY_PROVIDER:passculture-metier-ehp/infra-prod-gcp-workload-identity-provider
115+
ARTIFACT_REGISTRY_SERVICE_ACCOUNT:passculture-metier-ehp/passculture-main-artifact-registry-service-account
116+
117+
- uses: actions/setup-node@v6
118+
with:
119+
node-version-file: "pro/package.json"
120+
121+
- uses: KengoTODA/actions-setup-docker-compose@v1
122+
with:
123+
version: "2.23.3"
124+
125+
- name: "Fix local permissions"
126+
run: sudo chown -R $PCAPI_UID:$PCAPI_GID .
127+
working-directory: api
128+
env:
129+
PCAPI_UID: 1000
130+
PCAPI_GID: 1000
131+
132+
- name: "Install dependencies (3 attempts)"
133+
uses: nick-fields/retry@v3
134+
with:
135+
timeout_minutes: 2
136+
max_attempts: 3
137+
command: |
138+
cd pro
139+
yarn install --immutable
140+
141+
- name: "Install Playwright browsers"
142+
run: npx playwright install chromium --with-deps
143+
144+
- name: "OpenID Connect Authentication"
145+
id: openid-auth
146+
uses: "google-github-actions/auth@v3"
147+
with:
148+
create_credentials_file: false
149+
token_format: "access_token"
150+
workload_identity_provider: ${{ steps.secrets.outputs.ARTIFACT_REGISTRY_WORKLOAD_IDENTITY_PROVIDER }}
151+
service_account: ${{ steps.secrets.outputs.ARTIFACT_REGISTRY_SERVICE_ACCOUNT }}
152+
153+
- name: "Docker login"
154+
id: docker-login
155+
uses: "docker/login-action@v3"
156+
with:
157+
registry: "europe-west1-docker.pkg.dev"
158+
username: "oauth2accesstoken"
159+
password: "${{ steps.openid-auth.outputs.access_token }}"
160+
161+
- name: "Compute docker image name:tag"
162+
id: compute-image-name
163+
run: |
164+
echo "image_name=${{ inputs.image }}:${{ inputs.tag }}" | tee -a ${GITHUB_OUTPUT}
165+
echo "::notice:: Running playwright e2e-tests with ${{ inputs.image }}:${{ inputs.tag }}"
166+
167+
- name: "Run postgres and redis server"
168+
run: docker-compose -f ../docker-compose-backend.yml up postgres redis -d
169+
170+
- name: "Set up Cloud SDK"
171+
uses: "google-github-actions/setup-gcloud@v3"
172+
173+
- name: "Download artifact"
174+
if: ${{ inputs.tag != 'latest' }}
175+
uses: actions/download-artifact@v6
176+
with:
177+
name: ${{ inputs.image }}-${{ inputs.tag }}.tar
178+
path: ${{ runner.temp }}
179+
180+
- name: "Run API server"
181+
run: |
182+
if [ "${{ inputs.tag }}" != "latest" ]; then
183+
docker load --input ${{ runner.temp }}/${{ inputs.image }}-${{ inputs.tag }}.tar
184+
fi
185+
docker run \
186+
--name pc-api \
187+
--workdir /usr/src/app \
188+
--volume ./../api:/usr/src/app \
189+
--env-file ./../env_file \
190+
--tty \
191+
--detach \
192+
--network pass-culture-main_db_nw \
193+
--publish 5001:5001 \
194+
--publish 10002:10002 \
195+
--entrypoint bash \
196+
${{ steps.compute-image-name.outputs.image_name }} \
197+
-c "set -e ; flask install_postgres_extensions ; alembic upgrade pre@head ; alembic upgrade post@head ; flask install_data ; FLASK_USE_RELOADER=0 python src/pcapi/app.py"
198+
199+
- name: "Wait for migrations to be run"
200+
uses: iFaxity/wait-on-action@v1
201+
with:
202+
resource: http://localhost:5001/health/api
203+
timeout: 120000
204+
205+
- name: Download the build folder
206+
uses: actions/download-artifact@v6
207+
with:
208+
name: build-playwright
209+
path: pro/build
210+
211+
- name: "Serve vite preview"
212+
run: yarn serve &
213+
214+
- name: "Wait for front-end to listen"
215+
run: |
216+
timeout 300 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:3001)" != "200" ]]; do sleep 5; done' || false
217+
218+
- name: "Playwright run"
219+
run: npx playwright test --project=${{ matrix.project }}
220+
env:
221+
CI: true
222+
223+
- name: "Upload Playwright report"
224+
uses: actions/upload-artifact@v5
225+
if: always()
226+
with:
227+
name: playwright-report-${{ matrix.project }}
228+
path: pro/playwright-report/
229+
retention-days: 30
230+
231+
- name: "Show pcapi log when it fails"
232+
if: failure()
233+
run: docker logs pc-api
234+
235+
notify-playwright-failure:
236+
name: "Notification of Playwright tests failure"
237+
needs: playwright-run
238+
if: always() && needs.playwright-run.result == 'failure' && github.ref == 'refs/heads/master'
239+
uses: ./.github/workflows/dev_on_workflow_post_slack_message.yml
240+
with:
241+
channel: ${{vars.SLACK_DEV_CHANNEL_ID}}
242+
color: "#A30002"
243+
message: ":github-failure: <https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}|Pro Playwright E2E Tests> a échoué sur `master`"
244+
secrets:
245+
GCP_EHP_SERVICE_ACCOUNT: ${{ secrets.GCP_EHP_SERVICE_ACCOUNT }}
246+
GCP_EHP_WORKLOAD_IDENTITY_PROVIDER: ${{ secrets.GCP_EHP_WORKLOAD_IDENTITY_PROVIDER }}

pro/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
/cypress/downloads
1010
/cypress/screenshots
1111
/cypress/videos
12+
/test-results/
1213
.vitest_cache
1314
coverage
1415
bundleStats.html

pro/biome.jsonc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,9 @@
243243
"includes": [
244244
"!src/index.html",
245245
".templatron/**/*.mjs",
246+
"config/**/*.ts",
246247
"cypress/**/*.ts",
248+
"e2e/**/*.ts",
247249
"src/**/__mocks__/*.ts",
248250
"src/**/__specs__/*.ts",
249251
"src/**/tests/*.ts",

pro/config/playwright.config.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { defineConfig, devices } from '@playwright/test'
2+
3+
const BASE_URL = process.env.BASE_URL ?? 'http://localhost:3001'
4+
5+
export default defineConfig({
6+
expect: {
7+
timeout: 10000,
8+
},
9+
forbidOnly: !!process.env.CI,
10+
fullyParallel: false,
11+
maxFailures: 0,
12+
reporter: process.env.CI ? 'html' : 'list',
13+
retries: process.env.CI ? 2 : 0,
14+
testDir: '../e2e',
15+
timeout: 60000,
16+
workers: 1,
17+
18+
projects: [
19+
{
20+
name: 'chromium',
21+
use: {
22+
...devices['Desktop Chrome'],
23+
},
24+
testIgnore: /.*\.setup\.ts/,
25+
},
26+
{
27+
name: 'mobile-chrome',
28+
use: {
29+
...devices['Pixel 5'],
30+
},
31+
dependencies: ['chromium'],
32+
testIgnore: /.*\.setup\.ts/,
33+
},
34+
],
35+
36+
use: {
37+
baseURL: BASE_URL,
38+
trace: 'on-first-retry',
39+
screenshot: 'only-on-failure',
40+
video: 'on-first-retry',
41+
actionTimeout: 15000,
42+
navigationTimeout: 30000,
43+
},
44+
})

0 commit comments

Comments
 (0)