- 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>
95 lines
3.8 KiB
TypeScript
95 lines
3.8 KiB
TypeScript
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],
|
||
]);
|
||
});
|
||
});
|