Files
Pier_v1/tests/parse.test.ts
T
ypshimandClaude Haiku 5.5 727cd3b2e2 feat(parse): join pier, IP, and bearing tables across sheets by 교각명
- one workbook may hold the three tables on separate sheets (user decision,
  recorded in DOC/03_설계); spec 2.2 one-sheet-per-pier is superseded
- E05 for rows whose 교각명 has no matching 교각 정보 row, or a pier missing IP/받침
- helper sheets (IP only, 받침 only) are shown as 보조 표 시트, not selectable
- test: three-sheet workbook built from the P1 sheet

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-21 17:59:26 +09:00

95 lines
3.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import * as XLSX from 'xlsx';
import { describe, expect, it } from 'vitest';
import { parseWorkbook } from '../src/core/parseWorkbook';
import { loadP1, loadWorkbook } from './helpers';
describe('parseWorkbook (P1 sheet intent.PR)', () => {
it('finds exactly one pier P1 with the input values of the sheet', () => {
const { piers, issues } = parseWorkbook(loadWorkbook());
expect(issues).toEqual([]);
expect(piers.map((p) => p.name)).toEqual(['P1']);
const p1 = loadP1();
expect(p1.type).toBe('T형');
expect(p1.foundationType).toBe('말뚝기초');
expect(p1.copingTopEl).toBeCloseTo(43.411, 6);
expect(p1.footingBottomEl).toBeCloseTo(26.208, 6);
expect(p1.groundEl).toBeCloseTo(28.931, 6);
expect(p1.pileLengthMm).toBe(24000);
expect(p1.copingWidthMm).toBe(3100);
expect(p1.copingLengthMm).toBe(12000);
expect(p1.columnCount).toBe(1);
});
it('reads 4 IP points and 10 bearings (5 front, 5 back)', () => {
const p1 = loadP1();
expect(p1.ips.map((p) => p.name)).toEqual(['IP1', 'IP2', 'IP3', 'IP4']);
expect(p1.bearings).toHaveLength(10);
expect(p1.bearings.filter((b) => b.row === '전열')).toHaveLength(5);
expect(p1.bearings.filter((b) => b.row === '후열')).toHaveLength(5);
});
it('converts the bearing azimuth strings to decimal degrees', () => {
const p1 = loadP1();
expect(p1.bearings[0].azimuthDeg).toBeCloseTo(75.9489, 4);
});
});
describe('sheet report (spec §2.3)', () => {
it('marks the P1 sheet as selectable and counts its tables', () => {
const { sheets } = parseWorkbook(loadWorkbook());
expect(sheets).toHaveLength(1);
expect(sheets[0]).toMatchObject({ name: 'intent.PR', ok: true, piers: 1, tables: { pier: 1, ip: 1, bearing: 1 } });
});
it('marks a sheet with a bad azimuth (E03) as not selectable and drops its pier', () => {
const wb = loadWorkbook();
wb.Sheets['intent.PR']['F32'].v = '75.9';
const { piers, sheets, issues } = parseWorkbook(wb);
expect(issues.map((i) => i.code)).toContain('E03');
expect(sheets[0].ok).toBe(false);
expect(piers).toHaveLength(0);
});
});
describe('tables split across sheets (spec §2.2: 시트 1장 = 교각 1기)', () => {
it('reports E05 and drops the pier when the IP table is not on the same sheet', () => {
const wb = loadWorkbook();
wb.Sheets['intent.PR']['B25'].v = '기타';
const { piers, sheets, issues } = parseWorkbook(wb);
expect(issues.map((i) => i.code)).toContain('E05');
expect(piers).toHaveLength(0);
expect(sheets[0].ok).toBe(false);
});
});
describe('three-sheet input (교각 · IP · 받침 on separate sheets, joined by 교각명)', () => {
/** Splits the P1 sheet into the three sheets the user prepares: rows 22–23, 25–29, 31–41 (1-based). */
function threeSheets(): XLSX.WorkBook {
const src = loadWorkbook();
const grid = XLSX.utils.sheet_to_json<(string | number | null)[]>(src.Sheets['intent.PR'], {
header: 1,
raw: true,
defval: null,
});
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, XLSX.utils.aoa_to_sheet(grid.slice(21, 23)), '교각');
XLSX.utils.book_append_sheet(wb, XLSX.utils.aoa_to_sheet(grid.slice(24, 29)), 'IP');
XLSX.utils.book_append_sheet(wb, XLSX.utils.aoa_to_sheet(grid.slice(30, 41)), '받침');
return wb;
}
it('joins the three sheets into one pier with 4 IP points and 10 bearings', () => {
const { piers, issues, sheets } = parseWorkbook(threeSheets());
expect(issues).toEqual([]);
expect(piers).toHaveLength(1);
expect(piers[0]).toMatchObject({ name: 'P1', sheet: '교각' });
expect(piers[0].ips).toHaveLength(4);
expect(piers[0].bearings).toHaveLength(10);
expect(sheets.map((s) => [s.name, s.ok, s.piers])).toEqual([
['교각', true, 1],
['IP', true, 0],
['받침', true, 0],
]);
});
});