diff --git a/src/app/pages/algorithms/fluid/fluid-simulation.spec.ts b/src/app/pages/algorithms/fluid/fluid-simulation.spec.ts index ecf2e2a..dc362a1 100644 --- a/src/app/pages/algorithms/fluid/fluid-simulation.spec.ts +++ b/src/app/pages/algorithms/fluid/fluid-simulation.spec.ts @@ -1,4 +1,4 @@ -import {FluidParams, FluidSimulation} from './fluid-simulation'; +import type {FluidParams} from './fluid-simulation'; import {DEFAULT_SETTINGS, MAX_PRESSURE_ITERATIONS, Splat} from './fluid.model'; const renderCalls: string[] = []; @@ -62,7 +62,11 @@ function params(pressureIterations: number, splats: Splat[] = []): FluidParams { return {settings: {...DEFAULT_SETTINGS, pressureIterations}, splats}; } -function start(readParams: () => FluidParams) { +// gpu-state.ts is shared between specs and keeps the @babylonjs/core of whichever spec loaded it first (the real +// one, or another spec's mock). A fresh module graph per test makes it use this spec's mock. +async function start(readParams: () => FluidParams) { + vi.resetModules(); + const {FluidSimulation} = await import('./fluid-simulation'); renderCalls.length = 0; disposedTargets = 0; disposedWrappers = 0; @@ -78,9 +82,9 @@ function count(name: string): number { } describe('FluidSimulation', () => { - it('drawsNothingUntilAllShadersReady', () => { + it('drawsNothingUntilAllShadersReady', async () => { const readParams = vi.fn(() => params(1, [splat])); - const {scene} = start(readParams); + const {scene} = await start(readParams); ready['fluidAdvect'] = false; scene.frame(); @@ -93,9 +97,9 @@ describe('FluidSimulation', () => { expect(renderCalls).toContain('fluidSplat'); }); - it('readsParamsAtFrameStart', () => { + it('readsParamsAtFrameStart', async () => { let iterations = 5; - const {scene} = start(() => params(iterations)); + const {scene} = await start(() => params(iterations)); scene.frame(); expect(count('fluidPressure')).toBe(5); @@ -105,14 +109,14 @@ describe('FluidSimulation', () => { expect(count('fluidPressure')).toBe(12); }); - it('clampsPressureIterations', () => { - const {scene} = start(() => params(1000)); + it('clampsPressureIterations', async () => { + const {scene} = await start(() => params(1000)); scene.frame(); expect(count('fluidPressure')).toBe(MAX_PRESSURE_ITERATIONS); }); - it('passOrder', () => { - const {scene} = start(() => params(2, [splat])); + it('passOrder', async () => { + const {scene} = await start(() => params(2, [splat])); scene.frame(); renderCalls.length = 0; scene.frame(); @@ -123,8 +127,8 @@ describe('FluidSimulation', () => { ]); }); - it('resetClearsBeforeSplats', () => { - const {scene, simulation} = start(() => params(1, [splat])); + it('resetClearsBeforeSplats', async () => { + const {scene, simulation} = await start(() => params(1, [splat])); scene.frame(); renderCalls.length = 0; scene.frame(); @@ -136,8 +140,8 @@ describe('FluidSimulation', () => { expect(renderCalls.slice(0, 4)).toEqual(['fluidClear', 'fluidClear', 'fluidClear', 'fluidSplat']); }); - it('disposeFreesAllTargets', () => { - const {simulation} = start(() => params(1)); + it('disposeFreesAllTargets', async () => { + const {simulation} = await start(() => params(1)); simulation.dispose(); expect(disposedTargets).toBe(8); expect(disposedWrappers).toBe(8); diff --git a/src/app/pages/algorithms/gray-scott/gray-scott-simulation.spec.ts b/src/app/pages/algorithms/gray-scott/gray-scott-simulation.spec.ts index 79e671a..c1a941f 100644 --- a/src/app/pages/algorithms/gray-scott/gray-scott-simulation.spec.ts +++ b/src/app/pages/algorithms/gray-scott/gray-scott-simulation.spec.ts @@ -1,4 +1,4 @@ -import {GrayScottParams, GrayScottSimulation} from './gray-scott-simulation'; +import type {GrayScottParams} from './gray-scott-simulation'; import {DEFAULT_SETTINGS} from './gray-scott.model'; const renderCalls: string[] = []; @@ -55,9 +55,13 @@ function paramsWithSteps(stepsPerFrame: number): GrayScottParams { } describe('GrayScottSimulation', () => { - it('readsParamsAtFrameStart', () => { + it('readsParamsAtFrameStart', async () => { let stepsPerFrame = 1; const scene = fakeScene(); + // gpu-state.ts is shared between specs and keeps the @babylonjs/core of whichever spec loaded it first; a fresh + // module graph makes it use this spec's mock. + vi.resetModules(); + const {GrayScottSimulation} = await import('./gray-scott-simulation'); const simulation = new GrayScottSimulation(); simulation.init(scene as never, {} as never, 'float', () => paramsWithSteps(stepsPerFrame)); scene.frame(); diff --git a/src/app/pages/algorithms/lenia/lenia-simulation.spec.ts b/src/app/pages/algorithms/lenia/lenia-simulation.spec.ts index cbd95f7..f6c3f15 100644 --- a/src/app/pages/algorithms/lenia/lenia-simulation.spec.ts +++ b/src/app/pages/algorithms/lenia/lenia-simulation.spec.ts @@ -1,4 +1,4 @@ -import {LeniaParams, LeniaSimulation} from './lenia-simulation'; +import type {LeniaParams} from './lenia-simulation'; import {DEFAULT_SETTINGS} from './lenia.model'; const renderCalls: {name: string; target: unknown}[] = []; @@ -64,11 +64,15 @@ function paramsWithSteps(stepsPerFrame: number): LeniaParams { } describe('LeniaSimulation', () => { - it('keepsSeedWhileStepShaderCompiles', () => { + it('keepsSeedWhileStepShaderCompiles', async () => { renderCalls.length = 0; ready['leniaCopy'] = true; ready['leniaStep'] = false; const scene = fakeScene(); + // gpu-state.ts is shared between specs and keeps the @babylonjs/core of whichever spec loaded it first; a fresh + // module graph makes it use this spec's mock. + vi.resetModules(); + const {LeniaSimulation} = await import('./lenia-simulation'); const simulation = new LeniaSimulation(); simulation.init(scene as never, {} as never, 'float', () => paramsWithSteps(1)); simulation.seed(new Uint8Array(4)); @@ -85,12 +89,16 @@ describe('LeniaSimulation', () => { expect(firstStep.target).not.toBe(seededTarget); }); - it('readsParamsAtFrameStart', () => { + it('readsParamsAtFrameStart', async () => { renderCalls.length = 0; ready['leniaCopy'] = true; ready['leniaStep'] = true; let stepsPerFrame = 1; const scene = fakeScene(); + // gpu-state.ts is shared between specs and keeps the @babylonjs/core of whichever spec loaded it first; a fresh + // module graph makes it use this spec's mock. + vi.resetModules(); + const {LeniaSimulation} = await import('./lenia-simulation'); const simulation = new LeniaSimulation(); simulation.init(scene as never, {} as never, 'float', () => paramsWithSteps(stepsPerFrame)); simulation.seed(new Uint8Array(4));