9.1 KiB
9.1 KiB
Instructions
- Following Playwright test failed.
- Explain why, be concise, respect Playwright best practices.
- Provide a snippet of code with the fix, if possible.
Test info
- Name: 1-login.spec.ts >> Login Workflow >> should reject invalid local user credentials
- Location: e2e/workflows/1-login.spec.ts:66:7
Error details
Test timeout of 30000ms exceeded.
Error: page.fill: Test timeout of 30000ms exceeded.
Call log:
- waiting for locator('[data-testid="local-username-input"]')
Page snapshot
- generic [ref=e1]:
- generic [ref=e3]:
- generic [ref=e4]:
- img [ref=e6]
- heading "Identity Check" [level=2] [ref=e9]
- paragraph [ref=e10]: Select operator profile or use direct login
- generic [ref=e12]:
- generic [ref=e13]:
- button [ref=e14] [cursor=pointer]:
- img [ref=e15]
- generic [ref=e18]:
- paragraph [ref=e19]: Logging in as
- paragraph [ref=e20]: Manual Input
- generic [ref=e21]:
- text: Username
- generic [ref=e22]:
- img [ref=e23]
- textbox "Admin" [ref=e26]
- generic [ref=e27]:
- text: Password
- generic [ref=e28]:
- img [ref=e29]
- textbox "Enter password" [active] [ref=e32]
- button "Verify Identity" [ref=e33] [cursor=pointer]
- button "Open Next.js Dev Tools" [ref=e39] [cursor=pointer]:
- img [ref=e40]
- alert [ref=e43]
Test source
1 | import { test, expect } from '@playwright/test';
2 | import * as auth from '../fixtures/auth';
3 | import * as assertions from '../utils/assertions';
4 | import { LDAP_USERS, LOCAL_USERS } from '../fixtures/test-data';
5 |
6 | test.describe('Login Workflow', () => {
7 | const BASE_URL = process.env.BASE_URL || 'http://localhost:8917';
8 |
9 | test.beforeEach(async ({ page }) => {
10 | // Navigate to login page
11 | await page.goto(BASE_URL);
12 | // Wait for identity check overlay
13 | await page.waitForSelector('[data-testid="identity-check-overlay"]', { timeout: 10000 });
14 | });
15 |
16 | test('should display identity check overlay on app load', async ({ page }) => {
17 | const overlay = page.locator('[data-testid="identity-check-overlay"]');
18 | await expect(overlay).toBeVisible();
19 |
20 | // Verify tabs are available
21 | const ldapTab = page.locator('[data-testid="ldap-login-tab"]');
22 | const localTab = page.locator('[data-testid="local-login-tab"]');
23 |
24 | await expect(ldapTab).toBeVisible();
25 | await expect(localTab).toBeVisible();
26 | });
27 |
28 | test('should display login form with username and password fields', async ({ page }) => {
29 | await assertions.assertLoginFormVisible(page);
30 | });
31 |
32 | test('should reject empty login credentials', async ({ page }) => {
33 | const submitButton = page.locator('[data-testid="login-submit"]');
34 | await submitButton.click();
35 |
36 | // Should show validation error
37 | const errorMessage = page.locator('[data-testid="toast-error"]');
38 | await expect(errorMessage).toBeVisible({ timeout: 3000 });
39 | });
40 |
41 | test('should reject invalid LDAP credentials', async ({ page }) => {
42 | await auth.loginWithLdap(page, LDAP_USERS.invalid, BASE_URL);
43 |
44 | // Should show error message
45 | const errorToast = page.locator('[data-testid="toast-error"]');
46 | await expect(errorToast).toBeVisible({ timeout: 5000 });
47 |
48 | // Should still be on login page
49 | await expect(page).toHaveURL(BASE_URL);
50 | });
51 |
52 | test('should successfully login with valid LDAP credentials', async ({ page }) => {
53 | // Skip if LDAP is not configured in test environment
54 | test.skip(process.env.SKIP_LDAP === 'true', 'LDAP not available in test environment');
55 |
56 | await auth.loginWithLdap(page, LDAP_USERS.valid, BASE_URL);
57 |
58 | // Verify we're authenticated
59 | await assertions.assertUserAuthenticated(page, BASE_URL);
60 |
61 | // Verify token is stored
62 | const token = await auth.getAuthToken(page);
63 | expect(token).toBeTruthy();
64 | });
65 |
66 | test('should reject invalid local user credentials', async ({ page }) => {
67 | // Switch to local user tab
68 | const localTab = page.locator('[data-testid="local-login-tab"]');
69 | await localTab.click();
70 |
71 | // Try to login with invalid credentials
> 72 | await page.fill('[data-testid="local-username-input"]', 'invalid_user');
| ^ Error: page.fill: Test timeout of 30000ms exceeded.
73 | await page.fill('[data-testid="local-password-input"]', 'wrong_password');
74 | await page.click('[data-testid="local-login-submit"]');
75 |
76 | // Should show error
77 | const errorToast = page.locator('[data-testid="toast-error"]');
78 | await expect(errorToast).toBeVisible({ timeout: 5000 });
79 | });
80 |
81 | test('should successfully login with valid local user credentials', async ({ page }) => {
82 | // Switch to local user tab
83 | const localTab = page.locator('[data-testid="local-login-tab"]');
84 | await localTab.click();
85 |
86 | // Login with valid credentials
87 | await auth.loginWithLocalUser(page, LOCAL_USERS.admin, BASE_URL);
88 |
89 | // Verify authenticated
90 | await assertions.assertUserAuthenticated(page, BASE_URL);
91 | });
92 |
93 | test('should show user identity after successful login', async ({ page }) => {
94 | await auth.loginWithLocalUser(page, LOCAL_USERS.admin, BASE_URL);
95 |
96 | // Check that user info is displayed
97 | const userDisplay = page.locator('[data-testid="user-display"]');
98 | await expect(userDisplay).toBeVisible();
99 |
100 | // Verify username is shown
101 | const username = await userDisplay.textContent();
102 | expect(username).toContain(LOCAL_USERS.admin.username);
103 | });
104 |
105 | test('should maintain session across page reloads', async ({ page }) => {
106 | await auth.loginWithLocalUser(page, LOCAL_USERS.admin, BASE_URL);
107 | await assertions.assertUserAuthenticated(page, BASE_URL);
108 |
109 | // Reload page
110 | await page.reload();
111 |
112 | // Should still be authenticated
113 | const token = await auth.getAuthToken(page);
114 | expect(token).toBeTruthy();
115 |
116 | // Should not be on login page
117 | await expect(page).not.toHaveURL(BASE_URL);
118 | });
119 |
120 | test('should support logout functionality', async ({ page }) => {
121 | // Login first
122 | await auth.loginWithLocalUser(page, LOCAL_USERS.admin, BASE_URL);
123 | await assertions.assertUserAuthenticated(page, BASE_URL);
124 |
125 | // Logout
126 | await auth.logout(page, BASE_URL);
127 |
128 | // Should be back on login page
129 | const identityOverlay = page.locator('[data-testid="identity-check-overlay"]');
130 | await expect(identityOverlay).toBeVisible({ timeout: 5000 });
131 |
132 | // Token should be cleared
133 | const token = await auth.getAuthToken(page);
134 | expect(token).toBeFalsy();
135 | });
136 |
137 | test('should show admin button for admin users', async ({ page }) => {
138 | await auth.loginWithLocalUser(page, LOCAL_USERS.admin, BASE_URL);
139 | await assertions.assertUserAuthenticated(page, BASE_URL);
140 |
141 | // Admin button should be visible
142 | const adminButton = page.locator('[data-testid="admin-button"]');
143 | await expect(adminButton).toBeVisible();
144 | });
145 |
146 | test('should allow switching between LDAP and local login tabs', async ({ page }) => {
147 | const ldapTab = page.locator('[data-testid="ldap-login-tab"]');
148 | const localTab = page.locator('[data-testid="local-login-tab"]');
149 |
150 | // Start on LDAP tab
151 | let ldapForm = page.locator('[data-testid="ldap-login-form"]');
152 | await expect(ldapForm).toBeVisible();
153 |
154 | // Switch to local
155 | await localTab.click();
156 | ldapForm = page.locator('[data-testid="ldap-login-form"]');
157 | await expect(ldapForm).not.toBeVisible();
158 |
159 | // Switch back to LDAP
160 | await ldapTab.click();
161 | ldapForm = page.locator('[data-testid="ldap-login-form"]');
162 | await expect(ldapForm).toBeVisible();
163 | });
164 |
165 | test('should remember login preference on revisit', async ({ page, context }) => {
166 | // Login with local user
167 | await auth.loginWithLocalUser(page, LOCAL_USERS.admin, BASE_URL);
168 |
169 | // Close and reopen browser
170 | await page.close();
171 | const newPage = await context.newPage();
172 | await newPage.goto(BASE_URL);