Files
pleno-vue/tests/e2e/passkeyAuth.spec.ts
T
Jeppe Bundgaard b39b458f4f Add .prettierrc.json and refactor test files for improved formatting consistency:
- Introduced `.prettierrc.json` to enforce consistent code formatting across the project.
- Updated unit and e2e test files to address formatting issues, improve readability, and ensure alignment with the new Prettier configuration.
2026-04-13 09:13:27 +02:00

168 lines
6.0 KiB
TypeScript

import { test, expect } from "@playwright/test";
import { passkeyTestData, goToUserLogin, goToSubuserLogin, isPasskeyButtonVisible } from "./fixtures";
/** Passkey Authentication Tests */
// User Passkey Tests
test.describe("[AUTH][Passkey][User]", () => {
test("should display passkey login button on user login page when supported", async ({ page }) => {
await goToUserLogin(page);
// Check if passkey button is visible (depends on browser WebAuthn support)
const passkeyButton = page.locator('button[id="passkey-login-button"]');
// The button visibility depends on WebAuthn support
// In most modern browsers (Chrome, Edge, Firefox), it should be visible
const isVisible = await passkeyButton.isVisible();
if (isVisible) {
await expect(passkeyButton).toBeVisible();
await expect(passkeyButton.locator(".fa-fingerprint")).toBeVisible();
}
});
test("should have passkey button with fingerprint icon", async ({ page }) => {
await goToUserLogin(page);
const passkeyButton = page.locator('button[id="passkey-login-button"]');
// Skip test if passkeys not supported in this browser
if (!(await passkeyButton.isVisible())) {
test.skip();
return;
}
// Button should contain fingerprint icon
await expect(passkeyButton.locator(".fa-fingerprint")).toBeVisible();
});
test("should display loading spinner when passkey login is clicked", async ({ page }) => {
await goToUserLogin(page);
const passkeyButton = page.locator('button[id="passkey-login-button"]');
// Skip test if passkeys not supported
if (!(await passkeyButton.isVisible())) {
test.skip();
return;
}
// Click passkey button - this will trigger WebAuthn prompt
// Note: The actual WebAuthn flow cannot be completed in automated tests
// without additional browser configuration or mocking
await passkeyButton.click();
// Button should show loading spinner while waiting for authenticator
// (This may be brief or the test may need adjustment based on actual behavior)
await expect(passkeyButton.locator(".fa-spinner"))
.toBeVisible({ timeout: 1000 })
.catch(() => {
// Loading state may be too fast to catch
});
});
test("should not disable other login options when passkey is available", async ({ page }) => {
await goToUserLogin(page);
// Regular login form should still be functional
const customerNumberInput = page.locator('input[name="customer_number"]');
const passwordInput = page.locator('input[name="password"]');
const loginButton = page.locator('button[id="login-button"]');
await expect(customerNumberInput).toBeVisible();
await expect(passwordInput).toBeVisible();
await expect(loginButton).toBeVisible();
await expect(loginButton).not.toBeDisabled();
});
test("should show QR code login option alongside passkey", async ({ page }) => {
await goToUserLogin(page);
// QR code login should still be available
const qrLoginLink = page.locator('a[href="/auth/loginqr"], a:has-text("QR")');
await expect(qrLoginLink).toBeVisible();
});
});
// Subuser Passkey Tests
test.describe("[AUTH][Passkey][Subuser]", () => {
test("should display passkey login button on subuser login page when supported", async ({ page }) => {
await goToSubuserLogin(page);
const passkeyButton = page.locator('button[id="passkey-login-button"]');
// The button visibility depends on WebAuthn support
const isVisible = await passkeyButton.isVisible();
if (isVisible) {
await expect(passkeyButton).toBeVisible();
}
});
test("should not disable phone login when passkey is available", async ({ page }) => {
await goToSubuserLogin(page);
// Regular login form should still be functional
const phoneInput = page.locator('input[name="phone"]');
const passwordInput = page.locator('input[name="password"]');
const loginButton = page.locator('button[id="subuser-login-button"]');
await expect(phoneInput).toBeVisible();
await expect(passwordInput).toBeVisible();
await expect(loginButton).toBeVisible();
await expect(loginButton).not.toBeDisabled();
});
});
// Passkey Browser Support Tests
test.describe("[AUTH][Passkey][Browser Support]", () => {
test("should gracefully handle browsers without passkey support", async ({ page, browserName }) => {
await goToUserLogin(page);
// In browsers without WebAuthn, the passkey button should not be visible
const passkeyButton = page.locator('button[id="passkey-login-button"]');
// Get visibility state - this test documents the behavior rather than asserting specific state
const isVisible = await passkeyButton.isVisible();
// Log the state for test reporting
console.log(`Passkey button visible in ${browserName}: ${isVisible}`);
// The important thing is that the page loads correctly regardless
await expect(page.locator("form")).toBeVisible();
});
test("should always show password-based login as fallback", async ({ page }) => {
await goToUserLogin(page);
// Password login should always be available, regardless of passkey support
await expect(page.locator('input[name="customer_number"]')).toBeVisible();
await expect(page.locator('input[name="password"]')).toBeVisible();
await expect(page.locator('button[id="login-button"]')).toBeVisible();
});
});
// Passkey Button State Tests
test.describe("[AUTH][Passkey][Button State]", () => {
test("should disable passkey button while loading", async ({ page }) => {
await goToUserLogin(page);
const passkeyButton = page.locator('button[id="passkey-login-button"]');
// Skip if passkeys not supported
if (!(await passkeyButton.isVisible())) {
test.skip();
return;
}
// Initial state - button should be enabled
await expect(passkeyButton).not.toBeDisabled();
// After clicking, button should become disabled while loading
await passkeyButton.click();
// The button should be disabled during the authentication attempt
await expect(passkeyButton).toBeDisabled();
});
});