import { describe, it, expect } from 'vitest' import { findMerges } from '../../../composables/autoGroup/cooccurrence' import type { ClassSchema } from '../../../types/auto-group' const schema = (overrides: Partial = {}): ClassSchema => ({ classKind: 'biological', columns: [ { index: 0, name: 'A', sourceIndices: [0], uniqueValues: ['SAM'], cardinality: 1, role: 'factor' }, { index: 1, name: 'B', sourceIndices: [1], uniqueValues: ['SAH'], cardinality: 1, role: 'factor' }, ], groupBy: [], ...overrides, }) describe('findMerges', () => { it('suggests merging SAM + SAH when both columns are factors and mutually paired', () => { const s = schema({ columns: [ { index: 0, name: 'A', sourceIndices: [0], uniqueValues: ['SAM', 'WT'], cardinality: 2, role: 'factor' }, { index: 1, name: 'B', sourceIndices: [1], uniqueValues: ['SAH', 'CTL'], cardinality: 2, role: 'factor' }, ], }) const rows = [ ['SAM', 'SAH'], ['SAM', 'SAH'], ['SAM', 'SAH'], ['SAM', 'SAH'], ['WT', 'CTL'], ['WT', 'CTL'], ['WT', 'CTL'], ['WT', 'CTL'], ] const out = findMerges(s, rows) expect(out.length).toBe(1) expect(out[0].columnIndices).toEqual([0, 1]) expect(out[0].confidence).toBeGreaterThanOrEqual(0.95) }) it('rejects merge between two adjacent constants (no factor among them)', () => { const s = schema({ columns: [ { index: 0, name: 'A', sourceIndices: [0], uniqueValues: ['exp281'], cardinality: 1, role: 'constant' }, { index: 1, name: 'B', sourceIndices: [1], uniqueValues: ['260415'], cardinality: 1, role: 'constant' }, ], }) const rows = Array.from({ length: 10 }, () => ['exp281', '260415']) expect(findMerges(s, rows)).toEqual([]) }) it('rejects asymmetric pairing (forward functional but not backward)', () => { const s = schema({ columns: [ { index: 0, name: 'A', sourceIndices: [0], uniqueValues: ['a', 'b'], cardinality: 2, role: 'factor' }, { index: 1, name: 'B', sourceIndices: [1], uniqueValues: ['x'], cardinality: 1, role: 'constant' }, ], }) const rows = [ ['a', 'x'], ['a', 'x'], ['b', 'x'], ['b', 'x'], ] expect(findMerges(s, rows)).toEqual([]) }) it('rejects suggestions when class size < 4', () => { const s = schema({ columns: [ { index: 0, name: 'A', sourceIndices: [0], uniqueValues: ['a', 'b'], cardinality: 2, role: 'factor' }, { index: 1, name: 'B', sourceIndices: [1], uniqueValues: ['x', 'y'], cardinality: 2, role: 'factor' }, ], }) const rows = [ ['a', 'x'], ['b', 'y'], ['a', 'x'], ] expect(findMerges(s, rows)).toEqual([]) }) it('rejects merge that would collapse two adjacent factors into a single constant', () => { const s = schema({ columns: [ { index: 0, name: 'A', sourceIndices: [0], uniqueValues: ['x'], cardinality: 1, role: 'factor' }, { index: 1, name: 'B', sourceIndices: [1], uniqueValues: ['y'], cardinality: 1, role: 'factor' }, ], }) const rows = Array.from({ length: 6 }, () => ['x', 'y']) expect(findMerges(s, rows)).toEqual([]) }) })