- Add QWEN (qwen3.6) as primary AI backend with short system prompt - Hermes remains as fallback with 45s timeout - Increase QWEN timeout to 35s, max_tokens to 4000 - Add conversation history loading from whatsapp_messages (last 4 msgs) - Persist detected vehicle in whatsapp_sessions table - Add 'limpiar chat' / 'nuevo chat' / 'reset' commands to clear history - Fix CSS conflict: rename whatsapp chat-panel classes to wa-chat-panel - Fix JS ID conflicts with chat.js widget (waChatPanel, waChatMessages, etc.) - Improve no-stock response: conversational with alternatives - Split search_query by | for multi-part lookups - Add DEMO_PROMPTS.md and DEMO_PROMPTS_V2.md
89 lines
2.7 KiB
JavaScript
89 lines
2.7 KiB
JavaScript
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 mockInventoryAPIs(page) {
|
|
await page.route(/\/pos\/api\/inventory\/items\?page=.*&per_page=.*/, async (route) => {
|
|
await route.fulfill({
|
|
status: 200,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({
|
|
data: [
|
|
{
|
|
id: 1,
|
|
barcode: '123456789',
|
|
part_number: 'TEST-001',
|
|
name: 'Producto de prueba',
|
|
brand: 'TestBrand',
|
|
stock: 10,
|
|
cost: 50.0,
|
|
price_1: 100.0,
|
|
price_2: 90.0,
|
|
price_3: 80.0,
|
|
location: 'A-1',
|
|
},
|
|
],
|
|
pagination: { page: 1, total_pages: 1, total: 1 },
|
|
}),
|
|
});
|
|
});
|
|
|
|
await page.route(/\/pos\/api\/inventory\/items\/\d+/, async (route) => {
|
|
await route.fulfill({
|
|
status: 200,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({
|
|
id: 1,
|
|
barcode: '123456789',
|
|
part_number: 'TEST-001',
|
|
name: 'Producto de prueba',
|
|
brand: 'TestBrand',
|
|
location: 'A-1',
|
|
stock: 10,
|
|
cost: 50.0,
|
|
price_1: 100.0,
|
|
price_2: 90.0,
|
|
price_3: 80.0,
|
|
history: [],
|
|
}),
|
|
});
|
|
});
|
|
}
|
|
|
|
test.describe('Nexus POS — Inventory', () => {
|
|
test('inventory page loads with table', async ({ page }) => {
|
|
await setupAuth(page);
|
|
await mockInventoryAPIs(page);
|
|
await page.goto('/pos/inventory');
|
|
|
|
await expect(page).toHaveTitle(/Inventario/i);
|
|
await expect(page.locator('#stockTable')).toBeVisible({ timeout: 5000 });
|
|
// Wait for virtual-scroll rows to render
|
|
await page.waitForSelector('#productTableBody tr', { timeout: 5000 });
|
|
const rows = page.locator('#productTableBody tr');
|
|
await expect(rows.first()).toBeVisible();
|
|
});
|
|
|
|
test('product detail modal opens', async ({ page }) => {
|
|
await setupAuth(page);
|
|
await mockInventoryAPIs(page);
|
|
await page.goto('/pos/inventory');
|
|
|
|
await page.waitForSelector('#productTableBody tr', { timeout: 5000 });
|
|
const firstRow = page.locator('#productTableBody tr').first();
|
|
await firstRow.click();
|
|
|
|
// The detail view opens inside #historyModal
|
|
await expect(page.locator('#historyModal')).toHaveClass(/is-open/, { timeout: 5000 });
|
|
await expect(page.locator('#historyContent')).toContainText('Producto de prueba');
|
|
});
|
|
});
|