test: fix data-testid attribute names and update E2E test URLs to port 8917
@@ -52,7 +52,19 @@
|
||||
"Bash(sed -i 's|\"/api/items|\"/items|g' backend/tests/test_items.py)",
|
||||
"Bash(sed -i 's|\"/api/categories|\"/categories|g' backend/tests/test_categories.py)",
|
||||
"Bash(sed -i 's|\"/api/operations|\"/operations|g' backend/tests/test_operations.py)",
|
||||
"Bash(sed -i 's|\"/api/operations|\"/operations|g' backend/tests/test_offline_sync.py)"
|
||||
"Bash(sed -i 's|\"/api/operations|\"/operations|g' backend/tests/test_offline_sync.py)",
|
||||
"Bash(curl -sf http://localhost:8906/)",
|
||||
"Bash(curl -sf http://localhost:3000/)",
|
||||
"Bash(curl -s -o /dev/null -w \"%{http_code}\" http://localhost:3000/)",
|
||||
"Bash(NEXT_PUBLIC_API_URL=http://localhost:8906 npm run dev -- --port 3000)",
|
||||
"Bash(echo \"Frontend PID: $!\")",
|
||||
"Bash(curl -sf http://localhost:3000)",
|
||||
"Bash(curl -s http://localhost:3000/login)",
|
||||
"Bash(curl -s http://localhost:8906/users)",
|
||||
"Bash(curl -v http://localhost:8906/users)",
|
||||
"Bash(NEXT_PUBLIC_API_URL=http://localhost:8916 npm run dev -- --port 8917)",
|
||||
"Bash(curl -sf http://localhost:8917)",
|
||||
"Bash(xargs sed *)"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ export default function LoginPage() {
|
||||
|
||||
<div className="pt-2 grid grid-cols-2 gap-3">
|
||||
<button
|
||||
data-testid="local-login-tab"
|
||||
data-testid="ldap-login-tab"
|
||||
onClick={() => setIsEnterprise(true)}
|
||||
className="flex items-center justify-center gap-2 py-4 rounded-2xl border border-dashed border-slate-700 text-muted hover:text-white hover:border-slate-500 transition-all font-bold text-xs"
|
||||
>
|
||||
@@ -132,6 +132,7 @@ export default function LoginPage() {
|
||||
Enterprise
|
||||
</button>
|
||||
<button
|
||||
data-testid="local-login-tab"
|
||||
onClick={() => {
|
||||
setSelectedUserForLogin({ username: '' });
|
||||
// We use an empty username object to trigger the manual input view
|
||||
|
||||
@@ -4,7 +4,7 @@ import * as assertions from '../utils/assertions';
|
||||
import { LDAP_USERS, LOCAL_USERS } from '../fixtures/test-data';
|
||||
|
||||
test.describe('Login Workflow', () => {
|
||||
const BASE_URL = process.env.BASE_URL || 'http://localhost:3000';
|
||||
const BASE_URL = process.env.BASE_URL || 'http://localhost:8917';
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// Navigate to login page
|
||||
|
||||
@@ -5,7 +5,7 @@ import * as helpers from '../utils/helpers';
|
||||
import { LOCAL_USERS, TEST_ITEMS } from '../fixtures/test-data';
|
||||
|
||||
test.describe('Scan and Adjust Workflow', () => {
|
||||
const BASE_URL = process.env.BASE_URL || 'http://localhost:3000';
|
||||
const BASE_URL = process.env.BASE_URL || 'http://localhost:8917';
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// Navigate to app and login
|
||||
|
||||
@@ -5,7 +5,7 @@ import * as helpers from '../utils/helpers';
|
||||
import { LOCAL_USERS } from '../fixtures/test-data';
|
||||
|
||||
test.describe('AI Extraction Workflow', () => {
|
||||
const BASE_URL = process.env.BASE_URL || 'http://localhost:3000';
|
||||
const BASE_URL = process.env.BASE_URL || 'http://localhost:8917';
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// Navigate to app and login
|
||||
|
||||
@@ -5,7 +5,7 @@ import * as helpers from '../utils/helpers';
|
||||
import { LOCAL_USERS, TEST_CATEGORIES } from '../fixtures/test-data';
|
||||
|
||||
test.describe('Admin Settings Workflow', () => {
|
||||
const BASE_URL = process.env.BASE_URL || 'http://localhost:3000';
|
||||
const BASE_URL = process.env.BASE_URL || 'http://localhost:8917';
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// Navigate to app and login as admin
|
||||
|
||||
@@ -5,7 +5,7 @@ import * as helpers from '../utils/helpers';
|
||||
import { LOCAL_USERS, TEST_ITEMS, OFFLINE_SYNC_SCENARIOS } from '../fixtures/test-data';
|
||||
|
||||
test.describe('Offline Sync Workflow', () => {
|
||||
const BASE_URL = process.env.BASE_URL || 'http://localhost:3000';
|
||||
const BASE_URL = process.env.BASE_URL || 'http://localhost:8917';
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// Navigate to app and login
|
||||
|
||||
|
After Width: | Height: | Size: 25 KiB |
@@ -6,16 +6,52 @@
|
||||
|
||||
# Test info
|
||||
|
||||
- Name: 1-login.spec.ts >> Login Workflow >> should handle network errors gracefully
|
||||
- Location: e2e/workflows/1-login.spec.ts:181:7
|
||||
- Name: 1-login.spec.ts >> Login Workflow >> should display identity check overlay on app load
|
||||
- Location: e2e/workflows/1-login.spec.ts:16:7
|
||||
|
||||
# Error details
|
||||
|
||||
```
|
||||
Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
Call log:
|
||||
- navigating to "http://localhost:3000/", waiting until "load"
|
||||
Error: expect(locator).toBeVisible() failed
|
||||
|
||||
Locator: locator('[data-testid="ldap-login-tab"]')
|
||||
Expected: visible
|
||||
Timeout: 5000ms
|
||||
Error: element(s) not found
|
||||
|
||||
Call log:
|
||||
- Expect "toBeVisible" with timeout 5000ms
|
||||
- waiting for locator('[data-testid="ldap-login-tab"]')
|
||||
|
||||
```
|
||||
|
||||
# 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
|
||||
@@ -27,12 +63,11 @@ Call log:
|
||||
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:3000';
|
||||
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);
|
||||
| ^ Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
11 | await page.goto(BASE_URL);
|
||||
12 | // Wait for identity check overlay
|
||||
13 | await page.waitForSelector('[data-testid="identity-check-overlay"]', { timeout: 10000 });
|
||||
14 | });
|
||||
@@ -45,7 +80,8 @@ Call log:
|
||||
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();
|
||||
> 24 | await expect(ldapTab).toBeVisible();
|
||||
| ^ Error: expect(locator).toBeVisible() failed
|
||||
25 | await expect(localTab).toBeVisible();
|
||||
26 | });
|
||||
27 |
|
||||
@@ -133,4 +169,17 @@ Call log:
|
||||
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 |
|
||||
```
|
||||
90
frontend/playwright-report/index.html
Normal file
@@ -10,16 +10,16 @@ export default defineConfig({
|
||||
timeout: 30000,
|
||||
expect: { timeout: 5000 },
|
||||
use: {
|
||||
baseURL: 'http://localhost',
|
||||
baseURL: 'http://localhost:8917',
|
||||
trace: 'on-first-retry',
|
||||
screenshot: 'only-on-failure',
|
||||
},
|
||||
|
||||
webServer: {
|
||||
command: 'npm run dev',
|
||||
url: 'http://localhost:3000',
|
||||
command: 'NEXT_PUBLIC_API_URL=http://localhost:8916 npm run dev -- --port 8917',
|
||||
url: 'http://localhost:8917',
|
||||
reuseExistingServer: true,
|
||||
timeout: 60000,
|
||||
timeout: 120000,
|
||||
},
|
||||
|
||||
projects: [
|
||||
|
||||
6
frontend/test-results/.last-run.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"status": "failed",
|
||||
"failedTests": [
|
||||
"c505212a9f19102e22e9-48f621cdb716ff0f50ce"
|
||||
]
|
||||
}
|
||||
|
Before Width: | Height: | Size: 4.2 KiB |
@@ -1,136 +0,0 @@
|
||||
# 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: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
Call log:
|
||||
- navigating to "http://localhost:3000/", waiting until "load"
|
||||
|
||||
```
|
||||
|
||||
# Test source
|
||||
|
||||
```ts
|
||||
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:3000';
|
||||
8 |
|
||||
9 | test.beforeEach(async ({ page }) => {
|
||||
10 | // Navigate to login page
|
||||
> 11 | await page.goto(BASE_URL);
|
||||
| ^ Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
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');
|
||||
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 |
|
||||
```
|
||||
|
Before Width: | Height: | Size: 4.2 KiB |
@@ -1,136 +0,0 @@
|
||||
# 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 auto-login when clicking user from list
|
||||
- Location: e2e/workflows/1-login.spec.ts:215:7
|
||||
|
||||
# Error details
|
||||
|
||||
```
|
||||
Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
Call log:
|
||||
- navigating to "http://localhost:3000/", waiting until "load"
|
||||
|
||||
```
|
||||
|
||||
# Test source
|
||||
|
||||
```ts
|
||||
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:3000';
|
||||
8 |
|
||||
9 | test.beforeEach(async ({ page }) => {
|
||||
10 | // Navigate to login page
|
||||
> 11 | await page.goto(BASE_URL);
|
||||
| ^ Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
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');
|
||||
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 |
|
||||
```
|
||||
|
Before Width: | Height: | Size: 4.2 KiB |
@@ -1,136 +0,0 @@
|
||||
# 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 successfully login with valid local user credentials
|
||||
- Location: e2e/workflows/1-login.spec.ts:81:7
|
||||
|
||||
# Error details
|
||||
|
||||
```
|
||||
Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
Call log:
|
||||
- navigating to "http://localhost:3000/", waiting until "load"
|
||||
|
||||
```
|
||||
|
||||
# Test source
|
||||
|
||||
```ts
|
||||
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:3000';
|
||||
8 |
|
||||
9 | test.beforeEach(async ({ page }) => {
|
||||
10 | // Navigate to login page
|
||||
> 11 | await page.goto(BASE_URL);
|
||||
| ^ Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
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');
|
||||
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 |
|
||||
```
|
||||
|
Before Width: | Height: | Size: 4.2 KiB |
@@ -1,136 +0,0 @@
|
||||
# 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
|
||||
|
||||
```
|
||||
Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
Call log:
|
||||
- navigating to "http://localhost:3000/", waiting until "load"
|
||||
|
||||
```
|
||||
|
||||
# Test source
|
||||
|
||||
```ts
|
||||
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:3000';
|
||||
8 |
|
||||
9 | test.beforeEach(async ({ page }) => {
|
||||
10 | // Navigate to login page
|
||||
> 11 | await page.goto(BASE_URL);
|
||||
| ^ Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
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');
|
||||
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 |
|
||||
```
|
||||
|
Before Width: | Height: | Size: 4.2 KiB |
@@ -1,136 +0,0 @@
|
||||
# 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 successfully login with valid LDAP credentials
|
||||
- Location: e2e/workflows/1-login.spec.ts:52:7
|
||||
|
||||
# Error details
|
||||
|
||||
```
|
||||
Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
Call log:
|
||||
- navigating to "http://localhost:3000/", waiting until "load"
|
||||
|
||||
```
|
||||
|
||||
# Test source
|
||||
|
||||
```ts
|
||||
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:3000';
|
||||
8 |
|
||||
9 | test.beforeEach(async ({ page }) => {
|
||||
10 | // Navigate to login page
|
||||
> 11 | await page.goto(BASE_URL);
|
||||
| ^ Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
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');
|
||||
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 |
|
||||
```
|
||||
|
Before Width: | Height: | Size: 4.2 KiB |
@@ -1,136 +0,0 @@
|
||||
# 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 maintain session across page reloads
|
||||
- Location: e2e/workflows/1-login.spec.ts:105:7
|
||||
|
||||
# Error details
|
||||
|
||||
```
|
||||
Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
Call log:
|
||||
- navigating to "http://localhost:3000/", waiting until "load"
|
||||
|
||||
```
|
||||
|
||||
# Test source
|
||||
|
||||
```ts
|
||||
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:3000';
|
||||
8 |
|
||||
9 | test.beforeEach(async ({ page }) => {
|
||||
10 | // Navigate to login page
|
||||
> 11 | await page.goto(BASE_URL);
|
||||
| ^ Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
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');
|
||||
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 |
|
||||
```
|
||||
|
Before Width: | Height: | Size: 4.2 KiB |
@@ -1,136 +0,0 @@
|
||||
# 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 login form with username and password fields
|
||||
- Location: e2e/workflows/1-login.spec.ts:28:7
|
||||
|
||||
# Error details
|
||||
|
||||
```
|
||||
Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
Call log:
|
||||
- navigating to "http://localhost:3000/", waiting until "load"
|
||||
|
||||
```
|
||||
|
||||
# Test source
|
||||
|
||||
```ts
|
||||
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:3000';
|
||||
8 |
|
||||
9 | test.beforeEach(async ({ page }) => {
|
||||
10 | // Navigate to login page
|
||||
> 11 | await page.goto(BASE_URL);
|
||||
| ^ Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
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');
|
||||
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 |
|
||||
```
|
||||
|
Before Width: | Height: | Size: 4.2 KiB |
@@ -1,136 +0,0 @@
|
||||
# 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 show admin button for admin users
|
||||
- Location: e2e/workflows/1-login.spec.ts:137:7
|
||||
|
||||
# Error details
|
||||
|
||||
```
|
||||
Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
Call log:
|
||||
- navigating to "http://localhost:3000/", waiting until "load"
|
||||
|
||||
```
|
||||
|
||||
# Test source
|
||||
|
||||
```ts
|
||||
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:3000';
|
||||
8 |
|
||||
9 | test.beforeEach(async ({ page }) => {
|
||||
10 | // Navigate to login page
|
||||
> 11 | await page.goto(BASE_URL);
|
||||
| ^ Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
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');
|
||||
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 |
|
||||
```
|
||||
|
Before Width: | Height: | Size: 4.2 KiB |
@@ -1,136 +0,0 @@
|
||||
# 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 show user identity after successful login
|
||||
- Location: e2e/workflows/1-login.spec.ts:93:7
|
||||
|
||||
# Error details
|
||||
|
||||
```
|
||||
Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
Call log:
|
||||
- navigating to "http://localhost:3000/", waiting until "load"
|
||||
|
||||
```
|
||||
|
||||
# Test source
|
||||
|
||||
```ts
|
||||
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:3000';
|
||||
8 |
|
||||
9 | test.beforeEach(async ({ page }) => {
|
||||
10 | // Navigate to login page
|
||||
> 11 | await page.goto(BASE_URL);
|
||||
| ^ Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
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');
|
||||
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 |
|
||||
```
|
||||
|
Before Width: | Height: | Size: 4.2 KiB |
@@ -1,136 +0,0 @@
|
||||
# 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 remember login preference on revisit
|
||||
- Location: e2e/workflows/1-login.spec.ts:165:7
|
||||
|
||||
# Error details
|
||||
|
||||
```
|
||||
Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
Call log:
|
||||
- navigating to "http://localhost:3000/", waiting until "load"
|
||||
|
||||
```
|
||||
|
||||
# Test source
|
||||
|
||||
```ts
|
||||
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:3000';
|
||||
8 |
|
||||
9 | test.beforeEach(async ({ page }) => {
|
||||
10 | // Navigate to login page
|
||||
> 11 | await page.goto(BASE_URL);
|
||||
| ^ Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
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');
|
||||
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 |
|
||||
```
|
||||
@@ -1,136 +0,0 @@
|
||||
# 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 LDAP credentials
|
||||
- Location: e2e/workflows/1-login.spec.ts:41:7
|
||||
|
||||
# Error details
|
||||
|
||||
```
|
||||
Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
Call log:
|
||||
- navigating to "http://localhost:3000/", waiting until "load"
|
||||
|
||||
```
|
||||
|
||||
# Test source
|
||||
|
||||
```ts
|
||||
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:3000';
|
||||
8 |
|
||||
9 | test.beforeEach(async ({ page }) => {
|
||||
10 | // Navigate to login page
|
||||
> 11 | await page.goto(BASE_URL);
|
||||
| ^ Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
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');
|
||||
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 |
|
||||
```
|
||||
|
Before Width: | Height: | Size: 4.2 KiB |
@@ -12,10 +12,46 @@
|
||||
# Error details
|
||||
|
||||
```
|
||||
Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
Call log:
|
||||
- navigating to "http://localhost:3000/", waiting until "load"
|
||||
Error: expect(locator).toBeVisible() failed
|
||||
|
||||
Locator: locator('[data-testid="ldap-login-tab"]')
|
||||
Expected: visible
|
||||
Timeout: 5000ms
|
||||
Error: element(s) not found
|
||||
|
||||
Call log:
|
||||
- Expect "toBeVisible" with timeout 5000ms
|
||||
- waiting for locator('[data-testid="ldap-login-tab"]')
|
||||
|
||||
```
|
||||
|
||||
# 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
|
||||
@@ -27,12 +63,11 @@ Call log:
|
||||
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:3000';
|
||||
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);
|
||||
| ^ Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
11 | await page.goto(BASE_URL);
|
||||
12 | // Wait for identity check overlay
|
||||
13 | await page.waitForSelector('[data-testid="identity-check-overlay"]', { timeout: 10000 });
|
||||
14 | });
|
||||
@@ -45,7 +80,8 @@ Call log:
|
||||
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();
|
||||
> 24 | await expect(ldapTab).toBeVisible();
|
||||
| ^ Error: expect(locator).toBeVisible() failed
|
||||
25 | await expect(localTab).toBeVisible();
|
||||
26 | });
|
||||
27 |
|
||||
@@ -133,4 +169,17 @@ Call log:
|
||||
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 |
|
||||
```
|
||||
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 25 KiB |
@@ -1,136 +0,0 @@
|
||||
# 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: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
Call log:
|
||||
- navigating to "http://localhost:3000/", waiting until "load"
|
||||
|
||||
```
|
||||
|
||||
# Test source
|
||||
|
||||
```ts
|
||||
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:3000';
|
||||
8 |
|
||||
9 | test.beforeEach(async ({ page }) => {
|
||||
10 | // Navigate to login page
|
||||
> 11 | await page.goto(BASE_URL);
|
||||
| ^ Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
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');
|
||||
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 |
|
||||
```
|
||||
|
Before Width: | Height: | Size: 4.2 KiB |
@@ -1,136 +0,0 @@
|
||||
# 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 empty login credentials
|
||||
- Location: e2e/workflows/1-login.spec.ts:32:7
|
||||
|
||||
# Error details
|
||||
|
||||
```
|
||||
Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
Call log:
|
||||
- navigating to "http://localhost:3000/", waiting until "load"
|
||||
|
||||
```
|
||||
|
||||
# Test source
|
||||
|
||||
```ts
|
||||
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:3000';
|
||||
8 |
|
||||
9 | test.beforeEach(async ({ page }) => {
|
||||
10 | // Navigate to login page
|
||||
> 11 | await page.goto(BASE_URL);
|
||||
| ^ Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
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');
|
||||
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 |
|
||||
```
|
||||
|
Before Width: | Height: | Size: 4.2 KiB |
@@ -1,136 +0,0 @@
|
||||
# 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 support logout functionality
|
||||
- Location: e2e/workflows/1-login.spec.ts:120:7
|
||||
|
||||
# Error details
|
||||
|
||||
```
|
||||
Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
Call log:
|
||||
- navigating to "http://localhost:3000/", waiting until "load"
|
||||
|
||||
```
|
||||
|
||||
# Test source
|
||||
|
||||
```ts
|
||||
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:3000';
|
||||
8 |
|
||||
9 | test.beforeEach(async ({ page }) => {
|
||||
10 | // Navigate to login page
|
||||
> 11 | await page.goto(BASE_URL);
|
||||
| ^ Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
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');
|
||||
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 |
|
||||
```
|
||||
|
Before Width: | Height: | Size: 4.2 KiB |
@@ -1,137 +0,0 @@
|
||||
# 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: 2-scan-adjust.spec.ts >> Scan and Adjust Workflow >> should display scan input field
|
||||
- Location: e2e/workflows/2-scan-adjust.spec.ts:32:7
|
||||
|
||||
# Error details
|
||||
|
||||
```
|
||||
Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
Call log:
|
||||
- navigating to "http://localhost:3000/", waiting until "load"
|
||||
|
||||
```
|
||||
|
||||
# Test source
|
||||
|
||||
```ts
|
||||
1 | import { test, expect } from '@playwright/test';
|
||||
2 | import * as auth from '../fixtures/auth';
|
||||
3 | import * as assertions from '../utils/assertions';
|
||||
4 | import * as helpers from '../utils/helpers';
|
||||
5 | import { LOCAL_USERS, TEST_ITEMS } from '../fixtures/test-data';
|
||||
6 |
|
||||
7 | test.describe('Scan and Adjust Workflow', () => {
|
||||
8 | const BASE_URL = process.env.BASE_URL || 'http://localhost:3000';
|
||||
9 |
|
||||
10 | test.beforeEach(async ({ page }) => {
|
||||
11 | // Navigate to app and login
|
||||
> 12 | await page.goto(BASE_URL);
|
||||
| ^ Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
13 | await auth.loginWithLocalUser(page, LOCAL_USERS.admin, BASE_URL);
|
||||
14 | await assertions.assertUserAuthenticated(page, BASE_URL);
|
||||
15 |
|
||||
16 | // Navigate to scanner page
|
||||
17 | await page.goto(`${BASE_URL}/scanner`);
|
||||
18 | await assertions.assertScannerReady(page);
|
||||
19 | });
|
||||
20 |
|
||||
21 | test('should display scanner interface with camera view', async ({ page }) => {
|
||||
22 | await assertions.assertScannerReady(page);
|
||||
23 |
|
||||
24 | // Verify camera controls
|
||||
25 | const zoomButton = page.locator('[data-testid="zoom-control"]');
|
||||
26 | const cameraIndicator = page.locator('[data-testid="camera-indicator"]');
|
||||
27 |
|
||||
28 | await expect(zoomButton).toBeVisible();
|
||||
29 | await expect(cameraIndicator).toBeVisible();
|
||||
30 | });
|
||||
31 |
|
||||
32 | test('should display scan input field', async ({ page }) => {
|
||||
33 | const scanInput = page.locator('[data-testid="scan-input"]');
|
||||
34 | await expect(scanInput).toBeVisible();
|
||||
35 | await expect(scanInput).toBeFocused();
|
||||
36 | });
|
||||
37 |
|
||||
38 | test('should handle barcode scan and match to inventory item', async ({ page }) => {
|
||||
39 | // Simulate barcode scan by entering barcode in input
|
||||
40 | const scanInput = page.locator('[data-testid="scan-input"]');
|
||||
41 |
|
||||
42 | // Enter first test item's barcode
|
||||
43 | await scanInput.fill(TEST_ITEMS[0].barcode);
|
||||
44 | await scanInput.press('Enter');
|
||||
45 |
|
||||
46 | // Should show stock adjustment form
|
||||
47 | await assertions.assertStockAdjustmentVisible(page, TEST_ITEMS[0].name);
|
||||
48 |
|
||||
49 | // Verify item details are shown
|
||||
50 | const itemName = page.locator('[data-testid="adjustment-item-name"]');
|
||||
51 | await expect(itemName).toContainText(TEST_ITEMS[0].name);
|
||||
52 | });
|
||||
53 |
|
||||
54 | test('should default to check-in operation', async ({ page }) => {
|
||||
55 | const scanInput = page.locator('[data-testid="scan-input"]');
|
||||
56 | await scanInput.fill(TEST_ITEMS[0].barcode);
|
||||
57 | await scanInput.press('Enter');
|
||||
58 |
|
||||
59 | // Check-in radio should be selected
|
||||
60 | const checkInRadio = page.locator('[data-testid="operation-checkin"]');
|
||||
61 | await expect(checkInRadio).toBeChecked();
|
||||
62 | });
|
||||
63 |
|
||||
64 | test('should allow switching between check-in and check-out', async ({ page }) => {
|
||||
65 | const scanInput = page.locator('[data-testid="scan-input"]');
|
||||
66 | await scanInput.fill(TEST_ITEMS[0].barcode);
|
||||
67 | await scanInput.press('Enter');
|
||||
68 |
|
||||
69 | // Switch to check-out
|
||||
70 | const checkOutRadio = page.locator('[data-testid="operation-checkout"]');
|
||||
71 | await checkOutRadio.click();
|
||||
72 | await expect(checkOutRadio).toBeChecked();
|
||||
73 |
|
||||
74 | // Switch back to check-in
|
||||
75 | const checkInRadio = page.locator('[data-testid="operation-checkin"]');
|
||||
76 | await checkInRadio.click();
|
||||
77 | await expect(checkInRadio).toBeChecked();
|
||||
78 | });
|
||||
79 |
|
||||
80 | test('should allow quantity adjustment', async ({ page }) => {
|
||||
81 | const scanInput = page.locator('[data-testid="scan-input"]');
|
||||
82 | await scanInput.fill(TEST_ITEMS[0].barcode);
|
||||
83 | await scanInput.press('Enter');
|
||||
84 |
|
||||
85 | // Change quantity
|
||||
86 | const quantityInput = page.locator('[data-testid="adjustment-quantity-input"]');
|
||||
87 | await quantityInput.fill('10');
|
||||
88 |
|
||||
89 | // Verify value changed
|
||||
90 | const value = await helpers.getInputValue(page, '[data-testid="adjustment-quantity-input"]');
|
||||
91 | expect(value).toBe('10');
|
||||
92 | });
|
||||
93 |
|
||||
94 | test('should reject invalid quantities', async ({ page }) => {
|
||||
95 | const scanInput = page.locator('[data-testid="scan-input"]');
|
||||
96 | await scanInput.fill(TEST_ITEMS[0].barcode);
|
||||
97 | await scanInput.press('Enter');
|
||||
98 |
|
||||
99 | // Try invalid quantity
|
||||
100 | const quantityInput = page.locator('[data-testid="adjustment-quantity-input"]');
|
||||
101 | await quantityInput.fill('-5');
|
||||
102 |
|
||||
103 | // Submit should be disabled or show error
|
||||
104 | const submitButton = page.locator('[data-testid="adjustment-submit"]');
|
||||
105 | if (await submitButton.isEnabled()) {
|
||||
106 | await submitButton.click();
|
||||
107 | const errorToast = page.locator('[data-testid="toast-error"]');
|
||||
108 | await expect(errorToast).toBeVisible({ timeout: 3000 });
|
||||
109 | }
|
||||
110 | });
|
||||
111 |
|
||||
112 | test('should submit stock adjustment successfully', async ({ page }) => {
|
||||
```
|
||||
|
Before Width: | Height: | Size: 4.2 KiB |
@@ -1,137 +0,0 @@
|
||||
# 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: 2-scan-adjust.spec.ts >> Scan and Adjust Workflow >> should display scanner interface with camera view
|
||||
- Location: e2e/workflows/2-scan-adjust.spec.ts:21:7
|
||||
|
||||
# Error details
|
||||
|
||||
```
|
||||
Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
Call log:
|
||||
- navigating to "http://localhost:3000/", waiting until "load"
|
||||
|
||||
```
|
||||
|
||||
# Test source
|
||||
|
||||
```ts
|
||||
1 | import { test, expect } from '@playwright/test';
|
||||
2 | import * as auth from '../fixtures/auth';
|
||||
3 | import * as assertions from '../utils/assertions';
|
||||
4 | import * as helpers from '../utils/helpers';
|
||||
5 | import { LOCAL_USERS, TEST_ITEMS } from '../fixtures/test-data';
|
||||
6 |
|
||||
7 | test.describe('Scan and Adjust Workflow', () => {
|
||||
8 | const BASE_URL = process.env.BASE_URL || 'http://localhost:3000';
|
||||
9 |
|
||||
10 | test.beforeEach(async ({ page }) => {
|
||||
11 | // Navigate to app and login
|
||||
> 12 | await page.goto(BASE_URL);
|
||||
| ^ Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:3000/
|
||||
13 | await auth.loginWithLocalUser(page, LOCAL_USERS.admin, BASE_URL);
|
||||
14 | await assertions.assertUserAuthenticated(page, BASE_URL);
|
||||
15 |
|
||||
16 | // Navigate to scanner page
|
||||
17 | await page.goto(`${BASE_URL}/scanner`);
|
||||
18 | await assertions.assertScannerReady(page);
|
||||
19 | });
|
||||
20 |
|
||||
21 | test('should display scanner interface with camera view', async ({ page }) => {
|
||||
22 | await assertions.assertScannerReady(page);
|
||||
23 |
|
||||
24 | // Verify camera controls
|
||||
25 | const zoomButton = page.locator('[data-testid="zoom-control"]');
|
||||
26 | const cameraIndicator = page.locator('[data-testid="camera-indicator"]');
|
||||
27 |
|
||||
28 | await expect(zoomButton).toBeVisible();
|
||||
29 | await expect(cameraIndicator).toBeVisible();
|
||||
30 | });
|
||||
31 |
|
||||
32 | test('should display scan input field', async ({ page }) => {
|
||||
33 | const scanInput = page.locator('[data-testid="scan-input"]');
|
||||
34 | await expect(scanInput).toBeVisible();
|
||||
35 | await expect(scanInput).toBeFocused();
|
||||
36 | });
|
||||
37 |
|
||||
38 | test('should handle barcode scan and match to inventory item', async ({ page }) => {
|
||||
39 | // Simulate barcode scan by entering barcode in input
|
||||
40 | const scanInput = page.locator('[data-testid="scan-input"]');
|
||||
41 |
|
||||
42 | // Enter first test item's barcode
|
||||
43 | await scanInput.fill(TEST_ITEMS[0].barcode);
|
||||
44 | await scanInput.press('Enter');
|
||||
45 |
|
||||
46 | // Should show stock adjustment form
|
||||
47 | await assertions.assertStockAdjustmentVisible(page, TEST_ITEMS[0].name);
|
||||
48 |
|
||||
49 | // Verify item details are shown
|
||||
50 | const itemName = page.locator('[data-testid="adjustment-item-name"]');
|
||||
51 | await expect(itemName).toContainText(TEST_ITEMS[0].name);
|
||||
52 | });
|
||||
53 |
|
||||
54 | test('should default to check-in operation', async ({ page }) => {
|
||||
55 | const scanInput = page.locator('[data-testid="scan-input"]');
|
||||
56 | await scanInput.fill(TEST_ITEMS[0].barcode);
|
||||
57 | await scanInput.press('Enter');
|
||||
58 |
|
||||
59 | // Check-in radio should be selected
|
||||
60 | const checkInRadio = page.locator('[data-testid="operation-checkin"]');
|
||||
61 | await expect(checkInRadio).toBeChecked();
|
||||
62 | });
|
||||
63 |
|
||||
64 | test('should allow switching between check-in and check-out', async ({ page }) => {
|
||||
65 | const scanInput = page.locator('[data-testid="scan-input"]');
|
||||
66 | await scanInput.fill(TEST_ITEMS[0].barcode);
|
||||
67 | await scanInput.press('Enter');
|
||||
68 |
|
||||
69 | // Switch to check-out
|
||||
70 | const checkOutRadio = page.locator('[data-testid="operation-checkout"]');
|
||||
71 | await checkOutRadio.click();
|
||||
72 | await expect(checkOutRadio).toBeChecked();
|
||||
73 |
|
||||
74 | // Switch back to check-in
|
||||
75 | const checkInRadio = page.locator('[data-testid="operation-checkin"]');
|
||||
76 | await checkInRadio.click();
|
||||
77 | await expect(checkInRadio).toBeChecked();
|
||||
78 | });
|
||||
79 |
|
||||
80 | test('should allow quantity adjustment', async ({ page }) => {
|
||||
81 | const scanInput = page.locator('[data-testid="scan-input"]');
|
||||
82 | await scanInput.fill(TEST_ITEMS[0].barcode);
|
||||
83 | await scanInput.press('Enter');
|
||||
84 |
|
||||
85 | // Change quantity
|
||||
86 | const quantityInput = page.locator('[data-testid="adjustment-quantity-input"]');
|
||||
87 | await quantityInput.fill('10');
|
||||
88 |
|
||||
89 | // Verify value changed
|
||||
90 | const value = await helpers.getInputValue(page, '[data-testid="adjustment-quantity-input"]');
|
||||
91 | expect(value).toBe('10');
|
||||
92 | });
|
||||
93 |
|
||||
94 | test('should reject invalid quantities', async ({ page }) => {
|
||||
95 | const scanInput = page.locator('[data-testid="scan-input"]');
|
||||
96 | await scanInput.fill(TEST_ITEMS[0].barcode);
|
||||
97 | await scanInput.press('Enter');
|
||||
98 |
|
||||
99 | // Try invalid quantity
|
||||
100 | const quantityInput = page.locator('[data-testid="adjustment-quantity-input"]');
|
||||
101 | await quantityInput.fill('-5');
|
||||
102 |
|
||||
103 | // Submit should be disabled or show error
|
||||
104 | const submitButton = page.locator('[data-testid="adjustment-submit"]');
|
||||
105 | if (await submitButton.isEnabled()) {
|
||||
106 | await submitButton.click();
|
||||
107 | const errorToast = page.locator('[data-testid="toast-error"]');
|
||||
108 | await expect(errorToast).toBeVisible({ timeout: 3000 });
|
||||
109 | }
|
||||
110 | });
|
||||
111 |
|
||||
112 | test('should submit stock adjustment successfully', async ({ page }) => {
|
||||
```
|
||||
|
Before Width: | Height: | Size: 4.2 KiB |