137 lines
5.7 KiB
Markdown
137 lines
5.7 KiB
Markdown
# Instructions
|
|
|
|
- Following Playwright test failed.
|
|
- Explain why, be concise, respect Playwright best practices.
|
|
- Provide a snippet of code with the fix, if possible.
|
|
|
|
# Test info
|
|
|
|
- Name: 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 }) => {
|
|
``` |