feat(spreadsheet): 2단계 — 데이터 도구(텍스트 나누기·중복 제거·연속 채우기)
텍스트 나누기(구분 기호 탭·세미콜론·쉼표·공백·사용자 지정 또는 고정 폭 · 미리보기) · 중복된 항목 제거(비교할 열 고르기 · 머리글 포함 여부 · 지운 수를 토스트로 알림) · 채우기 연속 데이터(단계 값 · 끝 값 · 행/열 방향)를 새 파일로 짬. 셋 다 「칸」 명령 하나로만 문서를 바꿈. 순수 로직(나누기 · 중복 찾기 · 등차수열 짓기)은 DOM 없이도 시험 가능해 resources/tester/spreadsheet/test_stage2_data_tools.ts 로 다 검증함. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K7JS47SacjPxZ718QsZKyr
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
/* =============================================================================
|
||||
* test_stage2_data_tools.ts — spreadsheet_data_tools 시험(텍스트 나누기 · 중복 제거 · 연속 채우기).
|
||||
* 돌리기: npx tsx <이 파일> (`@ui/*` 별칭 때문에 plain node 안 됨)
|
||||
* ========================================================================== */
|
||||
|
||||
import {
|
||||
applyFillSeries,
|
||||
applyTextToColumns,
|
||||
buildLinearSeries,
|
||||
findDuplicateRowIndexes,
|
||||
removeDuplicateRows,
|
||||
splitDelimited,
|
||||
splitFixedWidth,
|
||||
} from "../../../A00_Common/spreadsheet/spreadsheet_data_tools.ts";
|
||||
import { a1, assertEqual, makeBook, makeCtx, makeSheet, v } from "./test_stage2_helpers.ts";
|
||||
|
||||
// ── 텍스트 나누기 ──────────────────────────────────────────────
|
||||
assertEqual(splitDelimited("가,나,다", ["쉼표"], ""), ["가", "나", "다"], "쉼표 나누기");
|
||||
assertEqual(splitDelimited("가\t나", ["탭"], ""), ["가", "나"], "탭 나누기");
|
||||
assertEqual(
|
||||
splitDelimited("가;나,다", ["세미콜론", "쉼표"], ""),
|
||||
["가", "나", "다"],
|
||||
"복수 구분 기호",
|
||||
);
|
||||
assertEqual(splitDelimited("가|나", ["사용자"], "|"), ["가", "나"], "사용자 지정 구분 기호");
|
||||
assertEqual(splitDelimited("가나다", [], ""), ["가나다"], "구분 기호 없으면 한 칸 그대로");
|
||||
|
||||
assertEqual(splitFixedWidth("2026-09-27", [4, 7]), ["2026", "-09", "-27"], "고정 폭 나누기");
|
||||
assertEqual(splitFixedWidth("ABC", [10]), ["ABC"], "자리가 글보다 길면 한 칸");
|
||||
|
||||
{
|
||||
const book = makeBook([makeSheet("s1", {})]);
|
||||
const ctx = makeCtx(book, "s1");
|
||||
applyTextToColumns(ctx, { r: 0, c: 0 }, [
|
||||
["가", "나"],
|
||||
["1", "2"],
|
||||
]);
|
||||
assertEqual(book.시트[0].칸[a1(0, 0)], { 값: "가" }, "나누기 결과 A1");
|
||||
assertEqual(book.시트[0].칸[a1(0, 1)], { 값: "나" }, "나누기 결과 B1");
|
||||
assertEqual(book.시트[0].칸[a1(1, 0)], { 값: 1 }, "나누기 결과 숫자는 수로");
|
||||
assertEqual(book.시트[0].칸[a1(1, 1)], { 값: 2 }, "나누기 결과 B2");
|
||||
}
|
||||
|
||||
// ── 중복된 항목 제거 ──────────────────────────────────────────
|
||||
assertEqual(
|
||||
findDuplicateRowIndexes(
|
||||
[
|
||||
["가", "1"],
|
||||
["나", "2"],
|
||||
["가", "1"],
|
||||
["다", "3"],
|
||||
["나", "2"],
|
||||
],
|
||||
[0, 1],
|
||||
),
|
||||
[2, 4],
|
||||
"중복 자리 찾기(모든 열 비교)",
|
||||
);
|
||||
assertEqual(
|
||||
findDuplicateRowIndexes(
|
||||
[
|
||||
["가", "1"],
|
||||
["가", "9"],
|
||||
],
|
||||
[0],
|
||||
),
|
||||
[1],
|
||||
"일부 열만 비교",
|
||||
);
|
||||
|
||||
{
|
||||
const book = makeBook([
|
||||
makeSheet("s1", {
|
||||
[a1(0, 0)]: v("가"),
|
||||
[a1(1, 0)]: v("나"),
|
||||
[a1(2, 0)]: v("가"),
|
||||
[a1(3, 0)]: v("다"),
|
||||
}),
|
||||
]);
|
||||
const ctx = makeCtx(book, "s1", {
|
||||
s1: { A1: "가", A2: "나", A3: "가", A4: "다" },
|
||||
});
|
||||
const removed = removeDuplicateRows(ctx, { r0: 0, c0: 0, r1: 3, c1: 0 }, [0], false);
|
||||
assertEqual(removed, 1, "지운 중복 행 수");
|
||||
assertEqual(book.시트[0].칸[a1(0, 0)], { 값: "가" }, "중복 제거 뒤 A1 그대로");
|
||||
assertEqual(book.시트[0].칸[a1(1, 0)], { 값: "나" }, "중복 제거 뒤 A2 그대로");
|
||||
assertEqual(book.시트[0].칸[a1(2, 0)], { 값: "다" }, "중복 제거 뒤 위로 당김");
|
||||
assertEqual(book.시트[0].칸[a1(3, 0)], undefined, "중복 제거 뒤 마지막 칸 비움");
|
||||
}
|
||||
|
||||
// ── 채우기 연속 데이터 ──────────────────────────────────────────
|
||||
assertEqual(buildLinearSeries(1, 1, null, 5), [1, 2, 3, 4, 5], "단계 1 · 5개");
|
||||
assertEqual(buildLinearSeries(0, 2, 6, 100), [0, 2, 4, 6], "끝값에서 멈춤");
|
||||
assertEqual(buildLinearSeries(10, -2, 4, 100), [10, 8, 6, 4], "내림차순 끝값에서 멈춤");
|
||||
|
||||
{
|
||||
const book = makeBook([makeSheet("s1", {})]);
|
||||
const ctx = makeCtx(book, "s1");
|
||||
applyFillSeries(ctx, { r: 0, c: 0 }, "열", [1, 2, 3]);
|
||||
assertEqual(book.시트[0].칸[a1(0, 0)], { 값: 1 }, "세로 채우기 A1");
|
||||
assertEqual(book.시트[0].칸[a1(1, 0)], { 값: 2 }, "세로 채우기 A2");
|
||||
assertEqual(book.시트[0].칸[a1(2, 0)], { 값: 3 }, "세로 채우기 A3");
|
||||
}
|
||||
{
|
||||
const book = makeBook([makeSheet("s1", {})]);
|
||||
const ctx = makeCtx(book, "s1");
|
||||
applyFillSeries(ctx, { r: 0, c: 0 }, "행", [1, 2]);
|
||||
assertEqual(book.시트[0].칸[a1(0, 0)], { 값: 1 }, "가로 채우기 A1");
|
||||
assertEqual(book.시트[0].칸[a1(0, 1)], { 값: 2 }, "가로 채우기 B1");
|
||||
}
|
||||
|
||||
if (process.exitCode) process.exit(process.exitCode);
|
||||
console.log("spreadsheet_data_tools 시험 끝");
|
||||
Reference in New Issue
Block a user