Skip to content

Commit 20fb022

Browse files
authored
test(playwright): remove redundant openNextBlockFromCockpit in word cloud test (#5146)
1 parent d6c7772 commit 20fb022

7 files changed

Lines changed: 218 additions & 48 deletions

File tree

.github/scripts/get-shard-files.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
const fs = require('fs');
2+
const path = require('path');
3+
4+
const shardIndex = parseInt(process.argv[2], 10);
5+
if (isNaN(shardIndex) || shardIndex < 1 || shardIndex > 5) {
6+
console.error('Invalid shard index. Must be between 1 and 5.');
7+
process.exit(1);
8+
}
9+
10+
const testsDir = path.join(__dirname, '../../playwright/tests');
11+
const allFiles = fs.readdirSync(testsDir).filter(file => file.endsWith('.spec.ts'));
12+
13+
// Load timings from playwright/timings.json
14+
const timingsPath = path.join(__dirname, '../../playwright/timings.json');
15+
let timings = { durations: [] };
16+
if (fs.existsSync(timingsPath)) {
17+
try {
18+
timings = JSON.parse(fs.readFileSync(timingsPath, 'utf8'));
19+
} catch (err) {
20+
console.error('Error parsing timings.json:', err);
21+
}
22+
}
23+
24+
// Map of spec file to duration
25+
const durationMap = new Map();
26+
for (const entry of timings.durations) {
27+
// Normalize spec path to just the filename
28+
const baseName = path.basename(entry.spec);
29+
durationMap.set(baseName, entry.duration);
30+
}
31+
32+
// Map each file to its estimated/historical duration
33+
const filesWithDuration = allFiles.map(file => {
34+
return {
35+
file,
36+
duration: durationMap.has(file) ? durationMap.get(file) : 30 // default to 30s for new tests
37+
};
38+
});
39+
40+
// Sort files by duration descending for the greedy bin-packing algorithm
41+
filesWithDuration.sort((a, b) => b.duration - a.duration);
42+
43+
// Initialize 5 shards
44+
const numShards = 5;
45+
const shards = Array.from({ length: numShards }, () => ({
46+
files: [],
47+
totalDuration: 0
48+
}));
49+
50+
// Distribute files using greedy bin-packing
51+
for (const item of filesWithDuration) {
52+
// Find the shard with the smallest total duration
53+
let minShard = shards[0];
54+
for (let i = 1; i < numShards; i++) {
55+
if (shards[i].totalDuration < minShard.totalDuration) {
56+
minShard = shards[i];
57+
}
58+
}
59+
minShard.files.push(item.file);
60+
minShard.totalDuration += item.duration;
61+
}
62+
63+
// Select the files for the requested shard
64+
const targetFiles = shards[shardIndex - 1].files;
65+
66+
// Map files to their relative path from the playwright package directory
67+
const relativePaths = targetFiles.map(file => `tests/${file}`);
68+
console.log(relativePaths.join(' '));

.github/workflows/cypress-testing.yml

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,6 @@
11
name: Klicker automated testing with cypress
22
on:
3-
push:
4-
branches: ['v3', 'v3*']
5-
# paths:
6-
# - apps/**
7-
# - packages/**
8-
pull_request:
9-
branches: ['v3', 'v3*']
10-
types: [opened, synchronize, reopened, ready_for_review]
11-
paths:
12-
- apps/**
13-
- packages/**
14-
- cypress/**
15-
- .github/workflows/cypress-testing.yml
16-
- util/_with_local_test_origins.sh
17-
- package.json
3+
workflow_dispatch:
184

195
concurrency:
206
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref_name }}

.github/workflows/playwright-testing.yml

Lines changed: 115 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,112 @@ env:
2626
REGISTRY: ghcr.io
2727

2828
jobs:
29+
build-and-compile:
30+
runs-on: ubuntu-24.04
31+
steps:
32+
- name: Define node version
33+
uses: actions/setup-node@v4
34+
with:
35+
node-version: 24
36+
37+
- name: Check out repository code
38+
uses: actions/checkout@v4
39+
40+
- uses: pnpm/action-setup@v4
41+
with:
42+
version: 11.5.0
43+
run_install: false
44+
45+
- name: Get pnpm store directory
46+
shell: bash
47+
run: |
48+
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
49+
50+
- name: Setup pnpm cache
51+
uses: actions/cache@v4
52+
with:
53+
path: |
54+
${{ env.STORE_PATH }}
55+
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
56+
restore-keys: |
57+
${{ runner.os }}-pnpm-store-
58+
59+
- name: Cache turbo build artifacts
60+
uses: actions/cache@v4
61+
with:
62+
path: |
63+
.turbo
64+
key: ${{ runner.os }}-turbo-${{ hashFiles('**/pnpm-lock.yaml', 'turbo.json') }}-${{ github.ref_name }}
65+
restore-keys: |
66+
${{ runner.os }}-turbo-${{ hashFiles('**/pnpm-lock.yaml', 'turbo.json') }}-
67+
${{ runner.os }}-turbo-
68+
69+
- name: Install dependencies
70+
run: pnpm install
71+
72+
- name: Build all packages and apps
73+
run: pnpm run --filter @klicker-uzh/prisma build:test && pnpm run build:test
74+
env:
75+
APP_SECRET: abcd
76+
DATABASE_URL: postgres://klicker-prod:klicker@localhost:5432/klicker-prod
77+
NODE_ENV: test
78+
REDIS_HOST: localhost
79+
REDIS_PASS: ''
80+
REDIS_PORT: 6379
81+
REDIS_CACHE_HOST: localhost
82+
REDIS_CACHE_PORT: 6379
83+
REDIS_ASSESSMENT_PORT: 6379
84+
REDIS_ASSESSMENT_PASS: ''
85+
REDIS_ASSESSMENT_HOST: localhost
86+
APP_ORIGIN_API: http://127.0.0.1:3000
87+
APP_ORIGIN_AUTH: http://127.0.0.1:3010
88+
APP_ORIGIN_LTI: http://127.0.0.1:4000
89+
APP_ORIGIN_PWA: http://127.0.0.1:3001
90+
APP_ORIGIN_MANAGE: http://127.0.0.1:3002
91+
APP_ORIGIN_CONTROL: http://127.0.0.1:3003
92+
APP_ORIGIN_ASSESSMENT_API: http://127.0.0.1:3000
93+
APP_ORIGIN_ASSESSMENT_PWA: http://127.0.0.1:3001
94+
95+
- name: Upload Playwright build outputs
96+
uses: actions/upload-artifact@v4
97+
with:
98+
name: playwright-build-artifact
99+
include-hidden-files: true
100+
path: |
101+
apps/auth/.next
102+
!apps/auth/.next/cache/**
103+
!apps/auth/.next/standalone/**
104+
apps/chat/.next
105+
!apps/chat/.next/cache/**
106+
!apps/chat/.next/standalone/**
107+
apps/frontend-control/.next
108+
!apps/frontend-control/.next/cache/**
109+
!apps/frontend-control/.next/standalone/**
110+
apps/frontend-manage/.next
111+
!apps/frontend-manage/.next/cache/**
112+
!apps/frontend-manage/.next/standalone/**
113+
apps/frontend-pwa/.next
114+
!apps/frontend-pwa/.next/cache/**
115+
!apps/frontend-pwa/.next/standalone/**
116+
apps/backend-docker/dist
117+
apps/hatchet-worker-general/dist
118+
apps/hatchet-worker-response-processor/dist
119+
apps/lti/dist
120+
apps/mcp-lecturer/dist
121+
apps/olat-api/dist
122+
apps/response-api/dist
123+
packages/export/dist
124+
packages/grading/dist
125+
packages/graphql/dist
126+
packages/hatchet/dist
127+
packages/markdown/dist
128+
packages/prisma/dist
129+
packages/types/dist
130+
packages/util/dist
131+
retention-days: 1
132+
29133
playwright-run:
134+
needs: build-and-compile
30135
runs-on: ubuntu-24.04
31136
container:
32137
image: mcr.microsoft.com/playwright:v1.58.2-noble
@@ -141,41 +246,18 @@ jobs:
141246
restore-keys: |
142247
${{ runner.os }}-pnpm-store-
143248
144-
- name: Cache turbo build artifacts
145-
uses: actions/cache@v4
146-
with:
147-
path: |
148-
.turbo
149-
key: ${{ runner.os }}-turbo-${{ hashFiles('**/pnpm-lock.yaml', 'turbo.json') }}-${{ github.ref_name }}
150-
restore-keys: |
151-
${{ runner.os }}-turbo-${{ hashFiles('**/pnpm-lock.yaml', 'turbo.json') }}-
152-
${{ runner.os }}-turbo-
153-
154249
- name: Install dependencies
155250
run: pnpm install
156251

157-
- name: Build all packages and apps
158-
run: pnpm run --filter @klicker-uzh/prisma build:test && pnpm run build:test
252+
- name: Download Playwright build outputs
253+
uses: actions/download-artifact@v4
254+
with:
255+
name: playwright-build-artifact
256+
257+
- name: Generate Prisma Client
258+
run: pnpm --filter @klicker-uzh/prisma generate
159259
env:
160-
APP_SECRET: abcd
161260
DATABASE_URL: postgres://klicker-prod:klicker@postgres:5432/klicker-prod
162-
NODE_ENV: test
163-
REDIS_HOST: redis_exec
164-
REDIS_PASS: ''
165-
REDIS_PORT: 6379
166-
REDIS_CACHE_HOST: redis_cache
167-
REDIS_CACHE_PORT: 6379
168-
REDIS_ASSESSMENT_PORT: 6379
169-
REDIS_ASSESSMENT_PASS: ''
170-
REDIS_ASSESSMENT_HOST: redis_assessment_exec
171-
APP_ORIGIN_API: http://127.0.0.1:3000
172-
APP_ORIGIN_AUTH: http://127.0.0.1:3010
173-
APP_ORIGIN_LTI: http://127.0.0.1:4000
174-
APP_ORIGIN_PWA: http://127.0.0.1:3001
175-
APP_ORIGIN_MANAGE: http://127.0.0.1:3002
176-
APP_ORIGIN_CONTROL: http://127.0.0.1:3003
177-
APP_ORIGIN_ASSESSMENT_API: http://127.0.0.1:3000
178-
APP_ORIGIN_ASSESSMENT_PWA: http://127.0.0.1:3001
179261

180262
- name: Prepare .env files
181263
run: |
@@ -200,11 +282,13 @@ jobs:
200282
timeout-minutes: 120
201283
run: |
202284
chmod +x .github/scripts/wait-for-services.sh
285+
TEST_FILES=$(node .github/scripts/get-shard-files.js ${{ matrix.shardIndex }})
286+
echo "Running tests for shard ${{ matrix.shardIndex }}: $TEST_FILES"
203287
.github/scripts/wait-for-services.sh -- \
204288
env NODE_ENV=test \
205289
pnpm --filter @klicker-uzh/playwright exec playwright test \
206290
--project=chromium \
207-
--shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
291+
$TEST_FILES
208292
env:
209293
APP_SECRET: abcd
210294
DATABASE_URL: postgres://klicker-prod:klicker@postgres:5432/klicker-prod

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@
8686
"release:rc:dry": "standard-version --dry-run --prerelease rc",
8787
"start": "turbo run start",
8888
"start:playwright": "run-s --npm-path pnpm build:test start:playwright:ci",
89-
"start:playwright:ci": "bash ./util/_with_local_test_origins.sh cross-env NODE_ENV=test turbo run start:test",
89+
"start:playwright:ci": "bash ./util/_with_local_test_origins.sh cross-env NODE_ENV=test turbo run start:test --filter=@klicker-uzh/frontend-manage --filter=@klicker-uzh/frontend-pwa --filter=@klicker-uzh/auth --filter=@klicker-uzh/chat --filter=@klicker-uzh/backend-docker --filter=@klicker-uzh/response-api --filter=@klicker-uzh/frontend-control --filter=@klicker-uzh/hatchet-worker-general --filter=@klicker-uzh/hatchet-worker-response-processor",
9090
"start:test": "run-s --npm-path pnpm build:test start:test:ci",
9191
"start:test:ci": "bash ./util/_with_local_test_origins.sh cross-env NODE_ENV=test turbo run start:test",
9292
"syncpack:format": "syncpack format",

playwright/tests/O-live-quiz.spec.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6608,7 +6608,6 @@ test.describe.serial('Different live-quiz workflows', () => {
66086608
await page
66096609
.getByTestId(`live-quiz-cockpit-${data.liveQuizWordCloud.name}`)
66106610
.click()
6611-
await openNextBlockFromCockpit(page)
66126611
await visitEvaluationFromCockpit(page)
66136612
await selectWordCloudChart(page)
66146613

playwright/tests/U-catalog.spec.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ test.describe
189189
ownership ? 'exist' : 'not.exist'
190190
)
191191
await page.getByTestId('close-share-object').click({ force: true })
192+
await expect(page.getByTestId('close-share-object')).toBeHidden()
192193
await clickCatalogCollectionAction(
193194
data.CCPublic,
194195
'delete-catalog-collection'
@@ -1143,6 +1144,7 @@ test.describe
11431144
'exist'
11441145
)
11451146
await page.getByTestId('close-share-object').click({ force: true })
1147+
await expect(page.getByTestId('close-share-object')).toBeHidden()
11461148
await clickCatalogCollectionAction(
11471149
data.CCRestricted,
11481150
'delete-catalog-collection'

playwright/timings.json

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"durations": [
3+
{ "spec": "tests/0-baseline-ops.spec.ts", "duration": 12 },
4+
{ "spec": "tests/A-login.spec.ts", "duration": 37 },
5+
{ "spec": "tests/B-feature-access.spec.ts", "duration": 21 },
6+
{ "spec": "tests/C-control.spec.ts", "duration": 17 },
7+
{ "spec": "tests/D-elements-content.spec.ts", "duration": 12 },
8+
{ "spec": "tests/E-elements-flashcards.spec.ts", "duration": 13 },
9+
{ "spec": "tests/F-elements-sc.spec.ts", "duration": 25 },
10+
{ "spec": "tests/G-elements-mc.spec.ts", "duration": 31 },
11+
{ "spec": "tests/H-elements-kprim.spec.ts", "duration": 25 },
12+
{ "spec": "tests/I-elements-numerical.spec.ts", "duration": 23 },
13+
{ "spec": "tests/J-elements-free-text.spec.ts", "duration": 14 },
14+
{ "spec": "tests/K-elements-selection.spec.ts", "duration": 40 },
15+
{ "spec": "tests/L-elements-case-study.spec.ts", "duration": 155 },
16+
{ "spec": "tests/MA-elements-operations.spec.ts", "duration": 255 },
17+
{ "spec": "tests/MB-instance-updates.spec.ts", "duration": 92 },
18+
{ "spec": "tests/N-course.spec.ts", "duration": 273 },
19+
{ "spec": "tests/O-live-quiz.spec.ts", "duration": 1288 },
20+
{ "spec": "tests/P-microlearning.spec.ts", "duration": 531 },
21+
{ "spec": "tests/Q-practice-quiz.spec.ts", "duration": 381 },
22+
{ "spec": "tests/R-bookmarking.spec.ts", "duration": 67 },
23+
{ "spec": "tests/S-group-activity.spec.ts", "duration": 572 },
24+
{ "spec": "tests/T-resources.spec.ts", "duration": 330 },
25+
{ "spec": "tests/U-catalog.spec.ts", "duration": 420 },
26+
{ "spec": "tests/V-template.spec.ts", "duration": 528 },
27+
{ "spec": "tests/W-activity-log.spec.ts", "duration": 119 },
28+
{ "spec": "tests/X-review.spec.ts", "duration": 208 },
29+
{ "spec": "tests/Y-chat.spec.ts", "duration": 120 }
30+
]
31+
}

0 commit comments

Comments
 (0)