Files
tfm_ainventory/frontend/playwright-report/data/c49d3316f329d7283ba0d5b666781aac30b68caa.md

7.8 KiB

Instructions

  • Following Playwright test failed.
  • Explain why, be concise, respect Playwright best practices.
  • Provide a snippet of code with the fix, if possible.

Test info

  • Name: 1-login.spec.ts >> Login Workflow >> should display login form with username and password fields
  • Location: e2e/workflows/1-login.spec.ts:28:7

Error details

Error: expect(locator).toBeVisible() failed

Locator: locator('[data-testid="login-form"]')
Expected: visible
Timeout: 5000ms
Error: element(s) not found

Call log:
  - Expect "toBeVisible" with timeout 5000ms
  - waiting for locator('[data-testid="login-form"]')

Page snapshot

- 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

  1   | import { expect, Page, Locator } from '@playwright/test';
  2   | 
  3   | /**
  4   |  * Custom Playwright assertions for E2E tests
  5   |  * Provides domain-specific matchers for inventory operations
  6   |  */
  7   | 
  8   | /**
  9   |  * Assert that an inventory item is visible with expected data
  10  |  */
  11  | export async function assertItemVisible(
  12  |   page: Page,
  13  |   itemName: string,
  14  |   expectedData?: { quantity?: number; category?: string }
  15  | ): Promise<void> {
  16  |   const itemRow = page.locator(`[data-testid="item-row"][data-item-name="${itemName}"]`);
  17  |   await expect(itemRow).toBeVisible();
  18  | 
  19  |   if (expectedData?.quantity !== undefined) {
  20  |     const quantityCell = itemRow.locator('[data-testid="quantity-cell"]');
  21  |     await expect(quantityCell).toContainText(expectedData.quantity.toString());
  22  |   }
  23  | 
  24  |   if (expectedData?.category !== undefined) {
  25  |     const categoryCell = itemRow.locator('[data-testid="category-cell"]');
  26  |     await expect(categoryCell).toContainText(expectedData.category);
  27  |   }
  28  | }
  29  | 
  30  | /**
  31  |  * Assert that a barcode scan was successful
  32  |  */
  33  | export async function assertScanSuccess(
  34  |   page: Page,
  35  |   expectedItemName: string,
  36  |   expectedQuantityChange: number
  37  | ): Promise<void> {
  38  |   // Check for success toast notification
  39  |   const successToast = page.locator('[data-testid="toast-success"]');
  40  |   await expect(successToast).toBeVisible({ timeout: 3000 });
  41  | 
  42  |   // Verify item quantity was updated
  43  |   const itemRow = page.locator(`[data-testid="item-row"][data-item-name="${expectedItemName}"]`);
  44  |   await expect(itemRow).toBeVisible();
  45  | }
  46  | 
  47  | /**
  48  |  * Assert that login form is displayed
  49  |  */
  50  | export async function assertLoginFormVisible(page: Page): Promise<void> {
  51  |   const loginForm = page.locator('[data-testid="login-form"]');
> 52  |   await expect(loginForm).toBeVisible();
      |                           ^ Error: expect(locator).toBeVisible() failed
  53  | 
  54  |   const usernameInput = page.locator('[data-testid="username-input"]');
  55  |   const passwordInput = page.locator('[data-testid="password-input"]');
  56  |   const submitButton = page.locator('[data-testid="login-submit"]');
  57  | 
  58  |   await expect(usernameInput).toBeVisible();
  59  |   await expect(passwordInput).toBeVisible();
  60  |   await expect(submitButton).toBeVisible();
  61  | }
  62  | 
  63  | /**
  64  |  * Assert that user is authenticated (on inventory page)
  65  |  */
  66  | export async function assertUserAuthenticated(page: Page, baseUrl: string = 'http://localhost'): Promise<void> {
  67  |   // Check URL is on an authenticated page
  68  |   await expect(page).toHaveURL(/inventory|dashboard|scanner/);
  69  | 
  70  |   // Verify logout button is visible
  71  |   const logoutButton = page.locator('[data-testid="logout-button"]');
  72  |   await expect(logoutButton).toBeVisible();
  73  | }
  74  | 
  75  | /**
  76  |  * Assert that admin dashboard is visible
  77  |  */
  78  | export async function assertAdminDashboardVisible(page: Page): Promise<void> {
  79  |   const adminOverlay = page.locator('[data-testid="admin-overlay"]');
  80  |   await expect(adminOverlay).toBeVisible();
  81  | 
  82  |   // Check for tabs
  83  |   const identityTab = page.locator('[data-testid="admin-tab-identity"]');
  84  |   const databaseTab = page.locator('[data-testid="admin-tab-database"]');
  85  | 
  86  |   await expect(identityTab).toBeVisible();
  87  |   await expect(databaseTab).toBeVisible();
  88  | }
  89  | 
  90  | /**
  91  |  * Assert that stock adjustment form is visible
  92  |  */
  93  | export async function assertStockAdjustmentVisible(page: Page, itemName: string): Promise<void> {
  94  |   const adjustmentForm = page.locator('[data-testid="stock-adjustment-form"]');
  95  |   await expect(adjustmentForm).toBeVisible();
  96  | 
  97  |   const itemNameDisplay = page.locator(`[data-testid="adjustment-item-name"]`);
  98  |   await expect(itemNameDisplay).toContainText(itemName);
  99  | 
  100 |   const quantityInput = page.locator('[data-testid="adjustment-quantity-input"]');
  101 |   await expect(quantityInput).toBeVisible();
  102 | }
  103 | 
  104 | /**
  105 |  * Assert that AI extraction is in progress
  106 |  */
  107 | export async function assertAiExtractionInProgress(page: Page): Promise<void> {
  108 |   const extractionOverlay = page.locator('[data-testid="ai-extraction-overlay"]');
  109 |   await expect(extractionOverlay).toBeVisible();
  110 | 
  111 |   const loadingSpinner = page.locator('[data-testid="extraction-loading"]');
  112 |   await expect(loadingSpinner).toBeVisible();
  113 | }
  114 | 
  115 | /**
  116 |  * Assert that AI extraction results are displayed
  117 |  */
  118 | export async function assertAiExtractionResults(
  119 |   page: Page,
  120 |   expectedFields: { name?: string; partNumber?: string; quantity?: string }
  121 | ): Promise<void> {
  122 |   const resultsForm = page.locator('[data-testid="extraction-results-form"]');
  123 |   await expect(resultsForm).toBeVisible();
  124 | 
  125 |   if (expectedFields.name) {
  126 |     const nameInput = resultsForm.locator('[data-testid="extracted-name"]');
  127 |     await expect(nameInput).toHaveValue(expectedFields.name);
  128 |   }
  129 | 
  130 |   if (expectedFields.partNumber) {
  131 |     const pnInput = resultsForm.locator('[data-testid="extracted-part-number"]');
  132 |     await expect(pnInput).toHaveValue(expectedFields.partNumber);
  133 |   }
  134 | 
  135 |   if (expectedFields.quantity) {
  136 |     const quantityInput = resultsForm.locator('[data-testid="extracted-quantity"]');
  137 |     await expect(quantityInput).toHaveValue(expectedFields.quantity);
  138 |   }
  139 | }
  140 | 
  141 | /**
  142 |  * Assert that offline sync is pending
  143 |  */
  144 | export async function assertOfflineSyncPending(page: Page): Promise<void> {
  145 |   const syncIndicator = page.locator('[data-testid="offline-sync-indicator"]');
  146 |   await expect(syncIndicator).toBeVisible();
  147 | 
  148 |   const pendingBadge = page.locator('[data-testid="sync-pending-badge"]');
  149 |   await expect(pendingBadge).toBeVisible();
  150 | }
  151 | 
  152 | /**