tests: co-locate every Vitest suite next to its subject under src/

Eliminate the parallel `tests/` tree. Each `*.test.ts` / `*.test.tsx`
now sits in the same directory as the module it covers, mirroring its
filename (`Foo.ts` ↔ `Foo.test.ts`). The renderer-SDK mock used by
component / hook tests moves to `src/__mocks__/nitro-renderer.ts` and
the Vitest setup file becomes `src/test-setup.ts` — both still wired
through `vitest.config.mts` exactly as before, only the paths changed.

All 13 suites + 178/178 cases still pass. The production build is
unaffected: rollup only follows imports from `src/index.tsx` and never
crosses into `.test.ts` files, so test code is naturally tree-shaken
out of the bundle. `yarn build` output is byte-for-byte the same on
the user-facing chunks.

tsconfig drops the now-redundant `tests` include entry. CLAUDE.md
'Layout convention' replaces the old `tests/` row with three rows
documenting the new co-located convention, the `__mocks__/` directory
and the `test-setup.ts` entry; ARCHITECTURE.md picks up the same
update. The 'DO NOT CHANGE' qualifier on the layout is preserved —
this rewrite IS the change, decided deliberately to make tests a
first-class part of the source tree rather than a sibling project.
This commit is contained in:
simoleo89
2026-05-16 11:35:03 +02:00
parent eb8d87969d
commit 8b4308af16
19 changed files with 47 additions and 46 deletions
@@ -0,0 +1,56 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { useRoomCreatorStore } from './navigatorRoomCreatorStore';
describe('useRoomCreatorStore', () =>
{
beforeEach(() =>
{
vi.useFakeTimers();
useRoomCreatorStore.setState({ isCreating: false });
});
afterEach(() =>
{
vi.useRealTimers();
});
it('starts with isCreating === false', () =>
{
expect(useRoomCreatorStore.getState().isCreating).toBe(false);
});
it('beginCreate() latches isCreating to true', () =>
{
useRoomCreatorStore.getState().beginCreate();
expect(useRoomCreatorStore.getState().isCreating).toBe(true);
});
it('isCreating auto-resets to false after the 5s lockout', () =>
{
useRoomCreatorStore.getState().beginCreate();
expect(useRoomCreatorStore.getState().isCreating).toBe(true);
vi.advanceTimersByTime(4999);
expect(useRoomCreatorStore.getState().isCreating).toBe(true);
vi.advanceTimersByTime(1);
expect(useRoomCreatorStore.getState().isCreating).toBe(false);
});
it('a second beginCreate() resets the lockout timer (no double-fire)', () =>
{
useRoomCreatorStore.getState().beginCreate();
vi.advanceTimersByTime(4000);
// Re-entry restarts the 5s window
useRoomCreatorStore.getState().beginCreate();
// At t=4500 (500ms past the second call), we should still be locked
vi.advanceTimersByTime(500);
expect(useRoomCreatorStore.getState().isCreating).toBe(true);
// Only after another 4500ms (total 5000 since the second call)
vi.advanceTimersByTime(4500);
expect(useRoomCreatorStore.getState().isCreating).toBe(false);
});
});