test(e2e): improve catalog test with mocked APIs and auth

- catalog.spec.js: added fake JWT auth setup, mocked brand/search APIs
  with Playwright route.fulfill, asserts actual rendered cards and
  search dropdown visibility
This commit is contained in:
2026-04-29 07:11:40 +00:00
parent cf46790ed8
commit 3cd2874ed7
2 changed files with 67 additions and 13 deletions

4
.gitignore vendored
View File

@@ -87,3 +87,7 @@ package-lock.json
# Backups # Backups
backups/ backups/
# Local tools (AWS CLI)
tools/

View File

@@ -1,24 +1,74 @@
const { test, expect } = require('@playwright/test'); const { test, expect } = require('@playwright/test');
const FAKE_TOKEN = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjk5OTk5OTk5OTksIm5hbWUiOiJUZXN0IFVzZXIifQ.signature';
async function setupAuth(page) {
await page.goto('/pos/login');
await page.evaluate((token) => {
localStorage.setItem('pos_token', token);
localStorage.setItem('pos_tenant_id', '11');
}, FAKE_TOKEN);
}
async function mockCatalogAPIs(page) {
await page.route('/pos/api/catalog/brands?mode=local', async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
data: [
{ id_brand: 1, name_brand: 'Toyota' },
{ id_brand: 2, name_brand: 'Nissan' },
],
}),
});
});
await page.route(/\/pos\/api\/catalog\/search\?q=.*&limit=20/, async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
data: [
{
id_part: 1,
oem_part_number: 'ABC-123',
name: 'Filtro de aceite',
vehicle_info: 'Toyota Corolla 2020',
local_stock: 5,
},
],
}),
});
});
}
test.describe('Nexus POS — Catalog', () => { test.describe('Nexus POS — Catalog', () => {
test('catalog page loads with brand grid', async ({ page }) => { test('catalog page loads with brand grid', async ({ page }) => {
await setupAuth(page);
await mockCatalogAPIs(page);
await page.goto('/pos/catalog'); await page.goto('/pos/catalog');
// Wait for app shell or main content
await expect(page.locator('#navGrid, .grid, .content-grid')).toBeVisible({ timeout: 10000 }); await expect(page).toHaveTitle(/Catalogo|Catálogo/i);
// Brand grid or loading state should exist await expect(page.locator('#navGrid')).toBeVisible({ timeout: 5000 });
const content = await page.locator('body').textContent(); // Wait for brands to render
expect(content).toMatch(/catálogo|catalogo|marca|brand/i); await page.waitForSelector('.nav-card', { timeout: 5000 });
const cards = page.locator('.nav-card');
await expect(cards).toHaveCount(2);
}); });
test('search functionality shows results or loading', async ({ page }) => { test('search functionality works', async ({ page }) => {
await setupAuth(page);
await mockCatalogAPIs(page);
await page.goto('/pos/catalog'); await page.goto('/pos/catalog');
const searchInput = page.locator('#searchInput, input[placeholder*="buscar" i], input[type="search"]').first();
await expect(searchInput).toBeVisible({ timeout: 10000 }); const searchInput = page.locator('#searchInput');
await searchInput.fill('balata'); await expect(searchInput).toBeVisible();
await searchInput.fill('filtro');
await searchInput.press('Enter'); await searchInput.press('Enter');
// Wait for dropdown or results to appear
await page.waitForTimeout(800); // Assert search dropdown becomes visible with results
const hasResults = await page.locator('#searchDropdown, .search-dropdown, .parts-grid, .grid').first().isVisible().catch(() => false); await expect(page.locator('#searchDropdown')).toHaveClass(/is-visible/, { timeout: 5000 });
expect(hasResults || true).toBe(true); // Smoke: search interaction completes await expect(page.locator('.search-result-item')).toBeVisible();
}); });
}); });