Files
pleno-vue/tests/e2e/passkeyAuth.spec.ts
T
Jeppe Bundgaard 60742bf947 Refactor and migrate Playwright E2E tests:
- Remove `playwright.config.js` to clean up configuration.
- Add new E2E test suites (`admin-pos-orders`, `admin-module-goals`, `admin-module-pos-mobile-order-flow`) to structure Admin module tests.
- Introduce reusable authentication and data seeding utilities in `fixtures` for streamlined test flows and maintainability.
2026-03-19 12:46:47 +01:00

171 lines
6.1 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();
});
});