import { describe, it, expect } from 'vitest' import { splitMulti, pickPrimaryDelimiter, parseDateToken, tokenizeBatch } from '../../../composables/autoGroup/tokenize' describe('pickPrimaryDelimiter', () => { it('should pick underscore when underscore field counts are most consistent', () => { const lines = ['a_b_c', 'd_e_f', 'g_h_i'] expect(pickPrimaryDelimiter(lines)).toBe('_') }) it('should pick hyphen when underscore is absent but hyphen is consistent', () => { const lines = ['a-b-c', 'd-e-f'] expect(pickPrimaryDelimiter(lines)).toBe('-') }) it('should fall back to underscore when no delimiter splits anything', () => { const lines = ['abc', 'def'] expect(pickPrimaryDelimiter(lines)).toBe('_') }) }) describe('splitMulti', () => { it('should split a single sample on the primary delimiter', () => { expect(splitMulti('a_b_c', '_')).toEqual(['a', 'b', 'c']) }) it('should not re-split on secondary delimiters', () => { expect(splitMulti('a-b_c-d', '_')).toEqual(['a-b', 'c-d']) }) it('should handle empty string as a single empty token', () => { expect(splitMulti('', '_')).toEqual(['']) }) }) describe('parseDateToken', () => { it('should read the date when the token is YYMMDD', () => { expect(parseDateToken('250919')).toBe('2025-09-19') }) it('should read the date when the token is YYYYMMDD', () => { expect(parseDateToken('20250211')).toBe('2025-02-11') }) it('should read DDMMYYYY when the first four digits are not a year', () => { expect(parseDateToken('13102025')).toBe('2025-10-13') }) it('should read DDMMYY when the year-first reading is outside the plausible window', () => { expect(parseDateToken('091123')).toBe('2023-11-09') }) it('should return undefined when the token is not a date', () => { expect(parseDateToken('999999')).toBeUndefined() }) }) describe('tokenizeBatch', () => { it('should move the header out of the rows when all names share it', () => { const batch = tokenizeBatch(['exp031_250318_SU_105_DMSO_A_23', 'exp031_250318_SU_270_TFP_B_09']) expect(batch.rows).toEqual([['105', 'DMSO', 'A', '23'], ['270', 'TFP', 'B', '09']]) }) it('should read the header when the operator is before the date', () => { const batch = tokenizeBatch(['exp157_LT_13102025_214_KI_13', 'exp157_LT_13102025_215_WT_35']) expect(batch.experiment).toEqual({ code: 'exp157', date: '2025-10-13', operator: 'LT' }) }) it('should keep a header field in the row when the batch has two values', () => { const batch = tokenizeBatch(['exp280_260413_YS_Plasma_M10_031', 'exp281_260413_YS_Tissues_M10_085']) expect(batch.rows[0]).toEqual(['exp280', 'Plasma', 'M10', '031']) }) it('should read no header when a name has no experiment code and no date', () => { expect(tokenizeBatch(['WT_Ctrl_1', 'KO_Ctrl_2']).rows[0]).toEqual(['WT', 'Ctrl', '1']) }) it('should drop the last token when it is a 14-digit acquisition stamp', () => { const batch = tokenizeBatch(['WT_blank_011_20251003200301', 'KO_blank_012']) expect(batch.rows[0]).toEqual(['WT', 'blank', '011']) }) it('should count the shared tokens when all names share a title after the header', () => { const batch = tokenizeBatch(['exp114_250730_YY_HEK_Put_HMW_1-1_35', 'exp114_250730_YY_HEK_Put_MMW_2-1_36']) expect(batch.sharedPrefix).toBe(2) }) it('should keep a decimal point inside a token when the delimiter is an underscore', () => { expect(tokenizeBatch(['exp_drugA_0.1uM', 'exp_drugB_1uM']).rows[0]).toEqual(['exp', 'drugA', '0.1uM']) }) }) describe('tokenizeBatch review regressions', () => { it('should keep a caps token in the row when only some names carry it after the date', () => { const batch = tokenizeBatch(['exp021_250101_QC_1', 'exp021_250101_QC_2', 'exp021_250101_Ctrl_1', 'exp021_250101_Ctrl_2']) expect(batch.rows[0]).toEqual(['QC', '1']) }) it('should keep rows aligned when one genotype looks like operator initials', () => { const batch = tokenizeBatch(['exp021_250101_WT_1', 'exp021_250101_WT_2', 'exp021_250101_Het_1', 'exp021_250101_Het_2']) expect(batch.rows.map(row => row.length)).toEqual([2, 2, 2, 2]) }) it('should count no shared prefix when the names have no experiment header', () => { expect(tokenizeBatch(['QC_01', 'QC_02', 'QC_03']).sharedPrefix).toBe(0) }) it('should reject a date that is not in the calendar when the token has six digits', () => { expect(parseDateToken('250231')).toBeUndefined() }) })