163 lines
6.7 KiB
TypeScript
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 });
|
|
});
|
|
});
|