tests: add Playwright event badge CRUD + interaction tests; add minimal V3 mocks and env helper; update presenter/badge smoke tests to use helpers; convert test locals to snake_case
This commit is contained in:
97
src/lib/ae_events/ae_events__event_badge.spec.ts
Normal file
97
src/lib/ae_events/ae_events__event_badge.spec.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
|
||||
// Use hoist-safe factories for vi.mock
|
||||
vi.mock('$lib/api/api', () => ({
|
||||
api: {
|
||||
create_nested_obj_v3: vi.fn(),
|
||||
update_nested_obj_v3: vi.fn(),
|
||||
delete_nested_ae_obj_v3: vi.fn(),
|
||||
search_ae_obj_v3: vi.fn()
|
||||
}
|
||||
}));
|
||||
vi.mock('$lib/ae_core/core__idb_dexie', () => ({ db_save_ae_obj_li__ae_obj: vi.fn() }));
|
||||
vi.mock('$lib/ae_events/db_events', () => ({ db_events: { badge: { get: vi.fn(), delete: vi.fn() } } }));
|
||||
vi.mock('$lib/ae_events/ae_events__event_badge_template', () => ({ load_ae_obj_id__event_badge_template: vi.fn() }));
|
||||
|
||||
import { create_ae_obj__event_badge } from './ae_events__event_badge';
|
||||
|
||||
describe('create_ae_obj__event_badge', () => {
|
||||
it('calls api.create_nested_obj_v3 with the correct params and returns the result', async () => {
|
||||
const mocked = await import('$lib/api/api');
|
||||
const mockCreateNested = mocked.api.create_nested_obj_v3 as jest.MockedFunction<any>;
|
||||
|
||||
const fakeResult = { event_badge_id: 'eb123', full_name: 'Test User' };
|
||||
mockCreateNested.mockResolvedValue(fakeResult);
|
||||
|
||||
const api_cfg = { base_url: 'http://localhost', headers: {} };
|
||||
const event_id = 'evt1';
|
||||
const data_kv = { full_name_override: 'Test User', email: 't@example.com' };
|
||||
|
||||
const result = await create_ae_obj__event_badge({ api_cfg, event_id, data_kv, try_cache: false });
|
||||
|
||||
expect(mockCreateNested).toHaveBeenCalled();
|
||||
const calledWith = mockCreateNested.mock.calls[0][0];
|
||||
expect(calledWith.parent_type).toBe('event');
|
||||
expect(calledWith.parent_id).toBe(event_id);
|
||||
expect(calledWith.child_type).toBe('event_badge');
|
||||
expect(calledWith.fields).toEqual(data_kv);
|
||||
|
||||
expect(result).toEqual(fakeResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('update_ae_obj__event_badge', () => {
|
||||
it('calls api.update_nested_obj_v3 with correct params and returns result', async () => {
|
||||
const mocked = await import('$lib/api/api');
|
||||
const mockUpdate = mocked.api.update_nested_obj_v3 as jest.MockedFunction<any>;
|
||||
const fakeResult = { event_badge_id: 'eb999', full_name: 'Updated' };
|
||||
mockUpdate.mockResolvedValue(fakeResult);
|
||||
|
||||
const { update_ae_obj__event_badge } = await import('./ae_events__event_badge');
|
||||
const api_cfg = { base_url: 'http://localhost', headers: {} };
|
||||
const res = await update_ae_obj__event_badge({ api_cfg, event_id: 'evt1', event_badge_id: 'eb999', data_kv: { full_name_override: 'Updated' }, try_cache: false });
|
||||
|
||||
expect(mockUpdate).toHaveBeenCalled();
|
||||
const called = mockUpdate.mock.calls[0][0];
|
||||
expect(called.child_id).toBe('eb999');
|
||||
expect(called.fields).toEqual({ full_name_override: 'Updated' });
|
||||
expect(res).toEqual(fakeResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('delete_ae_obj_id__event_badge', () => {
|
||||
it('calls api.delete_nested_ae_obj_v3 and deletes from local DB when try_cache true', async () => {
|
||||
const mocked = await import('$lib/api/api');
|
||||
const mockDelete = mocked.api.delete_nested_ae_obj_v3 as jest.MockedFunction<any>;
|
||||
mockDelete.mockResolvedValue({ success: true });
|
||||
|
||||
const db = await import('$lib/ae_events/db_events');
|
||||
const dbDelete = db.db_events.badge.delete as jest.MockedFunction<any>;
|
||||
|
||||
const { delete_ae_obj_id__event_badge } = await import('./ae_events__event_badge');
|
||||
|
||||
const api_cfg = { base_url: 'http://localhost', headers: {} };
|
||||
const res = await delete_ae_obj_id__event_badge({ api_cfg, event_id: 'evt1', event_badge_id: 'ebDel', try_cache: true });
|
||||
|
||||
expect(mockDelete).toHaveBeenCalled();
|
||||
expect(dbDelete).toHaveBeenCalledWith('ebDel');
|
||||
expect(res).toEqual({ success: true });
|
||||
});
|
||||
});
|
||||
|
||||
describe('search__event_badge', () => {
|
||||
it('calls api.search_ae_obj_v3 and returns list (handles data envelope)', async () => {
|
||||
const mocked = await import('$lib/api/api');
|
||||
const mockSearch = mocked.api.search_ae_obj_v3 as jest.MockedFunction<any>;
|
||||
const fakeList = [{ event_badge_id: 'eb1' }, { event_badge_id: 'eb2' }];
|
||||
mockSearch.mockResolvedValue({ data: fakeList });
|
||||
|
||||
const { search__event_badge } = await import('./ae_events__event_badge');
|
||||
const api_cfg = { base_url: 'http://localhost', headers: {} };
|
||||
const res = await search__event_badge({ api_cfg, event_id: 'evt1', fulltext_search_qry_str: 'Test', try_cache: false });
|
||||
|
||||
expect(mockSearch).toHaveBeenCalled();
|
||||
expect(Array.isArray(res)).toBe(true);
|
||||
expect((res as any).length).toBe(2);
|
||||
});
|
||||
});
|
||||
@@ -9,46 +9,6 @@
|
||||
let { data, children, log_lvl = 0 }: Props = $props();
|
||||
|
||||
// *** Import Svelte specific
|
||||
// import { liveQuery } from 'dexie';
|
||||
|
||||
// import type { key_val } from '$lib/stores/ae_stores';
|
||||
// import { ae_util } from '$lib/ae_utils/ae_utils';
|
||||
|
||||
// import { core_func } from '$lib/ae_core_functions';
|
||||
// import { db_events } from '$lib/ae_events/db_events';
|
||||
// import {
|
||||
// ae_snip,
|
||||
// ae_loc,
|
||||
// ae_sess,
|
||||
// ae_api,
|
||||
// ae_trig,
|
||||
// slct,
|
||||
// slct_trigger
|
||||
// } from '$lib/stores/ae_stores';
|
||||
// import {
|
||||
// events_loc,
|
||||
// events_sess,
|
||||
// events_slct,
|
||||
// events_trigger
|
||||
// } from '$lib/stores/ae_events_stores';
|
||||
// import { events_func } from '$lib/ae_events_functions';
|
||||
|
||||
// let lq__event_obj = $derived(
|
||||
// liveQuery(async () => {
|
||||
// if (log_lvl) {
|
||||
// console.log(
|
||||
// `*** LiveQuery: lq__event_obj *** event_id=${$events_slct.event_id}`
|
||||
// );
|
||||
// }
|
||||
// let results = await db_events.event.get(
|
||||
// $events_slct?.event_id ?? ''
|
||||
// );
|
||||
|
||||
// return results;
|
||||
// })
|
||||
// );
|
||||
|
||||
// let nav_y_height = $state(0);
|
||||
|
||||
let box: any;
|
||||
let xLeft = $state(0);
|
||||
@@ -73,10 +33,6 @@
|
||||
}
|
||||
|
||||
// *** Functions and Logic
|
||||
// $effect(() => {
|
||||
// // if ($events_trigger == 'load__event_badge_obj_li' && $events_slct.event_id) {
|
||||
// // }
|
||||
// });
|
||||
</script>
|
||||
|
||||
<!-- <svelte:head>
|
||||
@@ -92,6 +48,5 @@
|
||||
</svelte:head> -->
|
||||
<!-- - Badges - {$events_loc?.title} -->
|
||||
|
||||
<!-- +layout: Where is here??? -->
|
||||
|
||||
{@render children?.()}
|
||||
|
||||
@@ -55,3 +55,11 @@ git commit -m "test: add <description>"
|
||||
|
||||
Help
|
||||
- If a test fails due to external network calls or platform-specific behavior, try mocking the relevant endpoints and move the test to `tests/disabled` if it cannot be made deterministic.
|
||||
|
||||
|
||||
Development / Testing / Demo environment information
|
||||
Use snake_case (or Snake_Case or Snake_case or test_NASA_example or test_API_key)
|
||||
Aether test/demo base URL: 'http://demo.localhost:5173'
|
||||
Aether development API: 'https://dev-api.oneskyit.com'
|
||||
Aether test/demo account: '_XY7DXtc9MY' (1) "One Sky IT Demo"
|
||||
Aether test/demo event: 'pjrcghqwert' (1) "Demo One Sky IT Conference"
|
||||
17
tests/_helpers/env.ts
Normal file
17
tests/_helpers/env.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Centralized test environment constants for Playwright and unit tests.
|
||||
* Use snake_case names per project preference.
|
||||
*/
|
||||
export const test_base_url = 'http://demo.localhost:5173';
|
||||
export const dev_api_base = 'https://dev-api.oneskyit.com';
|
||||
export const demo_account_id = '_XY7DXtc9MY';
|
||||
export const demo_event_id = 'pjrcghqwert';
|
||||
|
||||
export const TEST_ENV = {
|
||||
test_base_url,
|
||||
dev_api_base,
|
||||
demo_account_id,
|
||||
demo_event_id
|
||||
};
|
||||
|
||||
export default TEST_ENV;
|
||||
73
tests/_helpers/minimal_v3_mocks.ts
Normal file
73
tests/_helpers/minimal_v3_mocks.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import { Page } from '@playwright/test';
|
||||
|
||||
export const minimal_event = (event_id: string) => ({
|
||||
data: {
|
||||
id: event_id,
|
||||
event_id: event_id,
|
||||
name: 'Test Event (minimal)',
|
||||
cfg_json: {},
|
||||
mod_pres_mgmt_json: {},
|
||||
mod_badges_json: {},
|
||||
mod_abstracts_json: {},
|
||||
mod_exhibits_json: {},
|
||||
mod_meetings_json: {},
|
||||
},
|
||||
});
|
||||
|
||||
export const minimal_badge = (overrides: Record<string, any> = {}) => ({
|
||||
event_badge_id: 'badge-1',
|
||||
full_name_override: 'Test User',
|
||||
email: 'test@example.com',
|
||||
badge_type: 'test',
|
||||
...overrides,
|
||||
});
|
||||
|
||||
/**
|
||||
* Attach minimal V3 route handlers to a Playwright `page`.
|
||||
* - Responds to event GET, badge search/create/update/delete, and a simple site_domain/search.
|
||||
* - Keeps created badge state in-memory for the page session.
|
||||
*/
|
||||
export async function attach_minimal_v3_routes(page: Page, event_id: string) {
|
||||
let created_badge: any = null;
|
||||
|
||||
await page.route('**/v3/**', async (route) => {
|
||||
const req = route.request();
|
||||
const url = req.url();
|
||||
const method = req.method();
|
||||
|
||||
if (url.includes('site_domain/search')) {
|
||||
return route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ data: [{ id: 'td', site_id: 'ts' }] }) });
|
||||
}
|
||||
|
||||
if (url.includes(`/v3/crud/event/${event_id}`) && method === 'GET') {
|
||||
return route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(minimal_event(event_id)) });
|
||||
}
|
||||
|
||||
if (url.includes(`/v3/crud/event/${event_id}/event_badge/search`) && method === 'POST') {
|
||||
return route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ data: created_badge ? [created_badge] : [] }) });
|
||||
}
|
||||
|
||||
if (url.includes(`/v3/crud/event/${event_id}/event_badge`) && method === 'POST') {
|
||||
const post = await req.postData();
|
||||
const body = post ? JSON.parse(post) : {};
|
||||
created_badge = { ...minimal_badge(body) };
|
||||
return route.fulfill({ status: 201, contentType: 'application/json', body: JSON.stringify({ data: created_badge }) });
|
||||
}
|
||||
|
||||
if (url.match(new RegExp(`/v3/crud/event/${event_id}/event_badge/.+`)) && (method === 'PATCH' || method === 'PUT')) {
|
||||
const post = await req.postData();
|
||||
const body = post ? JSON.parse(post) : {};
|
||||
if (created_badge) created_badge = { ...created_badge, ...body };
|
||||
return route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ data: created_badge }) });
|
||||
}
|
||||
|
||||
if (url.match(new RegExp(`/v3/crud/event/${event_id}/event_badge/.+`)) && method === 'DELETE') {
|
||||
created_badge = null;
|
||||
return route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ data: true }) });
|
||||
}
|
||||
|
||||
return route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ data: [] }) });
|
||||
});
|
||||
}
|
||||
|
||||
export default { minimal_event, minimal_badge, attach_minimal_v3_routes };
|
||||
@@ -1,5 +1,9 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { ae_app_local_data_defaults } from './_helpers/ae_defaults';
|
||||
import { demo_event_id, demo_account_id } from './_helpers/env';
|
||||
import { attach_minimal_v3_routes } from './_helpers/minimal_v3_mocks';
|
||||
|
||||
const demo_event = demo_event_id;
|
||||
|
||||
test.describe('Event Badge Page - smoke', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
@@ -8,25 +12,20 @@ test.describe('Event Badge Page - smoke', () => {
|
||||
if (msg.type() === 'error' || msg.type() === 'warn') console.error(`BROWSER [${msg.type().toUpperCase()}]: ${msg.text()}`);
|
||||
});
|
||||
|
||||
await page.route('**/*oneskyit.com/**', async (route) => {
|
||||
const url = route.request().url();
|
||||
if (url.includes('site_domain/search')) {
|
||||
return route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ data: [{ id: 'td', site_id: 'ts' }] }) });
|
||||
}
|
||||
return route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ data: [] }) });
|
||||
});
|
||||
await attach_minimal_v3_routes(page, demo_event);
|
||||
|
||||
await page.addInitScript((defaults) => {
|
||||
const testData = { ...defaults, account_id: 'smoke-account', manager_access: true };
|
||||
window.localStorage.setItem('ae_loc', JSON.stringify(testData));
|
||||
}, ae_app_local_data_defaults);
|
||||
await page.addInitScript((defaults, event_id, account_id) => {
|
||||
const test_data = { ...defaults, account_id: account_id, manager_access: true };
|
||||
test_data.mod = { ...defaults.mod, events: { ...defaults.mod.events, event_id } };
|
||||
window.localStorage.setItem('ae_loc', JSON.stringify(test_data));
|
||||
}, ae_app_local_data_defaults, demo_event, demo_account_id);
|
||||
});
|
||||
|
||||
test('loads badges list without console errors', async ({ page }) => {
|
||||
const errors: string[] = [];
|
||||
page.on('pageerror', (err) => errors.push(err.message));
|
||||
|
||||
await page.goto('/events/test-event/badges');
|
||||
await page.goto(`/events/${demo_event}/badges`);
|
||||
await page.waitForResponse((r) => r.url().includes('site_domain/search') && r.status() === 200);
|
||||
|
||||
expect(errors).toHaveLength(0);
|
||||
|
||||
136
tests/event_badge_crud.test.ts
Normal file
136
tests/event_badge_crud.test.ts
Normal file
@@ -0,0 +1,136 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { ae_app_local_data_defaults } from './_helpers/ae_defaults';
|
||||
import { demo_event_id, demo_account_id } from './_helpers/env';
|
||||
|
||||
const test_event_id = demo_event_id;
|
||||
|
||||
test.describe('event_badge_crud (create, find, edit, delete)', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
page.on('pageerror', (err) => console.error(`BROWSER ERROR: ${err.message}`));
|
||||
page.on('console', (msg) => {
|
||||
if (msg.type() === 'error' || msg.type() === 'warn')
|
||||
console.error(`BROWSER [${msg.type().toUpperCase()}]: ${msg.text()}`);
|
||||
});
|
||||
|
||||
// Minimal in-test state for created badge
|
||||
let created_badge: any = null;
|
||||
|
||||
await page.route('**/v3/**', async (route) => {
|
||||
const req = route.request();
|
||||
const url = req.url();
|
||||
const method = req.method();
|
||||
|
||||
if (url.includes('site_domain/search')) {
|
||||
return route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ data: [{ id: 'td', site_id: 'ts' }] }) });
|
||||
}
|
||||
|
||||
// Minimal event GET payload (include cfg_json and mod_* for bindings)
|
||||
if (url.includes(`/v3/crud/event/${test_event_id}`) && method === 'GET') {
|
||||
return route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({ data: { id: test_event_id, event_id: test_event_id, name: 'Test Event for Badge CRUD', cfg_json: {}, mod_pres_mgmt_json: {}, mod_badges_json: {}, mod_abstracts_json: {}, mod_exhibits_json: {}, mod_meetings_json: {} } })
|
||||
});
|
||||
}
|
||||
|
||||
// Search/list badges
|
||||
if (url.includes(`/v3/crud/event/${test_event_id}/event_badge/search`) && method === 'POST') {
|
||||
return route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ data: created_badge ? [created_badge] : [] }) });
|
||||
}
|
||||
|
||||
// Create badge - return created envelope with fixed id
|
||||
if (url.includes(`/v3/crud/event/${test_event_id}/event_badge`) && method === 'POST') {
|
||||
const post = await req.postData();
|
||||
const body = post ? JSON.parse(post) : {};
|
||||
created_badge = { ...body, event_badge_id: 'badge-1' };
|
||||
return route.fulfill({ status: 201, contentType: 'application/json', body: JSON.stringify({ data: created_badge }) });
|
||||
}
|
||||
|
||||
// Update badge
|
||||
if (url.match(new RegExp(`/v3/crud/event/${test_event_id}/event_badge/.+`)) && (method === 'PATCH' || method === 'PUT')) {
|
||||
const post = await req.postData();
|
||||
const body = post ? JSON.parse(post) : {};
|
||||
if (created_badge) created_badge = { ...created_badge, ...body };
|
||||
return route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ data: created_badge }) });
|
||||
}
|
||||
|
||||
// Delete badge
|
||||
if (url.match(new RegExp(`/v3/crud/event/${test_event_id}/event_badge/.+`)) && method === 'DELETE') {
|
||||
created_badge = null;
|
||||
return route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ data: true }) });
|
||||
}
|
||||
|
||||
return route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ data: [] }) });
|
||||
});
|
||||
|
||||
page.on('dialog', async (dialog) => { await dialog.accept(); });
|
||||
|
||||
await page.addInitScript(({ defaults, eventId, accountId }) => {
|
||||
const test_data = { ...defaults, account_id: accountId, manager_access: true, administrator_access: true, edit_mode: true, mod: { ...defaults.mod, events: { ...defaults.mod.events, event_id: eventId } } };
|
||||
window.localStorage.setItem('ae_loc', JSON.stringify(test_data));
|
||||
}, { defaults: ae_app_local_data_defaults, eventId: test_event_id, accountId: demo_account_id });
|
||||
});
|
||||
|
||||
test('create -> find -> edit -> delete badge', async ({ page }) => {
|
||||
// Create via Settings modal UI
|
||||
await page.goto(`/events/${test_event_id}/settings`);
|
||||
const add_btn = page.getByRole('button', { name: 'Add New Badge' });
|
||||
await expect(add_btn).toBeVisible();
|
||||
await add_btn.click();
|
||||
|
||||
const form = page.locator('form:has-text("Create Badge")');
|
||||
await expect(form).toBeVisible();
|
||||
await form.locator('label:has-text("Full Name Override") input').fill('CRUD User');
|
||||
await form.locator('label:has-text("Email") input').fill('crud@example.com');
|
||||
await form.locator('label:has-text("Badge Type") select').selectOption('test');
|
||||
|
||||
// Wait for POST create request and response
|
||||
const [create_req, create_resp] = await Promise.all([
|
||||
page.waitForRequest((r) => r.url().includes(`/v3/crud/event/${test_event_id}/event_badge`) && r.method() === 'POST'),
|
||||
page.waitForResponse((r) => r.url().includes(`/v3/crud/event/${test_event_id}/event_badge`) && (r.status() === 201 || r.status() === 200)),
|
||||
page.getByRole('button', { name: 'Create Badge' }).click()
|
||||
]);
|
||||
|
||||
const post_body = create_req.postData();
|
||||
const post_json = post_body ? JSON.parse(post_body) : {};
|
||||
expect(post_json.email).toBe('crud@example.com');
|
||||
|
||||
const created = await create_resp.json();
|
||||
expect(created.data).toBeDefined();
|
||||
const badge_id = created.data.event_badge_id || created.data.id || 'badge-1';
|
||||
|
||||
// Find badges via search endpoint (simulate listing page) using in-page fetch
|
||||
await page.goto(`/events/${test_event_id}/badges`);
|
||||
const search_json = await page.evaluate(async (eventId) => {
|
||||
const r = await fetch(`/v3/crud/event/${eventId}/event_badge/search`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({}) });
|
||||
return await r.json();
|
||||
}, test_event_id);
|
||||
expect(Array.isArray(search_json.data)).toBeTruthy();
|
||||
expect(search_json.data.length).toBeGreaterThanOrEqual(1);
|
||||
|
||||
// Edit badge via browser fetch (exercise nested update)
|
||||
const edit_resp = await page.evaluate(async (args) => {
|
||||
const { eventId, badgeId } = args;
|
||||
const r = await fetch(`/v3/crud/event/${eventId}/event_badge/${badgeId}/`, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ full_name_override: 'Edited User' }) });
|
||||
return { status: r.status, json: await r.json() };
|
||||
}, { eventId: test_event_id, badgeId: badge_id });
|
||||
expect(edit_resp.status === 200).toBeTruthy();
|
||||
expect(edit_resp.json.data.full_name_override).toBe('Edited User');
|
||||
|
||||
// Delete badge via browser fetch
|
||||
const del_resp = await page.evaluate(async (args) => {
|
||||
const { eventId, badgeId } = args;
|
||||
const r = await fetch(`/v3/crud/event/${eventId}/event_badge/${badgeId}/`, { method: 'DELETE' });
|
||||
return { status: r.status, ok: r.ok };
|
||||
}, { eventId: test_event_id, badgeId: badge_id });
|
||||
expect(del_resp.ok).toBeTruthy();
|
||||
|
||||
// Confirm search returns no items
|
||||
const post_delete_json = await page.evaluate(async (eventId) => {
|
||||
const r = await fetch(`/v3/crud/event/${eventId}/event_badge/search`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({}) });
|
||||
return await r.json();
|
||||
}, test_event_id);
|
||||
expect(Array.isArray(post_delete_json.data)).toBeTruthy();
|
||||
expect(post_delete_json.data.length).toBe(0);
|
||||
});
|
||||
});
|
||||
@@ -1,7 +1,8 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { ae_app_local_data_defaults } from './_helpers/ae_defaults';
|
||||
import { demo_event_id, demo_account_id } from './_helpers/env';
|
||||
|
||||
const testEventId = 'pjrcghqwert';
|
||||
const demo_event = demo_event_id;
|
||||
|
||||
test.describe('Event Badge - interaction', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
@@ -11,25 +12,19 @@ test.describe('Event Badge - interaction', () => {
|
||||
console.error(`BROWSER [${msg.type().toUpperCase()}]: ${msg.text()}`);
|
||||
});
|
||||
|
||||
// Minimal network mock: fulfill only what's necessary for the UI to render
|
||||
await page.route('**/v3/**', async (route) => {
|
||||
const req = route.request();
|
||||
const url = req.url();
|
||||
|
||||
if (url.includes('site_domain/search')) {
|
||||
return route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({ data: [{ id: 'test-site-domain-id', site_id: 'test-site-id', account_id: '_XY7DXtc9MY' }] })
|
||||
});
|
||||
}
|
||||
|
||||
if (url.includes(`/v3/crud/event/${testEventId}`) && req.method() === 'GET') {
|
||||
// Provide the minimal event payload for the settings page to render
|
||||
if (url.includes(`/v3/crud/event/${demo_event}`) && req.method() === 'GET') {
|
||||
return route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({ data: {
|
||||
id: testEventId,
|
||||
event_id: testEventId,
|
||||
id: demo_event,
|
||||
event_id: demo_event,
|
||||
name: 'Test Event for Badge Interaction',
|
||||
cfg_json: {},
|
||||
mod_pres_mgmt_json: {},
|
||||
@@ -41,14 +36,12 @@ test.describe('Event Badge - interaction', () => {
|
||||
});
|
||||
}
|
||||
|
||||
if (url.includes(`/v3/crud/event/${testEventId}/event_badge`) && req.method() === 'POST') {
|
||||
const post = await req.postData();
|
||||
console.log('Captured POST to event_badge endpoint:', url, post ? post.slice(0,200) : '');
|
||||
const body = post ? JSON.parse(post) : {};
|
||||
const created = { ...body, event_badge_id: 'new-badge-1' };
|
||||
return route.fulfill({ status: 201, contentType: 'application/json', body: JSON.stringify({ data: created }) });
|
||||
// For badge create requests, return a simple created envelope with a fixed id.
|
||||
if (url.includes(`/v3/crud/event/${demo_event}/event_badge`) && req.method() === 'POST') {
|
||||
return route.fulfill({ status: 201, contentType: 'application/json', body: JSON.stringify({ data: { event_badge_id: 'new-badge-1' } }) });
|
||||
}
|
||||
|
||||
// Default: empty envelope so other calls don't error
|
||||
return route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ data: [] }) });
|
||||
});
|
||||
|
||||
@@ -57,58 +50,60 @@ test.describe('Event Badge - interaction', () => {
|
||||
});
|
||||
|
||||
await page.addInitScript(
|
||||
({ defaults, eventId }) => {
|
||||
({ defaults, event_id, account_id }) => {
|
||||
const testData = {
|
||||
...defaults,
|
||||
account_id: '_XY7DXtc9MY',
|
||||
account_id: account_id,
|
||||
manager_access: true,
|
||||
administrator_access: true,
|
||||
edit_mode: true,
|
||||
mod: { ...defaults.mod, events: { ...defaults.mod.events, event_id: eventId } }
|
||||
mod: { ...defaults.mod, events: { ...defaults.mod.events, event_id: event_id } }
|
||||
};
|
||||
window.localStorage.setItem('ae_loc', JSON.stringify(testData));
|
||||
},
|
||||
{ defaults: ae_app_local_data_defaults, eventId: testEventId }
|
||||
{ defaults: ae_app_local_data_defaults, event_id: demo_event, account_id: demo_account_id }
|
||||
);
|
||||
});
|
||||
|
||||
test('creates a badge via UI and posts to nested endpoint', async ({ page }) => {
|
||||
await page.goto(`/events/${testEventId}/settings`);
|
||||
await page.goto(`/events/${demo_event}/settings`);
|
||||
|
||||
const addBtn = page.getByRole('button', { name: 'Add New Badge' });
|
||||
await expect(addBtn).toBeVisible();
|
||||
await addBtn.click();
|
||||
const add_btn = page.getByRole('button', { name: 'Add New Badge' });
|
||||
await expect(add_btn).toBeVisible();
|
||||
await add_btn.click();
|
||||
|
||||
const form = page.locator('form:has-text("Create Badge")');
|
||||
await expect(form).toBeVisible();
|
||||
|
||||
const fullNameInput = form.locator('label:has-text("Full Name Override") input');
|
||||
await expect(fullNameInput).toBeVisible();
|
||||
await fullNameInput.fill('Test User');
|
||||
const full_name_input = form.locator('label:has-text("Full Name Override") input');
|
||||
await expect(full_name_input).toBeVisible();
|
||||
await full_name_input.fill('Test User');
|
||||
|
||||
const emailInput = form.locator('label:has-text("Email") input');
|
||||
await emailInput.fill('testuser@example.com');
|
||||
const email_input = form.locator('label:has-text("Email") input');
|
||||
await email_input.fill('testuser@example.com');
|
||||
|
||||
const select = form.locator('label:has-text("Badge Type") select');
|
||||
await select.selectOption('test');
|
||||
const badge_type_select = form.locator('label:has-text("Badge Type") select');
|
||||
await badge_type_select.selectOption('test');
|
||||
|
||||
const checkbox = form.locator('label:has-text("Allow Tracking") input[type="checkbox"]');
|
||||
await checkbox.check();
|
||||
const allow_tracking_checkbox = form.locator('label:has-text("Allow Tracking") input[type="checkbox"]');
|
||||
await allow_tracking_checkbox.check();
|
||||
|
||||
const [request] = await Promise.all([
|
||||
page.waitForRequest((r) => r.url().includes(`/v3/crud/event/${testEventId}/event_badge`) && r.method() === 'POST'),
|
||||
page.getByRole('button', { name: 'Create Badge' }).click()
|
||||
]);
|
||||
const [create_request] = await Promise.all([
|
||||
page.waitForRequest((r) => r.url().includes(`/v3/crud/event/${demo_event}/event_badge`) && r.method() === 'POST'),
|
||||
page.getByRole('button', { name: 'Create Badge' }).click()
|
||||
]);
|
||||
|
||||
const postBody = request.postData();
|
||||
const postJson = postBody ? JSON.parse(postBody) : {};
|
||||
expect(postJson.email).toBe('testuser@example.com');
|
||||
expect(postJson.full_name_override).toBe('Test User');
|
||||
const post_body = create_request.postData();
|
||||
const post_json = post_body ? JSON.parse(post_body) : {};
|
||||
expect(post_json.email).toBe('testuser@example.com');
|
||||
expect(post_json.full_name_override).toBe('Test User');
|
||||
|
||||
const response = await page.waitForResponse((r) => r.url().includes(`/v3/crud/event/${testEventId}/event_badge`) && (r.status() === 201 || r.status() === 200));
|
||||
const respJson = await response.json();
|
||||
expect(respJson).toBeDefined();
|
||||
expect(respJson.data).toBeDefined();
|
||||
expect(respJson.data.event_badge_id).toBe('new-badge-1');
|
||||
// Use the request's response for reliability (page.request bypasses page.route otherwise)
|
||||
const response = await create_request.response();
|
||||
expect(response).not.toBeNull();
|
||||
const resp_json = response ? await response.json() : {};
|
||||
expect(resp_json).toBeDefined();
|
||||
expect(resp_json.data).toBeDefined();
|
||||
expect(resp_json.data.event_badge_id).toBe('new-badge-1');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { ae_app_local_data_defaults } from './_helpers/ae_defaults';
|
||||
import { demo_event_id, demo_account_id } from './_helpers/env';
|
||||
import { attach_minimal_v3_routes } from './_helpers/minimal_v3_mocks';
|
||||
|
||||
const demo_event = demo_event_id;
|
||||
|
||||
test.describe('Event Presenter Page - smoke', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
@@ -8,28 +12,21 @@ test.describe('Event Presenter Page - smoke', () => {
|
||||
if (msg.type() === 'error' || msg.type() === 'warn') console.error(`BROWSER [${msg.type().toUpperCase()}]: ${msg.text()}`);
|
||||
});
|
||||
|
||||
await page.route('**/*oneskyit.com/**', async (route) => {
|
||||
const url = route.request().url();
|
||||
if (url.includes('site_domain/search')) {
|
||||
return route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ data: [{ id: 'td', site_id: 'ts' }] }) });
|
||||
}
|
||||
if (url.includes('/v3/crud/event/')) {
|
||||
return route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ data: { id: 'test-event', name: 'Test' } }) });
|
||||
}
|
||||
return route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ data: [] }) });
|
||||
});
|
||||
await attach_minimal_v3_routes(page, demo_event);
|
||||
|
||||
await page.addInitScript((defaults) => {
|
||||
const testData = { ...defaults, account_id: 'smoke-account', manager_access: true };
|
||||
window.localStorage.setItem('ae_loc', JSON.stringify(testData));
|
||||
}, ae_app_local_data_defaults);
|
||||
await page.addInitScript((defaults, event_id, account_id) => {
|
||||
const test_data = { ...defaults, account_id: account_id, manager_access: true };
|
||||
// ensure the events module has the event id available
|
||||
test_data.mod = { ...defaults.mod, events: { ...defaults.mod.events, event_id } };
|
||||
window.localStorage.setItem('ae_loc', JSON.stringify(test_data));
|
||||
}, ae_app_local_data_defaults, demo_event, demo_account_id);
|
||||
});
|
||||
|
||||
test('opens presenter editor without throwing', async ({ page }) => {
|
||||
const errors: string[] = [];
|
||||
page.on('pageerror', (e) => errors.push(e.message));
|
||||
|
||||
await page.goto('/events/test-event/presenters');
|
||||
await page.goto(`/events/${demo_event}/presenters`);
|
||||
await page.waitForResponse((r) => r.url().includes('site_domain/search') && r.status() === 200);
|
||||
|
||||
expect(errors).toHaveLength(0);
|
||||
|
||||
42
tests/unit/create_event_badge.spec.ts
Normal file
42
tests/unit/create_event_badge.spec.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
|
||||
// Aether test/demo base URL: 'http://demo.localhost:5173'
|
||||
// Aether development API: 'https://dev-api.oneskyit.com'
|
||||
// Aether test/demo account: '_XY7DXtc9MY' (1) "One Sky IT Demo"
|
||||
// Aether test/demo event: 'pjrcghqwert' (1) "Demo One Sky IT Conference"
|
||||
|
||||
// Mock the api module used by the ae_events file
|
||||
const mockCreateNested = vi.fn();
|
||||
vi.mock('$lib/api/api', () => ({ api: { create_nested_obj_v3: mockCreateNested } }));
|
||||
|
||||
// Avoid touching IndexedDB caching in this unit test
|
||||
vi.mock('$lib/ae_core/core__idb_dexie', () => ({ db_save_ae_obj_li__ae_obj: vi.fn() }));
|
||||
|
||||
// Import the function under test after mocks
|
||||
import { create_ae_obj__event_badge } from '../../../src/lib/ae_events/ae_events__event_badge';
|
||||
|
||||
describe('create_ae_obj__event_badge', () => {
|
||||
beforeEach(() => {
|
||||
mockCreateNested.mockReset();
|
||||
});
|
||||
|
||||
it('calls api.create_nested_obj_v3 with the correct params and returns the result', async () => {
|
||||
const fakeResult = { event_badge_id: 'eb123', full_name: 'Test User' };
|
||||
mockCreateNested.mockResolvedValue(fakeResult);
|
||||
|
||||
const api_cfg = { base_url: 'http://localhost', headers: {} };
|
||||
const event_id = 'evt1';
|
||||
const data_kv = { full_name_override: 'Test User', email: 't@example.com' };
|
||||
|
||||
const result = await create_ae_obj__event_badge({ api_cfg, event_id, data_kv, try_cache: false });
|
||||
|
||||
expect(mockCreateNested).toHaveBeenCalled();
|
||||
const calledWith = mockCreateNested.mock.calls[0][0];
|
||||
expect(calledWith.parent_type).toBe('event');
|
||||
expect(calledWith.parent_id).toBe(event_id);
|
||||
expect(calledWith.child_type).toBe('event_badge');
|
||||
expect(calledWith.fields).toEqual(data_kv);
|
||||
|
||||
expect(result).toEqual(fakeResult);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user