feat: assemble responsive app shell navigation

This commit is contained in:
donghyeon-ka
2026-07-25 23:52:34 +09:00
parent 0925d252d9
commit baeda39057
17 changed files with 1238 additions and 60 deletions
+62 -1
View File
@@ -4,7 +4,10 @@ import {
createRedirectLoopGuard,
decideRouteAccess,
} from "../../src/presentation/routes/navigation-policy.js";
import { ROUTE_REGISTRY } from "../../src/contracts/routes.js";
import {
NAVIGATION_ROUTES,
ROUTE_REGISTRY,
} from "../../src/contracts/routes.js";
describe("route registry", () => {
it("matches the stable registry snapshot", () => {
@@ -15,35 +18,93 @@ describe("route registry", () => {
"chunkId": "route-home",
"errorSurface": "route-boundary",
"loadingSurface": "app-shell",
"navigationLabel": "시작",
"navigationOrder": 10,
"paramsSchema": null,
"path": "/",
"routeId": "APP_HOME",
"searchSchema": null,
"title": "시작",
},
"EXAMPLES_AUTH": {
"access": "public",
"chunkId": "route-examples-auth",
"errorSurface": "route-boundary",
"loadingSurface": "example-page",
"navigationLabel": "인증 연동",
"navigationOrder": 40,
"paramsSchema": null,
"path": "/examples/auth",
"routeId": "EXAMPLES_AUTH",
"searchSchema": null,
"title": "인증 연동",
},
"EXAMPLES_STATES": {
"access": "public",
"chunkId": "route-examples-states",
"errorSurface": "route-boundary",
"loadingSurface": "example-page",
"navigationLabel": "화면 상태",
"navigationOrder": 30,
"paramsSchema": null,
"path": "/examples/states",
"routeId": "EXAMPLES_STATES",
"searchSchema": null,
"title": "화면 상태",
},
"EXAMPLES_UI": {
"access": "public",
"chunkId": "route-examples-ui",
"errorSurface": "route-boundary",
"loadingSurface": "example-page",
"navigationLabel": "UI 구성요소",
"navigationOrder": 20,
"paramsSchema": null,
"path": "/examples/ui",
"routeId": "EXAMPLES_UI",
"searchSchema": null,
"title": "UI 구성요소",
},
"NOT_FOUND": {
"access": "public",
"chunkId": "route-not-found",
"errorSurface": "not-found",
"loadingSurface": "none",
"navigationLabel": null,
"navigationOrder": null,
"paramsSchema": null,
"path": "*",
"routeId": "NOT_FOUND",
"searchSchema": null,
"title": "페이지를 찾을 수 없음",
},
"SAMPLE_RESOURCE_LIST": {
"access": "integration-defined",
"chunkId": "route-sample-resources",
"errorSurface": "feature-boundary",
"loadingSurface": "sample-resource-list",
"navigationLabel": "보호된 연동 지점",
"navigationOrder": 50,
"paramsSchema": null,
"path": "/sample/resources",
"routeId": "SAMPLE_RESOURCE_LIST",
"searchSchema": "SampleResourceListQuery",
"title": "보호된 연동 지점",
},
}
`);
});
it("derives visible navigation in explicit order", () => {
expect(NAVIGATION_ROUTES.map(({ routeId }) => routeId)).toEqual([
"APP_HOME",
"EXAMPLES_UI",
"EXAMPLES_STATES",
"EXAMPLES_AUTH",
"SAMPLE_RESOURCE_LIST",
]);
});
it("treats client access as a UX hint, not authorization", () => {
expect(decideRouteAccess("APP_HOME", "unauthenticated")).toEqual({
allowed: true,