diff --git a/frontend/src/routes/settings/admin/application-configuration/+page.svelte b/frontend/src/routes/settings/admin/application-configuration/+page.svelte
index e8a9df12..432768ef 100644
--- a/frontend/src/routes/settings/admin/application-configuration/+page.svelte
+++ b/frontend/src/routes/settings/admin/application-configuration/+page.svelte
@@ -1,18 +1,14 @@
diff --git a/tests/specs/api.spec.ts b/tests/specs/api.spec.ts
index dd5a1aef..613e6dab 100644
--- a/tests/specs/api.spec.ts
+++ b/tests/specs/api.spec.ts
@@ -108,8 +108,8 @@ test('Grant a client user-delegated and client access to API permissions', async
// Nextcloud has no API access granted by default
await page.goto(`/settings/admin/oidc-clients/${oidcClients.nextcloud.id}`);
- // Expand the API access card, then edit the Orders API row
- await page.getByText('API access', { exact: true }).click();
+ // Open the API access tab, then edit the Orders API row
+ await page.getByRole('tab', { name: 'API access' }).click();
await page
.getByRole('row', { name: apis.orders.name })
.getByRole('button', { name: 'Edit' })
diff --git a/tests/specs/application-configuration.spec.ts b/tests/specs/application-configuration.spec.ts
index 0a619b76..8bc80fce 100644
--- a/tests/specs/application-configuration.spec.ts
+++ b/tests/specs/application-configuration.spec.ts
@@ -30,14 +30,14 @@ test('Update general configuration', async ({ page }) => {
test.describe('Update user creation configuration', () => {
test.beforeEach(async ({ page }) => {
- await page.getByRole('button', { name: 'Expand card' }).nth(1).click();
+ await page.getByRole('tab', { name: 'User Creation' }).click();
});
test('should save sign up mode', async ({ page }) => {
await page.getByRole('button', { name: 'Enable User Signups' }).click();
await page.getByRole('option', { name: 'Open Signup' }).click();
- await page.getByRole('button', { name: 'Save' }).nth(1).click();
+ await page.getByRole('button', { name: 'Save' }).click();
await expect(page.locator('[data-type="success"]').last()).toHaveText(
'User creation settings updated successfully.'
@@ -59,7 +59,7 @@ test.describe('Update user creation configuration', () => {
await expect(designersOption).toBeChecked();
await page.keyboard.press('Escape');
- await page.getByRole('button', { name: 'Save' }).nth(1).click();
+ await page.getByRole('button', { name: 'Save' }).click();
await expect(page.locator('[data-type="success"]').last()).toHaveText(
'User creation settings updated successfully.'
@@ -81,7 +81,7 @@ test.describe('Update user creation configuration', () => {
await page.getByPlaceholder('Key').nth(1).fill('another-claim');
await page.getByPlaceholder('Value').nth(1).fill('another-value');
- await page.getByRole('button', { name: 'Save' }).nth(1).click();
+ await page.getByRole('button', { name: 'Save' }).click();
await expect(page.locator('[data-type="success"]').last()).toHaveText(
'User creation settings updated successfully.'
@@ -97,7 +97,7 @@ test.describe('Update user creation configuration', () => {
});
test('Update email configuration', async ({ page }) => {
- await page.getByRole('button', { name: 'Expand card' }).nth(2).click();
+ await page.getByRole('tab', { name: 'Email' }).click();
await page.getByLabel('SMTP Host').fill('smtp.gmail.com');
await page.getByLabel('SMTP Port').fill('587');
@@ -109,7 +109,7 @@ test('Update email configuration', async ({ page }) => {
await page.getByLabel('Email Login Code from Admin').click();
await page.getByLabel('API Key Expiration').click();
- await page.getByRole('button', { name: 'Save' }).nth(1).click();
+ await page.getByRole('button', { name: 'Save' }).click();
await expect(page.locator('[data-type="success"]')).toHaveText(
'Email configuration updated successfully'
@@ -130,7 +130,7 @@ test('Update email configuration', async ({ page }) => {
test.describe('Update application images', () => {
test.beforeEach(async ({ page }) => {
- await page.getByRole('button', { name: 'Expand card' }).nth(4).click();
+ await page.getByRole('tab', { name: 'Images' }).click();
});
test('should upload images', async ({ page }) => {
@@ -144,7 +144,7 @@ test.describe('Update application images', () => {
.getByLabel('Default Profile Picture')
.setInputFiles('resources/images/pingvin-share-logo.png');
await page.getByLabel('Background Image').setInputFiles('resources/images/clouds.jpg');
- await page.getByRole('button', { name: 'Save' }).last().click();
+ await page.getByRole('button', { name: 'Save' }).click();
await expect(page.locator('[data-type="success"]')).toHaveText(
'Images updated successfully. It may take a few minutes to update.'
@@ -171,7 +171,7 @@ test.describe('Update application images', () => {
const emailLogoInput = page.getByLabel('Email Logo');
await emailLogoInput.setInputFiles('resources/images/cloud-logo.svg');
- await page.getByRole('button', { name: 'Save' }).last().click();
+ await page.getByRole('button', { name: 'Save' }).click();
await expect(page.locator('[data-type="error"]')).toHaveText(
'File must be of type .png or .jpg/jpeg'
diff --git a/tests/specs/ldap.spec.ts b/tests/specs/ldap.spec.ts
index ed77da60..85074e54 100644
--- a/tests/specs/ldap.spec.ts
+++ b/tests/specs/ldap.spec.ts
@@ -12,7 +12,7 @@ test.describe('LDAP Integration', () => {
test('LDAP configuration is working properly', async ({ page }) => {
await page.goto('/settings/admin/application-configuration');
- await page.getByRole('button', { name: 'Expand card' }).nth(3).click();
+ await page.getByRole('tab', { name: 'LDAP' }).click();
await expect(page.getByRole('button', { name: 'Disable', exact: true })).toBeVisible();
await expect(page.getByLabel('LDAP URL')).toHaveValue(/ldap:\/\/.*/);
diff --git a/tests/specs/oidc-client-settings.spec.ts b/tests/specs/oidc-client-settings.spec.ts
index ad41a640..577b7124 100644
--- a/tests/specs/oidc-client-settings.spec.ts
+++ b/tests/specs/oidc-client-settings.spec.ts
@@ -161,13 +161,14 @@ test('Filter OIDC clients by PAR requirement', async ({ page, request }) => {
test('Update OIDC client allowed user groups', async ({ page }) => {
await page.goto(`/settings/admin/oidc-clients/${oidcClients.nextcloud.id}`);
+ await page.getByRole('tab', { name: 'Allowed user groups' }).click();
await page.getByRole('button', { name: 'Restrict' }).click();
await page.getByRole('row', { name: userGroups.designers.name }).getByRole('checkbox').click();
await page.getByRole('row', { name: userGroups.developers.name }).getByRole('checkbox').click();
- await page.getByRole('button', { name: 'Save' }).nth(1).click();
+ await page.getByRole('button', { name: 'Save' }).click();
await expect(page.getByText('Allowed user groups updated successfully')).toBeVisible();
diff --git a/tests/specs/oidc.spec.ts b/tests/specs/oidc.spec.ts
index 76b55713..f556b331 100644
--- a/tests/specs/oidc.spec.ts
+++ b/tests/specs/oidc.spec.ts
@@ -1520,7 +1520,9 @@ test.describe('OIDC skip consent', () => {
// Disabling it and saving must persist across a reload
await toggle.click();
+ await expect(toggle).not.toBeChecked();
await page.getByRole('button', { name: /save/i }).click();
+ await expect(page.getByText('OIDC client updated successfully', { exact: true })).toBeVisible();
await page.reload();
await expect(page.getByRole('switch', { name: 'Skip Consent Screen' })).not.toBeChecked();
diff --git a/tests/specs/scim.spec.ts b/tests/specs/scim.spec.ts
index 2b7ccafe..8b775d84 100644
--- a/tests/specs/scim.spec.ts
+++ b/tests/specs/scim.spec.ts
@@ -5,7 +5,7 @@ import { oidcClients, userGroups, users } from '../data';
async function configureOidcClient(page: Page) {
await page.goto(`/settings/admin/oidc-clients/${oidcClients.scim.id}`);
- await page.getByText('SCIM Provisioning', { exact: true }).click();
+ await page.getByRole('tab', { name: 'SCIM Provisioning' }).click();
await page
.getByLabel('SCIM Endpoint')
@@ -16,6 +16,7 @@ async function configureOidcClient(page: Page) {
async function syncScimServiceProvider(page: Page) {
await page.goto(`/settings/admin/oidc-clients/${oidcClients.scim.id}`);
+ await page.getByRole('tab', { name: 'SCIM Provisioning' }).click();
await page.getByRole('button', { name: 'Sync now' }).click();
await page.waitForSelector('[data-type="success"]');
@@ -29,7 +30,7 @@ test.describe('SCIM Configuration', () => {
test('Enable SCIM for OIDC client', async ({ page }) => {
await page.goto(`/settings/admin/oidc-clients/${oidcClients.scim.id}`);
- await page.getByText('SCIM Provisioning', { exact: true }).click();
+ await page.getByRole('tab', { name: 'SCIM Provisioning' }).click();
await page.getByLabel('SCIM Endpoint').fill('http://scim.provider/api');
await page.getByLabel('SCIM Token').fill('supersecrettoken');
@@ -48,11 +49,12 @@ test.describe('SCIM Configuration', () => {
await configureOidcClient(page);
await page.goto(`/settings/admin/oidc-clients/${oidcClients.scim.id}`);
+ await page.getByRole('tab', { name: 'SCIM Provisioning' }).click();
await page.getByLabel('SCIM Endpoint').fill('http://new.scim.provider/api');
await page.getByLabel('SCIM Token').fill('evenmoresecrettoken');
- await page.getByRole('button', { name: 'Save' }).nth(1).click();
+ await page.getByRole('button', { name: 'Save' }).click();
await expect(page.locator('[data-type="success"]')).toHaveText(
'SCIM configuration updated successfully.'
@@ -68,6 +70,7 @@ test.describe('SCIM Configuration', () => {
await configureOidcClient(page);
await page.goto(`/settings/admin/oidc-clients/${oidcClients.scim.id}`);
+ await page.getByRole('tab', { name: 'SCIM Provisioning' }).click();
await page.getByRole('button', { name: 'Disable' }).click();
await page.getByRole('button', { name: 'Disable' }).nth(1).click();
@@ -123,15 +126,16 @@ test.describe('SCIM Sync', () => {
test('Remove allowed group and sync', async ({ page }) => {
await syncScimServiceProvider(page);
- await page.getByRole('button', { name: 'Expand card' }).first().click();
+ await page.getByRole('tab', { name: 'Allowed user groups' }).click();
- await page
+ const developersCheckbox = page
.getByRole('row', { name: userGroups.developers.name })
- .getByRole('cell')
- .first()
- .click();
+ .getByRole('checkbox');
+ await developersCheckbox.click();
+ await expect(developersCheckbox).toHaveAttribute('data-state', 'unchecked');
- await page.getByRole('button', { name: 'Save' }).nth(1).click();
+ await page.getByRole('button', { name: 'Save' }).click();
+ await expect(page.getByText('Allowed user groups updated successfully', { exact: true })).toBeVisible();
await syncScimServiceProvider(page);
@@ -149,7 +153,7 @@ test.describe('SCIM Sync', () => {
test('Remove group restrictions and sync', async ({ page }) => {
await syncScimServiceProvider(page);
- await page.getByRole('button', { name: 'Expand card' }).first().click();
+ await page.getByRole('tab', { name: 'Allowed user groups' }).click();
await page.getByRole('button', { name: 'Unrestrict' }).click();
await page.getByRole('button', { name: 'Unrestrict' }).nth(1).click();
diff --git a/tests/specs/user-group.spec.ts b/tests/specs/user-group.spec.ts
index 590cce1a..a58b08e5 100644
--- a/tests/specs/user-group.spec.ts
+++ b/tests/specs/user-group.spec.ts
@@ -44,11 +44,12 @@ test('Edit user group', async ({ page }) => {
test('Update user group users', async ({ page }) => {
const group = userGroups.designers;
await page.goto(`/settings/admin/user-groups/${group.id}`);
+ await page.getByRole('tab', { name: 'Users' }).click();
await page.getByRole('row', { name: users.tim.username }).getByRole('checkbox').click();
await page.getByRole('row', { name: users.craig.username }).getByRole('checkbox').click();
- await page.getByRole('button', { name: 'Save' }).nth(1).click();
+ await page.getByRole('button', { name: 'Save' }).click();
await expect(page.locator('[data-type="success"]')).toHaveText('Users updated successfully');
@@ -77,7 +78,7 @@ test('Delete user group', async ({ page }) => {
test('Update user group custom claims', async ({ page }) => {
await page.goto(`/settings/admin/user-groups/${userGroups.designers.id}`);
- await page.getByRole('button', { name: 'Expand card' }).first().click();
+ await page.getByRole('tab', { name: 'Custom Claims' }).click();
// Add two custom claims
await page.getByRole('button', { name: 'Add custom claim' }).click();
@@ -89,7 +90,7 @@ test('Update user group custom claims', async ({ page }) => {
await page.getByPlaceholder('Key').nth(1).fill('customClaim2');
await page.getByPlaceholder('Value').nth(1).fill('customClaim2_value');
- await page.getByRole('button', { name: 'Save' }).nth(2).click();
+ await page.getByRole('button', { name: 'Save' }).click();
await expect(page.locator('[data-type="success"]')).toHaveText(
'Custom claims updated successfully'
@@ -106,7 +107,7 @@ test('Update user group custom claims', async ({ page }) => {
// Remove one custom claim
await page.getByLabel('Remove custom claim').first().click();
- await page.getByRole('button', { name: 'Save' }).nth(2).click();
+ await page.getByRole('button', { name: 'Save' }).click();
await expect(page.locator('[data-type="success"]')).toHaveText(
'Custom claims updated successfully'
@@ -123,7 +124,7 @@ test('Update user group custom claims', async ({ page }) => {
test('Update user group allowed user groups', async ({ page }) => {
await page.goto(`/settings/admin/user-groups/${userGroups.designers.id}`);
- await page.getByRole('button', { name: 'Expand card' }).nth(1).click();
+ await page.getByRole('tab', { name: 'Allowed OIDC Clients' }).click();
// Unrestricted OIDC clients should be checked and disabled
const nextcloudRow = page
@@ -135,7 +136,7 @@ test('Update user group allowed user groups', async ({ page }) => {
await page.getByRole('row', { name: oidcClients.tailscale.name }).getByRole('checkbox').click();
await page.getByRole('row', { name: oidcClients.immich.name }).getByRole('checkbox').click();
- await page.getByRole('button', { name: 'Save' }).nth(2).click();
+ await page.getByRole('button', { name: 'Save' }).click();
await expect(page.locator('[data-type="success"]')).toHaveText(
'Allowed OIDC clients updated successfully'
diff --git a/tests/specs/user-settings.spec.ts b/tests/specs/user-settings.spec.ts
index 84cd1d87..38ee694b 100644
--- a/tests/specs/user-settings.spec.ts
+++ b/tests/specs/user-settings.spec.ts
@@ -187,7 +187,7 @@ test('Update user fails with already taken username in different casing', async
test('Update user custom claims', async ({ page }) => {
await page.goto(`/settings/admin/users/${users.craig.id}`);
- await page.getByRole('button', { name: 'Expand card' }).nth(1).click();
+ await page.getByRole('tab', { name: 'Custom Claims' }).click();
// Add two custom claims
await page.getByRole('button', { name: 'Add custom claim' }).click();
@@ -199,7 +199,7 @@ test('Update user custom claims', async ({ page }) => {
await page.getByPlaceholder('Key').nth(1).fill('customClaim2');
await page.getByPlaceholder('Value').nth(1).fill('customClaim2_value');
- await page.getByRole('button', { name: 'Save' }).nth(1).click();
+ await page.getByRole('button', { name: 'Save' }).click();
await expect(page.locator('[data-type="success"]')).toHaveText(
'Custom claims updated successfully'
@@ -215,7 +215,7 @@ test('Update user custom claims', async ({ page }) => {
// Remove one custom claim
await page.getByLabel('Remove custom claim').first().click();
- await page.getByRole('button', { name: 'Save' }).nth(1).click();
+ await page.getByRole('button', { name: 'Save' }).click();
await expect(page.locator('[data-type="success"]')).toHaveText(
'Custom claims updated successfully'
@@ -232,12 +232,12 @@ test('Update user group assignments', async ({ page }) => {
const user = users.craig;
await page.goto(`/settings/admin/users/${user.id}`);
- page.getByRole('button', { name: 'Expand card' }).first().click();
+ await page.getByRole('tab', { name: 'User Groups' }).click();
await page.getByRole('row', { name: userGroups.developers.name }).getByRole('checkbox').click();
await page.getByRole('row', { name: userGroups.designers.name }).getByRole('checkbox').click();
- await page.getByRole('button', { name: 'Save' }).nth(1).click();
+ await page.getByRole('button', { name: 'Save' }).click();
await expect(page.locator('[data-type="success"]')).toHaveText(
'User groups updated successfully'
@@ -255,6 +255,7 @@ test('Update user group assignments', async ({ page }) => {
test('Admin can view another user passkeys', async ({ page }) => {
await page.goto(`/settings/admin/users/${users.craig.id}`);
+ await page.getByRole('tab', { name: 'Passkeys' }).click();
await expect(page.getByText('Passkey 2')).toBeVisible();
await expect(page.getByText(/Added on/)).toBeVisible();
@@ -262,8 +263,13 @@ test('Admin can view another user passkeys', async ({ page }) => {
test('Admin can delete another user passkey and audit log is created', async ({ page }) => {
await page.goto(`/settings/admin/users/${users.craig.id}`);
+ await page.getByRole('tab', { name: 'Passkeys' }).click();
- await page.locator('[data-slot="item"]').filter({ hasText: 'Passkey 2' }).getByLabel('Delete').click();
+ await page
+ .locator('[data-slot="item"]')
+ .filter({ hasText: 'Passkey 2' })
+ .getByLabel('Delete')
+ .click();
await page.getByRole('alertdialog').getByRole('button', { name: 'Delete' }).click();
await expect(page.locator('[data-type="success"]')).toHaveText('Passkey deleted successfully');
diff --git a/tests/specs/user-signup.spec.ts b/tests/specs/user-signup.spec.ts
index 1ad2ae16..2871bfc1 100644
--- a/tests/specs/user-signup.spec.ts
+++ b/tests/specs/user-signup.spec.ts
@@ -10,10 +10,10 @@ async function setSignupMode(
) {
await page.goto('/settings/admin/application-configuration');
- await page.getByRole('button', { name: 'Expand card' }).nth(1).click();
+ await page.getByRole('tab', { name: 'User Creation' }).click();
await page.getByRole('button', { name: 'Enable User Signups' }).click();
await page.getByRole('option', { name: mode }).click();
- await page.getByRole('button', { name: 'Save' }).nth(1).click();
+ await page.getByRole('button', { name: 'Save' }).click();
await expect(page.locator('[data-type="success"]').last()).toHaveText(
'User creation settings updated successfully.'