test("should handle all TypedArray types", async () => {
const data = {
int8: new Int8Array([1, 2, 3]),
uint8: new Uint8Array([4, 5, 6]),
uint8clamped: new Uint8ClampedArray([7, 8, 9]),
int16: new Int16Array([10, 11, 12]),
uint16: new Uint16Array([13, 14, 15]),
int32: new Int32Array([16, 17, 18]),
uint32: new Uint32Array([19, 20, 21]),
float32: new Float32Array([1.1, 2.2, 3.3]),
float64: new Float64Array([4.4, 5.5, 6.6]),
bigInt64: new BigInt64Array([1n, 2n, 3n]),
bigUint64: new BigUint64Array([4n, 5n, 6n]),
};
const stream = renderToReadableStream(data);
const result = await createFromReadableStream(stream);
expect(result.int8).toBeInstanceOf(Int8Array);
expect(result.uint8).toBeInstanceOf(Uint8Array);
expect(result.uint8clamped).toBeInstanceOf(Uint8ClampedArray);
expect(result.int16).toBeInstanceOf(Int16Array);
expect(result.uint16).toBeInstanceOf(Uint16Array);
expect(result.int32).toBeInstanceOf(Int32Array);
expect(result.uint32).toBeInstanceOf(Uint32Array);
expect(result.float32).toBeInstanceOf(Float32Array);
expect(result.float64).toBeInstanceOf(Float64Array);
expect(result.bigInt64).toBeInstanceOf(BigInt64Array);
expect(result.bigUint64).toBeInstanceOf(BigUint64Array);
});
test("should handle Date at epoch", async () => {
const data = {
epoch: new Date(0),
negative: new Date(-1000),
};
const stream = renderToReadableStream(data);
const result = await createFromReadableStream(stream);
expect(result.epoch.getTime()).toBe(0);
expect(result.negative.getTime()).toBe(-1000);
});
test("should handle Symbol.for with various names", async () => {
const data = {
sym1: Symbol.for("custom.symbol"),
sym2: Symbol.for("another.symbol"),
sym3: Symbol.for(""), // Empty string symbol
};
const stream = renderToReadableStream(data);
const result = await createFromReadableStream(stream);
expect(result.sym1).toBe(Symbol.for("custom.symbol"));
expect(result.sym2).toBe(Symbol.for("another.symbol"));
});
test("should handle RegExp with all flag combinations", async () => {
const data = {
basic: /test/,
global: /test/g,
ignoreCase: /test/i,
multiline: /test/m,
dotAll: /test/s,
unicode: /test/u,
sticky: /test/y,
combined: /test/gimsu,
};
const stream = renderToReadableStream(data);
const result = await createFromReadableStream(stream);
expect(result.basic.source).toBe("test");
expect(result.global.flags).toContain("g");
expect(result.ignoreCase.flags).toContain("i");
expect(result.multiline.flags).toContain("m");
});
test("should handle complex nested structures", async () => {
const data = {
level1: {
level2: {
level3: {
array: [{ map: new Map([["k", "v"]]) }, { set: new Set([1, 2]) }],
date: new Date("2024-01-01"),
bigint: BigInt(123456789),
regex: /pattern/gi,
},
},
},
};
const stream = renderToReadableStream(data);
const result = await createFromReadableStream(stream);
expect(result.level1.level2.level3.array[0].map).toBeInstanceOf(Map);
expect(result.level1.level2.level3.array[1].set).toBeInstanceOf(Set);
expect(result.level1.level2.level3.date).toBeInstanceOf(Date);
expect(result.level1.level2.level3.bigint).toBe(BigInt(123456789));
expect(result.level1.level2.level3.regex).toBeInstanceOf(RegExp);
});
});
describe("createFromFetch error handling", () => {
test("should throw error for non-ok HTTP response", async () => {
const mockResponse = {
ok: false,
status: 404,
statusText: "Not Found",
};
await expect(
createFromFetch(Promise.resolve(mockResponse))
).rejects.toThrow("HTTP 404: Not Found");
});
test("should throw error for 500 Internal Server Error", async () => {
const mockResponse = {
ok: false,
status: 500,
statusText: "Internal Server Error",
};
await expect(
createFromFetch(Promise.resolve(mockResponse))
).rejects.toThrow("HTTP 500: Internal Server Error");
});
test("should throw error when response has no body", async () => {
const mockResponse = {
ok: true,
status: 200,
statusText: "OK",
body: null,
};
await expect(
createFromFetch(Promise.resolve(mockResponse))
).rejects.toThrow("Response has no body");
});
test("should throw error when response body is undefined", async () => {
const mockResponse = {
ok: true,
status: 200,
statusText: "OK",
body: undefined,
};
await expect(
createFromFetch(Promise.resolve(mockResponse))
).rejects.toThrow("Response has no body");
});
});
describe("Client reference resolution errors", () => {
test("should serialize error when client reference cannot be resolved", async () => {
// Create a client reference without $$id and without a resolver
const unresolvedClientRef = {
$$typeof: Symbol.for("react.client.reference"),
// No $$id property
};
const stream = renderToReadableStream(unresolvedClientRef, {
moduleResolver: {
resolveClientReference: () => null, // Resolver returns null
},
});
// The stream should contain an error row with the message
const output = await streamToString(stream);
expect(output).toContain("Client reference could not be resolved");
});
test("should serialize error for client component without resolver or id", async () => {
// Create a client component reference as a React element
const ClientComponent = function ClientComponent() {
return { type: "div" };
};
ClientComponent.$$typeof = Symbol.for("react.client.reference");
// No $$id and resolver returns null
const element = {
$$typeof: Symbol.for("react.transitional.element"),
type: ClientComponent,
props: {},
key: null,
ref: null,
};
const stream = renderToReadableStream(element, {
moduleResolver: {
resolveClientReference: () => null,
},
});
// Should contain error - either "could not be resolved" or "Unsupported element type"
const output = await streamToString(stream);
expect(output).toContain("E{"); // Error row marker