import { describe, expect, it } from 'vitest'; import * as THREE from 'three'; import { buildPier } from '../src/core/geometry'; import { DIAMETER_GROUPS, diameterGroupIndex, memberOfBar } from '../src/core/rebar/color'; import { buildRebar3D } from '../src/view/rebar3d'; import { loadP1 } from './helpers'; const rb = buildRebar3D(buildPier(loadP1())); const colorOf = (name: string) => (rb.byName.get(name)![0].material as THREE.MeshStandardMaterial).color.getHex(); describe('③ 3D 색 기준 (spec §6.7 승인 2026-10-23)', () => { it('every bar of P1 belongs to a known member (none falls into 기타)', () => { const names = [...rb.byName.keys()]; expect(names.filter((n) => memberOfBar(n) === 'other')).toEqual([]); }); it('H and S of the same size share one diameter group; a non-rebar diameter has none', () => { expect(DIAMETER_GROUPS[diameterGroupIndex(15.9)].label).toBe('H16 · S16'); expect(DIAMETER_GROUPS[diameterGroupIndex(25.4)].label).toBe('H25 · S25'); expect(DIAMETER_GROUPS).toHaveLength(8); expect(diameterGroupIndex(60)).toBe(-1); }); it('role is the default colour; diameter and member modes recolour every bar and can switch back', () => { const role = colorOf('C1'); rb.setColorMode('member'); expect(colorOf('C1')).not.toBe(role); rb.setColorMode('diameter'); expect(colorOf('C1')).not.toBe(role); rb.setColorMode('role'); expect(colorOf('C1')).toBe(role); }); it('member mode: all bars of one member share one colour', () => { rb.setColorMode('member'); expect(colorOf('C1')).toBe(colorOf('C14')); expect(colorOf('P1')).toBe(colorOf('P6')); expect(colorOf('C1')).not.toBe(colorOf('P1')); rb.setColorMode('role'); }); it('diameter mode: bars of one size share a colour, a different size does not (C1 and C7 are H29, C9 is H25)', () => { rb.setColorMode('diameter'); expect(colorOf('C1')).toBe(colorOf('C7')); expect(colorOf('C1')).not.toBe(colorOf('C9')); rb.setColorMode('role'); }); it('legend lists only the items the model has; role mode has none', () => { expect(rb.legend('role')).toEqual([]); expect(rb.legend('member').map((i) => i.label)).toEqual(['받침블럭', '코핑', '기둥', '확대기초']); const sizes = rb.legend('diameter').map((i) => i.label); expect(sizes.length).toBeGreaterThan(0); expect(sizes.length).toBeLessThanOrEqual(8); }); });