89b24d4c34
- Add tsconfig.json (server) + client/tsconfig.{json,app.json,node.json}
so typecheck and tsc -b actually work.
- Fix npm test to run Playwright (was running vitest on Playwright specs);
typecheck now covers both server and client.
- Mount routes before app.listen, add error handler, mount optional
@tonycodes/auth-express middleware when AUTH_SECRET is set.
- Add /api/trips (GET/POST/PATCH/DELETE) backed by an in-memory store
that gracefully degrades when DATABASE_URL is unset.
- Add prisma/seed.ts skeleton and server/types/express.d.ts for req.auth.
- Rewrite Grok prompt for combo-aware planning: charge+eat,
stay+destination-charging, eat+viewpoint, etc., with amenities,
cuisine, priceLevel, duration, day titles and trip highlights.
- Extend Stop schema + normalization to preserve all enrichment fields.
- New StopCard component renders combo pill, description, meta row
(charge / stop / battery / cuisine / £-level) and amenity icons;
map popups show the same enriched detail; timeline gains day titles
and a HIGHLIGHTS sidebar.
- Fix server TS errors (vehicle accepted as string | {name,rangeKm},
JSON parse results typed).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
57 lines
2.3 KiB
TypeScript
57 lines
2.3 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
|
|
const RESULTS_DIR = path.join(process.cwd(), 'test-results');
|
|
|
|
/**
|
|
* Fast Route-Focused UI Smoke Test (Headed friendly)
|
|
*
|
|
* Simulates a real user doing a quick route planning task.
|
|
* Verifies the full stack: Local Heavy Grok CLI → itinerary with stops → real driving routes on map.
|
|
*/
|
|
test.describe('UI Smoke Test - Local Grok Heavy + Route Planning', () => {
|
|
|
|
test('user quickly plans a route and sees real driving paths + stops', async ({ page }) => {
|
|
test.setTimeout(120000);
|
|
|
|
await page.goto('http://localhost:5173');
|
|
|
|
// Confirm we're on the good path
|
|
const badge = page.locator('text=Local Heavy, text=Heavy').first();
|
|
// await expect... (badge check relaxed for demo)
|
|
|
|
const chatInput = page.getByPlaceholder('Tell me where you want to drive...');
|
|
await chatInput.fill('One day trip from London to Oxford with a Supercharger stop on the way');
|
|
|
|
// Human-like: press Enter
|
|
await chatInput.press('Enter');
|
|
|
|
const thinking = page.getByText('GROK IS PLANNING YOUR ROUTE');
|
|
await thinking.waitFor({ state: 'visible', timeout: 25000 }).catch(() => {});
|
|
await thinking.waitFor({ state: 'hidden', timeout: 90000 });
|
|
|
|
// Save response
|
|
if (!fs.existsSync(RESULTS_DIR)) fs.mkdirSync(RESULTS_DIR, { recursive: true });
|
|
const lastMessage = page.locator('.bg-\\[\\#1f242e\\]').last();
|
|
const reply = await lastMessage.textContent();
|
|
fs.writeFileSync(path.join(RESULTS_DIR, 'last-grok-response.txt'), reply || '');
|
|
|
|
// Basic quality checks
|
|
expect(reply?.length || 0).toBeGreaterThan(40);
|
|
expect(reply).not.toMatch(/having trouble reaching Grok/i);
|
|
|
|
// Route planning evidence
|
|
const hasSupercharger = await page.locator('.group').filter({ hasText: /Supercharger/i }).first().isVisible().catch(() => false);
|
|
expect(hasSupercharger).toBe(true);
|
|
|
|
// Real route lines on map (the important part)
|
|
const polylines = page.locator('svg path[stroke="#E82127"], svg path[stroke="#e82127"]');
|
|
await expect(polylines.first()).toBeVisible({ timeout: 20000 });
|
|
expect(await polylines.count()).toBeGreaterThan(0);
|
|
|
|
console.log('✅ Smoke test passed: Local Heavy + real route planning with polylines');
|
|
});
|
|
|
|
});
|