tests: consolidate into tests/ dirs, fix import paths

Move all test files out of source dirs into per-workspace tests/:
- shared/tests/   (3 unit test files)
- server/tests/   (1 integration test)
- src/tests/      (8 characterization + scenario tests + testHelpers)

Fix all relative import paths (App, storage, __mocks__, testHelpers).
Fix jest.config testMatch globs in shared/ and server/ (rootDir +
<rootDir>/tests pattern).

Delete scripts/repro-pause-bug.js (debug scratch, superseded by
turn.pause-add.test.js).

Keep scripts/replay-combat.js + scripts/audit-rotation.js as manual
demo/exploratory tools (NOT unit tests, not deterministic).

No logic changes. All green: shared 49 + 1 validated RED, server 23,
FE 62. Scenario test unchanged (240s timeout, pre-existing slow).
This commit is contained in:
david raistrick
2026-06-29 16:02:22 -04:00
parent 33e0e52789
commit f81308a0df
16 changed files with 26 additions and 100 deletions
@@ -6,7 +6,7 @@
import React from 'react';
import { screen, fireEvent, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom';
import { getCalls, MOCK_DB } from './__mocks__/firebase/_mock-db';
import { getCalls, MOCK_DB } from '../__mocks__/firebase/_mock-db';
import { renderApp, createCampaignViaUI, selectCampaignByName } from './testHelpers';
function findCall(fn, pathSub) {
@@ -3,7 +3,7 @@
import React from 'react';
import { screen, fireEvent, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom';
import { getCalls } from './__mocks__/firebase/_mock-db';
import { getCalls } from '../__mocks__/firebase/_mock-db';
import { setupReady, addMonsterViaUI, startCombatViaUI } from './testHelpers';
function findCallsEnc() {
@@ -10,12 +10,12 @@
import React from 'react';
import { screen, fireEvent, waitFor, within } from '@testing-library/react';
import '@testing-library/jest-dom';
import App from './App';
import App from '../App';
import {
renderApp, createCampaignViaUI, selectCampaignByName,
createEncounterViaUI, selectEncounterByName, addMonsterViaUI, setupReady,
} from './testHelpers';
import { getCalls, MOCK_DB } from './__mocks__/firebase/_mock-db';
import { getCalls, MOCK_DB } from '../__mocks__/firebase/_mock-db';
// ---------- scenario helpers (UI only, same buttons as human) ----------
@@ -6,9 +6,9 @@
import React from 'react';
import { render, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom';
import App from './App';
import { MOCK_DB } from './__mocks__/firebase/_mock-db';
import { getAdapterCalls, resetAdapterCalls } from './storage/firebase';
import App from '../App';
import { MOCK_DB } from '../__mocks__/firebase/_mock-db';
import { getAdapterCalls, resetAdapterCalls } from '../storage/firebase';
// Seed activeDisplay + campaign + encounter so DisplayView has data to subscribe to.
function seedActiveDisplay() {
@@ -3,7 +3,7 @@
import React from 'react';
import { screen, fireEvent, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom';
import { getCalls } from './__mocks__/firebase/_mock-db';
import { getCalls } from '../__mocks__/firebase/_mock-db';
import { renderApp, createCampaignViaUI, selectCampaignByName, createEncounterViaUI, selectEncounterByName } from './testHelpers';
function findCall(fn, pathSub) {
@@ -3,7 +3,7 @@
import React from 'react';
import { screen, fireEvent, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom';
import { getCalls } from './__mocks__/firebase/_mock-db';
import { getCalls } from '../__mocks__/firebase/_mock-db';
import { setupReady, addMonsterViaUI, startCombatViaUI } from './testHelpers';
function findLogCalls() {
@@ -16,7 +16,7 @@ function lastEncCall() {
// Navigate to /logs view. App reads pathname at mount; must re-render with path preset.
import { render } from '@testing-library/react';
import App from './App';
import App from '../App';
async function goToLogs() {
// unmount current tree isn't needed; App checks pathname in useEffect.
// Re-render a fresh App instance in same container.
@@ -3,7 +3,7 @@
import React from 'react';
import { screen, fireEvent, waitFor, within } from '@testing-library/react';
import '@testing-library/jest-dom';
import { getCalls } from './__mocks__/firebase/_mock-db';
import { getCalls } from '../__mocks__/firebase/_mock-db';
import { setupReady, addMonsterViaUI, getParticipantForm, startCombatViaUI } from './testHelpers';
function findCallsEnc() {
@@ -2,7 +2,7 @@
// TDD: contract = spec. Run against memory first. RED until memory.js built.
'use strict';
const { runStorageContract } = require('./contract');
const { createMemoryStorage } = require('./memory');
const { runStorageContract } = require('../storage/contract');
const { createMemoryStorage } = require('../storage/memory');
runStorageContract('memory', () => createMemoryStorage());
@@ -1,8 +1,8 @@
// test helpers: drive App UI to states. Used across characterization suites.
import React from 'react';
import { render, screen, fireEvent, waitFor, within } from '@testing-library/react';
import App from './App';
import { MOCK_DB } from './__mocks__/firebase/_mock-db';
import App from '../App';
import { MOCK_DB } from '../__mocks__/firebase/_mock-db';
// Scoped container: the "Add Participants" section (avoids label clashes with CharacterManager).
export function getParticipantForm() {
@@ -34,7 +34,7 @@ export async function createCampaignViaUI(name = 'Test Campaign') {
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');
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
@@ -53,7 +53,7 @@ export async function createEncounterViaUI(name = 'Test Encounter') {
await waitFor(() => screen.getByLabelText(/Encounter Name/i));
fireEvent.change(screen.getByLabelText(/Encounter Name/i), { target: { value: name } });
fireEvent.click(screen.getByRole('button', { name: /^Create$/i }));
const { getCalls } = require('./__mocks__/firebase/_mock-db');
const { getCalls } = require('../__mocks__/firebase/_mock-db');
await waitFor(() => getCalls().find(c => c.fn === 'setDoc' && c.path.includes('/encounters/')));
const call = getCalls().find(c => c.fn === 'setDoc' && c.path.includes('/encounters/'));
return call.path.split('/').pop();
@@ -73,7 +73,7 @@ export async function addMonsterViaUI(name = 'Goblin', maxHp = 7, initMod = 2) {
fireEvent.change(form.getByLabelText(/Init Mod/i), { target: { value: String(initMod) } });
fireEvent.change(form.getByLabelText(/Max HP/i), { target: { value: String(maxHp) } });
fireEvent.click(form.getByRole('button', { name: /Add to Encounter/i }));
const { getCalls } = require('./__mocks__/firebase/_mock-db');
const { getCalls } = require('../__mocks__/firebase/_mock-db');
await waitFor(() => {
const calls = getCalls().filter(c => c.fn === 'updateDoc' && c.path.includes('/encounters/'));
const last = calls[calls.length - 1];
@@ -93,7 +93,7 @@ export async function setupReady(campName = 'Camp', encName = 'Enc') {
// Start combat. Assumes encounter selected with active participants.
export async function startCombatViaUI() {
fireEvent.click(screen.getByRole('button', { name: /Start Combat/i }));
const { getCalls } = require('./__mocks__/firebase/_mock-db');
const { getCalls } = require('../__mocks__/firebase/_mock-db');
await waitFor(() => {
const calls = getCalls().filter(c => c.fn === 'updateDoc' && c.path.includes('/encounters/'));
const last = calls[calls.length - 1];