1
0
mirror of https://github.com/pocket-id/pocket-id.git synced 2026-02-04 17:24:48 +00:00

refactor: add formatter to Playwright tests

This commit is contained in:
Elias Schneider
2025-06-27 23:33:26 +02:00
parent d070b9a778
commit 73e7e0b1c5
22 changed files with 1581 additions and 1764 deletions

View File

@@ -1,135 +1,116 @@
import test, { expect } from "@playwright/test";
import { users } from "../data";
import authUtil from "../utils/auth.util";
import { cleanupBackend } from "../utils/cleanup.util";
import passkeyUtil from "../utils/passkey.util";
import test, { expect } from '@playwright/test';
import { users } from '../data';
import authUtil from '../utils/auth.util';
import { cleanupBackend } from '../utils/cleanup.util';
import passkeyUtil from '../utils/passkey.util';
test.beforeEach(cleanupBackend);
test("Update account details", async ({ page }) => {
await page.goto("/settings/account");
test('Update account details', async ({ page }) => {
await page.goto('/settings/account');
await page.getByLabel("First name").fill("Timothy");
await page.getByLabel("Last name").fill("Apple");
await page.getByLabel("Email").fill("timothy.apple@test.com");
await page.getByLabel("Username").fill("timothy");
await page.getByRole("button", { name: "Save" }).click();
await page.getByLabel('First name').fill('Timothy');
await page.getByLabel('Last name').fill('Apple');
await page.getByLabel('Email').fill('timothy.apple@test.com');
await page.getByLabel('Username').fill('timothy');
await page.getByRole('button', { name: 'Save' }).click();
await expect(page.locator('[data-type="success"]')).toHaveText(
"Account details updated successfully"
);
await expect(page.locator('[data-type="success"]')).toHaveText(
'Account details updated successfully'
);
});
test("Update account details fails with already taken email", async ({
page,
}) => {
await page.goto("/settings/account");
test('Update account details fails with already taken email', async ({ page }) => {
await page.goto('/settings/account');
await page.getByLabel("Email").fill(users.craig.email);
await page.getByLabel('Email').fill(users.craig.email);
await page.getByRole("button", { name: "Save" }).click();
await page.getByRole('button', { name: 'Save' }).click();
await expect(page.locator('[data-type="error"]')).toHaveText(
"Email is already in use"
);
await expect(page.locator('[data-type="error"]')).toHaveText('Email is already in use');
});
test("Update account details fails with already taken username", async ({
page,
}) => {
await page.goto("/settings/account");
test('Update account details fails with already taken username', async ({ page }) => {
await page.goto('/settings/account');
await page.getByLabel("Username").fill(users.craig.username);
await page.getByLabel('Username').fill(users.craig.username);
await page.getByRole("button", { name: "Save" }).click();
await page.getByRole('button', { name: 'Save' }).click();
await expect(page.locator('[data-type="error"]')).toHaveText(
"Username is already in use"
);
await expect(page.locator('[data-type="error"]')).toHaveText('Username is already in use');
});
test("Change Locale", async ({ page }) => {
await page.goto("/settings/account");
test('Change Locale', async ({ page }) => {
await page.goto('/settings/account');
await page.getByLabel("Select Locale").click();
await page.getByRole("option", { name: "Nederlands" }).click();
await page.getByLabel('Select Locale').click();
await page.getByRole('option', { name: 'Nederlands' }).click();
// Check if th language heading now says 'Taal' instead of 'Language'
await expect(page.getByText("Taal", { exact: true })).toBeVisible();
// Check if th language heading now says 'Taal' instead of 'Language'
await expect(page.getByText('Taal', { exact: true })).toBeVisible();
// Check if the validation messages are translated because they are provided by Zod
await page.getByRole("textbox", { name: "Voornaam" }).fill("");
await page.getByRole("button", { name: "Opslaan" }).click();
await expect(page.getByText("Te kort: verwacht dat string")).toBeVisible();
// Check if the validation messages are translated because they are provided by Zod
await page.getByRole('textbox', { name: 'Voornaam' }).fill('');
await page.getByRole('button', { name: 'Opslaan' }).click();
await expect(page.getByText('Te kort: verwacht dat string')).toBeVisible();
// Clear all cookies and sign in again to check if the language is still set to Dutch
await page.context().clearCookies();
await authUtil.authenticate(page);
// Clear all cookies and sign in again to check if the language is still set to Dutch
await page.context().clearCookies();
await authUtil.authenticate(page);
await expect(page.getByText("Taal", { exact: true })).toBeVisible();
await expect(page.getByText('Taal', { exact: true })).toBeVisible();
await page.getByRole("textbox", { name: "Voornaam" }).fill("");
await page.getByRole("button", { name: "Opslaan" }).click();
await expect(page.getByText("Te kort: verwacht dat string")).toBeVisible();
await page.getByRole('textbox', { name: 'Voornaam' }).fill('');
await page.getByRole('button', { name: 'Opslaan' }).click();
await expect(page.getByText('Te kort: verwacht dat string')).toBeVisible();
});
test("Add passkey to an account", async ({ page }) => {
await page.goto("/settings/account");
test('Add passkey to an account', async ({ page }) => {
await page.goto('/settings/account');
await (await passkeyUtil.init(page)).addPasskey("timNew");
await (await passkeyUtil.init(page)).addPasskey('timNew');
await page.getByRole("button", { name: "Add Passkey" }).click();
await page.getByRole('button', { name: 'Add Passkey' }).click();
await page.getByLabel("Name", { exact: true }).fill("Test Passkey");
await page
.getByLabel("Name Passkey")
.getByRole("button", { name: "Save" })
.click();
await page.getByLabel('Name', { exact: true }).fill('Test Passkey');
await page.getByLabel('Name Passkey').getByRole('button', { name: 'Save' }).click();
await expect(page.getByText("Test Passkey")).toBeVisible();
await expect(page.getByText('Test Passkey')).toBeVisible();
});
test("Rename passkey", async ({ page }) => {
await page.goto("/settings/account");
test('Rename passkey', async ({ page }) => {
await page.goto('/settings/account');
await page.getByLabel("Rename").first().click();
await page.getByLabel('Rename').first().click();
await page.getByLabel("Name", { exact: true }).fill("Renamed Passkey");
await page
.getByLabel("Name Passkey")
.getByRole("button", { name: "Save" })
.click();
await page.getByLabel('Name', { exact: true }).fill('Renamed Passkey');
await page.getByLabel('Name Passkey').getByRole('button', { name: 'Save' }).click();
await expect(page.getByText("Renamed Passkey")).toBeVisible();
await expect(page.getByText('Renamed Passkey')).toBeVisible();
});
test("Delete passkey from account", async ({ page }) => {
await page.goto("/settings/account");
test('Delete passkey from account', async ({ page }) => {
await page.goto('/settings/account');
await page.getByLabel("Delete").first().click();
await page.getByText("Delete", { exact: true }).click();
await page.getByLabel('Delete').first().click();
await page.getByText('Delete', { exact: true }).click();
await expect(page.locator('[data-type="success"]')).toHaveText(
"Passkey deleted successfully"
);
await expect(page.locator('[data-type="success"]')).toHaveText('Passkey deleted successfully');
});
test("Generate own one time access token as non admin", async ({
page,
context,
}) => {
await context.clearCookies();
await page.goto("/login");
await (await passkeyUtil.init(page)).addPasskey("craig");
test('Generate own one time access token as non admin', async ({ page, context }) => {
await context.clearCookies();
await page.goto('/login');
await (await passkeyUtil.init(page)).addPasskey('craig');
await page.getByRole("button", { name: "Authenticate" }).click();
await page.waitForURL("/settings/account");
await page.getByRole('button', { name: 'Authenticate' }).click();
await page.waitForURL('/settings/account');
await page.getByRole("button", { name: "Create" }).click();
const link = await page.getByTestId("login-code-link").textContent();
await page.getByRole('button', { name: 'Create' }).click();
const link = await page.getByTestId('login-code-link').textContent();
await context.clearCookies();
await context.clearCookies();
await page.goto(link!);
await page.waitForURL("/settings/account");
await page.goto(link!);
await page.waitForURL('/settings/account');
});

View File

@@ -1,79 +1,70 @@
// frontend/tests/api-key.spec.ts
import { expect, test } from "@playwright/test";
import { apiKeys } from "../data";
import { cleanupBackend } from "../utils/cleanup.util";
import { expect, test } from '@playwright/test';
import { apiKeys } from '../data';
import { cleanupBackend } from '../utils/cleanup.util';
test.describe("API Key Management", () => {
test.beforeEach(async ({ page }) => {
await cleanupBackend();
await page.goto("/settings/admin/api-keys");
});
test.describe('API Key Management', () => {
test.beforeEach(async ({ page }) => {
await cleanupBackend();
await page.goto('/settings/admin/api-keys');
});
test("Create new API key", async ({ page }) => {
await page.getByRole("button", { name: "Add API Key" }).click();
test('Create new API key', async ({ page }) => {
await page.getByRole('button', { name: 'Add API Key' }).click();
// Fill out the API key form
const name = "New Test API Key";
await page.getByLabel("Name").fill(name);
await page.getByLabel("Description").fill("Created by automated test");
// Fill out the API key form
const name = 'New Test API Key';
await page.getByLabel('Name').fill(name);
await page.getByLabel('Description').fill('Created by automated test');
// Choose the date
const currentDate = new Date();
await page.getByRole("button", { name: "Select a date" }).click();
await page.getByLabel("Select year").click();
// Select the next year
await page.getByText((currentDate.getFullYear() + 1).toString()).click();
// Select the first day of the month
await page
.getByRole("button", { name: /([A-Z][a-z]+), ([A-Z][a-z]+) 1, (\d{4})/ })
.first()
.click();
// Choose the date
const currentDate = new Date();
await page.getByRole('button', { name: 'Select a date' }).click();
await page.getByLabel('Select year').click();
// Select the next year
await page.getByText((currentDate.getFullYear() + 1).toString()).click();
// Select the first day of the month
await page
.getByRole('button', { name: /([A-Z][a-z]+), ([A-Z][a-z]+) 1, (\d{4})/ })
.first()
.click();
// Submit the form
await page.getByRole("button", { name: "Save" }).click();
// Submit the form
await page.getByRole('button', { name: 'Save' }).click();
// Verify the success dialog appears
await expect(
page.getByRole("heading", { name: "API Key Created" })
).toBeVisible();
// Verify the success dialog appears
await expect(page.getByRole('heading', { name: 'API Key Created' })).toBeVisible();
// Verify the key details are shown
await expect(page.getByRole("cell", { name })).toBeVisible();
// Verify the key details are shown
await expect(page.getByRole('cell', { name })).toBeVisible();
// Verify the token is displayed (should be 32 characters)
const token = await page.locator(".font-mono").textContent();
expect(token?.length).toBe(32);
// Verify the token is displayed (should be 32 characters)
const token = await page.locator('.font-mono').textContent();
expect(token?.length).toBe(32);
// Close the dialog
await page
.getByRole("button", { name: "Close", exact: true })
.nth(1)
.click();
// Close the dialog
await page.getByRole('button', { name: 'Close', exact: true }).nth(1).click();
await page.reload();
await page.reload();
// Verify the key appears in the list
await expect(page.getByRole("cell", { name }).first()).toContainText(name);
});
// Verify the key appears in the list
await expect(page.getByRole('cell', { name }).first()).toContainText(name);
});
test("Revoke API key", async ({ page }) => {
const apiKey = apiKeys[0];
test('Revoke API key', async ({ page }) => {
const apiKey = apiKeys[0];
await page
.getByRole("row", { name: apiKey.name })
.getByRole("button", { name: "Revoke" })
.click();
await page
.getByRole('row', { name: apiKey.name })
.getByRole('button', { name: 'Revoke' })
.click();
await page.getByText("Revoke", { exact: true }).click();
await page.getByText('Revoke', { exact: true }).click();
// Verify success message
await expect(page.locator('[data-type="success"]')).toHaveText(
"API key revoked successfully"
);
// Verify success message
await expect(page.locator('[data-type="success"]')).toHaveText('API key revoked successfully');
// Verify key is no longer in the list
await expect(
page.getByRole("cell", { name: apiKey.name })
).not.toBeVisible();
});
// Verify key is no longer in the list
await expect(page.getByRole('cell', { name: apiKey.name })).not.toBeVisible();
});
});

View File

@@ -1,99 +1,83 @@
import test, { expect } from "@playwright/test";
import { cleanupBackend } from "../utils/cleanup.util";
import test, { expect } from '@playwright/test';
import { cleanupBackend } from '../utils/cleanup.util';
test.beforeEach(cleanupBackend);
test("Update general configuration", async ({ page }) => {
await page.goto("/settings/admin/application-configuration");
test('Update general configuration', async ({ page }) => {
await page.goto('/settings/admin/application-configuration');
await page
.getByLabel("Application Name", { exact: true })
.fill("Updated Name");
await page.getByLabel("Session Duration").fill("30");
await page.getByRole("button", { name: "Save" }).first().click();
await page.getByLabel('Application Name', { exact: true }).fill('Updated Name');
await page.getByLabel('Session Duration').fill('30');
await page.getByRole('button', { name: 'Save' }).first().click();
await expect(page.locator('[data-type="success"]')).toHaveText(
"Application configuration updated successfully"
);
await expect(page.getByTestId("application-name")).toHaveText("Updated Name");
await expect(page.locator('[data-type="success"]')).toHaveText(
'Application configuration updated successfully'
);
await expect(page.getByTestId('application-name')).toHaveText('Updated Name');
await page.reload();
await page.reload();
await expect(
page.getByLabel("Application Name", { exact: true })
).toHaveValue("Updated Name");
await expect(page.getByLabel("Session Duration")).toHaveValue("30");
await expect(page.getByLabel('Application Name', { exact: true })).toHaveValue('Updated Name');
await expect(page.getByLabel('Session Duration')).toHaveValue('30');
});
test("Update email configuration", async ({ page }) => {
await page.goto("/settings/admin/application-configuration");
test('Update email configuration', async ({ page }) => {
await page.goto('/settings/admin/application-configuration');
await page.getByRole("button", { name: "Expand card" }).nth(1).click();
await page.getByRole('button', { name: 'Expand card' }).nth(1).click();
await page.getByLabel("SMTP Host").fill("smtp.gmail.com");
await page.getByLabel("SMTP Port").fill("587");
await page.getByLabel("SMTP User").fill("test@gmail.com");
await page.getByLabel("SMTP Password").fill("password");
await page.getByLabel("SMTP From").fill("test@gmail.com");
await page.getByLabel("Email Login Notification").click();
await page.getByLabel("Email Login Code Requested by User").click();
await page.getByLabel("Email Login Code from Admin").click();
await page.getByLabel("API Key Expiration").click();
await page.getByLabel('SMTP Host').fill('smtp.gmail.com');
await page.getByLabel('SMTP Port').fill('587');
await page.getByLabel('SMTP User').fill('test@gmail.com');
await page.getByLabel('SMTP Password').fill('password');
await page.getByLabel('SMTP From').fill('test@gmail.com');
await page.getByLabel('Email Login Notification').click();
await page.getByLabel('Email Login Code Requested by User').click();
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' }).nth(1).click();
await expect(page.locator('[data-type="success"]')).toHaveText(
"Email configuration updated successfully"
);
await expect(page.locator('[data-type="success"]')).toHaveText(
'Email configuration updated successfully'
);
await page.reload();
await page.reload();
await expect(page.getByLabel("SMTP Host")).toHaveValue("smtp.gmail.com");
await expect(page.getByLabel("SMTP Port")).toHaveValue("587");
await expect(page.getByLabel("SMTP User")).toHaveValue("test@gmail.com");
await expect(page.getByLabel("SMTP Password")).toHaveValue("password");
await expect(page.getByLabel("SMTP From")).toHaveValue("test@gmail.com");
await expect(page.getByLabel("Email Login Notification")).toBeChecked();
await expect(
page.getByLabel("Email Login Code Requested by User")
).toBeChecked();
await expect(page.getByLabel("Email Login Code from Admin")).toBeChecked();
await expect(page.getByLabel("API Key Expiration")).toBeChecked();
await expect(page.getByLabel('SMTP Host')).toHaveValue('smtp.gmail.com');
await expect(page.getByLabel('SMTP Port')).toHaveValue('587');
await expect(page.getByLabel('SMTP User')).toHaveValue('test@gmail.com');
await expect(page.getByLabel('SMTP Password')).toHaveValue('password');
await expect(page.getByLabel('SMTP From')).toHaveValue('test@gmail.com');
await expect(page.getByLabel('Email Login Notification')).toBeChecked();
await expect(page.getByLabel('Email Login Code Requested by User')).toBeChecked();
await expect(page.getByLabel('Email Login Code from Admin')).toBeChecked();
await expect(page.getByLabel('API Key Expiration')).toBeChecked();
});
test("Update application images", async ({ page }) => {
await page.goto("/settings/admin/application-configuration");
test('Update application images', async ({ page }) => {
await page.goto('/settings/admin/application-configuration');
await page.getByRole("button", { name: "Expand card" }).nth(3).click();
await page.getByRole('button', { name: 'Expand card' }).nth(3).click();
await page
.getByLabel("Favicon")
.setInputFiles("assets/w3-schools-favicon.ico");
await page
.getByLabel("Light Mode Logo")
.setInputFiles("assets/pingvin-share-logo.png");
await page
.getByLabel("Dark Mode Logo")
.setInputFiles("assets/nextcloud-logo.png");
await page
.getByLabel("Background Image")
.setInputFiles("assets/clouds.jpg");
await page.getByRole("button", { name: "Save" }).nth(1).click();
await page.getByLabel('Favicon').setInputFiles('assets/w3-schools-favicon.ico');
await page.getByLabel('Light Mode Logo').setInputFiles('assets/pingvin-share-logo.png');
await page.getByLabel('Dark Mode Logo').setInputFiles('assets/nextcloud-logo.png');
await page.getByLabel('Background Image').setInputFiles('assets/clouds.jpg');
await page.getByRole('button', { name: 'Save' }).nth(1).click();
await expect(page.locator('[data-type="success"]')).toHaveText(
"Images updated successfully"
);
await expect(page.locator('[data-type="success"]')).toHaveText('Images updated successfully');
await page.request
.get("/api/application-configuration/favicon")
.then((res) => expect.soft(res.status()).toBe(200));
await page.request
.get("/api/application-configuration/logo?light=true")
.then((res) => expect.soft(res.status()).toBe(200));
await page.request
.get("/api/application-configuration/logo?light=false")
.then((res) => expect.soft(res.status()).toBe(200));
await page.request
.get("/api/application-configuration/background-image")
.then((res) => expect.soft(res.status()).toBe(200));
await page.request
.get('/api/application-configuration/favicon')
.then((res) => expect.soft(res.status()).toBe(200));
await page.request
.get('/api/application-configuration/logo?light=true')
.then((res) => expect.soft(res.status()).toBe(200));
await page.request
.get('/api/application-configuration/logo?light=false')
.then((res) => expect.soft(res.status()).toBe(200));
await page.request
.get('/api/application-configuration/background-image')
.then((res) => expect.soft(res.status()).toBe(200));
});

View File

@@ -4,85 +4,94 @@ import { cleanupBackend } from '../utils/cleanup.util';
test.beforeEach(cleanupBackend);
test.describe('LDAP Integration', () => {
test.skip(process.env.SKIP_LDAP_TESTS === 'true', 'Skipping LDAP tests due to SKIP_LDAP_TESTS environment variable');
test.skip(
process.env.SKIP_LDAP_TESTS === 'true',
'Skipping LDAP tests due to SKIP_LDAP_TESTS environment variable'
);
test('LDAP configuration is working properly', async ({ page }) => {
await page.goto('/settings/admin/application-configuration');
test('LDAP configuration is working properly', async ({ page }) => {
await page.goto('/settings/admin/application-configuration');
await page.getByRole('button', { name: 'Expand card' }).nth(2).click();
await page.getByRole('button', { name: 'Expand card' }).nth(2).click();
await expect(page.getByRole('button', { name: 'Disable', exact: true })).toBeVisible();
await expect(page.getByLabel('LDAP URL')).toHaveValue(/ldap:\/\/.*/);
await expect(page.getByLabel('LDAP Base DN')).not.toBeEmpty();
await expect(page.getByRole('button', { name: 'Disable', exact: true })).toBeVisible();
await expect(page.getByLabel('LDAP URL')).toHaveValue(/ldap:\/\/.*/);
await expect(page.getByLabel('LDAP Base DN')).not.toBeEmpty();
await expect(page.getByLabel('User Unique Identifier Attribute')).not.toBeEmpty();
await expect(page.getByLabel('Username Attribute')).not.toBeEmpty();
await expect(page.getByLabel('User Mail Attribute')).not.toBeEmpty();
await expect(page.getByLabel('Group Name Attribute')).not.toBeEmpty();
await expect(page.getByLabel('User Unique Identifier Attribute')).not.toBeEmpty();
await expect(page.getByLabel('Username Attribute')).not.toBeEmpty();
await expect(page.getByLabel('User Mail Attribute')).not.toBeEmpty();
await expect(page.getByLabel('Group Name Attribute')).not.toBeEmpty();
const syncButton = page.getByRole('button', { name: 'Sync now' });
await syncButton.click();
await expect(page.locator('[data-type="success"]')).toHaveText('LDAP sync finished');
});
const syncButton = page.getByRole('button', { name: 'Sync now' });
await syncButton.click();
await expect(page.locator('[data-type="success"]')).toHaveText('LDAP sync finished');
});
test('LDAP users are synced into PocketID', async ({ page }) => {
// Navigate to user management
await page.goto('/settings/admin/users');
test('LDAP users are synced into PocketID', async ({ page }) => {
// Navigate to user management
await page.goto('/settings/admin/users');
// Verify the LDAP users exist
await expect(page.getByText('testuser1@pocket-id.org')).toBeVisible();
await expect(page.getByText('testuser2@pocket-id.org')).toBeVisible();
// Verify the LDAP users exist
await expect(page.getByText('testuser1@pocket-id.org')).toBeVisible();
await expect(page.getByText('testuser2@pocket-id.org')).toBeVisible();
// Check LDAP user details
await page.getByRole('row', { name: 'testuser1' }).getByRole('button').click();
await page.getByRole('menuitem', { name: 'Edit' }).click();
// Check LDAP user details
await page.getByRole('row', { name: 'testuser1' }).getByRole('button').click();
await page.getByRole('menuitem', { name: 'Edit' }).click();
// Verify user source is LDAP
await expect(page.getByText('LDAP').first()).toBeVisible();
// Verify user source is LDAP
await expect(page.getByText('LDAP').first()).toBeVisible();
// Verify essential fields are filled
await expect(page.getByLabel('Username')).not.toBeEmpty();
await expect(page.getByLabel('Email')).not.toBeEmpty();
});
// Verify essential fields are filled
await expect(page.getByLabel('Username')).not.toBeEmpty();
await expect(page.getByLabel('Email')).not.toBeEmpty();
});
test('LDAP groups are synced into PocketID', async ({ page }) => {
// Navigate to user groups
await page.goto('/settings/admin/user-groups');
test('LDAP groups are synced into PocketID', async ({ page }) => {
// Navigate to user groups
await page.goto('/settings/admin/user-groups');
// Verify LDAP groups exist
await expect(page.getByRole('cell', { name: 'test_group' }).first()).toBeVisible();
await expect(page.getByRole('cell', { name: 'admin_group' }).first()).toBeVisible();
// Verify LDAP groups exist
await expect(page.getByRole('cell', { name: 'test_group' }).first()).toBeVisible();
await expect(page.getByRole('cell', { name: 'admin_group' }).first()).toBeVisible();
await page.getByRole('row', { name: 'test_group' }).getByRole('button', { name: 'Toggle menu' }).click();
await page.getByRole('menuitem', { name: 'Edit' }).click();
await page
.getByRole('row', { name: 'test_group' })
.getByRole('button', { name: 'Toggle menu' })
.click();
await page.getByRole('menuitem', { name: 'Edit' }).click();
// Verify group source is LDAP
await expect(page.getByText('LDAP').first()).toBeVisible();
});
// Verify group source is LDAP
await expect(page.getByText('LDAP').first()).toBeVisible();
});
test('LDAP users cannot be modified in PocketID', async ({ page }) => {
// Navigate to LDAP user details
await page.goto('/settings/admin/users');
await page.waitForLoadState('networkidle');
test('LDAP users cannot be modified in PocketID', async ({ page }) => {
// Navigate to LDAP user details
await page.goto('/settings/admin/users');
await page.waitForLoadState('networkidle');
await page.getByRole('row', { name: 'testuser1' }).getByRole('button').click();
await page.getByRole('menuitem', { name: 'Edit' }).click();
await page.getByRole('row', { name: 'testuser1' }).getByRole('button').click();
await page.getByRole('menuitem', { name: 'Edit' }).click();
// Verify key fields are disabled
const usernameInput = page.getByLabel('Username');
await expect(usernameInput).toBeDisabled();
});
// Verify key fields are disabled
const usernameInput = page.getByLabel('Username');
await expect(usernameInput).toBeDisabled();
});
test('LDAP groups cannot be modified in PocketID', async ({ page }) => {
// Navigate to LDAP group details
await page.goto('/settings/admin/user-groups');
await page.waitForLoadState('networkidle');
test('LDAP groups cannot be modified in PocketID', async ({ page }) => {
// Navigate to LDAP group details
await page.goto('/settings/admin/user-groups');
await page.waitForLoadState('networkidle');
await page.getByRole('row', { name: 'test_group' }).getByRole('button', { name: 'Toggle menu' }).click();
await page.getByRole('menuitem', { name: 'Edit' }).click();
await page
.getByRole('row', { name: 'test_group' })
.getByRole('button', { name: 'Toggle menu' })
.click();
await page.getByRole('menuitem', { name: 'Edit' }).click();
// Verify key fields are disabled
const nameInput = page.getByLabel('Name', { exact: true });
await expect(nameInput).toBeDisabled();
});
// Verify key fields are disabled
const nameInput = page.getByLabel('Name', { exact: true });
await expect(nameInput).toBeDisabled();
});
});

View File

@@ -1,100 +1,80 @@
import test, { expect } from "@playwright/test";
import { oidcClients } from "../data";
import { cleanupBackend } from "../utils/cleanup.util";
import test, { expect } from '@playwright/test';
import { oidcClients } from '../data';
import { cleanupBackend } from '../utils/cleanup.util';
test.beforeEach(cleanupBackend);
test("Create OIDC client", async ({ page }) => {
await page.goto("/settings/admin/oidc-clients");
const oidcClient = oidcClients.pingvinShare;
test('Create OIDC client', async ({ page }) => {
await page.goto('/settings/admin/oidc-clients');
const oidcClient = oidcClients.pingvinShare;
await page.getByRole("button", { name: "Add OIDC Client" }).click();
await page.getByLabel("Name").fill(oidcClient.name);
await page.getByRole('button', { name: 'Add OIDC Client' }).click();
await page.getByLabel('Name').fill(oidcClient.name);
await page.getByRole("button", { name: "Add" }).nth(1).click();
await page.getByTestId("callback-url-1").fill(oidcClient.callbackUrl);
await page.getByRole("button", { name: "Add another" }).click();
await page.getByTestId("callback-url-2").fill(oidcClient.secondCallbackUrl!);
await page.getByRole('button', { name: 'Add' }).nth(1).click();
await page.getByTestId('callback-url-1').fill(oidcClient.callbackUrl);
await page.getByRole('button', { name: 'Add another' }).click();
await page.getByTestId('callback-url-2').fill(oidcClient.secondCallbackUrl!);
await page.getByLabel("logo").setInputFiles("assets/pingvin-share-logo.png");
await page.getByRole("button", { name: "Save" }).click();
await page.getByLabel('logo').setInputFiles('assets/pingvin-share-logo.png');
await page.getByRole('button', { name: 'Save' }).click();
const clientId = await page.getByTestId("client-id").textContent();
const clientId = await page.getByTestId('client-id').textContent();
await expect(page.locator('[data-type="success"]')).toHaveText(
"OIDC client created successfully"
);
expect(clientId?.length).toBe(36);
expect((await page.getByTestId("client-secret").textContent())?.length).toBe(
32
);
await expect(page.getByLabel("Name")).toHaveValue(oidcClient.name);
await expect(page.getByTestId("callback-url-1")).toHaveValue(
oidcClient.callbackUrl
);
await expect(page.getByTestId("callback-url-2")).toHaveValue(
oidcClient.secondCallbackUrl!
);
await expect(
page.getByRole("img", { name: `${oidcClient.name} logo` })
).toBeVisible();
await page.request
.get(`/api/oidc/clients/${clientId}/logo`)
.then((res) => expect.soft(res.status()).toBe(200));
await expect(page.locator('[data-type="success"]')).toHaveText(
'OIDC client created successfully'
);
expect(clientId?.length).toBe(36);
expect((await page.getByTestId('client-secret').textContent())?.length).toBe(32);
await expect(page.getByLabel('Name')).toHaveValue(oidcClient.name);
await expect(page.getByTestId('callback-url-1')).toHaveValue(oidcClient.callbackUrl);
await expect(page.getByTestId('callback-url-2')).toHaveValue(oidcClient.secondCallbackUrl!);
await expect(page.getByRole('img', { name: `${oidcClient.name} logo` })).toBeVisible();
await page.request
.get(`/api/oidc/clients/${clientId}/logo`)
.then((res) => expect.soft(res.status()).toBe(200));
});
test("Edit OIDC client", async ({ page }) => {
const oidcClient = oidcClients.nextcloud;
await page.goto(`/settings/admin/oidc-clients/${oidcClient.id}`);
test('Edit OIDC client', async ({ page }) => {
const oidcClient = oidcClients.nextcloud;
await page.goto(`/settings/admin/oidc-clients/${oidcClient.id}`);
await page.getByLabel("Name").fill("Nextcloud updated");
await page
.getByTestId("callback-url-1")
.first()
.fill("http://nextcloud-updated/auth/callback");
await page.getByLabel("logo").setInputFiles("assets/nextcloud-logo.png");
await page.getByRole("button", { name: "Save" }).click();
await page.getByLabel('Name').fill('Nextcloud updated');
await page.getByTestId('callback-url-1').first().fill('http://nextcloud-updated/auth/callback');
await page.getByLabel('logo').setInputFiles('assets/nextcloud-logo.png');
await page.getByRole('button', { name: 'Save' }).click();
await expect(page.locator('[data-type="success"]')).toHaveText(
"OIDC client updated successfully"
);
await expect(
page.getByRole("img", { name: "Nextcloud updated logo" })
).toBeVisible();
await page.request
.get(`/api/oidc/clients/${oidcClient.id}/logo`)
.then((res) => expect.soft(res.status()).toBe(200));
await expect(page.locator('[data-type="success"]')).toHaveText(
'OIDC client updated successfully'
);
await expect(page.getByRole('img', { name: 'Nextcloud updated logo' })).toBeVisible();
await page.request
.get(`/api/oidc/clients/${oidcClient.id}/logo`)
.then((res) => expect.soft(res.status()).toBe(200));
});
test("Create new OIDC client secret", async ({ page }) => {
const oidcClient = oidcClients.nextcloud;
await page.goto(`/settings/admin/oidc-clients/${oidcClient.id}`);
test('Create new OIDC client secret', async ({ page }) => {
const oidcClient = oidcClients.nextcloud;
await page.goto(`/settings/admin/oidc-clients/${oidcClient.id}`);
await page.getByLabel("Create new client secret").click();
await page.getByRole("button", { name: "Generate" }).click();
await page.getByLabel('Create new client secret').click();
await page.getByRole('button', { name: 'Generate' }).click();
await expect(page.locator('[data-type="success"]')).toHaveText(
"New client secret created successfully"
);
expect((await page.getByTestId("client-secret").textContent())?.length).toBe(
32
);
await expect(page.locator('[data-type="success"]')).toHaveText(
'New client secret created successfully'
);
expect((await page.getByTestId('client-secret').textContent())?.length).toBe(32);
});
test("Delete OIDC client", async ({ page }) => {
const oidcClient = oidcClients.nextcloud;
await page.goto("/settings/admin/oidc-clients");
test('Delete OIDC client', async ({ page }) => {
const oidcClient = oidcClients.nextcloud;
await page.goto('/settings/admin/oidc-clients');
await page
.getByRole("row", { name: oidcClient.name })
.getByLabel("Delete")
.click();
await page.getByText("Delete", { exact: true }).click();
await page.getByRole('row', { name: oidcClient.name }).getByLabel('Delete').click();
await page.getByText('Delete', { exact: true }).click();
await expect(page.locator('[data-type="success"]')).toHaveText(
"OIDC client deleted successfully"
);
await expect(
page.getByRole("row", { name: oidcClient.name })
).not.toBeVisible();
await expect(page.locator('[data-type="success"]')).toHaveText(
'OIDC client deleted successfully'
);
await expect(page.getByRole('row', { name: oidcClient.name })).not.toBeVisible();
});

File diff suppressed because it is too large Load Diff

View File

@@ -1,48 +1,48 @@
import test, { expect } from "@playwright/test";
import { oneTimeAccessTokens } from "../data";
import { cleanupBackend } from "../utils/cleanup.util";
import test, { expect } from '@playwright/test';
import { oneTimeAccessTokens } from '../data';
import { cleanupBackend } from '../utils/cleanup.util';
test.beforeEach(cleanupBackend);
// Disable authentication for these tests
test.use({ storageState: { cookies: [], origins: [] } });
test("Sign in with login code", async ({ page }) => {
const token = oneTimeAccessTokens.filter((t) => !t.expired)[0];
await page.goto(`/lc/${token.token}`);
test('Sign in with login code', async ({ page }) => {
const token = oneTimeAccessTokens.filter((t) => !t.expired)[0];
await page.goto(`/lc/${token.token}`);
await page.waitForURL("/settings/account");
await page.waitForURL('/settings/account');
});
test("Sign in with login code entered manually", async ({ page }) => {
const token = oneTimeAccessTokens.filter((t) => !t.expired)[0];
await page.goto("/lc");
test('Sign in with login code entered manually', async ({ page }) => {
const token = oneTimeAccessTokens.filter((t) => !t.expired)[0];
await page.goto('/lc');
await page.getByPlaceholder("Code").first().fill(token.token);
await page.getByPlaceholder('Code').first().fill(token.token);
await page.getByText("Submit").first().click();
await page.getByText('Submit').first().click();
await page.waitForURL("/settings/account");
await page.waitForURL('/settings/account');
});
test("Sign in with expired login code fails", async ({ page }) => {
const token = oneTimeAccessTokens.filter((t) => t.expired)[0];
await page.goto(`/lc/${token.token}`);
test('Sign in with expired login code fails', async ({ page }) => {
const token = oneTimeAccessTokens.filter((t) => t.expired)[0];
await page.goto(`/lc/${token.token}`);
await expect(page.getByRole("paragraph")).toHaveText(
"Token is invalid or expired. Please try again."
);
await expect(page.getByRole('paragraph')).toHaveText(
'Token is invalid or expired. Please try again.'
);
});
test("Sign in with login code entered manually fails", async ({ page }) => {
const token = oneTimeAccessTokens.filter((t) => t.expired)[0];
await page.goto("/lc");
test('Sign in with login code entered manually fails', async ({ page }) => {
const token = oneTimeAccessTokens.filter((t) => t.expired)[0];
await page.goto('/lc');
await page.getByPlaceholder("Code").first().fill(token.token);
await page.getByPlaceholder('Code').first().fill(token.token);
await page.getByText("Submit").first().click();
await page.getByText('Submit').first().click();
await expect(page.getByRole("paragraph")).toHaveText(
"Token is invalid or expired. Please try again."
);
await expect(page.getByRole('paragraph')).toHaveText(
'Token is invalid or expired. Please try again.'
);
});

View File

@@ -1,152 +1,115 @@
import test, { expect } from "@playwright/test";
import { userGroups, users } from "../data";
import { cleanupBackend } from "../utils/cleanup.util";
import test, { expect } from '@playwright/test';
import { userGroups, users } from '../data';
import { cleanupBackend } from '../utils/cleanup.util';
test.beforeEach(cleanupBackend);
test("Create user group", async ({ page }) => {
await page.goto("/settings/admin/user-groups");
const group = userGroups.humanResources;
test('Create user group', async ({ page }) => {
await page.goto('/settings/admin/user-groups');
const group = userGroups.humanResources;
await page.getByRole("button", { name: "Add Group" }).click();
await page.getByLabel("Friendly Name").fill(group.friendlyName);
await page.getByRole('button', { name: 'Add Group' }).click();
await page.getByLabel('Friendly Name').fill(group.friendlyName);
await page.getByRole("button", { name: "Save" }).click();
await page.getByRole('button', { name: 'Save' }).click();
await expect(page.locator('[data-type="success"]')).toHaveText(
"User group created successfully"
);
await expect(page.locator('[data-type="success"]')).toHaveText('User group created successfully');
await page.waitForURL("/settings/admin/user-groups/*");
await page.waitForURL('/settings/admin/user-groups/*');
await expect(page.getByLabel("Friendly Name")).toHaveValue(
group.friendlyName
);
await expect(page.getByLabel("Name", { exact: true })).toHaveValue(
group.name
);
await expect(page.getByLabel('Friendly Name')).toHaveValue(group.friendlyName);
await expect(page.getByLabel('Name', { exact: true })).toHaveValue(group.name);
});
test("Edit user group", async ({ page }) => {
await page.goto("/settings/admin/user-groups");
const group = userGroups.developers;
test('Edit user group', async ({ page }) => {
await page.goto('/settings/admin/user-groups');
const group = userGroups.developers;
await page
.getByRole("row", { name: group.name })
.getByRole("button")
.click();
await page.getByRole("menuitem", { name: "Edit" }).click();
await page.getByRole('row', { name: group.name }).getByRole('button').click();
await page.getByRole('menuitem', { name: 'Edit' }).click();
await page.getByLabel("Friendly Name").fill("Developers updated");
await page.getByLabel('Friendly Name').fill('Developers updated');
await expect(page.getByLabel("Name", { exact: true })).toHaveValue(
group.name
);
await expect(page.getByLabel('Name', { exact: true })).toHaveValue(group.name);
await page.getByLabel("Name", { exact: true }).fill("developers_updated");
await page.getByLabel('Name', { exact: true }).fill('developers_updated');
await page.getByRole("button", { name: "Save" }).nth(0).click();
await page.getByRole('button', { name: 'Save' }).nth(0).click();
await expect(page.locator('[data-type="success"]')).toHaveText(
"User group updated successfully"
);
await expect(page.getByLabel("Friendly Name")).toHaveValue(
"Developers updated"
);
await expect(page.getByLabel("Name", { exact: true })).toHaveValue(
"developers_updated"
);
await expect(page.locator('[data-type="success"]')).toHaveText('User group updated successfully');
await expect(page.getByLabel('Friendly Name')).toHaveValue('Developers updated');
await expect(page.getByLabel('Name', { exact: true })).toHaveValue('developers_updated');
});
test("Update user group users", async ({ page }) => {
const group = userGroups.designers;
await page.goto(`/settings/admin/user-groups/${group.id}`);
test('Update user group users', async ({ page }) => {
const group = userGroups.designers;
await page.goto(`/settings/admin/user-groups/${group.id}`);
await page
.getByRole("row", { name: users.tim.email })
.getByRole("checkbox")
.click();
await page
.getByRole("row", { name: users.craig.email })
.getByRole("checkbox")
.click();
await page.getByRole('row', { name: users.tim.email }).getByRole('checkbox').click();
await page.getByRole('row', { name: users.craig.email }).getByRole('checkbox').click();
await page.getByRole("button", { name: "Save" }).nth(1).click();
await page.getByRole('button', { name: 'Save' }).nth(1).click();
await expect(page.locator('[data-type="success"]')).toHaveText(
"Users updated successfully"
);
await expect(page.locator('[data-type="success"]')).toHaveText('Users updated successfully');
await page.reload();
await page.reload();
await expect(
page.getByRole("row", { name: users.tim.email }).getByRole("checkbox")
).toHaveAttribute("data-state", "unchecked");
await expect(
page.getByRole("row", { name: users.craig.email }).getByRole("checkbox")
).toHaveAttribute("data-state", "checked");
await expect(
page.getByRole('row', { name: users.tim.email }).getByRole('checkbox')
).toHaveAttribute('data-state', 'unchecked');
await expect(
page.getByRole('row', { name: users.craig.email }).getByRole('checkbox')
).toHaveAttribute('data-state', 'checked');
});
test("Delete user group", async ({ page }) => {
const group = userGroups.developers;
await page.goto("/settings/admin/user-groups");
test('Delete user group', async ({ page }) => {
const group = userGroups.developers;
await page.goto('/settings/admin/user-groups');
await page.getByRole("row", { name: group.name }).getByRole("button").click();
await page.getByRole("menuitem", { name: "Delete" }).click();
await page.getByRole("button", { name: "Delete" }).click();
await page.getByRole('row', { name: group.name }).getByRole('button').click();
await page.getByRole('menuitem', { name: 'Delete' }).click();
await page.getByRole('button', { name: 'Delete' }).click();
await expect(page.locator('[data-type="success"]')).toHaveText(
"User group deleted successfully"
);
await expect(page.getByRole("row", { name: group.name })).not.toBeVisible();
await expect(page.locator('[data-type="success"]')).toHaveText('User group deleted successfully');
await expect(page.getByRole('row', { name: group.name })).not.toBeVisible();
});
test("Update user group custom claims", async ({ page }) => {
await page.goto(`/settings/admin/user-groups/${userGroups.designers.id}`);
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" }).click();
await page.getByRole('button', { name: 'Expand card' }).click();
// Add two custom claims
await page.getByRole("button", { name: "Add custom claim" }).click();
// Add two custom claims
await page.getByRole('button', { name: 'Add custom claim' }).click();
await page.getByPlaceholder("Key").fill("customClaim1");
await page.getByPlaceholder("Value").fill("customClaim1_value");
await page.getByPlaceholder('Key').fill('customClaim1');
await page.getByPlaceholder('Value').fill('customClaim1_value');
await page.getByRole("button", { name: "Add another" }).click();
await page.getByPlaceholder("Key").nth(1).fill("customClaim2");
await page.getByPlaceholder("Value").nth(1).fill("customClaim2_value");
await page.getByRole('button', { name: 'Add another' }).click();
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' }).nth(2).click();
await expect(page.locator('[data-type="success"]')).toHaveText(
"Custom claims updated successfully"
);
await expect(page.locator('[data-type="success"]')).toHaveText(
'Custom claims updated successfully'
);
await page.reload();
await page.reload();
// Check if custom claims are saved
await expect(page.getByPlaceholder("Key").first()).toHaveValue(
"customClaim1"
);
await expect(page.getByPlaceholder("Value").first()).toHaveValue(
"customClaim1_value"
);
await expect(page.getByPlaceholder("Key").nth(1)).toHaveValue("customClaim2");
await expect(page.getByPlaceholder("Value").nth(1)).toHaveValue(
"customClaim2_value"
);
// Check if custom claims are saved
await expect(page.getByPlaceholder('Key').first()).toHaveValue('customClaim1');
await expect(page.getByPlaceholder('Value').first()).toHaveValue('customClaim1_value');
await expect(page.getByPlaceholder('Key').nth(1)).toHaveValue('customClaim2');
await expect(page.getByPlaceholder('Value').nth(1)).toHaveValue('customClaim2_value');
// Remove one custom claim
await page.getByLabel("Remove custom claim").first().click();
await page.getByRole("button", { name: "Save" }).nth(2).click();
// Remove one custom claim
await page.getByLabel('Remove custom claim').first().click();
await page.getByRole('button', { name: 'Save' }).nth(2).click();
await page.reload();
await page.reload();
// Check if custom claim is removed
await expect(page.getByPlaceholder("Key").first()).toHaveValue(
"customClaim2"
);
await expect(page.getByPlaceholder("Value").first()).toHaveValue(
"customClaim2_value"
);
// Check if custom claim is removed
await expect(page.getByPlaceholder('Key').first()).toHaveValue('customClaim2');
await expect(page.getByPlaceholder('Value').first()).toHaveValue('customClaim2_value');
});

View File

@@ -1,253 +1,217 @@
import test, { expect } from "@playwright/test";
import { userGroups, users } from "../data";
import { cleanupBackend } from "../utils/cleanup.util";
import test, { expect } from '@playwright/test';
import { userGroups, users } from '../data';
import { cleanupBackend } from '../utils/cleanup.util';
test.beforeEach(cleanupBackend);
test("Create user", async ({ page }) => {
const user = users.steve;
test('Create user', async ({ page }) => {
const user = users.steve;
await page.goto("/settings/admin/users");
await page.goto('/settings/admin/users');
await page.getByRole("button", { name: "Add User" }).click();
await page.getByLabel("First name").fill(user.firstname);
await page.getByLabel("Last name").fill(user.lastname);
await page.getByLabel("Email").fill(user.email);
await page.getByLabel("Username").fill(user.username);
await page.getByRole("button", { name: "Save" }).click();
await page.getByRole('button', { name: 'Add User' }).click();
await page.getByLabel('First name').fill(user.firstname);
await page.getByLabel('Last name').fill(user.lastname);
await page.getByLabel('Email').fill(user.email);
await page.getByLabel('Username').fill(user.username);
await page.getByRole('button', { name: 'Save' }).click();
await expect(
page.getByRole("row", { name: `${user.firstname} ${user.lastname}` })
).toBeVisible();
await expect(page.locator('[data-type="success"]')).toHaveText(
"User created successfully"
);
await expect(page.getByRole('row', { name: `${user.firstname} ${user.lastname}` })).toBeVisible();
await expect(page.locator('[data-type="success"]')).toHaveText('User created successfully');
});
test("Create user fails with already taken email", async ({ page }) => {
const user = users.steve;
test('Create user fails with already taken email', async ({ page }) => {
const user = users.steve;
await page.goto("/settings/admin/users");
await page.goto('/settings/admin/users');
await page.getByRole("button", { name: "Add User" }).click();
await page.getByLabel("First name").fill(user.firstname);
await page.getByLabel("Last name").fill(user.lastname);
await page.getByLabel("Email").fill(users.tim.email);
await page.getByLabel("Username").fill(user.username);
await page.getByRole("button", { name: "Save" }).click();
await page.getByRole('button', { name: 'Add User' }).click();
await page.getByLabel('First name').fill(user.firstname);
await page.getByLabel('Last name').fill(user.lastname);
await page.getByLabel('Email').fill(users.tim.email);
await page.getByLabel('Username').fill(user.username);
await page.getByRole('button', { name: 'Save' }).click();
await expect(page.locator('[data-type="error"]')).toHaveText(
"Email is already in use"
);
await expect(page.locator('[data-type="error"]')).toHaveText('Email is already in use');
});
test("Create user fails with already taken username", async ({ page }) => {
const user = users.steve;
test('Create user fails with already taken username', async ({ page }) => {
const user = users.steve;
await page.goto("/settings/admin/users");
await page.goto('/settings/admin/users');
await page.getByRole("button", { name: "Add User" }).click();
await page.getByLabel("First name").fill(user.firstname);
await page.getByLabel("Last name").fill(user.lastname);
await page.getByLabel("Email").fill(user.email);
await page.getByLabel("Username").fill(users.tim.username);
await page.getByRole("button", { name: "Save" }).click();
await page.getByRole('button', { name: 'Add User' }).click();
await page.getByLabel('First name').fill(user.firstname);
await page.getByLabel('Last name').fill(user.lastname);
await page.getByLabel('Email').fill(user.email);
await page.getByLabel('Username').fill(users.tim.username);
await page.getByRole('button', { name: 'Save' }).click();
await expect(page.locator('[data-type="error"]')).toHaveText(
"Username is already in use"
);
await expect(page.locator('[data-type="error"]')).toHaveText('Username is already in use');
});
test("Create one time access token", async ({ page, context }) => {
await page.goto("/settings/admin/users");
test('Create one time access token', async ({ page, context }) => {
await page.goto('/settings/admin/users');
await page
.getByRole("row", {
name: `${users.craig.firstname} ${users.craig.lastname}`,
})
.getByRole("button")
.click();
await page
.getByRole('row', {
name: `${users.craig.firstname} ${users.craig.lastname}`
})
.getByRole('button')
.click();
await page.getByRole("menuitem", { name: "Login Code" }).click();
await page.getByRole('menuitem', { name: 'Login Code' }).click();
await page.getByLabel("Expiration").click();
await page.getByRole("option", { name: "12 hours" }).click();
await page.getByRole("button", { name: "Show Code" }).click();
await page.getByLabel('Expiration').click();
await page.getByRole('option', { name: '12 hours' }).click();
await page.getByRole('button', { name: 'Show Code' }).click();
const link = await page.getByTestId("login-code-link").textContent();
await context.clearCookies();
const link = await page.getByTestId('login-code-link').textContent();
await context.clearCookies();
await page.goto(link!);
await page.waitForURL("/settings/account");
await page.goto(link!);
await page.waitForURL('/settings/account');
});
test("Delete user", async ({ page }) => {
await page.goto("/settings/admin/users");
test('Delete user', async ({ page }) => {
await page.goto('/settings/admin/users');
await page
.getByRole("row", {
name: `${users.craig.firstname} ${users.craig.lastname}`,
})
.getByRole("button")
.click();
await page.getByRole("menuitem", { name: "Delete" }).click();
await page.getByRole("button", { name: "Delete" }).click();
await page
.getByRole('row', {
name: `${users.craig.firstname} ${users.craig.lastname}`
})
.getByRole('button')
.click();
await page.getByRole('menuitem', { name: 'Delete' }).click();
await page.getByRole('button', { name: 'Delete' }).click();
await expect(page.locator('[data-type="success"]')).toHaveText(
"User deleted successfully"
);
await expect(
page.getByRole("row", {
name: `${users.craig.firstname} ${users.craig.lastname}`,
})
).not.toBeVisible();
await expect(page.locator('[data-type="success"]')).toHaveText('User deleted successfully');
await expect(
page.getByRole('row', {
name: `${users.craig.firstname} ${users.craig.lastname}`
})
).not.toBeVisible();
});
test("Update user", async ({ page }) => {
const user = users.craig;
test('Update user', async ({ page }) => {
const user = users.craig;
await page.goto("/settings/admin/users");
await page.goto('/settings/admin/users');
await page
.getByRole("row", { name: `${user.firstname} ${user.lastname}` })
.getByRole("button")
.click();
await page.getByRole("menuitem", { name: "Edit" }).click();
await page
.getByRole('row', { name: `${user.firstname} ${user.lastname}` })
.getByRole('button')
.click();
await page.getByRole('menuitem', { name: 'Edit' }).click();
await page.getByLabel("First name").fill("Crack");
await page.getByLabel("Last name").fill("Apple");
await page.getByLabel("Email").fill("crack.apple@test.com");
await page.getByLabel("Username").fill("crack");
await page.getByRole("button", { name: "Save" }).first().click();
await page.getByLabel('First name').fill('Crack');
await page.getByLabel('Last name').fill('Apple');
await page.getByLabel('Email').fill('crack.apple@test.com');
await page.getByLabel('Username').fill('crack');
await page.getByRole('button', { name: 'Save' }).first().click();
await expect(page.locator('[data-type="success"]')).toHaveText(
"User updated successfully"
);
await expect(page.locator('[data-type="success"]')).toHaveText('User updated successfully');
});
test("Update user fails with already taken email", async ({ page }) => {
const user = users.craig;
test('Update user fails with already taken email', async ({ page }) => {
const user = users.craig;
await page.goto("/settings/admin/users");
await page.goto('/settings/admin/users');
await page
.getByRole("row", { name: `${user.firstname} ${user.lastname}` })
.getByRole("button")
.click();
await page.getByRole("menuitem", { name: "Edit" }).click();
await page
.getByRole('row', { name: `${user.firstname} ${user.lastname}` })
.getByRole('button')
.click();
await page.getByRole('menuitem', { name: 'Edit' }).click();
await page.getByLabel("Email").fill(users.tim.email);
await page.getByRole("button", { name: "Save" }).first().click();
await page.getByLabel('Email').fill(users.tim.email);
await page.getByRole('button', { name: 'Save' }).first().click();
await expect(page.locator('[data-type="error"]')).toHaveText(
"Email is already in use"
);
await expect(page.locator('[data-type="error"]')).toHaveText('Email is already in use');
});
test("Update user fails with already taken username", async ({ page }) => {
const user = users.craig;
test('Update user fails with already taken username', async ({ page }) => {
const user = users.craig;
await page.goto("/settings/admin/users");
await page.goto('/settings/admin/users');
await page
.getByRole("row", { name: `${user.firstname} ${user.lastname}` })
.getByRole("button")
.click();
await page.getByRole("menuitem", { name: "Edit" }).click();
await page
.getByRole('row', { name: `${user.firstname} ${user.lastname}` })
.getByRole('button')
.click();
await page.getByRole('menuitem', { name: 'Edit' }).click();
await page.getByLabel("Username").fill(users.tim.username);
await page.getByRole("button", { name: "Save" }).first().click();
await page.getByLabel('Username').fill(users.tim.username);
await page.getByRole('button', { name: 'Save' }).first().click();
await expect(page.locator('[data-type="error"]')).toHaveText(
"Username is already in use"
);
await expect(page.locator('[data-type="error"]')).toHaveText('Username is already in use');
});
test("Update user custom claims", async ({ page }) => {
await page.goto(`/settings/admin/users/${users.craig.id}`);
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('button', { name: 'Expand card' }).nth(1).click();
// Add two custom claims
await page.getByRole("button", { name: "Add custom claim" }).click();
// Add two custom claims
await page.getByRole('button', { name: 'Add custom claim' }).click();
await page.getByPlaceholder("Key").fill("customClaim1");
await page.getByPlaceholder("Value").fill("customClaim1_value");
await page.getByPlaceholder('Key').fill('customClaim1');
await page.getByPlaceholder('Value').fill('customClaim1_value');
await page.getByRole("button", { name: "Add another" }).click();
await page.getByPlaceholder("Key").nth(1).fill("customClaim2");
await page.getByPlaceholder("Value").nth(1).fill("customClaim2_value");
await page.getByRole('button', { name: 'Add another' }).click();
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' }).nth(1).click();
await expect(page.locator('[data-type="success"]')).toHaveText(
"Custom claims updated successfully"
);
await expect(page.locator('[data-type="success"]')).toHaveText(
'Custom claims updated successfully'
);
await page.reload();
await page.reload();
// Check if custom claims are saved
await expect(page.getByPlaceholder("Key").first()).toHaveValue(
"customClaim1"
);
await expect(page.getByPlaceholder("Value").first()).toHaveValue(
"customClaim1_value"
);
await expect(page.getByPlaceholder("Key").nth(1)).toHaveValue("customClaim2");
await expect(page.getByPlaceholder("Value").nth(1)).toHaveValue(
"customClaim2_value"
);
// Check if custom claims are saved
await expect(page.getByPlaceholder('Key').first()).toHaveValue('customClaim1');
await expect(page.getByPlaceholder('Value').first()).toHaveValue('customClaim1_value');
await expect(page.getByPlaceholder('Key').nth(1)).toHaveValue('customClaim2');
await expect(page.getByPlaceholder('Value').nth(1)).toHaveValue('customClaim2_value');
// Remove one custom claim
await page.getByLabel("Remove custom claim").first().click();
await page.getByRole("button", { name: "Save" }).nth(1).click();
// Remove one custom claim
await page.getByLabel('Remove custom claim').first().click();
await page.getByRole('button', { name: 'Save' }).nth(1).click();
await expect(page.locator('[data-type="success"]')).toHaveText(
"Custom claims updated successfully"
);
await expect(page.locator('[data-type="success"]')).toHaveText(
'Custom claims updated successfully'
);
await page.reload();
await page.reload();
// Check if custom claim is removed
await expect(page.getByPlaceholder("Key").first()).toHaveValue(
"customClaim2"
);
await expect(page.getByPlaceholder("Value").first()).toHaveValue(
"customClaim2_value"
);
// Check if custom claim is removed
await expect(page.getByPlaceholder('Key').first()).toHaveValue('customClaim2');
await expect(page.getByPlaceholder('Value').first()).toHaveValue('customClaim2_value');
});
test("Update user group assignments", async ({ page }) => {
const user = users.craig;
await page.goto(`/settings/admin/users/${user.id}`);
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();
page.getByRole('button', { name: 'Expand card' }).first().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('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' }).nth(1).click();
await expect(page.locator('[data-type="success"]')).toHaveText(
"User groups updated successfully"
);
await expect(page.locator('[data-type="success"]')).toHaveText(
'User groups updated successfully'
);
await page.reload();
await page.reload();
await expect(
page
.getByRole("row", { name: userGroups.designers.name })
.getByRole("checkbox")
).toHaveAttribute("data-state", "checked");
await expect(
page
.getByRole("row", { name: userGroups.developers.name })
.getByRole("checkbox")
).toHaveAttribute("data-state", "unchecked");
await expect(
page.getByRole('row', { name: userGroups.designers.name }).getByRole('checkbox')
).toHaveAttribute('data-state', 'checked');
await expect(
page.getByRole('row', { name: userGroups.developers.name }).getByRole('checkbox')
).toHaveAttribute('data-state', 'unchecked');
});

View File

@@ -6,170 +6,174 @@ import { users, signupTokens } from 'data';
test.beforeEach(cleanupBackend);
test.describe('User Signup', () => {
async function setSignupMode(page: any, mode: 'Disabled' | 'Signup with token' | 'Open Signup') {
await page.goto('/settings/admin/application-configuration');
async function setSignupMode(page: any, mode: 'Disabled' | 'Signup with token' | 'Open Signup') {
await page.goto('/settings/admin/application-configuration');
await page.getByLabel('Enable user signups').click();
await page.getByRole('option', { name: mode }).click();
await page.getByLabel('Enable user signups').click();
await page.getByRole('option', { name: mode }).click();
await page.getByRole('button', { name: 'Save' }).first().click();
await expect(page.locator('[data-type="success"]')).toHaveText('Application configuration updated successfully');
await page.waitForLoadState('networkidle');
await page.getByRole('button', { name: 'Save' }).first().click();
await expect(page.locator('[data-type="success"]')).toHaveText(
'Application configuration updated successfully'
);
await page.waitForLoadState('networkidle');
await page.context().clearCookies();
await page.goto('/login');
}
await page.context().clearCookies();
await page.goto('/login');
}
test('Signup is disabled - shows error message', async ({ page }) => {
await setSignupMode(page, 'Disabled');
test('Signup is disabled - shows error message', async ({ page }) => {
await setSignupMode(page, 'Disabled');
await page.goto('/signup');
await page.goto('/signup');
await expect(page.getByText('User signups are currently disabled')).toBeVisible();
});
await expect(page.getByText('User signups are currently disabled')).toBeVisible();
});
test('Signup with token - success flow', async ({ page }) => {
await setSignupMode(page, 'Signup with token');
test('Signup with token - success flow', async ({ page }) => {
await setSignupMode(page, 'Signup with token');
await page.goto(`/st/${signupTokens.valid.token}`);
await page.goto(`/st/${signupTokens.valid.token}`);
await page.getByLabel('First name').fill('John');
await page.getByLabel('Last name').fill('Doe');
await page.getByLabel('Username').fill('johndoe');
await page.getByLabel('Email').fill('john.doe@test.com');
await page.getByLabel('First name').fill('John');
await page.getByLabel('Last name').fill('Doe');
await page.getByLabel('Username').fill('johndoe');
await page.getByLabel('Email').fill('john.doe@test.com');
await page.getByRole('button', { name: 'Sign Up' }).click();
await page.getByRole('button', { name: 'Sign Up' }).click();
await page.waitForURL('/signup/add-passkey');
await expect(page.getByText('Set up your passkey')).toBeVisible();
});
await page.waitForURL('/signup/add-passkey');
await expect(page.getByText('Set up your passkey')).toBeVisible();
});
test('Signup with token - invalid token shows error', async ({ page }) => {
await setSignupMode(page, 'Signup with token');
test('Signup with token - invalid token shows error', async ({ page }) => {
await setSignupMode(page, 'Signup with token');
await page.goto('/st/invalid-token-123');
await page.getByLabel('First name').fill('Complete');
await page.getByLabel('Last name').fill('User');
await page.getByLabel('Username').fill('completeuser');
await page.getByLabel('Email').fill('complete.user@test.com');
await page.getByRole('button', { name: 'Sign Up' }).click();
await page.goto('/st/invalid-token-123');
await page.getByLabel('First name').fill('Complete');
await page.getByLabel('Last name').fill('User');
await page.getByLabel('Username').fill('completeuser');
await page.getByLabel('Email').fill('complete.user@test.com');
await page.getByRole('button', { name: 'Sign Up' }).click();
await expect(page.getByText('Token is invalid or expired.')).toBeVisible();
});
await expect(page.getByText('Token is invalid or expired.')).toBeVisible();
});
test('Signup with token - no token in URL shows error', async ({ page }) => {
await setSignupMode(page, 'Signup with token');
test('Signup with token - no token in URL shows error', async ({ page }) => {
await setSignupMode(page, 'Signup with token');
await page.goto('/signup');
await page.goto('/signup');
await expect(page.getByText('A valid signup token is required to create an account.')).toBeVisible();
});
await expect(
page.getByText('A valid signup token is required to create an account.')
).toBeVisible();
});
test('Open signup - success flow', async ({ page }) => {
await setSignupMode(page, 'Open Signup');
test('Open signup - success flow', async ({ page }) => {
await setSignupMode(page, 'Open Signup');
await page.goto('/signup');
await page.goto('/signup');
await expect(page.getByText('Create your account to get started')).toBeVisible();
await expect(page.getByText('Create your account to get started')).toBeVisible();
await page.getByLabel('First name').fill('Jane');
await page.getByLabel('Last name').fill('Smith');
await page.getByLabel('Username').fill('janesmith');
await page.getByLabel('Email').fill('jane.smith@test.com');
await page.getByLabel('First name').fill('Jane');
await page.getByLabel('Last name').fill('Smith');
await page.getByLabel('Username').fill('janesmith');
await page.getByLabel('Email').fill('jane.smith@test.com');
await page.getByRole('button', { name: 'Sign Up' }).click();
await page.getByRole('button', { name: 'Sign Up' }).click();
await page.waitForURL('/signup/add-passkey');
await expect(page.getByText('Set up your passkey')).toBeVisible();
});
await page.waitForURL('/signup/add-passkey');
await expect(page.getByText('Set up your passkey')).toBeVisible();
});
test('Open signup - validation errors', async ({ page }) => {
await setSignupMode(page, 'Open Signup');
test('Open signup - validation errors', async ({ page }) => {
await setSignupMode(page, 'Open Signup');
await page.goto('/signup');
await page.goto('/signup');
await page.getByRole('button', { name: 'Sign Up' }).click();
await page.getByRole('button', { name: 'Sign Up' }).click();
await expect(page.getByText('Invalid input').first()).toBeVisible();
});
await expect(page.getByText('Invalid input').first()).toBeVisible();
});
test('Open signup - duplicate email shows error', async ({ page }) => {
await setSignupMode(page, 'Open Signup');
test('Open signup - duplicate email shows error', async ({ page }) => {
await setSignupMode(page, 'Open Signup');
await page.goto('/signup');
await page.goto('/signup');
await page.getByLabel('First name').fill('Test');
await page.getByLabel('Last name').fill('User');
await page.getByLabel('Username').fill('testuser123');
await page.getByLabel('Email').fill(users.tim.email);
await page.getByLabel('First name').fill('Test');
await page.getByLabel('Last name').fill('User');
await page.getByLabel('Username').fill('testuser123');
await page.getByLabel('Email').fill(users.tim.email);
await page.getByRole('button', { name: 'Sign Up' }).click();
await page.getByRole('button', { name: 'Sign Up' }).click();
await expect(page.getByText('Email is already in use.')).toBeVisible();
});
await expect(page.getByText('Email is already in use.')).toBeVisible();
});
test('Open signup - duplicate username shows error', async ({ page }) => {
await setSignupMode(page, 'Open Signup');
test('Open signup - duplicate username shows error', async ({ page }) => {
await setSignupMode(page, 'Open Signup');
await page.goto('/signup');
await page.goto('/signup');
await page.getByLabel('First name').fill('Test');
await page.getByLabel('Last name').fill('User');
await page.getByLabel('Username').fill(users.tim.username);
await page.getByLabel('Email').fill('newuser@test.com');
await page.getByLabel('First name').fill('Test');
await page.getByLabel('Last name').fill('User');
await page.getByLabel('Username').fill(users.tim.username);
await page.getByLabel('Email').fill('newuser@test.com');
await page.getByRole('button', { name: 'Sign Up' }).click();
await page.getByRole('button', { name: 'Sign Up' }).click();
await expect(page.getByText('Username is already in use.')).toBeVisible();
});
await expect(page.getByText('Username is already in use.')).toBeVisible();
});
test('Complete signup flow with passkey creation', async ({ page }) => {
await setSignupMode(page, 'Open Signup');
test('Complete signup flow with passkey creation', async ({ page }) => {
await setSignupMode(page, 'Open Signup');
await page.goto('/signup');
await page.getByLabel('First name').fill('Complete');
await page.getByLabel('Last name').fill('User');
await page.getByLabel('Username').fill('completeuser');
await page.getByLabel('Email').fill('complete.user@test.com');
await page.getByRole('button', { name: 'Sign Up' }).click();
await page.goto('/signup');
await page.getByLabel('First name').fill('Complete');
await page.getByLabel('Last name').fill('User');
await page.getByLabel('Username').fill('completeuser');
await page.getByLabel('Email').fill('complete.user@test.com');
await page.getByRole('button', { name: 'Sign Up' }).click();
await page.waitForURL('/signup/add-passkey');
await page.waitForURL('/signup/add-passkey');
await (await passkeyUtil.init(page)).addPasskey('timNew');
await page.getByRole('button', { name: 'Add Passkey' }).click();
await (await passkeyUtil.init(page)).addPasskey('timNew');
await page.getByRole('button', { name: 'Add Passkey' }).click();
await page.waitForURL('/settings/account');
await expect(page.getByText('Single Passkey Configured')).toBeVisible();
});
await page.waitForURL('/settings/account');
await expect(page.getByText('Single Passkey Configured')).toBeVisible();
});
test('Skip passkey creation during signup', async ({ page }) => {
await setSignupMode(page, 'Open Signup');
test('Skip passkey creation during signup', async ({ page }) => {
await setSignupMode(page, 'Open Signup');
await page.goto('/signup');
await page.getByLabel('First name').fill('Skip');
await page.getByLabel('Last name').fill('User');
await page.getByLabel('Username').fill('skipuser');
await page.getByLabel('Email').fill('skip.user@test.com');
await page.getByRole('button', { name: 'Sign Up' }).click();
await page.goto('/signup');
await page.getByLabel('First name').fill('Skip');
await page.getByLabel('Last name').fill('User');
await page.getByLabel('Username').fill('skipuser');
await page.getByLabel('Email').fill('skip.user@test.com');
await page.getByRole('button', { name: 'Sign Up' }).click();
await page.waitForURL('/signup/add-passkey');
await page.waitForURL('/signup/add-passkey');
await page.getByRole('button', { name: 'Skip for now' }).click();
await page.getByRole('button', { name: 'Skip for now' }).click();
await page.waitForURL('/settings/account');
await expect(page.getByText('Passkey missing')).toBeVisible();
});
await page.waitForURL('/settings/account');
await expect(page.getByText('Passkey missing')).toBeVisible();
});
test('Token usage limit is enforced', async ({ page }) => {
await setSignupMode(page, 'Signup with token');
test('Token usage limit is enforced', async ({ page }) => {
await setSignupMode(page, 'Signup with token');
await page.goto(`/st/${signupTokens.fullyUsed.token}`);
await page.getByLabel('First name').fill('Complete');
await page.getByLabel('Last name').fill('User');
await page.getByLabel('Username').fill('completeuser');
await page.getByLabel('Email').fill('complete.user@test.com');
await page.getByRole('button', { name: 'Sign Up' }).click();
await page.goto(`/st/${signupTokens.fullyUsed.token}`);
await page.getByLabel('First name').fill('Complete');
await page.getByLabel('Last name').fill('User');
await page.getByLabel('Username').fill('completeuser');
await page.getByLabel('Email').fill('complete.user@test.com');
await page.getByRole('button', { name: 'Sign Up' }).click();
await expect(page.getByText('Token is invalid or expired.')).toBeVisible();
});
await expect(page.getByText('Token is invalid or expired.')).toBeVisible();
});
});