test: campaign characterization (7 tests)

- src/testHelpers.js: renderApp, createCampaignViaUI, selectCampaignByName
- App.characterization.test.js: createCampaign, addCharacter, updateCharacter, deleteCharacter, deleteCampaign + path namespace + bg url
- mock firestore writeBatch sync (was async, app no-await)

Locks path + payload shape per action. Refactor guard.
This commit is contained in:
david raistrick
2026-06-28 18:12:27 -04:00
parent 84dd17e174
commit b6555648ee
3 changed files with 151 additions and 41 deletions
+37
View File
@@ -0,0 +1,37 @@
// test helpers: drive App UI to states. Used across characterization suites.
import React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import App from './App';
import { MOCK_DB } from './__mocks__/firebase/_mock-db';
// Render app, wait for auth + campaign list.
export async function renderApp() {
window.history.replaceState({}, '', '/');
global.alert = jest.fn();
window.open = jest.fn();
const utils = render(<App />);
await waitFor(() => screen.getByRole('button', { name: /Create Campaign/i }));
return utils;
}
// Open create-campaign modal, fill name, submit. Returns campaign id from recorded call.
export async function createCampaignViaUI(name = 'Test Campaign') {
fireEvent.click(screen.getByRole('button', { name: /Create Campaign/i }));
await waitFor(() => screen.getByLabelText(/Campaign Name/i));
fireEvent.change(screen.getByLabelText(/Campaign Name/i), { target: { value: name } });
fireEvent.click(screen.getByRole('button', { name: /^Create$/i }));
// wait for setDoc recorded
const { getCalls } = require('./__mocks__/firebase/_mock-db');
await waitFor(() => getCalls().find(c => c.fn === 'setDoc' && c.path.includes('/campaigns/')));
const call = getCalls().find(c => c.fn === 'setDoc' && c.path.includes('/campaigns/'));
return call.path.split('/').pop(); // campaign id
}
// Click campaign card by name to select it. Returns selected campaign id.
export async function selectCampaignByName(name) {
const card = await waitFor(() => screen.getByText(name));
fireEvent.click(card);
await waitFor(() => screen.getByText(/Managing:/i));
}
export { MOCK_DB };