test: save E2E test progress - data-testid attributes added, 1/16 login tests passing
This commit is contained in:
@@ -0,0 +1,238 @@
|
||||
# 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 allow switching between LDAP and local login tabs
|
||||
- Location: e2e/workflows/1-login.spec.ts:146:7
|
||||
|
||||
# Error details
|
||||
|
||||
```
|
||||
Error: expect(locator).toBeVisible() failed
|
||||
|
||||
Locator: locator('[data-testid="ldap-login-form"]')
|
||||
Expected: visible
|
||||
Timeout: 5000ms
|
||||
Error: element(s) not found
|
||||
|
||||
Call log:
|
||||
- Expect "toBeVisible" with timeout 5000ms
|
||||
- waiting for locator('[data-testid="ldap-login-form"]')
|
||||
|
||||
```
|
||||
|
||||
# Page snapshot
|
||||
|
||||
```yaml
|
||||
- generic [active] [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=e11]:
|
||||
- button "newuser user" [ref=e12] [cursor=pointer]:
|
||||
- generic [ref=e13]:
|
||||
- img [ref=e15]
|
||||
- generic [ref=e18]:
|
||||
- paragraph [ref=e19]: newuser
|
||||
- paragraph [ref=e20]: user
|
||||
- img [ref=e21]
|
||||
- generic [ref=e23]:
|
||||
- button "Enterprise" [ref=e24] [cursor=pointer]:
|
||||
- img [ref=e25]
|
||||
- text: Enterprise
|
||||
- button "Manual Login" [ref=e28] [cursor=pointer]:
|
||||
- img [ref=e29]
|
||||
- text: Manual Login
|
||||
- button "Open Next.js Dev Tools" [ref=e37] [cursor=pointer]:
|
||||
- img [ref=e38]
|
||||
- alert [ref=e41]
|
||||
```
|
||||
|
||||
# Test source
|
||||
|
||||
```ts
|
||||
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');
|
||||
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();
|
||||
| ^ Error: expect(locator).toBeVisible() failed
|
||||
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);
|
||||
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 |
|
||||
```
|
||||
Reference in New Issue
Block a user