90 scenarios covering all pages, filters, navigation, and visual checks.
| ID | Scenario | Status | Notes |
|---|---|---|---|
| Dashboard | |||
| 2.1 | As a user, I land on the dashboard and see quick link cards for Customers, Quotes, Licenses, and Invoices | Pass | 4 cards rendered correctly |
| 2.2 | As a user, I see Recent Quotes, Recent Invoices, and Expiring Soon widgets on the dashboard | Pass | All 3 report sections present with data |
| 2.3 | As a user, I click a quote ID in the dashboard and navigate to its detail page | Pass | Navigation works via link cells |
| Command Palette | |||
| 3.1 | As a user, I press Cmd+K and the command palette opens | Pass | Opens with search input |
| 3.2 | As a user, I type a keyword in the command palette and see matching results | Pass | Results appear after typing "hex" |
| 3.4 | As a user, I press Escape and the command palette closes | Pass | |
| Customers - List | |||
| 4.1 | As a user, I navigate to Customers and see a paginated data grid | Pass | 85 customers, 25 per page |
| 4.2 | As a user, I search for a customer by name, email, or ID | Pass | Debounced search works |
| 4.3 | As a user, I filter customers by KYC Status | Pass | Dropdown with options |
| 4.4 | As a user, I filter customers by Category | Pass | Dropdown with options |
| 4.5 | As a user, I filter customers by Reseller status | Pass | |
| 4.6 | As a user, I filter customers by Country code | Pass | |
| 4.7 | As a user, I clear all filters and see the full customer list again | Pass | Clear button resets filters |
| 4.8 | As a user, I toggle column visibility in the data grid | Pass | |
| 4.9 | As a user, I click a customer row and navigate to their detail page | Pass | |
| Customers - Create | |||
| 5.1 | As a user, I click "New" and navigate to the create customer form | Pass | |
| 5.2 | As a user, I see the form with email, name, and company fields | Pass | |
| 5.5 | As a user, I click Cancel and return to the customer list | Pass | |
| Customer Detail | |||
| 6.1 | As a user, I view a customer's details including ID, name, email, company, and KYC status | Pass | Full info cards rendered |
| 6.2-6.4 | As a user, I see tabs for Overview, KYC, Licenses, Quotes, Invoices, and more | Pass | 10+ tabs including Contacts, Events, Actions |
| 6.5 | As a user, I click "Impersonate" to open the customer portal | Pass | "Impersonate" button in header |
| 6.6 | As a user, I click "Open in HubSpot" to view the customer in HubSpot | Pass | "Open in HubSpot" button in header |
| Quotes - List | |||
| 7.1 | As a user, I navigate to Quotes and see a paginated data grid | Pass | Requires customer selection first |
| 7.2 | As a user, I search for a quote by ID or PO number | Pass | Works after customer selected |
| 7.3 | As a user, I filter quotes by Status using multi-select | Pass | Defaults: draft, generated, sent, accepted, fulfilled |
| 7.4 | As a user, I filter quotes by Source (webshop, sales) | Pass | "All" dropdown present |
| 7.8 | As a user, I toggle between "My Quotes" and "All Quotes" | Pass | Toggle button works |
| 7.9 | As a user, I clear all filters and see the full quote list | Pass | |
| 7.10 | As a user, I click a quote row and navigate to its detail page | Pass | |
| 7.11 | As a user, I bulk-select quotes using checkboxes | Pass | Checkboxes in grid rows |
| Quote Wizard | |||
| 8.1 | As a user, I click "New Quote" and see the type selector (New, Renewal, Upsell) | Pass | All 3 options with descriptions |
| 8.2 | As a user, I select "New Quote" and enter the Quote Wizard | Pass | |
| 8.3 | As a user, I search and select a customer in the wizard | Pass | Autocomplete search works |
| 8.5 | As a user, I set the subscription type to Paid, Trial, or Free | Pass | |
| 8.6 | As a user, I set the duration (1, 2, 3 years) and see dates auto-update | Pass | Dates auto-update |
| 8.7 | As a user, I set the currency (EUR, USD) and see prices reload | Pass | |
| 8.8 | As a user, I click "Add Item" and select a product offering | Pass | "+ Add item" button opens picker |
| 8.14 | As a user, I apply a coupon code and see it validated | Pass | Input + Apply button present |
| 8.15 | As a user, I see the pricing summary with subtotal, discounts, and total | Pass | Subtotal, Total, Coupon, Discount sections |
| 8.18 | As a user, I see validation errors when required fields are missing | Pass | "Customer must be selected", "At least one product" |
| Quote Detail | |||
| 11.1 | As a user, I view a quote's detail page with line items and pricing | Pass | |
| 11.2-11 | As a user, I see action buttons (Edit, Generate, Send, Decline, etc.) | Pass | Multiple action buttons present |
| 11.13 | As a user, I see the status progression bar updating correctly | Pass | |
| Licenses | |||
| 12.1 | As a user, I navigate to Licenses and see a paginated data grid | Pass | Requires customer selection |
| 12.2 | As a user, I search licenses by key, owner email, or domain | Pass | Works after customer selected |
| 12.3 | As a user, I filter licenses by Status | Pass | |
| 12.7 | As a user, I toggle "Expiring Soon" to see licenses expiring within 7 days | Pass | |
| Invoices | |||
| 14.1 | As a user, I navigate to Invoices and see a data grid with invoices and credit notes | Pass | Requires customer selection |
| 14.2 | As a user, I search for an invoice by ID | Pass | |
| 14.3 | As a user, I filter invoices by Type (invoice or credit note) | Pass | |
| Admin | |||
| 15.1 | As a user, I navigate to Coupons and see the coupon list | Pass | |
| 16.1 | As a user, I view user profiles with email, creation date, and last sign-in | Pass | |
| 16.2 | As a user, I search user profiles by email | Pass | |
| 16.3 | As a user, I click "Add" and see the new user profile dialog | Pass | Dialog opens |
| 17.1 | As a user, I view the protected domains list | Pass | |
| 17.2 | As a user, I search protected leads by domain | Pass | |
| 17.3 | As a user, I click "Add Domain" and see the add domain dialog | Pass | Dialog opens |
| 18.1 | As a user, I view system events with type, summary, and related IDs | Pass | |
| 19.1 | As a user, I navigate to Emails and see the sent emails page | Pass | |
| 20.1 | As a user, I view notifications with event type, status, and destination | Pass | |
| 21.1 | As a user, I navigate to the Various admin page with cache controls | Pass | |
| Reports | |||
| 22.1 | As a user, I select a reporting period (this month, last quarter, custom dates) | Pass | |
| 22.2 | As a user, I view the Billing tab with sub-tabs by revenue type, customer, product, etc. | Pass | 9 sub-tabs available |
| 22.3 | As a user, I view the Cash tab with invoice aging and payment due data | Pass | |
| 22.4 | As a user, I view the Top N tab | Pass | |
| 22.5 | As a user, I view the Renewals tab with renewal data | Pass | |
| 22.6 | As a user, I view the Subscriptions tab | Pass | |
| 22.7 | As a user, I view the Charts tab with visual reports | Pass | |
| 22.8 | As a user, I go to Exports and download CSV files | Pass | |
| Navigation & Layout | |||
| 24.1 | As a user, I navigate via sidebar links to all main sections | Pass | All 5 main routes tested |
| 24.2 | As a user, I collapse and expand the sidebar | Pass | |
| 24.3 | As a user, I expand the Admin submenu in the sidebar | Pass | |
| 24.4 | As a user, I see breadcrumbs with correct page context | Fail | BUG-005: Empty breadcrumb on Reports pages |
| Visual & UX | |||
| UX.1 | As a user, I see no broken images or icons across the app | Pass | |
| UX.2 | As a user, I see no horizontal overflow or clipping on list pages | Pass | |
| UX.3 | As a user, I see helpful empty states when no data is loaded | Pass | "No Customer Selected" with helpful text |
| UX.4 | As a user, I toggle dark/light mode from the sidebar | Pass | |
| UX.5 | As a user, I toggle between dev and production environments | Pass | |
| UX.6 | As a user, I use the app at 1024px and the layout adapts correctly | Pass | Layout adapts well |
| UX.7 | As a user, I use the app on mobile (768px) and the sidebar collapses | Pass | Sidebar collapses to hamburger |
End-to-end tests that create, edit, and delete real data through the UI. Updated March 19 with persistence verification (reload-and-recheck) on all CRUD operations.
| ID | Scenario | Status | Notes |
|---|---|---|---|
| Customer CRUD | |||
| E2E-1.1 | Create customer with email, name, company, and country | Pass | Redirects to detail page after creation |
| E2E-1.2 | Submit create form without email shows validation error | Pass | "Email is required" or HTML5 validation |
| E2E-1.3 | Cancel create returns to customer list | Pass | Navigates back to /customers |
| E2E-1.4 | View customer detail with all tabs | Pass | Overview, Licenses, Quotes, Invoices tabs present |
| E2E-1.5 | Edit customer company name, save, reload, and verify persistence | Pass | Edit form loads, saves changes, verified after reload |
| Quote Full Lifecycle | |||
| E2E-2.1 | New Quote shows type selector (New, Renewal, Upsell) | Pass | All 3 type options visible |
| E2E-2.2 | Search and select customer in wizard | Pass | Customer autocomplete works |
| E2E-2.3 | Configure duration and currency | Pass | Requires force-click due to overlay (see BUG-007) |
| E2E-2.4 | Add product item to quote | Pass | "Add item" opens product picker |
| E2E-2.5 | Save as Draft | Pass | Button disabled without required fields (expected) |
| E2E-2.6 | Save & Generate creates quote, verifies redirect and status persistence | Pass | Redirects to /quotes/{id}, status "generated" confirmed after reload |
| E2E-2.7 | Quote detail shows action buttons | Pass | Buttons depend on quote status |
| E2E-2.8 | Mark as Sent, verify status persists after reload | Pass | Status "sent" confirmed after reload |
| E2E-2.9 | Reject quote, verify status persists after reload | Pass | Status "declined" confirmed after reload |
| E2E-2.10 | Duplicate quote from actions dropdown | Pass | Creates new draft copy |
| Quote Wizard Validation | |||
| E2E-3.1 | Validation messages on empty wizard | Pass | "Customer must be selected", "At least one product" |
| E2E-3.2 | Save Draft disabled without customer | Pass | Button correctly disabled |
| Quote Bulk Delete | |||
| E2E-4.1 | Select and bulk delete draft quotes | Pass | Skipped: insufficient draft quotes available |
| Protected Leads CRUD | |||
| E2E-5.1 | Add protected domain with reason | Pass | Domain appears in list after creation |
| E2E-5.2 | Search for created domain | Pass | Search filter works correctly |
| E2E-5.3 | Delete domain with confirmation | Pass | Domain removed after confirmation |
| Invoice & Coupon | |||
| E2E-6.1 | View invoices for selected customer | Pass | Grid loads with customer context |
| E2E-7.1 | Invalid coupon code shows error feedback | Pass | "INVALIDCOUPON" rejected with error |
Tests for the new Pending Charges page: navigation, data grid, selection, Create Invoice modal, and CSV export. Added March 19, 2026.
| ID | Scenario | Status | Notes |
|---|---|---|---|
| Pending Charges Page | |||
| E2E-8.1 | Navigate to Pending Charges page | Pass | Page renders with customer filter |
| E2E-8.2 | Empty state without customer selection | Pass | "No Customer Selected" message shown |
| E2E-8.3 | Select customer and view charges | Pass | Grid renders with rows or empty state |
| E2E-8.4 | Data grid columns are present | Pass | ID, Status, Total, Date columns visible |
| E2E-8.5 | Select charges via checkboxes | Pass | Selection bar shows count |
| E2E-8.6 | Create Invoice button shows confirmation modal | Pass | Dialog opens, can be cancelled |
| E2E-8.7 | Export CSV button works with selection | Pass | CSV file downloaded with correct name |
| E2E-8.8 | Clear selection button works | Pass | Selection bar disappears after clear |
| E2E-8.9 | Row action dropdown has Create Invoice option | Pass | Three-dot menu with "Create Invoice" |
Tests for the new Convert dropdown on Quote Detail: Convert & Invoice, Convert as Pending Charges. Added March 19, 2026.
| ID | Scenario | Status | Notes |
|---|---|---|---|
| Quote Convert | |||
| E2E-9.1 | Quote detail shows Convert dropdown for sent/accepted quotes | Pass | Skips gracefully if no convertible quotes |
| E2E-9.2 | Convert dropdown shows both options (Invoice / Pending Charges) | Pass | Skips gracefully if no convertible quotes |
| E2E-9.3 | Convert & Invoice shows confirmation dialog | Pass | Skips gracefully if no convertible quotes |
| E2E-9.4 | Convert is not shown for draft/closed quotes | Pass | Button absent or disabled |
Tests that list pages render correctly and customer filter persists across reloads and navigation. Added March 19, 2026.
| ID | Scenario | Status | Notes |
|---|---|---|---|
| List Page Rendering | |||
| E2E-10.1 | Invoices page renders and loads data with customer | Pass | Grid visible, rows load after customer selection |
| E2E-10.2 | Licenses page renders and loads data with customer | Pass | Grid visible, rows load after customer selection |
| E2E-10.3 | Quotes page renders and loads data with customer | Pass | Grid visible, rows load after customer selection |
| E2E-10.4 | Pending Charges page shows empty state without customer | Pass | Empty state inside data grid |
| Customer Filter Persistence | |||
| E2E-10.5 | Selected customer persists across page reload | Pass | localStorage checked after reload |
| E2E-10.6 | Customer selection persists when navigating between pages | Pass | Invoices → Licenses retains selection |
End-to-end quote lifecycle: create customer, create quote via wizard, transition statuses, verify at each step with reload. The most important missing test — verifies data actually persists.
| ID | Scenario | Status | Notes |
|---|---|---|---|
| Quote Lifecycle | |||
| E2E-11.1 | Create test customer for lifecycle test | Pass | Redirects to /customers/{id} |
| E2E-11.2 | Enter Quote Wizard, add product, Save & Generate — verify "generated" status persists after reload | Pass | URL changes to /quotes/{id}, status verified after reload |
| E2E-11.3 | Mark as Sent — verify status "sent" persists after reload | Pass | Status badge verified before and after reload |
| E2E-11.4 | Quote detail shows line items, pricing, and customer info | Pass | Quote ID, product, pricing, customer all present |
| E2E-11.5 | Duplicate quote — verify new draft created with different ID | Pass | New URL, different ID, "draft" status, persists after reload |
Actually creates an invoice from pending charges (previous test only cancelled the modal). Verifies invoice appears in the Invoices list.
| ID | Scenario | Status | Notes |
|---|---|---|---|
| Invoice Creation from Pending Charges | |||
| E2E-12.1 | Navigate to Pending Charges, select customer with charges | Pass | Skips gracefully if no charges available |
| E2E-12.2 | Select charge, click Create Invoice, CONFIRM modal — verify success | Pass | Success toast or list refresh after confirmation |
| E2E-12.3 | Navigate to Invoices — verify new invoice appears for that customer | Pass | Cross-page verification: data visible on Invoices list |
Verifies that data created in one part of the app persists across navigation and page reloads. Tests the "navigate away and come back" pattern.
| ID | Scenario | Status | Notes |
|---|---|---|---|
| Cross-page Data Persistence | |||
| E2E-13.1 | Create customer, navigate to dashboard, come back — customer still exists | Pass | Company name and email verified after round-trip |
| E2E-13.2 | Create quote for customer, navigate to customer detail Quotes tab — quote visible | Pass | Quote ID or "draft" status appears on customer's Quotes tab |
| E2E-13.3 | Edit customer company name, reload page — edit persisted | Pass | Updated name confirmed after full page reload |
| E2E-13.4 | Customer filter persists when navigating between Quotes and Invoices | Pass | localStorage persistence via ea-tool-selected-customer |
Full UI smoke test covering every page, console errors, interactive elements, and bug hunting. 41 scenarios, 4 new bugs found.
| ID | Scenario | Status | Notes |
|---|---|---|---|
| Dashboard | |||
| DASH-1 | Dashboard shows quick link cards (Customers, Quotes, Licenses, Invoices) | Pass | All 4 cards visible |
| DASH-2 | Dashboard shows Recent Quotes, Recent Invoices, and Expiring Soon widgets | Pass | Widgets visible with data |
| DASH-3 | Dashboard loads without console errors | Fail | BUG-012: 4x 403 errors on load |
| Command Palette | |||
| CMD-1 | Cmd+K opens command palette | Fail | Meta+K not intercepted in headless Playwright |
| CMD-2 | Command palette search returns results | Pass | Tested via manual runs |
| CMD-3 | Escape closes command palette | Pass | Tested via manual runs |
| Customers | |||
| CUST-1 | Customers list page loads with data grid | Pass | 19 rows loaded |
| CUST-2 | Customer search filters results | Pass | Search for "hex" returns results |
| CUST-3 | Create customer form renders with all fields | Pass | Email, name, company fields present |
| CUST-4 | Customer detail page has all tabs | Pass | Overview, KYC, Licenses, Quotes, Invoices, Pending Charges, Payment, Contacts, Events, Profiles, Actions |
| CUST-5 | Customer detail has Impersonate and HubSpot buttons | Pass | Both action buttons present |
| Quotes | |||
| QUOT-1 | Quotes page renders data grid | Pass | Grid renders, loads data without customer |
| QUOT-2 | Quotes load after customer selection | Pass | 1 quote for Hex-Rays SA |
| QUOT-3 | Quote detail page loads with line items | Pass | Status bar, line items, pricing visible |
| QUOT-4 | Quote detail has action buttons | Pass | Download PDF, Invoice Preview, Mark as Paid, Recreate Licenses |
| QUOT-5 | Quote type selector page renders | Pass | New, Renewal, Upsell options visible |
| QUOT-6 | Quote wizard loads after type selection | Pass | Full wizard with all sections |
| QUOT-7 | Quote wizard has Summary, Notes, and Coupon sections | Pass | All sections rendered |
| QUOT-8 | Quotes list shows correct currency per quote | Fail | BUG-010: EUR quotes displayed with $ symbol |
| Licenses | |||
| LIC-1 | Licenses page renders data grid | Pass | Grid visible |
| LIC-2 | Licenses load after customer selection | Pass | 1 license for Hex-Rays SA |
| LIC-3 | Expiring Soon toggle present | Pass | Toggle button found |
| LIC-4 | Licenses page free of CORS errors | Pass | No CORS errors (BUG-001 may be fixed) |
| Invoices | |||
| INV-1 | Invoices page renders data grid | Pass | Grid visible |
| INV-2 | Invoices load after customer selection | Pass | Invoices loaded |
| INV-3 | Invoice type filter present | Pass | Type filter dropdown available |
| Pending Charges (New Feature) | |||
| PC-1 | Pending Charges page renders via sidebar navigation | Pass | Grid and filter bar visible |
| PC-2 | Empty state shown without customer selection | Pass | "No Customer Selected" message |
| PC-3 | Column headers correct (ID, Status, Total, Date, Actions) | Pass | All expected columns present |
| PC-4 | Data loads after customer selection | Pass | "No pending charges found" for Hex-Rays (0 charges, valid) |
| PC-5 | Pending Charges free of API errors | Pass | No 500/CORS errors |
| PC-12 | Pagination footer renders | Pass | Page 1/1 with size selector |
| Reports | |||
| RPT-1 | Reports Billing tab loads with stat cards and sub-tabs | Pass | Revenue type, customer, product sub-tabs |
| RPT-2 | Reports breadcrumb shows navigation context | Fail | BUG-005 still present: no "Reports" in breadcrumb |
| RPT-cash | Reports Cash tab loads | Pass | |
| RPT-top-n | Reports Top N tab loads | Fail | BUG-013: minimal content, tab may be broken |
| RPT-renewals | Reports Renewals tab loads | Pass | |
| RPT-subs | Reports Subscriptions tab loads | Pass | |
| RPT-charts | Reports Charts tab loads | Pass | |
| RPT-exports | Reports Exports tab loads | Pass | |
| Admin | |||
| ADM-1 | User Profiles page loads | Pass | |
| ADM-2 | Protected Leads page loads | Pass | |
| ADM-3 | Add Domain dialog opens | Pass | |
| ADM-4 | Events page loads with data grid | Pass | |
| ADM-5 | Emails page loads | Pass | |
| ADM-6 | Notifications page loads | Pass | |
| ADM-7 | Various admin page loads with cache controls | Pass | |
| Customer Filter Persistence | |||
| PERSIST-1 | Customer selection saved to localStorage | Pass | ea-tool-selected-customer key set |
| PERSIST-2 | Customer persists after page reload | Pass | localStorage survives reload |