rwsdk 1.0.0-beta.5 → 1.0.0-beta.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/rw-scripts.mjs +13 -13
- package/dist/lib/constants.d.mts +1 -0
- package/dist/lib/constants.mjs +7 -4
- package/dist/lib/e2e/browser.mjs +6 -2
- package/dist/lib/e2e/constants.d.mts +4 -0
- package/dist/lib/e2e/constants.mjs +49 -12
- package/dist/lib/e2e/dev.mjs +49 -57
- package/dist/lib/e2e/environment.d.mts +2 -0
- package/dist/lib/e2e/environment.mjs +201 -64
- package/dist/lib/e2e/index.d.mts +2 -0
- package/dist/lib/e2e/index.mjs +2 -0
- package/dist/lib/e2e/poll.d.mts +1 -1
- package/dist/lib/e2e/release.d.mts +1 -0
- package/dist/lib/e2e/release.mjs +57 -52
- package/dist/lib/e2e/tarball.mjs +2 -34
- package/dist/lib/e2e/testHarness.d.mts +39 -3
- package/dist/lib/e2e/testHarness.mjs +239 -92
- package/dist/lib/e2e/utils.d.mts +1 -0
- package/dist/lib/e2e/utils.mjs +15 -0
- package/dist/lib/normalizeModulePath.mjs +1 -1
- package/dist/runtime/client/client.d.ts +64 -2
- package/dist/runtime/client/client.js +156 -15
- package/dist/runtime/client/navigation.d.ts +45 -0
- package/dist/runtime/client/navigation.js +68 -14
- package/dist/runtime/client/navigationCache.d.ts +68 -0
- package/dist/runtime/client/navigationCache.js +294 -0
- package/dist/runtime/client/navigationCache.test.js +469 -0
- package/dist/runtime/client/types.d.ts +26 -5
- package/dist/runtime/client/types.js +8 -1
- package/dist/runtime/entries/no-react-server-ssr-bridge.d.ts +0 -0
- package/dist/runtime/entries/no-react-server-ssr-bridge.js +2 -0
- package/dist/runtime/entries/no-react-server.js +3 -1
- package/dist/runtime/entries/react-server-only.js +1 -1
- package/dist/runtime/entries/router.d.ts +1 -0
- package/dist/runtime/entries/routerClient.d.ts +1 -0
- package/dist/runtime/entries/routerClient.js +1 -0
- package/dist/runtime/entries/worker.d.ts +4 -0
- package/dist/runtime/entries/worker.js +4 -0
- package/dist/runtime/imports/__mocks__/use-client-lookup.d.ts +6 -0
- package/dist/runtime/imports/__mocks__/use-client-lookup.js +6 -0
- package/dist/runtime/lib/db/SqliteDurableObject.d.ts +2 -2
- package/dist/runtime/lib/db/SqliteDurableObject.js +2 -2
- package/dist/runtime/lib/db/createDb.d.ts +1 -2
- package/dist/runtime/lib/db/createDb.js +4 -0
- package/dist/runtime/lib/db/typeInference/builders/alterTable.d.ts +13 -3
- package/dist/runtime/lib/db/typeInference/builders/columnDefinition.d.ts +35 -21
- package/dist/runtime/lib/db/typeInference/builders/createTable.d.ts +9 -2
- package/dist/runtime/lib/db/typeInference/database.d.ts +16 -2
- package/dist/runtime/lib/db/typeInference/typetests/alterTable.typetest.js +80 -5
- package/dist/runtime/lib/db/typeInference/typetests/createTable.typetest.js +104 -2
- package/dist/runtime/lib/db/typeInference/typetests/testUtils.d.ts +1 -0
- package/dist/runtime/lib/db/typeInference/utils.d.ts +59 -9
- package/dist/runtime/lib/links.d.ts +21 -7
- package/dist/runtime/lib/links.js +84 -26
- package/dist/runtime/lib/links.test.d.ts +1 -0
- package/dist/runtime/lib/links.test.js +20 -0
- package/dist/runtime/lib/manifest.d.ts +1 -1
- package/dist/runtime/lib/manifest.js +7 -4
- package/dist/runtime/lib/realtime/client.js +28 -6
- package/dist/runtime/lib/realtime/worker.d.ts +1 -1
- package/dist/runtime/lib/router.d.ts +154 -35
- package/dist/runtime/lib/router.js +491 -105
- package/dist/runtime/lib/router.test.js +611 -1
- package/dist/runtime/lib/stitchDocumentAndAppStreams.d.ts +66 -0
- package/dist/runtime/lib/stitchDocumentAndAppStreams.js +302 -35
- package/dist/runtime/lib/stitchDocumentAndAppStreams.test.d.ts +1 -0
- package/dist/runtime/lib/stitchDocumentAndAppStreams.test.js +418 -0
- package/dist/runtime/lib/{rwContext.d.ts → types.d.ts} +1 -0
- package/dist/runtime/lib/types.js +1 -0
- package/dist/runtime/register/client.d.ts +1 -1
- package/dist/runtime/register/client.js +10 -3
- package/dist/runtime/register/worker.js +13 -4
- package/dist/runtime/render/normalizeActionResult.js +8 -1
- package/dist/runtime/render/renderDocumentHtmlStream.d.ts +1 -1
- package/dist/runtime/render/renderToStream.d.ts +4 -2
- package/dist/runtime/render/renderToStream.js +53 -24
- package/dist/runtime/render/renderToString.d.ts +3 -6
- package/dist/runtime/requestInfo/types.d.ts +5 -1
- package/dist/runtime/requestInfo/utils.d.ts +9 -0
- package/dist/runtime/requestInfo/utils.js +45 -0
- package/dist/runtime/requestInfo/worker.d.ts +0 -1
- package/dist/runtime/requestInfo/worker.js +5 -11
- package/dist/runtime/script.d.ts +1 -3
- package/dist/runtime/script.js +1 -10
- package/dist/runtime/server.d.ts +52 -0
- package/dist/runtime/server.js +88 -0
- package/dist/runtime/state.d.ts +3 -0
- package/dist/runtime/state.js +13 -0
- package/dist/runtime/worker.d.ts +3 -1
- package/dist/runtime/worker.js +45 -2
- package/dist/scripts/debug-sync.mjs +18 -20
- package/dist/scripts/worker-run.d.mts +1 -1
- package/dist/scripts/worker-run.mjs +59 -113
- package/dist/use-synced-state/SyncedStateServer.d.mts +36 -0
- package/dist/use-synced-state/SyncedStateServer.mjs +196 -0
- package/dist/use-synced-state/__tests__/SyncStateServer.test.d.mts +1 -0
- package/dist/use-synced-state/__tests__/SyncStateServer.test.mjs +116 -0
- package/dist/use-synced-state/__tests__/useSyncState.test.d.ts +1 -0
- package/dist/use-synced-state/__tests__/useSyncState.test.js +115 -0
- package/dist/use-synced-state/__tests__/useSyncedState.test.d.ts +1 -0
- package/dist/use-synced-state/__tests__/useSyncedState.test.js +115 -0
- package/dist/use-synced-state/__tests__/worker.test.d.mts +1 -0
- package/dist/use-synced-state/__tests__/worker.test.mjs +70 -0
- package/dist/use-synced-state/client-core.d.ts +29 -0
- package/dist/use-synced-state/client-core.js +103 -0
- package/dist/use-synced-state/client.d.ts +3 -0
- package/dist/use-synced-state/client.js +4 -0
- package/dist/use-synced-state/constants.d.mts +1 -0
- package/dist/use-synced-state/constants.mjs +1 -0
- package/dist/use-synced-state/useSyncedState.d.ts +21 -0
- package/dist/use-synced-state/useSyncedState.js +64 -0
- package/dist/use-synced-state/worker.d.mts +14 -0
- package/dist/use-synced-state/worker.mjs +135 -0
- package/dist/vite/buildApp.mjs +34 -2
- package/dist/vite/cloudflarePreInitPlugin.d.mts +11 -0
- package/dist/vite/cloudflarePreInitPlugin.mjs +40 -0
- package/dist/vite/configPlugin.mjs +9 -14
- package/dist/vite/constants.d.mts +1 -0
- package/dist/vite/constants.mjs +1 -0
- package/dist/vite/createDirectiveLookupPlugin.mjs +10 -7
- package/dist/vite/devServerTimingPlugin.mjs +4 -0
- package/dist/vite/diagnosticAssetGraphPlugin.d.mts +4 -0
- package/dist/vite/diagnosticAssetGraphPlugin.mjs +41 -0
- package/dist/vite/directiveModulesDevPlugin.mjs +9 -1
- package/dist/vite/directivesPlugin.mjs +4 -4
- package/dist/vite/envResolvers.d.mts +11 -0
- package/dist/vite/envResolvers.mjs +20 -0
- package/dist/vite/getViteEsbuild.mjs +2 -1
- package/dist/vite/hmrStabilityPlugin.d.mts +2 -0
- package/dist/vite/hmrStabilityPlugin.mjs +73 -0
- package/dist/vite/injectVitePreamblePlugin.mjs +0 -4
- package/dist/vite/knownDepsResolverPlugin.d.mts +0 -6
- package/dist/vite/knownDepsResolverPlugin.mjs +25 -17
- package/dist/vite/linkerPlugin.d.mts +2 -1
- package/dist/vite/linkerPlugin.mjs +11 -3
- package/dist/vite/linkerPlugin.test.mjs +15 -0
- package/dist/vite/miniflareHMRPlugin.mjs +6 -38
- package/dist/vite/moveStaticAssetsPlugin.mjs +35 -4
- package/dist/vite/redwoodPlugin.mjs +9 -11
- package/dist/vite/redwoodPlugin.test.mjs +4 -4
- package/dist/vite/runDirectivesScan.mjs +75 -19
- package/dist/vite/ssrBridgePlugin.mjs +132 -40
- package/dist/vite/ssrBridgeWrapPlugin.d.mts +2 -0
- package/dist/vite/ssrBridgeWrapPlugin.mjs +85 -0
- package/dist/vite/staleDepRetryPlugin.d.mts +2 -0
- package/dist/vite/staleDepRetryPlugin.mjs +74 -0
- package/dist/vite/statePlugin.d.mts +4 -0
- package/dist/vite/statePlugin.mjs +62 -0
- package/dist/vite/transformClientComponents.test.mjs +32 -0
- package/dist/vite/transformJsxScriptTagsPlugin.mjs +0 -5
- package/dist/vite/transformServerFunctions.mjs +66 -4
- package/dist/vite/transformServerFunctions.test.mjs +35 -0
- package/dist/vite/virtualPlugin.mjs +6 -7
- package/package.json +45 -20
- package/dist/vite/manifestPlugin.d.mts +0 -4
- package/dist/vite/manifestPlugin.mjs +0 -63
- /package/dist/runtime/{lib/rwContext.js → client/navigationCache.test.d.ts} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { describe, expect, it } from "vitest";
|
|
3
|
-
import { defineRoutes, layout, matchPath, prefix, render, route, } from "./router";
|
|
3
|
+
import { defineRoutes, except, layout, matchPath, prefix, render, route, } from "./router";
|
|
4
4
|
describe("matchPath", () => {
|
|
5
5
|
// Test case 1: Static paths
|
|
6
6
|
it("should match static paths", () => {
|
|
@@ -34,6 +34,11 @@ describe("matchPath", () => {
|
|
|
34
34
|
it("should match empty wildcard", () => {
|
|
35
35
|
expect(matchPath("/files/*/", "/files//")).toEqual({ $0: "" });
|
|
36
36
|
});
|
|
37
|
+
it("should match wildcard route against root path", () => {
|
|
38
|
+
// Wildcard route should match the root path "/"
|
|
39
|
+
// This tests the regression where route("*") stopped matching "/"
|
|
40
|
+
expect(matchPath("/*", "/")).toEqual({ $0: "" });
|
|
41
|
+
});
|
|
37
42
|
// Test case 4: Paths with both parameters and wildcards
|
|
38
43
|
it("should match paths with both parameters and wildcards", () => {
|
|
39
44
|
expect(matchPath("/products/:productId/*/", "/products/abc/details/more/")).toEqual({ productId: "abc", $0: "details/more" });
|
|
@@ -62,6 +67,7 @@ describe("defineRoutes - Request Handling Behavior", () => {
|
|
|
62
67
|
const createMockDependencies = () => {
|
|
63
68
|
const mockRequestInfo = {
|
|
64
69
|
request: new Request("http://localhost:3000/"),
|
|
70
|
+
path: "/",
|
|
65
71
|
params: {},
|
|
66
72
|
ctx: {},
|
|
67
73
|
rw: {
|
|
@@ -71,6 +77,8 @@ describe("defineRoutes - Request Handling Behavior", () => {
|
|
|
71
77
|
ssr: true,
|
|
72
78
|
databases: new Map(),
|
|
73
79
|
scriptsToBeLoaded: new Set(),
|
|
80
|
+
entryScripts: new Set(),
|
|
81
|
+
inlineScripts: new Set(),
|
|
74
82
|
pageRouteResolved: undefined,
|
|
75
83
|
},
|
|
76
84
|
cf: {},
|
|
@@ -291,6 +299,109 @@ describe("defineRoutes - Request Handling Behavior", () => {
|
|
|
291
299
|
expect(executionOrder).toEqual(["prefixedMiddleware"]);
|
|
292
300
|
expect(await response.text()).toBe("From prefixed middleware");
|
|
293
301
|
});
|
|
302
|
+
it("should pass prefix parameters to route handlers", async () => {
|
|
303
|
+
let capturedParams = null;
|
|
304
|
+
const TaskDetailPage = (requestInfo) => {
|
|
305
|
+
capturedParams = requestInfo.params;
|
|
306
|
+
return React.createElement("div", {}, "Task Detail");
|
|
307
|
+
};
|
|
308
|
+
const router = defineRoutes([
|
|
309
|
+
...prefix("/tasks/:containerId", [route("/", TaskDetailPage)]),
|
|
310
|
+
]);
|
|
311
|
+
const deps = createMockDependencies();
|
|
312
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/tasks/123/");
|
|
313
|
+
const request = new Request("http://localhost:3000/tasks/123/");
|
|
314
|
+
await router.handle({
|
|
315
|
+
request,
|
|
316
|
+
renderPage: deps.mockRenderPage,
|
|
317
|
+
getRequestInfo: deps.getRequestInfo,
|
|
318
|
+
onError: deps.onError,
|
|
319
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
320
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
321
|
+
});
|
|
322
|
+
expect(capturedParams).toEqual({ containerId: "123" });
|
|
323
|
+
});
|
|
324
|
+
it("should pass prefix parameters to middlewares within a parameterized prefix", async () => {
|
|
325
|
+
const executionOrder = [];
|
|
326
|
+
let capturedParams = null;
|
|
327
|
+
const prefixedMiddleware = (requestInfo) => {
|
|
328
|
+
executionOrder.push("prefixedMiddleware");
|
|
329
|
+
capturedParams = requestInfo.params;
|
|
330
|
+
};
|
|
331
|
+
const PageComponent = () => {
|
|
332
|
+
executionOrder.push("PageComponent");
|
|
333
|
+
return React.createElement("div", {}, "Page");
|
|
334
|
+
};
|
|
335
|
+
const router = defineRoutes([
|
|
336
|
+
...prefix("/tasks/:containerId", [
|
|
337
|
+
prefixedMiddleware,
|
|
338
|
+
route("/", PageComponent),
|
|
339
|
+
]),
|
|
340
|
+
]);
|
|
341
|
+
const deps = createMockDependencies();
|
|
342
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/tasks/123/");
|
|
343
|
+
const request = new Request("http://localhost:3000/tasks/123/");
|
|
344
|
+
await router.handle({
|
|
345
|
+
request,
|
|
346
|
+
renderPage: deps.mockRenderPage,
|
|
347
|
+
getRequestInfo: deps.getRequestInfo,
|
|
348
|
+
onError: deps.onError,
|
|
349
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
350
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
351
|
+
});
|
|
352
|
+
expect(executionOrder).toEqual(["prefixedMiddleware", "PageComponent"]);
|
|
353
|
+
// The wildcard captures the trailing slash as an empty string
|
|
354
|
+
expect(capturedParams).toEqual({ containerId: "123", $0: "" });
|
|
355
|
+
});
|
|
356
|
+
it("should pass prefix parameters to route handlers (array)", async () => {
|
|
357
|
+
let capturedParamsInMiddleware = null;
|
|
358
|
+
let capturedParamsInComponent = null;
|
|
359
|
+
const middleware = (requestInfo) => {
|
|
360
|
+
capturedParamsInMiddleware = requestInfo.params;
|
|
361
|
+
};
|
|
362
|
+
const Component = (requestInfo) => {
|
|
363
|
+
capturedParamsInComponent = requestInfo.params;
|
|
364
|
+
return React.createElement("div", {}, "Component");
|
|
365
|
+
};
|
|
366
|
+
const router = defineRoutes([
|
|
367
|
+
...prefix("/tasks/:containerId", [route("/", [middleware, Component])]),
|
|
368
|
+
]);
|
|
369
|
+
const deps = createMockDependencies();
|
|
370
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/tasks/123/");
|
|
371
|
+
const request = new Request("http://localhost:3000/tasks/123/");
|
|
372
|
+
await router.handle({
|
|
373
|
+
request,
|
|
374
|
+
renderPage: deps.mockRenderPage,
|
|
375
|
+
getRequestInfo: deps.getRequestInfo,
|
|
376
|
+
onError: deps.onError,
|
|
377
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
378
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
379
|
+
});
|
|
380
|
+
expect(capturedParamsInMiddleware).toEqual({ containerId: "123" });
|
|
381
|
+
expect(capturedParamsInComponent).toEqual({ containerId: "123" });
|
|
382
|
+
});
|
|
383
|
+
it("should match even if prefix has a trailing slash", async () => {
|
|
384
|
+
let capturedParams = null;
|
|
385
|
+
const TaskDetailPage = (requestInfo) => {
|
|
386
|
+
capturedParams = requestInfo.params;
|
|
387
|
+
return React.createElement("div", {}, "Task Detail");
|
|
388
|
+
};
|
|
389
|
+
const router = defineRoutes([
|
|
390
|
+
...prefix("/tasks/:containerId/", [route("/", TaskDetailPage)]),
|
|
391
|
+
]);
|
|
392
|
+
const deps = createMockDependencies();
|
|
393
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/tasks/123/");
|
|
394
|
+
const request = new Request("http://localhost:3000/tasks/123/");
|
|
395
|
+
await router.handle({
|
|
396
|
+
request,
|
|
397
|
+
renderPage: deps.mockRenderPage,
|
|
398
|
+
getRequestInfo: deps.getRequestInfo,
|
|
399
|
+
onError: deps.onError,
|
|
400
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
401
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
402
|
+
});
|
|
403
|
+
expect(capturedParams).toEqual({ containerId: "123" });
|
|
404
|
+
});
|
|
294
405
|
});
|
|
295
406
|
describe("RSC Action Handling", () => {
|
|
296
407
|
it("should handle RSC actions before the first route definition", async () => {
|
|
@@ -435,6 +546,28 @@ describe("defineRoutes - Request Handling Behavior", () => {
|
|
|
435
546
|
expect(response.status).toBe(404);
|
|
436
547
|
expect(await response.text()).toBe("Not Found");
|
|
437
548
|
});
|
|
549
|
+
it("should match wildcard route against root path", async () => {
|
|
550
|
+
// Regression test: wildcard route should match the root path "/"
|
|
551
|
+
const executionOrder = [];
|
|
552
|
+
const WildcardPage = () => {
|
|
553
|
+
executionOrder.push("WildcardPage");
|
|
554
|
+
return React.createElement("div", {}, "Wildcard Page");
|
|
555
|
+
};
|
|
556
|
+
const router = defineRoutes([route("*", WildcardPage)]);
|
|
557
|
+
const deps = createMockDependencies();
|
|
558
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/");
|
|
559
|
+
deps.mockRequestInfo.path = "/";
|
|
560
|
+
const request = new Request("http://localhost:3000/");
|
|
561
|
+
await router.handle({
|
|
562
|
+
request,
|
|
563
|
+
renderPage: deps.mockRenderPage,
|
|
564
|
+
getRequestInfo: deps.getRequestInfo,
|
|
565
|
+
onError: deps.onError,
|
|
566
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
567
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
568
|
+
});
|
|
569
|
+
expect(executionOrder).toEqual(["WildcardPage"]);
|
|
570
|
+
});
|
|
438
571
|
});
|
|
439
572
|
describe("Multiple Render Blocks with SSR Configuration", () => {
|
|
440
573
|
it("should short-circuit on first matching render block and not apply later configurations", async () => {
|
|
@@ -593,6 +726,245 @@ describe("defineRoutes - Request Handling Behavior", () => {
|
|
|
593
726
|
expect(extractedParams).toEqual({ id: "123" });
|
|
594
727
|
});
|
|
595
728
|
});
|
|
729
|
+
describe("HTTP Method Routing", () => {
|
|
730
|
+
it("should route GET request to get handler", async () => {
|
|
731
|
+
const router = defineRoutes([
|
|
732
|
+
route("/test/", {
|
|
733
|
+
get: () => new Response("GET Response"),
|
|
734
|
+
post: () => new Response("POST Response"),
|
|
735
|
+
}),
|
|
736
|
+
]);
|
|
737
|
+
const deps = createMockDependencies();
|
|
738
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/test/", {
|
|
739
|
+
method: "GET",
|
|
740
|
+
});
|
|
741
|
+
const request = new Request("http://localhost:3000/test/", {
|
|
742
|
+
method: "GET",
|
|
743
|
+
});
|
|
744
|
+
const response = await router.handle({
|
|
745
|
+
request,
|
|
746
|
+
renderPage: deps.mockRenderPage,
|
|
747
|
+
getRequestInfo: deps.getRequestInfo,
|
|
748
|
+
onError: deps.onError,
|
|
749
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
750
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
751
|
+
});
|
|
752
|
+
expect(await response.text()).toBe("GET Response");
|
|
753
|
+
});
|
|
754
|
+
it("should route POST request to post handler", async () => {
|
|
755
|
+
const router = defineRoutes([
|
|
756
|
+
route("/test/", {
|
|
757
|
+
get: () => new Response("GET Response"),
|
|
758
|
+
post: () => new Response("POST Response"),
|
|
759
|
+
}),
|
|
760
|
+
]);
|
|
761
|
+
const deps = createMockDependencies();
|
|
762
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/test/", {
|
|
763
|
+
method: "POST",
|
|
764
|
+
});
|
|
765
|
+
const request = new Request("http://localhost:3000/test/", {
|
|
766
|
+
method: "POST",
|
|
767
|
+
});
|
|
768
|
+
const response = await router.handle({
|
|
769
|
+
request,
|
|
770
|
+
renderPage: deps.mockRenderPage,
|
|
771
|
+
getRequestInfo: deps.getRequestInfo,
|
|
772
|
+
onError: deps.onError,
|
|
773
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
774
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
775
|
+
});
|
|
776
|
+
expect(await response.text()).toBe("POST Response");
|
|
777
|
+
});
|
|
778
|
+
it("should return 405 for unsupported method with Allow header", async () => {
|
|
779
|
+
const router = defineRoutes([
|
|
780
|
+
route("/test/", {
|
|
781
|
+
get: () => new Response("GET Response"),
|
|
782
|
+
post: () => new Response("POST Response"),
|
|
783
|
+
}),
|
|
784
|
+
]);
|
|
785
|
+
const deps = createMockDependencies();
|
|
786
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/test/", {
|
|
787
|
+
method: "DELETE",
|
|
788
|
+
});
|
|
789
|
+
const request = new Request("http://localhost:3000/test/", {
|
|
790
|
+
method: "DELETE",
|
|
791
|
+
});
|
|
792
|
+
const response = await router.handle({
|
|
793
|
+
request,
|
|
794
|
+
renderPage: deps.mockRenderPage,
|
|
795
|
+
getRequestInfo: deps.getRequestInfo,
|
|
796
|
+
onError: deps.onError,
|
|
797
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
798
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
799
|
+
});
|
|
800
|
+
expect(response.status).toBe(405);
|
|
801
|
+
expect(await response.text()).toBe("Method Not Allowed");
|
|
802
|
+
expect(response.headers.get("Allow")).toBe("GET, OPTIONS, POST");
|
|
803
|
+
});
|
|
804
|
+
it("should handle OPTIONS request with Allow header", async () => {
|
|
805
|
+
const router = defineRoutes([
|
|
806
|
+
route("/test/", {
|
|
807
|
+
get: () => new Response("GET Response"),
|
|
808
|
+
post: () => new Response("POST Response"),
|
|
809
|
+
}),
|
|
810
|
+
]);
|
|
811
|
+
const deps = createMockDependencies();
|
|
812
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/test/", {
|
|
813
|
+
method: "OPTIONS",
|
|
814
|
+
});
|
|
815
|
+
const request = new Request("http://localhost:3000/test/", {
|
|
816
|
+
method: "OPTIONS",
|
|
817
|
+
});
|
|
818
|
+
const response = await router.handle({
|
|
819
|
+
request,
|
|
820
|
+
renderPage: deps.mockRenderPage,
|
|
821
|
+
getRequestInfo: deps.getRequestInfo,
|
|
822
|
+
onError: deps.onError,
|
|
823
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
824
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
825
|
+
});
|
|
826
|
+
expect(response.status).toBe(204);
|
|
827
|
+
expect(response.headers.get("Allow")).toBe("GET, OPTIONS, POST");
|
|
828
|
+
});
|
|
829
|
+
it("should support custom methods (case-insensitive)", async () => {
|
|
830
|
+
const router = defineRoutes([
|
|
831
|
+
route("/test/", {
|
|
832
|
+
custom: {
|
|
833
|
+
report: () => new Response("REPORT Response"),
|
|
834
|
+
},
|
|
835
|
+
}),
|
|
836
|
+
]);
|
|
837
|
+
const deps = createMockDependencies();
|
|
838
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/test/", {
|
|
839
|
+
method: "REPORT",
|
|
840
|
+
});
|
|
841
|
+
const request = new Request("http://localhost:3000/test/", {
|
|
842
|
+
method: "REPORT",
|
|
843
|
+
});
|
|
844
|
+
const response = await router.handle({
|
|
845
|
+
request,
|
|
846
|
+
renderPage: deps.mockRenderPage,
|
|
847
|
+
getRequestInfo: deps.getRequestInfo,
|
|
848
|
+
onError: deps.onError,
|
|
849
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
850
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
851
|
+
});
|
|
852
|
+
expect(await response.text()).toBe("REPORT Response");
|
|
853
|
+
});
|
|
854
|
+
it("should normalize custom method keys to lowercase", async () => {
|
|
855
|
+
const router = defineRoutes([
|
|
856
|
+
route("/test/", {
|
|
857
|
+
custom: {
|
|
858
|
+
REPORT: () => new Response("REPORT Response"),
|
|
859
|
+
},
|
|
860
|
+
}),
|
|
861
|
+
]);
|
|
862
|
+
const deps = createMockDependencies();
|
|
863
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/test/", {
|
|
864
|
+
method: "report",
|
|
865
|
+
});
|
|
866
|
+
const request = new Request("http://localhost:3000/test/", {
|
|
867
|
+
method: "report",
|
|
868
|
+
});
|
|
869
|
+
const response = await router.handle({
|
|
870
|
+
request,
|
|
871
|
+
renderPage: deps.mockRenderPage,
|
|
872
|
+
getRequestInfo: deps.getRequestInfo,
|
|
873
|
+
onError: deps.onError,
|
|
874
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
875
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
876
|
+
});
|
|
877
|
+
expect(await response.text()).toBe("REPORT Response");
|
|
878
|
+
});
|
|
879
|
+
it("should disable 405 when config.disable405 is true", async () => {
|
|
880
|
+
const router = defineRoutes([
|
|
881
|
+
route("/test/", {
|
|
882
|
+
get: () => new Response("GET Response"),
|
|
883
|
+
config: {
|
|
884
|
+
disable405: true,
|
|
885
|
+
},
|
|
886
|
+
}),
|
|
887
|
+
]);
|
|
888
|
+
const deps = createMockDependencies();
|
|
889
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/test/", {
|
|
890
|
+
method: "POST",
|
|
891
|
+
});
|
|
892
|
+
const request = new Request("http://localhost:3000/test/", {
|
|
893
|
+
method: "POST",
|
|
894
|
+
});
|
|
895
|
+
const response = await router.handle({
|
|
896
|
+
request,
|
|
897
|
+
renderPage: deps.mockRenderPage,
|
|
898
|
+
getRequestInfo: deps.getRequestInfo,
|
|
899
|
+
onError: deps.onError,
|
|
900
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
901
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
902
|
+
});
|
|
903
|
+
expect(response.status).toBe(404);
|
|
904
|
+
expect(await response.text()).toBe("Not Found");
|
|
905
|
+
});
|
|
906
|
+
it("should disable OPTIONS when config.disableOptions is true", async () => {
|
|
907
|
+
const router = defineRoutes([
|
|
908
|
+
route("/test/", {
|
|
909
|
+
get: () => new Response("GET Response"),
|
|
910
|
+
post: () => new Response("POST Response"),
|
|
911
|
+
config: {
|
|
912
|
+
disableOptions: true,
|
|
913
|
+
},
|
|
914
|
+
}),
|
|
915
|
+
]);
|
|
916
|
+
const deps = createMockDependencies();
|
|
917
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/test/", {
|
|
918
|
+
method: "OPTIONS",
|
|
919
|
+
});
|
|
920
|
+
const request = new Request("http://localhost:3000/test/", {
|
|
921
|
+
method: "OPTIONS",
|
|
922
|
+
});
|
|
923
|
+
const response = await router.handle({
|
|
924
|
+
request,
|
|
925
|
+
renderPage: deps.mockRenderPage,
|
|
926
|
+
getRequestInfo: deps.getRequestInfo,
|
|
927
|
+
onError: deps.onError,
|
|
928
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
929
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
930
|
+
});
|
|
931
|
+
expect(response.status).toBe(405);
|
|
932
|
+
expect(await response.text()).toBe("Method Not Allowed");
|
|
933
|
+
expect(response.headers.get("Allow")).toBe("GET, POST");
|
|
934
|
+
});
|
|
935
|
+
it("should support middleware arrays in method handlers", async () => {
|
|
936
|
+
const executionOrder = [];
|
|
937
|
+
const authMiddleware = () => {
|
|
938
|
+
executionOrder.push("authMiddleware");
|
|
939
|
+
};
|
|
940
|
+
const getHandler = () => {
|
|
941
|
+
executionOrder.push("getHandler");
|
|
942
|
+
return new Response("GET Response");
|
|
943
|
+
};
|
|
944
|
+
const router = defineRoutes([
|
|
945
|
+
route("/test/", {
|
|
946
|
+
get: [authMiddleware, getHandler],
|
|
947
|
+
}),
|
|
948
|
+
]);
|
|
949
|
+
const deps = createMockDependencies();
|
|
950
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/test/", {
|
|
951
|
+
method: "GET",
|
|
952
|
+
});
|
|
953
|
+
const request = new Request("http://localhost:3000/test/", {
|
|
954
|
+
method: "GET",
|
|
955
|
+
});
|
|
956
|
+
const response = await router.handle({
|
|
957
|
+
request,
|
|
958
|
+
renderPage: deps.mockRenderPage,
|
|
959
|
+
getRequestInfo: deps.getRequestInfo,
|
|
960
|
+
onError: deps.onError,
|
|
961
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
962
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
963
|
+
});
|
|
964
|
+
expect(executionOrder).toEqual(["authMiddleware", "getHandler"]);
|
|
965
|
+
expect(await response.text()).toBe("GET Response");
|
|
966
|
+
});
|
|
967
|
+
});
|
|
596
968
|
describe("Edge Cases", () => {
|
|
597
969
|
it("should handle middleware-only apps with RSC actions", async () => {
|
|
598
970
|
const executionOrder = [];
|
|
@@ -643,4 +1015,242 @@ describe("defineRoutes - Request Handling Behavior", () => {
|
|
|
643
1015
|
expect(await response.text()).toBe("Rendered: Element");
|
|
644
1016
|
});
|
|
645
1017
|
});
|
|
1018
|
+
describe("except - Error Handling", () => {
|
|
1019
|
+
it("should catch errors from global middleware", async () => {
|
|
1020
|
+
const errorMessage = "Middleware error";
|
|
1021
|
+
const middleware = () => {
|
|
1022
|
+
throw new Error(errorMessage);
|
|
1023
|
+
};
|
|
1024
|
+
const errorHandler = except((error) => {
|
|
1025
|
+
return new Response(`Caught: ${error instanceof Error ? error.message : String(error)}`, {
|
|
1026
|
+
status: 500,
|
|
1027
|
+
});
|
|
1028
|
+
});
|
|
1029
|
+
const router = defineRoutes([
|
|
1030
|
+
middleware,
|
|
1031
|
+
errorHandler,
|
|
1032
|
+
route("/test/", () => React.createElement("div")),
|
|
1033
|
+
]);
|
|
1034
|
+
const deps = createMockDependencies();
|
|
1035
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/test/");
|
|
1036
|
+
const request = new Request("http://localhost:3000/test/");
|
|
1037
|
+
const response = await router.handle({
|
|
1038
|
+
request,
|
|
1039
|
+
renderPage: deps.mockRenderPage,
|
|
1040
|
+
getRequestInfo: deps.getRequestInfo,
|
|
1041
|
+
onError: deps.onError,
|
|
1042
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
1043
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
1044
|
+
});
|
|
1045
|
+
expect(response.status).toBe(500);
|
|
1046
|
+
expect(await response.text()).toBe(`Caught: ${errorMessage}`);
|
|
1047
|
+
});
|
|
1048
|
+
it("should catch errors from route handlers (components)", async () => {
|
|
1049
|
+
const errorMessage = "Component error";
|
|
1050
|
+
const PageComponent = () => {
|
|
1051
|
+
throw new Error(errorMessage);
|
|
1052
|
+
};
|
|
1053
|
+
const errorHandler = except((error) => {
|
|
1054
|
+
return new Response(`Caught: ${error instanceof Error ? error.message : String(error)}`, {
|
|
1055
|
+
status: 500,
|
|
1056
|
+
});
|
|
1057
|
+
});
|
|
1058
|
+
const router = defineRoutes([
|
|
1059
|
+
errorHandler,
|
|
1060
|
+
route("/test/", PageComponent),
|
|
1061
|
+
]);
|
|
1062
|
+
const deps = createMockDependencies();
|
|
1063
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/test/");
|
|
1064
|
+
const request = new Request("http://localhost:3000/test/");
|
|
1065
|
+
const response = await router.handle({
|
|
1066
|
+
request,
|
|
1067
|
+
renderPage: deps.mockRenderPage,
|
|
1068
|
+
getRequestInfo: deps.getRequestInfo,
|
|
1069
|
+
onError: deps.onError,
|
|
1070
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
1071
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
1072
|
+
});
|
|
1073
|
+
expect(response.status).toBe(500);
|
|
1074
|
+
expect(await response.text()).toBe(`Caught: ${errorMessage}`);
|
|
1075
|
+
});
|
|
1076
|
+
it("should catch errors from route handlers (functions)", async () => {
|
|
1077
|
+
const errorMessage = "Handler error";
|
|
1078
|
+
const routeHandler = () => {
|
|
1079
|
+
throw new Error(errorMessage);
|
|
1080
|
+
};
|
|
1081
|
+
const errorHandler = except((error) => {
|
|
1082
|
+
return new Response(`Caught: ${error instanceof Error ? error.message : String(error)}`, {
|
|
1083
|
+
status: 500,
|
|
1084
|
+
});
|
|
1085
|
+
});
|
|
1086
|
+
const router = defineRoutes([
|
|
1087
|
+
errorHandler,
|
|
1088
|
+
route("/test/", routeHandler),
|
|
1089
|
+
]);
|
|
1090
|
+
const deps = createMockDependencies();
|
|
1091
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/test/");
|
|
1092
|
+
const request = new Request("http://localhost:3000/test/");
|
|
1093
|
+
const response = await router.handle({
|
|
1094
|
+
request,
|
|
1095
|
+
renderPage: deps.mockRenderPage,
|
|
1096
|
+
getRequestInfo: deps.getRequestInfo,
|
|
1097
|
+
onError: deps.onError,
|
|
1098
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
1099
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
1100
|
+
});
|
|
1101
|
+
expect(response.status).toBe(500);
|
|
1102
|
+
expect(await response.text()).toBe(`Caught: ${errorMessage}`);
|
|
1103
|
+
});
|
|
1104
|
+
it("should catch errors from RSC actions", async () => {
|
|
1105
|
+
const errorMessage = "RSC action error";
|
|
1106
|
+
const errorHandler = except((error) => {
|
|
1107
|
+
return new Response(`Caught: ${error instanceof Error ? error.message : String(error)}`, {
|
|
1108
|
+
status: 500,
|
|
1109
|
+
});
|
|
1110
|
+
});
|
|
1111
|
+
const router = defineRoutes([
|
|
1112
|
+
errorHandler,
|
|
1113
|
+
route("/test/", () => React.createElement("div")),
|
|
1114
|
+
]);
|
|
1115
|
+
const deps = createMockDependencies();
|
|
1116
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/test/?__rsc_action_id=test");
|
|
1117
|
+
deps.mockRscActionHandler = async () => {
|
|
1118
|
+
throw new Error(errorMessage);
|
|
1119
|
+
};
|
|
1120
|
+
const request = new Request("http://localhost:3000/test/?__rsc_action_id=test");
|
|
1121
|
+
const response = await router.handle({
|
|
1122
|
+
request,
|
|
1123
|
+
renderPage: deps.mockRenderPage,
|
|
1124
|
+
getRequestInfo: deps.getRequestInfo,
|
|
1125
|
+
onError: deps.onError,
|
|
1126
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
1127
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
1128
|
+
});
|
|
1129
|
+
expect(response.status).toBe(500);
|
|
1130
|
+
expect(await response.text()).toBe(`Caught: ${errorMessage}`);
|
|
1131
|
+
});
|
|
1132
|
+
it("should use the most recent except handler before the error", async () => {
|
|
1133
|
+
const errorMessage = "Route error";
|
|
1134
|
+
const firstHandler = except((error) => {
|
|
1135
|
+
return new Response("First handler", { status: 500 });
|
|
1136
|
+
});
|
|
1137
|
+
const secondHandler = except((error) => {
|
|
1138
|
+
return new Response("Second handler", { status: 500 });
|
|
1139
|
+
});
|
|
1140
|
+
const PageComponent = () => {
|
|
1141
|
+
throw new Error(errorMessage);
|
|
1142
|
+
};
|
|
1143
|
+
const router = defineRoutes([
|
|
1144
|
+
firstHandler,
|
|
1145
|
+
secondHandler,
|
|
1146
|
+
route("/test/", PageComponent),
|
|
1147
|
+
]);
|
|
1148
|
+
const deps = createMockDependencies();
|
|
1149
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/test/");
|
|
1150
|
+
const request = new Request("http://localhost:3000/test/");
|
|
1151
|
+
const response = await router.handle({
|
|
1152
|
+
request,
|
|
1153
|
+
renderPage: deps.mockRenderPage,
|
|
1154
|
+
getRequestInfo: deps.getRequestInfo,
|
|
1155
|
+
onError: deps.onError,
|
|
1156
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
1157
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
1158
|
+
});
|
|
1159
|
+
// Should use the second handler (most recent before the route)
|
|
1160
|
+
expect(response.status).toBe(500);
|
|
1161
|
+
expect(await response.text()).toBe("Second handler");
|
|
1162
|
+
});
|
|
1163
|
+
it("should try next except handler if current one throws", async () => {
|
|
1164
|
+
const errorMessage = "Route error";
|
|
1165
|
+
const firstHandler = except(() => {
|
|
1166
|
+
throw new Error("First handler error");
|
|
1167
|
+
});
|
|
1168
|
+
const secondHandler = except((error) => {
|
|
1169
|
+
return new Response(`Caught by second: ${error instanceof Error ? error.message : String(error)}`, {
|
|
1170
|
+
status: 500,
|
|
1171
|
+
});
|
|
1172
|
+
});
|
|
1173
|
+
const PageComponent = () => {
|
|
1174
|
+
throw new Error(errorMessage);
|
|
1175
|
+
};
|
|
1176
|
+
const router = defineRoutes([
|
|
1177
|
+
secondHandler, // Outer handler
|
|
1178
|
+
firstHandler, // Inner handler (closer to route)
|
|
1179
|
+
route("/test/", PageComponent),
|
|
1180
|
+
]);
|
|
1181
|
+
const deps = createMockDependencies();
|
|
1182
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/test/");
|
|
1183
|
+
const request = new Request("http://localhost:3000/test/");
|
|
1184
|
+
const response = await router.handle({
|
|
1185
|
+
request,
|
|
1186
|
+
renderPage: deps.mockRenderPage,
|
|
1187
|
+
getRequestInfo: deps.getRequestInfo,
|
|
1188
|
+
onError: deps.onError,
|
|
1189
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
1190
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
1191
|
+
});
|
|
1192
|
+
// Should catch the error from the first handler with the second handler
|
|
1193
|
+
expect(response.status).toBe(500);
|
|
1194
|
+
expect(await response.text()).toBe("Caught by second: First handler error");
|
|
1195
|
+
});
|
|
1196
|
+
it("should return JSX element from except handler", async () => {
|
|
1197
|
+
const errorMessage = "Route error";
|
|
1198
|
+
function ErrorComponent() {
|
|
1199
|
+
return React.createElement("div", {}, "Error Page");
|
|
1200
|
+
}
|
|
1201
|
+
const errorHandler = except(() => {
|
|
1202
|
+
return React.createElement(ErrorComponent);
|
|
1203
|
+
});
|
|
1204
|
+
const PageComponent = () => {
|
|
1205
|
+
throw new Error(errorMessage);
|
|
1206
|
+
};
|
|
1207
|
+
const router = defineRoutes([
|
|
1208
|
+
errorHandler,
|
|
1209
|
+
route("/test/", PageComponent),
|
|
1210
|
+
]);
|
|
1211
|
+
const deps = createMockDependencies();
|
|
1212
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/test/");
|
|
1213
|
+
const request = new Request("http://localhost:3000/test/");
|
|
1214
|
+
const response = await router.handle({
|
|
1215
|
+
request,
|
|
1216
|
+
renderPage: deps.mockRenderPage,
|
|
1217
|
+
getRequestInfo: deps.getRequestInfo,
|
|
1218
|
+
onError: deps.onError,
|
|
1219
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
1220
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
1221
|
+
});
|
|
1222
|
+
expect(await response.text()).toBe("Rendered: ErrorComponent");
|
|
1223
|
+
});
|
|
1224
|
+
it("should work with prefix and layout", async () => {
|
|
1225
|
+
const errorMessage = "Route error";
|
|
1226
|
+
const errorHandler = except((error) => {
|
|
1227
|
+
return new Response(`Caught: ${error instanceof Error ? error.message : String(error)}`, {
|
|
1228
|
+
status: 500,
|
|
1229
|
+
});
|
|
1230
|
+
});
|
|
1231
|
+
const PageComponent = () => {
|
|
1232
|
+
throw new Error(errorMessage);
|
|
1233
|
+
};
|
|
1234
|
+
const Layout = ({ children }) => {
|
|
1235
|
+
return React.createElement("div", {}, children);
|
|
1236
|
+
};
|
|
1237
|
+
const router = defineRoutes([
|
|
1238
|
+
errorHandler,
|
|
1239
|
+
layout(Layout, [prefix("/api", [route("/test/", PageComponent)])]),
|
|
1240
|
+
]);
|
|
1241
|
+
const deps = createMockDependencies();
|
|
1242
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/api/test/");
|
|
1243
|
+
const request = new Request("http://localhost:3000/api/test/");
|
|
1244
|
+
const response = await router.handle({
|
|
1245
|
+
request,
|
|
1246
|
+
renderPage: deps.mockRenderPage,
|
|
1247
|
+
getRequestInfo: deps.getRequestInfo,
|
|
1248
|
+
onError: deps.onError,
|
|
1249
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
1250
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
1251
|
+
});
|
|
1252
|
+
expect(response.status).toBe(500);
|
|
1253
|
+
expect(await response.text()).toBe(`Caught: ${errorMessage}`);
|
|
1254
|
+
});
|
|
1255
|
+
});
|
|
646
1256
|
});
|