const assert = require("node:assert/strict"); const { test } = require("node:test"); const { loadTypeScript } = require("./load-typescript.cjs"); const apiPath = "src/features/dredging/api/dredging-api.ts"; const adapters = loadTypeScript( "src/features/dredging/api/response-adapters.ts", ); test("준설 페이지 raw/wrapper의 page0·total0·items 참조와 필드를 보존", () => { const page = { items: [], total: 0, page: 0, size: 2000, extra: "retained" }; assert.equal(adapters.toDredgingRecordPage(page), page); assert.equal(adapters.toDredgingRecordPage({ data: page }), page); assert.deepEqual(page, { items: [], total: 0, page: 0, size: 2000, extra: "retained", }); }); test("준설사진의 원본 촬영일시·첨부필드는 유지하고 기존 null fallback 적용", () => { const photos = [ { photoSn: 1, capturedAt: "2026-09-01T12:13:14", atflCd: "A", atflId: "B" }, ]; assert.equal(adapters.toDredgingPhotos(photos), photos); assert.equal(adapters.toDredgingPhotos({ data: photos }), photos); assert.deepEqual(adapters.toDredgingPhotos(null), []); assert.deepEqual(adapters.toDredgingPhotos(undefined), []); }); test("최근접관로의 식별자·위치·0값·nullable 기본값과 raw/wrapper를 유지", () => { const row = { locationKey: "photo-1", selected: { fid: "F-1", mngInstCd: "4173000", fcltMngNo: "P-1", distanceMeters: 0, snappedLongitude: 127, snappedLatitude: 37, }, }; const expected = { fid: "F-1", mngInstCd: "4173000", fcltMngNo: "P-1", pipeDiameterMm: 0, pipeLengthM: 0, pipeMaterial: "", installationYear: null, swtrmtZoneFid: null, swtrmtZoneNm: "", distanceMeters: 0, snappedLongitude: 127, snappedLatitude: 37, isMock: false, }; assert.deepEqual( adapters.toNearestPipeMatches([row]).get("photo-1"), expected, ); assert.deepEqual( adapters.toNearestPipeMatches({ data: [row] }).get("photo-1"), expected, ); assert.equal(adapters.toNearestPipeMatches(null).size, 0); }); test("최근접관로 부분 실패는 성공 Map을 반환하지 않고 중복 안내를 합친다", () => { const rows = [ { locationKey: "A", failureCode: "PIPE_NOT_FOUND" }, { locationKey: "B", failureCode: "PIPE_NOT_FOUND" }, ]; assert.throws(() => adapters.toNearestPipeMatches(rows), { message: "50m 이내에 관로가 없습니다. 지도에서 준설위치를 다시 확인해주세요.", }); assert.throws( () => adapters.toNearestPipeMatches([ { locationKey: "A", failureMessage: " 원인 안내 " }, ]), { message: "원인 안내" }, ); }); test("실제 API 목록/사진이 기존 URL과 query를 사용하고 adapter로 응답 반환", async () => { const calls = []; const page = { items: [{ id: "one" }], page: 0, size: 10, total: 1 }; const api = loadTypeScript(apiPath, { "@/components/lib/api": { getRawJson: async (url) => { calls.push(url); return { data: url.includes("/photos?") ? [] : page }; }, }, "@/shared/lib/fetch-all-pages": {}, }); assert.equal( await api.fetchDredgingRecords({ fromDate: "2026-09-01", toDate: "2026-09-10", ctpv: " 경기 ", page: 0, size: 10, }), page, ); assert.equal( calls[0], "v1/dredging/records?fromDate=2026-09-01&toDate=2026-09-10&page=0&size=10&ctpv=%EA%B2%BD%EA%B8%B0", ); assert.deepEqual(await api.fetchDredgingPhotos("job/1", "pipe 1"), []); assert.equal(calls[1], "v1/dredging/records/job%2F1/photos?fid=pipe%201"); }); test("실제 전체페이지 조회는 page0부터 순회하며 row·total을 유지", async () => { const pages = []; const api = loadTypeScript(apiPath, { "@/components/lib/api": { getRawJson: async (url) => { const query = new URL(url, "http://fixture").searchParams; const page = Number(query.get("page")); pages.push(page); return { data: { items: page === 0 ? [{ id: "A" }, { id: "B" }] : [{ id: "C" }], total: 3, page, size: 2000, }, }; }, }, "@/shared/lib/fetch-all-pages": loadTypeScript( "src/shared/lib/fetch-all-pages.ts", ), }); const result = await api.fetchAllDredgingRecords({ fromDate: "2026-09-01", toDate: "2026-09-10", }); assert.deepEqual(result, { items: [{ id: "A" }, { id: "B" }, { id: "C" }], total: 3, }); assert.deepEqual(pages, [0, 1]); }); test("BE409 충돌은 자동 재시도하지 않고 기존 준설 실패 경로로 전달", async (t) => { t.mock.method(console, "warn", () => {}); let calls = 0; const api = loadTypeScript(apiPath, { "@/components/lib/api": { postRawJson: async () => { calls++; throw Object.assign(new Error("conflict"), { status: 409, body: { error: { code: "DREDGING_REQUEST_CONFLICT" } }, }); }, }, "@/shared/lib/fetch-all-pages": {}, }); await assert.rejects( api.saveDredgingRegistrations({ clientRequestId: "same-key", groups: [] }), { message: "준설결과를 저장하지 못했습니다. 잠시 후 다시 시도해주세요." }, ); assert.equal(calls, 1); });