174 lines
6.4 KiB
Markdown
174 lines
6.4 KiB
Markdown
# 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 display user list in local login tab
|
|
- Location: e2e/workflows/1-login.spec.ts:202:7
|
|
|
|
# Error details
|
|
|
|
```
|
|
Error: expect(received).toBeGreaterThan(expected)
|
|
|
|
Expected: > 0
|
|
Received: 0
|
|
```
|
|
|
|
# Page snapshot
|
|
|
|
```yaml
|
|
- 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
|
|
|
|
```ts
|
|
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);
|
|
173 |
|
|
174 | // Should still be authenticated
|
|
175 | const authenticated = await auth.isAuthenticated(newPage);
|
|
176 | expect(authenticated).toBe(true);
|
|
177 |
|
|
178 | await newPage.close();
|
|
179 | });
|
|
180 |
|
|
181 | test('should handle network errors gracefully', async ({ page }) => {
|
|
182 | // Enable offline mode
|
|
183 | await page.context().setOffline(true);
|
|
184 |
|
|
185 | // Try to login
|
|
186 | const usernameInput = page.locator('[data-testid="username-input"]');
|
|
187 | const passwordInput = page.locator('[data-testid="password-input"]');
|
|
188 | const submitButton = page.locator('[data-testid="login-submit"]');
|
|
189 |
|
|
190 | await usernameInput.fill(LOCAL_USERS.admin.username);
|
|
191 | await passwordInput.fill(LOCAL_USERS.admin.password);
|
|
192 | await submitButton.click();
|
|
193 |
|
|
194 | // Should show network error
|
|
195 | const errorToast = page.locator('[data-testid="toast-error"]');
|
|
196 | await expect(errorToast).toBeVisible({ timeout: 5000 });
|
|
197 |
|
|
198 | // Re-enable network
|
|
199 | await page.context().setOffline(false);
|
|
200 | });
|
|
201 |
|
|
202 | test('should display user list in local login tab', async ({ page }) => {
|
|
203 | const localTab = page.locator('[data-testid="local-login-tab"]');
|
|
204 | await localTab.click();
|
|
205 |
|
|
206 | // User list should be visible
|
|
207 | const userList = page.locator('[data-testid="user-list"]');
|
|
208 | await expect(userList).toBeVisible();
|
|
209 |
|
|
210 | // Should have at least one user
|
|
211 | const userItems = page.locator('[data-testid="user-list-item"]');
|
|
> 212 | expect(await userItems.count()).toBeGreaterThan(0);
|
|
| ^ Error: expect(received).toBeGreaterThan(expected)
|
|
213 | });
|
|
214 |
|
|
215 | test('should auto-login when clicking user from list', async ({ page }) => {
|
|
216 | const localTab = page.locator('[data-testid="local-login-tab"]');
|
|
217 | await localTab.click();
|
|
218 |
|
|
219 | // Click first user in list
|
|
220 | const firstUser = page.locator('[data-testid="user-list-item"]').first();
|
|
221 | await firstUser.click();
|
|
222 |
|
|
223 | // Password input should be focused
|
|
224 | const passwordInput = page.locator('[data-testid="local-password-input"]');
|
|
225 | await expect(passwordInput).toBeFocused();
|
|
226 | });
|
|
227 | });
|
|
228 |
|
|
``` |