mirror of
https://github.com/zenstackhq/zenstack
synced 2026-05-24 10:08:55 +00:00
137 lines
5.1 KiB
TypeScript
137 lines
5.1 KiB
TypeScript
/**
|
|
* @vitest-environment happy-dom
|
|
*/
|
|
|
|
import { act, renderHook, waitFor } from '@testing-library/react';
|
|
import { deserialize, serialize } from '@zenstackhq/client-helpers/fetch';
|
|
import nock from 'nock';
|
|
import { describe, expect, it } from 'vitest';
|
|
import { AnyNull, DbNull, JsonNull, useClientQueries } from '../../src/react';
|
|
import { schema } from '../schemas/basic/schema-lite';
|
|
import { BASE_URL, createWrapper, registerCleanup } from './helpers';
|
|
|
|
registerCleanup();
|
|
|
|
describe('JSON null value serialization', () => {
|
|
it('encodes DbNull in query filter and includes serialization metadata in URL', async () => {
|
|
const { wrapper } = createWrapper();
|
|
let capturedUri = '';
|
|
|
|
nock(BASE_URL)
|
|
.get(/.*/)
|
|
.reply(200, function (uri) {
|
|
capturedUri = uri;
|
|
return { data: [] };
|
|
});
|
|
|
|
const { result } = renderHook(
|
|
() => useClientQueries(schema).user.useFindMany({ where: { name: DbNull } } as any),
|
|
{ wrapper },
|
|
);
|
|
|
|
await waitFor(() => expect(result.current.isSuccess).toBe(true));
|
|
|
|
const url = new URL(capturedUri, BASE_URL);
|
|
expect(url.searchParams.has('meta')).toBe(true);
|
|
|
|
const q = JSON.parse(decodeURIComponent(url.searchParams.get('q')!));
|
|
const meta = JSON.parse(decodeURIComponent(url.searchParams.get('meta')!));
|
|
const reconstructed = deserialize(q, meta.serialization) as any;
|
|
expect(reconstructed.where.name.__brand).toBe('DbNull');
|
|
});
|
|
|
|
it('encodes JsonNull in query filter and includes serialization metadata in URL', async () => {
|
|
const { wrapper } = createWrapper();
|
|
let capturedUri = '';
|
|
|
|
nock(BASE_URL)
|
|
.get(/.*/)
|
|
.reply(200, function (uri) {
|
|
capturedUri = uri;
|
|
return { data: [] };
|
|
});
|
|
|
|
const { result } = renderHook(
|
|
() => useClientQueries(schema).user.useFindMany({ where: { name: JsonNull } } as any),
|
|
{ wrapper },
|
|
);
|
|
|
|
await waitFor(() => expect(result.current.isSuccess).toBe(true));
|
|
|
|
const url = new URL(capturedUri, BASE_URL);
|
|
expect(url.searchParams.has('meta')).toBe(true);
|
|
|
|
const q = JSON.parse(decodeURIComponent(url.searchParams.get('q')!));
|
|
const meta = JSON.parse(decodeURIComponent(url.searchParams.get('meta')!));
|
|
const reconstructed = deserialize(q, meta.serialization) as any;
|
|
expect(reconstructed.where.name.__brand).toBe('JsonNull');
|
|
});
|
|
|
|
it('encodes AnyNull in query filter and includes serialization metadata in URL', async () => {
|
|
const { wrapper } = createWrapper();
|
|
let capturedUri = '';
|
|
|
|
nock(BASE_URL)
|
|
.get(/.*/)
|
|
.reply(200, function (uri) {
|
|
capturedUri = uri;
|
|
return { data: [] };
|
|
});
|
|
|
|
const { result } = renderHook(
|
|
() => useClientQueries(schema).user.useFindMany({ where: { name: AnyNull } } as any),
|
|
{ wrapper },
|
|
);
|
|
|
|
await waitFor(() => expect(result.current.isSuccess).toBe(true));
|
|
|
|
const url = new URL(capturedUri, BASE_URL);
|
|
expect(url.searchParams.has('meta')).toBe(true);
|
|
|
|
const q = JSON.parse(decodeURIComponent(url.searchParams.get('q')!));
|
|
const meta = JSON.parse(decodeURIComponent(url.searchParams.get('meta')!));
|
|
const reconstructed = deserialize(q, meta.serialization) as any;
|
|
expect(reconstructed.where.name.__brand).toBe('AnyNull');
|
|
});
|
|
|
|
it('encodes DbNull in mutation body with serialization metadata', async () => {
|
|
const { wrapper } = createWrapper();
|
|
let capturedBody: any;
|
|
|
|
nock(BASE_URL)
|
|
.post(/.*/)
|
|
.reply(200, function (_uri, body) {
|
|
capturedBody = body;
|
|
return { data: { id: '1', name: null } };
|
|
});
|
|
|
|
const { result } = renderHook(() => useClientQueries(schema).user.useCreate(), { wrapper });
|
|
|
|
act(() => result.current.mutate({ data: { email: 'test@example.com', name: DbNull } } as any));
|
|
|
|
await waitFor(() => expect(result.current.isSuccess).toBe(true));
|
|
|
|
expect(capturedBody.meta?.serialization).toBeDefined();
|
|
const reconstructed = deserialize({ data: capturedBody.data }, capturedBody.meta.serialization) as any;
|
|
expect(reconstructed.data.name.__brand).toBe('DbNull');
|
|
});
|
|
|
|
it('deserializes null sentinels in server response back to branded instances', async () => {
|
|
const { wrapper } = createWrapper();
|
|
|
|
const responseData = { id: '1', email: 'test@example.com', name: DbNull };
|
|
const { data: serializedData, meta: serializedMeta } = serialize(responseData);
|
|
|
|
nock(BASE_URL)
|
|
.get(/.*/)
|
|
.reply(200, { data: serializedData, meta: { serialization: serializedMeta } });
|
|
|
|
const { result } = renderHook(() => useClientQueries(schema).user.useFindUnique({ where: { id: '1' } }), {
|
|
wrapper,
|
|
});
|
|
|
|
await waitFor(() => expect(result.current.isSuccess).toBe(true));
|
|
|
|
expect((result.current.data as any).name.__brand).toBe('DbNull');
|
|
});
|
|
});
|