Skip to content

Commit 6c6aab5

Browse files
committed
test: stablize playwright tests
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
1 parent 519c475 commit 6c6aab5

11 files changed

Lines changed: 279 additions & 120 deletions

‎package-lock.json‎

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

‎package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@
7373
},
7474
"devDependencies": {
7575
"@nextcloud/browserslist-config": "^3.1.2",
76-
"@nextcloud/e2e-test-server": "^0.4.0",
76+
"@nextcloud/e2e-test-server": "^0.5.0",
7777
"@nextcloud/eslint-config": "^9.0.0-rc.9",
7878
"@nextcloud/stylelint-config": "^3.2.2",
7979
"@nextcloud/typings": "^1.10.0",

‎tests/playwright/e2e/appstore/admin-settings-apps.spec.ts‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,9 @@ import { handlePasswordConfirmation } from '../../support/utils/password-confirm
1111
test.describe('Settings: App management', () => {
1212
test.beforeEach(async ({ appstorePage }) => {
1313
// Disable QA testing app if already enabled
14-
expect(await runOcc(['app:disable', 'testing']))
15-
.toMatch(/(No such app enabled|testing .+ disabled)/)
14+
await runOcc(['app:disable', 'testing'], { failOnError: false })
1615
// Enable update notification app if disabled
17-
expect(await runOcc(['app:enable', 'updatenotification']))
18-
.toMatch(/(updatenotification already enabled|updatenotification .+ enabled)/)
16+
await runOcc(['app:enable', 'updatenotification'], { failOnError: false })
1917

2018
// Open the installed apps page
2119
await appstorePage.openInstalledApps()

‎tests/playwright/e2e/files/files-download.spec.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,13 +216,13 @@ test.describe('Files: Download files using selection', () => {
216216
* uid, which `createRandomUser()` cannot produce, so it provisions its own
217217
* user via the docker helper and logs in at the API level.
218218
*/
219-
test('can download selected files with email uid', async ({ page, context, filesListPage }) => {
219+
test('can download selected files with email uid', async ({ page, filesListPage }) => {
220220
const randomString = (length: number) => Math.random().toString(36).slice(2, 2 + length)
221221
const uid = `${randomString(5)}@${randomString(3)}`
222222
const emailUser = new User(uid, uid, 'en')
223223

224224
await addUser(emailUser)
225-
await login(context.request, emailUser)
225+
await login(page.request, emailUser)
226226

227227
try {
228228
await uploadContent(page.request, emailUser, '<content>', 'text/plain', '/file.txt')

‎tests/playwright/e2e/files_external/admin-settings-home-folder-root-mount.spec.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,6 @@ test('Does not show write actions on read-only storage mounted at the root of th
4444

4545
/** Read the `overwrites_home_folders` files app config as a trimmed string. */
4646
async function getOverwritesHomeFolders(): Promise<string> {
47-
const result = await runOcc(['config:app:get', 'files', 'overwrites_home_folders', '--default-value=[]'])
48-
return result.trim()
47+
const { stdout } = await runOcc(['config:app:get', 'files', 'overwrites_home_folders', '--default-value=[]'])
48+
return stdout.trim()
4949
}

‎tests/playwright/e2e/users/users-groups.spec.ts‎

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,9 @@ userGroupTest('Account Management: Assign user to a group', async ({ page, testG
7474
// user is now group now shows 1 member
7575
await expect(settingsPage.groupMemberCount(testGroup)).toHaveText('1')
7676
// backend confirms the user is in the group
77-
const info = JSON.parse(await runOcc(['user:info', '--output=json', user.userId]))
78-
expect(info?.groups).toContain(testGroup)
77+
const { stdout: jsonList } = await runOcc(['user:info', '--output=json', user.userId])
78+
const { groups } = JSON.parse(jsonList)
79+
expect(groups).toContain(testGroup)
7980
})
8081

8182
// ── Delete an empty group ─────────────────────────────────────────────────────
@@ -108,7 +109,10 @@ test.describe('Settings: Delete an empty group', () => {
108109
await expect(settingsPage.groupListItem(groupName)).toHaveCount(0)
109110

110111
// Verify backend
111-
const groups: Record<string, unknown> = JSON.parse(await runOcc(['group:list', '--output=json']))
112+
// `group:list --output=json` returns the group map directly ({"name":[members]}),
113+
// with no `groups` wrapper — unlike `user:info`.
114+
const { stdout: jsonList } = await runOcc(['group:list', '--output=json'])
115+
const groups = JSON.parse(jsonList)
112116
expect(Object.keys(groups)).not.toContain(groupName)
113117
})
114118
})
@@ -145,7 +149,10 @@ test.describe('Settings: Delete a non-empty group', () => {
145149

146150
await expect(settingsPage.groupListItem(groupName)).toHaveCount(0)
147151

148-
const groups: Record<string, unknown> = JSON.parse(await runOcc(['group:list', '--output=json']))
152+
// `group:list --output=json` returns the group map directly ({"name":[members]}),
153+
// with no `groups` wrapper — unlike `user:info`.
154+
const { stdout: jsonList } = await runOcc(['group:list', '--output=json'])
155+
const groups = JSON.parse(jsonList)
149156
expect(Object.keys(groups)).not.toContain(groupName)
150157
})
151158
})

‎tests/playwright/e2e/users/users-modify.spec.ts‎

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ test.describe('Settings: Change user properties', () => {
2727
await expect(page.getByText(/Account updated/i)).toBeVisible()
2828

2929
// Verify backend
30-
const info = JSON.parse(await runOcc(['user:info', '--output=json', user.userId]))
30+
const { stdout: jsonList } = await runOcc(['user:info', '--output=json', user.userId])
31+
const info = JSON.parse(jsonList)
3132
expect(info?.display_name).toBe('John Doe')
3233
})
3334

@@ -68,7 +69,8 @@ test.describe('Settings: Change user properties', () => {
6869
await expect(page.getByText(/Account updated/i)).toBeVisible()
6970

7071
// Verify backend
71-
const info = JSON.parse(await runOcc(['user:info', '--output=json', user.userId]))
72+
const { stdout: jsonList } = await runOcc(['user:info', '--output=json', user.userId])
73+
const info = JSON.parse(jsonList)
7274
expect(info?.email).toBe('mymail@example.com')
7375
})
7476

@@ -90,7 +92,8 @@ test.describe('Settings: Change user properties', () => {
9092
await expect(page.getByText(/Account updated/i)).toBeVisible()
9193

9294
// Verify backend
93-
const info = JSON.parse(await runOcc(['user:info', '--output=json', user.userId]))
95+
const { stdout: jsonList } = await runOcc(['user:info', '--output=json', user.userId])
96+
const info = JSON.parse(jsonList)
9497
expect(info?.quota).toBe('5 GB')
9598
})
9699

@@ -112,7 +115,8 @@ test.describe('Settings: Change user properties', () => {
112115
await expect(page.getByText(/Account updated/i)).toBeVisible()
113116

114117
// Verify backend (stored as bytes)
115-
const info = JSON.parse(await runOcc(['user:info', '--output=json', user.userId]))
118+
const { stdout: jsonList } = await runOcc(['user:info', '--output=json', user.userId])
119+
const info = JSON.parse(jsonList)
116120
expect(info?.quota).not.toBe('none')
117121
})
118122

‎tests/playwright/support/fixtures/random-user-session.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ export const test = randomUserTest.extend({
1515
const page = await browser.newPage()
1616
try {
1717
await login(page.request, user)
18-
} catch {
19-
// Retry once on transient auth failure
18+
} catch (error) {
19+
console.info('Failed to authenticate as random user, retrying', error)
2020
await new Promise((resolve) => setTimeout(resolve, 800))
2121
await login(page.request, user)
2222
}

‎tests/playwright/support/fixtures/random-user.ts‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,15 @@ import { test as baseTest } from '@playwright/test'
1515
*/
1616
export const test = baseTest.extend<{ user: User }>({
1717
user: async ({}, use) => {
18-
const user = await createRandomUser()
18+
let user: User
19+
try {
20+
user = await createRandomUser()
21+
} catch {
22+
// Retry once on transient failure
23+
await new Promise((resolve) => setTimeout(resolve, 800))
24+
user = await createRandomUser()
25+
}
1926
await use(user)
20-
await runOcc(['user:delete', user.userId]).catch(() => {})
27+
await runOcc(['user:delete', user.userId], { failOnError: false })
2128
},
2229
})

‎tests/playwright/support/utils/files_external.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export async function createStorageWithConfig(
6161
command.push('--user', user.userId)
6262
}
6363

64-
const stdout = await runOcc(command)
64+
const { stdout } = await runOcc(command)
6565
// Plain output is "Storage created with id <id>"; keep only the trailing id
6666
return stdout.replace('Storage created with id ', '').trim()
6767
}
@@ -83,7 +83,7 @@ export async function setStorageMountOptions(mountId: string, options: StorageMo
8383
* listed here, so this is safe to call without disturbing the per-user specs.
8484
*/
8585
export async function deleteAllGlobalStorages(): Promise<void> {
86-
const stdout = await runOcc(['files_external:list', '--output=json'])
86+
const { stdout } = await runOcc(['files_external:list', '--output=json'])
8787
const list = JSON.parse(stdout) as Array<{ mount_id: number }>
8888
for (const { mount_id: mountId } of list) {
8989
await runOcc(['files_external:delete', String(mountId), '--yes'])

0 commit comments

Comments
 (0)