import assert from "node:assert/strict"; import { existsSync, readFileSync } from "node:fs"; import test from "node:test"; import { birthPlaceDraftFromLevels, formatBirthPlaceCoordinate, formatBirthPlaceTimezone, hasVirtualCityLevel, findProvinceNode, resolveBirthPlaceNode, } from "../src/lib/china-birth-place.ts"; const pickerSource = readFileSync(new URL("../src/components/birth-place-picker.tsx", import.meta.url), "utf8"); const pageSource = readFileSync(new URL("../src/app/page.tsx", import.meta.url), "utf8"); test("resolves a province, city and district to the district centre", () => { const resolved = resolveBirthPlaceNode({ provinceCode: "130000", cityCode: "130400", districtCode: "130402" }); assert.ok(resolved); assert.equal(resolved.label, "河北省 · 邯郸市 · 邯山区"); assert.equal(resolved.placeType, "district"); assert.equal(resolved.node.code, "130402"); assert.equal(resolved.latitude, 36.603196); assert.equal(resolved.longitude, 114.484989); }); test("falls back to the city centre when the district is left unnamed", () => { const resolved = resolveBirthPlaceNode({ provinceCode: "130000", cityCode: "130400", districtCode: "" }); assert.ok(resolved); assert.equal(resolved.label, "河北省 · 邯郸市"); assert.equal(resolved.placeType, "city"); assert.equal(resolved.node.code, "130400"); assert.equal(resolved.latitude, 36.612273); }); test("collapses the repeated city level of municipalities and special regions", () => { assert.equal(hasVirtualCityLevel(findProvinceNode("110000")!), true); assert.equal(hasVirtualCityLevel(findProvinceNode("130000")!), false); // The city code may be absent because the picker never shows that level. const resolved = resolveBirthPlaceNode({ provinceCode: "110000", cityCode: "", districtCode: "110105" }); assert.ok(resolved); assert.equal(resolved.label, "北京市 · 朝阳区"); assert.equal(resolved.placeType, "district"); }); test("completes at the city for prefecture cities that have no districts", () => { const resolved = resolveBirthPlaceNode({ provinceCode: "440000", cityCode: "441900", districtCode: "" }); assert.ok(resolved); assert.equal(resolved.label, "广东省 · 东莞市"); assert.equal(resolved.placeType, "city"); assert.equal(resolved.node.code, "441900"); }); test("completes at the province when neither lower level offers a choice", () => { const resolved = resolveBirthPlaceNode({ provinceCode: "710000", cityCode: "", districtCode: "" }); assert.ok(resolved); assert.equal(resolved.label, "台湾省"); assert.equal(resolved.placeType, "province"); }); test("rejects codes that do not belong together", () => { assert.equal(resolveBirthPlaceNode({ provinceCode: "999999", cityCode: "", districtCode: "" }), null); assert.equal(resolveBirthPlaceNode({ provinceCode: "130000", cityCode: "440100", districtCode: "" }), null); assert.equal(resolveBirthPlaceNode({ provinceCode: "130000", cityCode: "130400", districtCode: "110105" }), null); }); test("re-syncing a saved profile keeps the same draft so the picker cannot clear itself", () => { const saved = { provinceCode: "130000", cityCode: "130400", districtCode: "" }; const draft = birthPlaceDraftFromLevels(saved); assert.deepEqual(draft, { provinceCode: "130000", cityCode: "130400", districtCode: "", cityCentre: true }); assert.deepEqual(birthPlaceDraftFromLevels(draft), draft); // A city without districts is complete without being marked as an unsure centre. assert.deepEqual(birthPlaceDraftFromLevels({ provinceCode: "440000", cityCode: "441900", districtCode: "" }), { provinceCode: "440000", cityCode: "441900", districtCode: "", cityCentre: false, }); // A municipality resumes with its virtual city filled in. assert.deepEqual(birthPlaceDraftFromLevels({ provinceCode: "110000", cityCode: "", districtCode: "110105" }), { provinceCode: "110000", cityCode: "110000-city", districtCode: "110105", cityCentre: false, }); }); test("states coordinates and the resolved offset in plain Chinese", () => { assert.equal(formatBirthPlaceCoordinate(36.612273, 114.490686), "东经 114.49° · 北纬 36.61°"); assert.equal(formatBirthPlaceTimezone("Asia/Shanghai", 8), "Asia/Shanghai · UTC+8"); assert.equal(formatBirthPlaceTimezone("Asia/Kathmandu", 5.75), "Asia/Kathmandu · UTC+5:45"); assert.equal(formatBirthPlaceTimezone("Asia/Shanghai", null), "Asia/Shanghai"); }); test("the picker offers three cascading levels instead of a free-text search", () => { assert.equal(existsSync(new URL("../src/components/location-search-combobox.tsx", import.meta.url)), false); assert.doesNotMatch(pickerSource, /role="combobox"/); assert.match(pickerSource, /aria-label="出生省份"/); assert.match(pickerSource, /aria-label="出生城市"/); assert.match(pickerSource, /aria-label="出生区县"/); // The level is hidden rather than shown empty when it carries no choice. assert.match(pickerSource, /\{province && !virtualCity && \(/); assert.match(pickerSource, /\{city && districts\.length > 0 && \(/); assert.match(pickerSource, /不确定,用市区中心/); assert.match(pickerSource, /精确到区 \/ 县就足够/); }); test("timezone is resolved once for the chosen place rather than during browsing", () => { assert.equal(existsSync(new URL("../src/app/api/locations/timezone/route.ts", import.meta.url)), true); assert.match(pickerSource, /fetch\("\/api\/locations\/timezone"/); // Browsing the levels cannot spend a lookup: only a resolved place gets a sync key. assert.match(pickerSource, /if \(syncKey === "empty"\)/); assert.match(pickerSource, /: \{ status: "loading" \};/); // An unresolved zone must not be reported upward as a usable birth place. assert.match(pickerSource, /setOutcome\(\{ key: syncKey, state: \{ status: "error" \} \}\);\s*onChangeRef\.current\(null\);/); const service = readFileSync(new URL("../src/lib/birth-location-timezone-service.ts", import.meta.url), "utf8"); assert.match(service, /\/api\/location\/timezone/); assert.match(service, /timezoneSource: "iana_historical"/); }); test("mounting a saved birth place neither refetches nor clears the stored location", () => { // Reporting null on mount would look like a location edit and would drop a // rectified birth-time candidate just because the profile dialog was opened. assert.match(pickerSource, /const savedIsCurrent = resolved !== null/); assert.match(pickerSource, /if \(syncKey === "saved"\) return;/); assert.match(pickerSource, /if \(saved\.provinceCode \|\| saved\.timezoneId\) onChangeRef\.current\(null\);/); // A changed birth date invalidates the stored offset, so the zone is resolved again. assert.match(pickerSource, /mountedMoment === birthMoment/); }); test("the profile stores administrative codes alongside coordinates and the IANA zone", () => { assert.match(pageSource, / { assert.match(pageSource, /profile\.timezoneId\.trim\(\)/); assert.match(pageSource, /profile\.timezoneOffset === null \|\| Number\.isFinite\(profile\.timezoneOffset\)/); });