Files
OSIT-AE-App-Svelte/tests/leads_payment.test.ts

163 lines
6.7 KiB
TypeScript

import { test, expect } from '@playwright/test';
import { testing_event_id } from './_helpers/env';
import {
testing_exhibit_id,
exhibit_staff_passcode,
setup_leads_test_page,
} from './_helpers/leads_helpers';
const event_id = testing_event_id;
const exhibit_id = testing_exhibit_id;
const exhibit_url = `/events/${event_id}/leads/exhibit/${exhibit_id}`;
const signed_in_kv = { [exhibit_id]: { key: exhibit_staff_passcode, type: 'shared' } };
/** Locator for the CreditCard header button (Payment & Upgrades). */
const payment_btn = (page: Parameters<typeof expect>[0]) =>
(page as import('@playwright/test').Page).locator(
'header button[title="Payment & Upgrades"]'
);
/** Locator for the Manage / Settings header button. */
const manage_btn = (page: Parameters<typeof expect>[0]) =>
(page as import('@playwright/test').Page).locator(
'header button[title="Manage Exhibit"]'
);
test.describe('Leads — Payment Gate (leads_require_payment)', () => {
// -----------------------------------------------------------------------
// 1. leads_require_payment = false → no CreditCard button in header
//
// When the event-level flag is disabled the payment tab is not surfaced
// at all — the button must be absent so exhibitors cannot accidentally
// navigate to the Stripe flow when the event organiser covers costs.
// -----------------------------------------------------------------------
test('payment not required: CreditCard button absent from header', async ({ page }) => {
await setup_leads_test_page(page, event_id, exhibit_id, {
auth_kv: signed_in_kv,
event_data_overrides: {
mod_exhibits_json: { leads_require_payment: false },
},
});
await page.goto(exhibit_url);
// Wait for the event GET to complete so we know liveQuery has fired
await page.waitForResponse(
(r) => r.url().includes(`crud/event/${event_id}`) && r.status() === 200,
{ timeout: 8_000 }
);
// CreditCard button must remain absent after the event has loaded
await expect(payment_btn(page)).not.toBeVisible({ timeout: 3_000 });
});
// -----------------------------------------------------------------------
// 2. leads_require_payment = true → CreditCard button visible in header
//
// Default mock event has leads_require_payment: true — button must appear
// once the event record is written to Dexie and lq__event_obj fires.
// -----------------------------------------------------------------------
test('payment required: CreditCard button visible in header', async ({ page }) => {
await setup_leads_test_page(page, event_id, exhibit_id, {
auth_kv: signed_in_kv,
// Default mock event already has leads_require_payment: true
});
await page.goto(exhibit_url);
await expect(payment_btn(page)).toBeVisible({ timeout: 8_000 });
});
// -----------------------------------------------------------------------
// 3. Clicking CreditCard button opens the payment tab
//
// The button toggles active_tab to 'payment'. The payment component
// (.ae-exhibit-payment or similar) must render inside the content area.
// We verify by asserting the button switches to filled-success variant
// (active tab styling) and the header primary button stays visible.
// -----------------------------------------------------------------------
test('clicking CreditCard button switches to payment tab', async ({ page }) => {
await setup_leads_test_page(page, event_id, exhibit_id, {
auth_kv: signed_in_kv,
});
await page.goto(exhibit_url);
// Wait for the payment button to appear
await expect(payment_btn(page)).toBeVisible({ timeout: 8_000 });
// Click it
await payment_btn(page).click();
// Active tab styling: button gets preset-filled-success class
await expect(payment_btn(page)).toHaveClass(/preset-filled-success/, {
timeout: 3_000,
});
// Primary "Add Lead / Lead List" toggle must still be visible
await expect(
page.locator('header button.preset-filled-primary')
).toBeVisible({ timeout: 3_000 });
});
// -----------------------------------------------------------------------
// 4. Manage tab: Billing accordion present when payment required
//
// When leads_require_payment is true, the Manage tab shows a collapsible
// "Licenses & Billing" section so exhibitors can manage payment status.
// -----------------------------------------------------------------------
test('manage tab: billing accordion visible when payment required', async ({ page }) => {
await setup_leads_test_page(page, event_id, exhibit_id, {
auth_kv: signed_in_kv,
});
await page.goto(exhibit_url);
// Wait for payment button (confirms event loaded and lq__event_obj is live)
await expect(payment_btn(page)).toBeVisible({ timeout: 8_000 });
// Navigate to manage tab
await manage_btn(page).click();
// Billing accordion row must be present
await expect(
page.locator('button:has-text("Licenses & Billing")')
).toBeVisible({ timeout: 5_000 });
});
// -----------------------------------------------------------------------
// 5. Manage tab: Billing accordion absent when payment not required
//
// When the flag is disabled the accordion is not rendered at all — the
// conditional {#if leads_require_payment} in ae_tab__manage.svelte hides it.
// -----------------------------------------------------------------------
test('manage tab: billing accordion hidden when payment not required', async ({ page }) => {
await setup_leads_test_page(page, event_id, exhibit_id, {
auth_kv: signed_in_kv,
event_data_overrides: {
mod_exhibits_json: { leads_require_payment: false },
},
});
await page.goto(exhibit_url);
// Wait for event GET to complete
await page.waitForResponse(
(r) => r.url().includes(`crud/event/${event_id}`) && r.status() === 200,
{ timeout: 8_000 }
);
// Navigate to manage tab
await manage_btn(page).click();
// "Booth Profile" section heading confirms manage tab is rendered
await expect(page.locator('text=Booth Profile')).toBeVisible({ timeout: 5_000 });
// Billing accordion must NOT appear
await expect(
page.locator('button:has-text("Licenses & Billing")')
).not.toBeVisible({ timeout: 3_000 });
});
});