import { expect, Page, Locator } from '@playwright/test'; /** * Custom Playwright assertions for E2E tests * Provides domain-specific matchers for inventory operations */ /** * Assert that an inventory item is visible with expected data */ export async function assertItemVisible( page: Page, itemName: string, expectedData?: { quantity?: number; category?: string } ): Promise { const itemRow = page.locator(`[data-testid="item-row"][data-item-name="${itemName}"]`); await expect(itemRow).toBeVisible(); if (expectedData?.quantity !== undefined) { const quantityCell = itemRow.locator('[data-testid="quantity-cell"]'); await expect(quantityCell).toContainText(expectedData.quantity.toString()); } if (expectedData?.category !== undefined) { const categoryCell = itemRow.locator('[data-testid="category-cell"]'); await expect(categoryCell).toContainText(expectedData.category); } } /** * Assert that a barcode scan was successful */ export async function assertScanSuccess( page: Page, expectedItemName: string, expectedQuantityChange: number ): Promise { // Check for success toast notification const successToast = page.locator('[data-testid="toast-success"]'); await expect(successToast).toBeVisible({ timeout: 3000 }); // Verify item quantity was updated const itemRow = page.locator(`[data-testid="item-row"][data-item-name="${expectedItemName}"]`); await expect(itemRow).toBeVisible(); } /** * Assert that login form is displayed */ export async function assertLoginFormVisible(page: Page): Promise { const loginForm = page.locator('[data-testid="login-form"]'); await expect(loginForm).toBeVisible(); const usernameInput = page.locator('[data-testid="username-input"]'); const passwordInput = page.locator('[data-testid="password-input"]'); const submitButton = page.locator('[data-testid="login-submit"]'); await expect(usernameInput).toBeVisible(); await expect(passwordInput).toBeVisible(); await expect(submitButton).toBeVisible(); } /** * Assert that user is authenticated (on inventory page) */ export async function assertUserAuthenticated(page: Page, baseUrl: string = 'http://localhost'): Promise { // Check URL is on an authenticated page await expect(page).toHaveURL(/inventory|dashboard|scanner/); // Verify logout button is visible const logoutButton = page.locator('[data-testid="logout-button"]'); await expect(logoutButton).toBeVisible(); } /** * Assert that admin dashboard is visible */ export async function assertAdminDashboardVisible(page: Page): Promise { const adminOverlay = page.locator('[data-testid="admin-overlay"]'); await expect(adminOverlay).toBeVisible(); // Check for tabs const identityTab = page.locator('[data-testid="admin-tab-identity"]'); const databaseTab = page.locator('[data-testid="admin-tab-database"]'); await expect(identityTab).toBeVisible(); await expect(databaseTab).toBeVisible(); } /** * Assert that stock adjustment form is visible */ export async function assertStockAdjustmentVisible(page: Page, itemName: string): Promise { const adjustmentForm = page.locator('[data-testid="stock-adjustment-form"]'); await expect(adjustmentForm).toBeVisible(); const itemNameDisplay = page.locator(`[data-testid="adjustment-item-name"]`); await expect(itemNameDisplay).toContainText(itemName); const quantityInput = page.locator('[data-testid="adjustment-quantity-input"]'); await expect(quantityInput).toBeVisible(); } /** * Assert that AI extraction is in progress */ export async function assertAiExtractionInProgress(page: Page): Promise { const extractionOverlay = page.locator('[data-testid="ai-extraction-overlay"]'); await expect(extractionOverlay).toBeVisible(); const loadingSpinner = page.locator('[data-testid="extraction-loading"]'); await expect(loadingSpinner).toBeVisible(); } /** * Assert that AI extraction results are displayed */ export async function assertAiExtractionResults( page: Page, expectedFields: { name?: string; partNumber?: string; quantity?: string } ): Promise { const resultsForm = page.locator('[data-testid="extraction-results-form"]'); await expect(resultsForm).toBeVisible(); if (expectedFields.name) { const nameInput = resultsForm.locator('[data-testid="extracted-name"]'); await expect(nameInput).toHaveValue(expectedFields.name); } if (expectedFields.partNumber) { const pnInput = resultsForm.locator('[data-testid="extracted-part-number"]'); await expect(pnInput).toHaveValue(expectedFields.partNumber); } if (expectedFields.quantity) { const quantityInput = resultsForm.locator('[data-testid="extracted-quantity"]'); await expect(quantityInput).toHaveValue(expectedFields.quantity); } } /** * Assert that offline sync is pending */ export async function assertOfflineSyncPending(page: Page): Promise { const syncIndicator = page.locator('[data-testid="offline-sync-indicator"]'); await expect(syncIndicator).toBeVisible(); const pendingBadge = page.locator('[data-testid="sync-pending-badge"]'); await expect(pendingBadge).toBeVisible(); } /** * Assert that offline sync completed */ export async function assertOfflineSyncComplete(page: Page): Promise { const syncIndicator = page.locator('[data-testid="offline-sync-indicator"]'); await expect(syncIndicator).not.toBeVisible({ timeout: 10000 }); const successBadge = page.locator('[data-testid="sync-success-badge"]'); await expect(successBadge).toBeVisible(); } /** * Assert that error message is displayed */ export async function assertErrorMessage(page: Page, errorText?: string): Promise { const errorToast = page.locator('[data-testid="toast-error"]'); await expect(errorToast).toBeVisible(); if (errorText) { await expect(errorToast).toContainText(errorText); } } /** * Assert that category list is visible */ export async function assertCategoryListVisible(page: Page): Promise { const categoryList = page.locator('[data-testid="category-list"]'); await expect(categoryList).toBeVisible(); const categoryItems = page.locator('[data-testid="category-item"]'); const count = await categoryItems.count(); expect(count).toBeGreaterThan(0); } /** * Assert that scanner interface is ready */ export async function assertScannerReady(page: Page): Promise { const scannerContainer = page.locator('[data-testid="scanner-container"]'); await expect(scannerContainer).toBeVisible(); const cameraView = page.locator('[data-testid="camera-view"]'); await expect(cameraView).toBeVisible(); const scanInput = page.locator('[data-testid="scan-input"]'); await expect(scanInput).toBeVisible(); } /** * Assert that item creation form is visible */ export async function assertItemCreationFormVisible(page: Page): Promise { const createForm = page.locator('[data-testid="create-item-form"]'); await expect(createForm).toBeVisible(); const nameInput = page.locator('[data-testid="item-name-input"]'); const categorySelect = page.locator('[data-testid="item-category-select"]'); const submitButton = page.locator('[data-testid="item-create-submit"]'); await expect(nameInput).toBeVisible(); await expect(categorySelect).toBeVisible(); await expect(submitButton).toBeVisible(); } /** * Assert element count matches expected */ export async function assertElementCount( page: Page, selector: string, expectedCount: number ): Promise { const elements = page.locator(selector); const count = await elements.count(); expect(count).toBe(expectedCount); } /** * Assert element is disabled */ export async function assertElementDisabled(locator: Locator): Promise { await expect(locator).toBeDisabled(); } /** * Assert element is enabled */ export async function assertElementEnabled(locator: Locator): Promise { await expect(locator).toBeEnabled(); } /** * Assert modal is open */ export async function assertModalOpen(page: Page, modalId: string): Promise { const modal = page.locator(`[data-testid="${modalId}"]`); await expect(modal).toBeVisible(); const backdrop = page.locator('[data-testid="modal-backdrop"]'); await expect(backdrop).toBeVisible(); } /** * Assert modal is closed */ export async function assertModalClosed(page: Page, modalId: string): Promise { const modal = page.locator(`[data-testid="${modalId}"]`); await expect(modal).not.toBeVisible(); }