61f006f62d
Dev — Build & local smoke test / build-smoke (pull_request) Successful in 1m54s
- Strip [javascript-obfuscator-cli] progress line from elc --obfuscate output before writing to dist/js/ (was prepended to every compiled JS file, causing browser parse errors on stage) - Remove spurious waitForFunction(signUpWithEmail) guards from buyer-name and buyer-email structural tests (pure DOM tests, no auth) - Switch chat.spec.ts beforeEach to domcontentloaded (SSR elements present at DOM ready; networkidle caused cold-start timeouts)
76 lines
3.2 KiB
TypeScript
76 lines
3.2 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
|
|
// The demo widget is rendered server-side via El components and injected into
|
|
// the landing page. Element IDs are stable: #neuron-demo-panel, #neuron-demo-btn,
|
|
// #neuron-demo-auth, #neuron-demo-text, #neuron-demo-send, etc.
|
|
|
|
test.describe('Demo chat widget — structure', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await page.goto('/');
|
|
await page.waitForLoadState('domcontentloaded');
|
|
});
|
|
|
|
test('Demo panel (#neuron-demo-panel) is in the DOM', async ({ page }) => {
|
|
await expect(page.locator('#neuron-demo-panel')).toBeAttached();
|
|
});
|
|
|
|
test('Demo open button (#neuron-demo-btn) is in the DOM', async ({ page }) => {
|
|
await expect(page.locator('#neuron-demo-btn')).toBeAttached();
|
|
});
|
|
|
|
test('Demo auth section (#neuron-demo-auth) is in the DOM', async ({ page }) => {
|
|
await expect(page.locator('#neuron-demo-auth')).toBeAttached();
|
|
});
|
|
|
|
test('Demo text input (#neuron-demo-text) is in the DOM', async ({ page }) => {
|
|
await expect(page.locator('#neuron-demo-text')).toBeAttached();
|
|
});
|
|
|
|
test('Demo send button (#neuron-demo-send) is in the DOM', async ({ page }) => {
|
|
await expect(page.locator('#neuron-demo-send')).toBeAttached();
|
|
});
|
|
});
|
|
|
|
test.describe('Demo chat widget — auth gate', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
// Clear any stored Supabase session so we test the unauthenticated state
|
|
await page.goto('/');
|
|
await page.evaluate(() => {
|
|
Object.keys(localStorage)
|
|
.filter(k => k.startsWith('sb-') || k.includes('supabase'))
|
|
.forEach(k => localStorage.removeItem(k));
|
|
});
|
|
await page.reload();
|
|
await page.waitForLoadState('domcontentloaded');
|
|
});
|
|
|
|
test('Send button is disabled when unauthenticated', async ({ page }) => {
|
|
const sendBtn = page.locator('#neuron-demo-send');
|
|
await expect(sendBtn).toBeAttached();
|
|
// The send button starts disabled until a valid session is confirmed
|
|
const isDisabled = await sendBtn.isDisabled().catch(() => true);
|
|
const isHidden = !(await sendBtn.isVisible().catch(() => false));
|
|
expect(isDisabled || isHidden).toBe(true);
|
|
});
|
|
|
|
test('Auth gate (#neuron-demo-auth) or gate (#neuron-demo-gate) is visible or panel is closed', async ({ page }) => {
|
|
// Either the auth pane is visible, OR the panel itself is closed (not visible).
|
|
// Both are correct unauthenticated states.
|
|
const authVisible = await page.locator('#neuron-demo-auth').isVisible().catch(() => false);
|
|
const gateVisible = await page.locator('#neuron-demo-gate').isVisible().catch(() => false);
|
|
const panelClosed = !(await page.locator('#neuron-demo-panel').isVisible().catch(() => true));
|
|
expect(authVisible || gateVisible || panelClosed).toBe(true);
|
|
});
|
|
});
|
|
|
|
test.describe('Demo chat widget — API gate (no browser session)', () => {
|
|
test('/api/demo rejects unauthenticated POST and returns auth_required', async ({ page }) => {
|
|
// Use the Playwright request context to hit the API directly
|
|
const r = await page.request.post('/api/demo', {
|
|
data: { message: 'Hello Neuron' },
|
|
});
|
|
const body = await r.json() as Record<string, unknown>;
|
|
expect(body.auth_required).toBe(true);
|
|
});
|
|
});
|