/** * A row lighting up where an asset is listed, without being selected (#221, Unity's ping). The row * itself needs text measurement, which Node lacks – e2e 28l-ii looks at it in the browser. */ import { describe, expect, it } from 'vitest'; import { EditorState } from '../../src/editor/state'; import { type ListItem, PING_MS, pingAlpha, sameListItem } from '../../src/ui/widgets/ListView'; describe('pingAlpha', () => { it('holds full for the first fifth, then fades to nothing at PING_MS', () => { const full = pingAlpha(0); expect(full).toBeGreaterThan(0); expect(pingAlpha(PING_MS / 5)).toBe(full); expect(pingAlpha(PING_MS * 0.6)).toBeCloseTo(full / 2); expect(pingAlpha(PING_MS * 0.9)).toBeLessThan(pingAlpha(PING_MS * 0.6)); expect(pingAlpha(PING_MS)).toBe(0); expect(pingAlpha(-1)).toBe(0); }); }); describe('sameListItem (#347)', () => { it('keeps a row only while everything it draws is the same', () => { const row: ListItem = { id: 'a', label: 'Crate', hint: '2', depth: 1, icon: '', marks: [''] }; expect(sameListItem(row, { ...row, marks: [''] })).toBe(true); expect( sameListItem({ id: 'a', label: 'Crate' }, { id: 'a', label: 'Crate', depth: 0, overridden: false }), ).toBe(true); const changes: Partial[] = [ { id: 'b' }, { label: 'Box' }, { hint: '3' }, { depth: 2 }, { expanded: true }, { overridden: true }, { icon: '' }, { iconAtEnd: true }, { heading: true }, { marks: [] }, { marks: [''] }, ]; for (const change of changes) expect(sameListItem(row, { ...row, ...change })).toBe(false); }); }); describe('EditorState.pingAsset', () => { it('names the asset and tells the listeners, but leaves the selection alone', () => { const state = new EditorState(); state.select({ kind: 'asset', assetId: 'sprite' }); const heard: string[] = []; state.on('ping', () => heard.push(state.pingedAssetId ?? '')); state.on('selection', () => heard.push('selection')); state.on('open', () => heard.push('open')); state.pingAsset('texture'); expect(heard).toEqual(['texture']); expect(state.selection).toEqual({ kind: 'asset', assetId: 'sprite' }); }); });