import { nextTick } from 'vue' import { beforeEach, describe, expect, it, vi } from 'vitest' const mockGet = vi.fn() const mockPut = vi.fn() const mockDelete = vi.fn() const mockUseApi = vi.fn((_options?: unknown) => ({ get: mockGet, put: mockPut, delete: mockDelete, })) vi.mock('../../composables/useApi', () => ({ useApi: (options: unknown) => mockUseApi(options), })) import { useBioTemplatePresetWorkspace } from '../../composables/useBioTemplatePresetWorkspace' import { extractTemplateCollection, } from '../../templates' import type { PlateMapTemplate, } from '../../templates' describe('useBioTemplatePresetWorkspace', () => { beforeEach(() => { vi.clearAllMocks() mockGet.mockResolvedValue({}) mockPut.mockResolvedValue({}) mockDelete.mockResolvedValue({}) window.history.replaceState({}, '', '/') }) it('creates controls, renderer props, and component bindings from one preset id', () => { const workspace = useBioTemplatePresetWorkspace('wellplate-screen') expect(workspace.presetId).toBe('wellplate-screen') expect(workspace.presetInfo.value?.label).toBe('Well-plate screen') expect(workspace.presetLabel.value).toBe('Well-plate screen') expect(workspace.collection.value.metadata?.preset).toBe('wellplate-screen') expect(workspace.controlSchema).toBe(workspace.controls.controls) expect(workspace.controlValues.value.sampleNames).toEqual(['Control', 'Treatment']) expect(workspace.sidebar.panels.design.map(panel => panel.id)).toContain('dose') expect(workspace.form.modelValue).toBe(workspace.controlValues.value) expect(workspace.sidebar.modelValue).toBe(workspace.controlValues.value) expect(workspace.sidebar.values).toBe(workspace.controlValues.value) expect(workspace.sidebar.activeView).toBe('design') expect(workspace.pillNav.items).toEqual(workspace.controls.viewItems) expect(workspace.pillNav.currentItemId).toBe('design') expect(workspace.topBarSettings.settingsConfig.values).toBe(workspace.controlValues.value) expect(workspace.bindings.form).toBe(workspace.form) expect(workspace.bindings.sidebar).toBe(workspace.sidebar) expect(workspace.bindings.topBarSettings).toBe(workspace.topBarSettings) expect(workspace.bindings.pillNav).toBe(workspace.pillNav) expect(workspace.bindings.topBar.value.currentPillId).toBe('design') expect(workspace.controlViewIds.value).toEqual(['design']) expect(workspace.controlViewItems.value).toEqual([{ id: 'design', label: 'Design' }]) expect(workspace.activeControlView.value).toBe('design') expect(workspace.renderer.value.target).toBe(workspace.collection.value) expect(workspace.bindings.renderer.value.target).toBe(workspace.collection.value) expect(workspace.componentBindings.value.map(binding => binding.component)).toContain('DoseCalculator') expect(workspace.componentBindingsById.value['dose-response:DoseCalculator'].component).toBe('DoseCalculator') expect(workspace.componentBindingsById.value['dose-response:DoseCalculator'].props.mode).toBe('serial') expect(workspace.componentProps.value.map(binding => binding.component)).toContain('WellPlate') expect(workspace.componentPropsById.value['dose-response:DoseCalculator'].mode).toBe('serial') expect(workspace.bindings.componentPropsById.value['dose-response:DoseCalculator'].mode).toBe('serial') expect(workspace.bindings.componentBindingsById.value['dose-response:DoseCalculator'].props.mode).toBe('serial') expect(workspace.componentPropsByComponent.value.WellPlate).toHaveLength(2) expect(workspace.getComponentProps('DoseCalculator')?.mode).toBe('serial') expect(workspace.bindings.getComponentProps('DoseCalculator')?.mode).toBe('serial') expect(workspace.componentUsage.value?.template).toContain(' { const workspace = useBioTemplatePresetWorkspace('lcms-batch') expect(workspace.controlViewIds.value).toEqual(['run', 'analysis']) expect(workspace.controlViewItems.value).toEqual([ { id: 'run', label: 'Run' }, { id: 'analysis', label: 'Analysis' }, ]) expect(workspace.activeControlView.value).toBe('run') workspace.setActiveControlView('analysis') expect(workspace.activeControlView.value).toBe('analysis') expect(workspace.sidebar.activeView).toBe('analysis') expect(workspace.topBar.value.currentPillId).toBe('analysis') expect(workspace.pillNav.currentItemId).toBe('analysis') workspace.setActiveControlView('missing') expect(workspace.activeControlView.value).toBe('analysis') }) it('exposes live FormBuilder, AppSidebar, AppTopBar, and pillNav bindings', () => { const workspace = useBioTemplatePresetWorkspace('lcms-batch') workspace.form['onUpdate:modelValue']({ ...workspace.controlValues.value, operator: 'Ada', }) expect(workspace.controlValues.value.operator).toBe('Ada') expect(workspace.form.modelValue).toBe(workspace.controlValues.value) expect(workspace.sidebar.values).toBe(workspace.controlValues.value) expect(workspace.topBarSettings.settingsConfig.values).toBe(workspace.controlValues.value) workspace.pillNav.onSelect({ id: 'analysis', label: 'Analysis' }) expect(workspace.activeControlView.value).toBe('analysis') expect(workspace.sidebar.activeView).toBe('analysis') expect(workspace.topBar.value.currentPillId).toBe('analysis') expect(workspace.bindings.topBar.value.currentPillId).toBe('analysis') workspace.topBar.value.onPillSelect({ id: 'run', label: 'Run' }) expect(workspace.activeControlView.value).toBe('run') expect(workspace.pillNav.currentItemId).toBe('run') expect(workspace.bindings.topBar.value.currentPillId).toBe('run') }) it('accepts direct initial values for generated preset controls and collection data', () => { const workspace = useBioTemplatePresetWorkspace('wellplate-screen', { controlOptions: { initialValues: { sampleNames: ['Nested default'], unit: 'uM', }, }, initialValues: { sampleNames: ['Vehicle', 'Drug'], unit: 'nM', }, }) const plate = extractTemplateCollection(workspace.collection.value)['plate-map'] as PlateMapTemplate expect(workspace.controlValues.value.sampleNames).toEqual(['Vehicle', 'Drug']) expect(workspace.controlValues.value.unit).toBe('nM') expect(plate.data.samples.map(sample => sample.name)).toEqual(['Vehicle', 'Drug']) }) it('rebuilds the template collection when generated controls change', async () => { const workspace = useBioTemplatePresetWorkspace('wellplate-screen') workspace.controlValues.value = { ...workspace.controlValues.value, sampleNames: ['Vehicle', 'Drug'], } await nextTick() const plate = extractTemplateCollection(workspace.collection.value)['plate-map'] as PlateMapTemplate expect(plate.data.samples.map(sample => sample.name)).toEqual(['Vehicle', 'Drug']) }) it('sets, updates, and resets generated control values without direct ref mutation', () => { const workspace = useBioTemplatePresetWorkspace('wellplate-screen') const setCollection = workspace.setControlValues({ sampleNames: ['Vehicle', 'Drug'], unit: 'nM', replicates: 2, }) let plate = extractTemplateCollection(setCollection)['plate-map'] as PlateMapTemplate expect(workspace.collection.value).toBe(setCollection) expect(workspace.controlValues.value).toEqual({ sampleNames: ['Vehicle', 'Drug'], unit: 'nM', replicates: 2, }) expect(plate.data.samples.map(sample => sample.name)).toEqual(['Vehicle', 'Drug']) const updatedCollection = workspace.updateControlValues({ sampleNames: ['Updated'] }) plate = extractTemplateCollection(updatedCollection)['plate-map'] as PlateMapTemplate expect(workspace.collection.value).toBe(updatedCollection) expect(workspace.controlValues.value.unit).toBe('nM') expect(workspace.controlValues.value.sampleNames).toEqual(['Updated']) expect(plate.data.samples.map(sample => sample.name)).toEqual(['Updated']) const resetCollection = workspace.resetToDefaultCollection() plate = extractTemplateCollection(resetCollection)['plate-map'] as PlateMapTemplate expect(workspace.collection.value).toBe(resetCollection) expect(workspace.controlValues.value.sampleNames).toEqual(['Control', 'Treatment']) expect(plate.data.samples.map(sample => sample.name)).toEqual(['Control', 'Treatment']) }) it('saves the generated collection through current experiment wiring', async () => { window.history.replaceState({}, '', '/experiments/42/templates') const workspace = useBioTemplatePresetWorkspace('lcms-batch', { pluginId: 'p1' }) const ok = await workspace.saveCurrent() expect(ok).toBe(true) expect(mockPut).toHaveBeenCalledWith('/experiments/42/data', { plugin_id: 'p1', data: workspace.collection.value, schema_version: '1.0', }) }) })