Files
pn-new-crm/tests/e2e/smoke/03-pipeline.spec.ts
Matt 221ae5784e chore(autonomous-session): consolidate uncommitted work from prior session
Bundles the prior autonomous-session output that was sitting unstaged:

- Em-dash sweep across src/ + tests/ (en-dash/em-dash to hyphen, ~2280 instances)
- country-flag-icons rollout (CountryFlag component, replaces emoji glyphs that
  never rendered on Windows; lazy-loads the 3x2 SVG index as a single chunk
  after the per-subpath dynamic-import approach silently failed in webpack)
- Admin IA Phase 1+2: 7-domain regroup, 41 to 38 pages, /admin/berths index,
  redirects (ocr to ai, reports to dashboard, invitations to users),
  docs/admin-ia-proposal.md
- Per-template email tester (registry + endpoint + UI on Email admin page)
- Cancel-document mode picker (delete-from-Documenso vs keep-for-audit)
- Dashboard PDF report: 25 widgets, SVG charts, date-range picker, 11 resolvers
- Customize-widgets per-region sortables at xl+ (charts/rails/feed); single
  flat sortable below xl when the layout stacks; per-viewport saved orders
- Audit doc updates capturing each shipped item
- Lint fixes: react-compiler immutability in DonutChart (reduce instead of
  let-reassign), set-state-in-effect disables in CountryFlag and
  UploadForSigning preview-bytes effect, unused 'confirm' destructures in
  interest contract + reservation tabs, unescaped apostrophe in test-template
  card copy
2026-05-23 00:52:59 +02:00

146 lines
5.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { test, expect } from '@playwright/test';
import { login, navigateTo, waitForSheet } from './helpers';
test.describe('Interest Pipeline', () => {
test.beforeEach(async ({ page }) => {
await login(page, 'super_admin');
});
test('create a client and interest', async ({ page }) => {
// First create a client
await navigateTo(page, '/clients');
await page
.getByRole('button', { name: /new client/i })
.first()
.click();
await waitForSheet(page);
const clientName = `Pipeline Client ${Date.now()}`;
const sheet = page.locator('[role="dialog"]');
await sheet.locator('input[name="fullName"]').fill(clientName);
await sheet.locator('input[name="contacts.0.value"]').fill('pipeline@test.com');
await sheet.getByRole('button', { name: /create client/i }).click();
await expect(sheet).not.toBeVisible({ timeout: 10_000 });
await page.waitForTimeout(2000);
// Now create an interest
await navigateTo(page, '/interests');
await page.waitForTimeout(2000);
const newBtn = page.getByRole('button', { name: /new interest/i }).first();
await expect(newBtn).toBeVisible({ timeout: 10_000 });
await newBtn.click();
await waitForSheet(page);
const interestSheet = page.locator('[role="dialog"]');
// Click the client combobox trigger button to open the popover
const clientTrigger = interestSheet.getByRole('combobox').first();
await clientTrigger.click();
await page.waitForTimeout(2000);
// Wait for the popover to load initial options (no search needed - they load on mount)
// The options API returns all clients for this port
const cmdItems = page.locator('[cmdk-item]');
await expect(cmdItems.first()).toBeVisible({ timeout: 10_000 });
// Wait for actual client data to load (not just "Loading..." or "No clients found")
let selected = false;
for (let attempt = 0; attempt < 5; attempt++) {
const count = await cmdItems.count();
for (let i = 0; i < count; i++) {
const text = await cmdItems.nth(i).textContent();
if (text && text.includes('Pipeline')) {
await cmdItems.nth(i).click();
selected = true;
break;
}
}
if (selected) break;
await page.waitForTimeout(1000);
}
if (!selected) {
console.log(' ⚠️ No matching client found. Skipping interest creation.');
await page.keyboard.press('Escape');
await page.keyboard.press('Escape');
return;
}
await page.waitForTimeout(500);
await interestSheet.getByRole('button', { name: /create interest/i }).click();
// Wait for the sheet heading to disappear (form submitted successfully)
const sheetHeading = page.getByRole('heading', { name: 'New Interest' });
await expect(sheetHeading).not.toBeVisible({ timeout: 15_000 });
await page.waitForTimeout(2000);
});
test('interests page loads with data', async ({ page }) => {
await navigateTo(page, '/interests');
await page.waitForLoadState('networkidle');
// Should see interests page content
const heading = page.getByText(/interests/i).first();
await expect(heading).toBeVisible({ timeout: 15_000 });
// Wait for either the table or pipeline board to render (dev-mode JIT can
// take >3s on first hit). `isVisible()` is non-waiting; use `expect.poll`
// to actually wait for one of the views to appear.
await expect
.poll(
async () => {
const table = await page
.locator('table')
.isVisible()
.catch(() => false);
const board = await page
.locator('[data-testid="pipeline-board"], [class*="board"]')
.first()
.isVisible()
.catch(() => false);
return table || board;
},
{ timeout: 15_000 },
)
.toBe(true);
});
test('interest detail page works', async ({ page }) => {
await navigateTo(page, '/interests');
await page.waitForLoadState('networkidle');
await page.waitForTimeout(3000);
// Try clicking a table row to navigate to detail
const rows = page.locator('table tbody tr');
const rowCount = await rows.count();
if (rowCount > 0) {
// Click the first row - it may navigate or open a link
const firstRow = rows.first();
const link = firstRow.locator('a').first();
if (await link.isVisible({ timeout: 3_000 }).catch(() => false)) {
await link.click();
} else {
await firstRow.click();
}
await page.waitForTimeout(3000);
// Check if we navigated to a detail page
const url = page.url();
if (url.includes('/interests/')) {
// We're on the detail page - look for content
const content = page.getByText(/pipeline|stage|notes|activity|client/i);
await expect(content.first()).toBeVisible({ timeout: 10_000 });
} else {
// The table rows don't navigate - this is fine for a smoke test
console.log(' Table rows do not navigate to detail pages');
}
} else {
console.log(' No interest rows in table');
}
});
});