Skip to content

Commit

Permalink
fixes jlalmes#14 add transformer serizliation to emited data in subsc…
Browse files Browse the repository at this point in the history
…ription routes
  • Loading branch information
firemuzzy committed Nov 20, 2023
1 parent af6cc54 commit 5c472d6
Show file tree
Hide file tree
Showing 3 changed files with 275 additions and 1 deletion.
3 changes: 2 additions & 1 deletion src/adapter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,11 @@ export const createChromeHandler = <TRouter extends AnyRouter>(

const subscription = result.subscribe({
next: (data) => {
const serializedData = transformer.output.serialize(data);
sendResponse({
result: {
type: 'data',
data,
data: serializedData,
},
});
},
Expand Down
45 changes: 45 additions & 0 deletions test/webext.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,51 @@ test('with subscription', async () => {
expect(onStoppedMock).toHaveBeenCalledTimes(1);
});

test('with nested subscription', async () => {
// background
createChromeHandler({ router: appRouter });
expect(chrome.runtime.onConnect.addListener).toHaveBeenCalledTimes(1);

// content
const port = chrome.runtime.connect();
const trpc = createTRPCProxyClient<typeof appRouter>({
links: [chromeLink({ port })],
});

const onDataMock = jest.fn();
const onCompleteMock = jest.fn();
const onErrorMock = jest.fn();
const onStartedMock = jest.fn();
const onStoppedMock = jest.fn();
const subscription = await new Promise<Unsubscribable>((resolve) => {
const subscription = trpc.nestedRouter.echoSubscription.subscribe(
{ payload: 'subscription1' },
{
onData: (data) => {
onDataMock(data);
resolve(subscription);
},
onComplete: onCompleteMock,
onError: onErrorMock,
onStarted: onStartedMock,
onStopped: onStoppedMock,
},
);
});
expect(onDataMock).toHaveBeenCalledTimes(1);
expect(onDataMock).toHaveBeenNthCalledWith(1, { payload: 'subscription1' });
expect(onCompleteMock).toHaveBeenCalledTimes(0);
expect(onErrorMock).toHaveBeenCalledTimes(0);
expect(onStartedMock).toHaveBeenCalledTimes(1);
expect(onStoppedMock).toHaveBeenCalledTimes(0);
subscription.unsubscribe();
expect(onDataMock).toHaveBeenCalledTimes(1);
expect(onCompleteMock).toHaveBeenCalledTimes(1);
expect(onErrorMock).toHaveBeenCalledTimes(0);
expect(onStartedMock).toHaveBeenCalledTimes(1);
expect(onStoppedMock).toHaveBeenCalledTimes(1);
});

// with subscription
// with error
// with createcontext
Expand Down
228 changes: 228 additions & 0 deletions test/webextWTransfromer.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
import { resetMocks } from './__setup';

import { createTRPCProxyClient } from '@trpc/client';
import { initTRPC } from '@trpc/server';
import { Unsubscribable, observable } from '@trpc/server/observable';
import superjson from 'superjson';
import { z } from 'zod';

import { createChromeHandler } from '../src/adapter';
import { chromeLink } from '../src/link';

afterEach(() => {
resetMocks();
});

const t = initTRPC.create({ transformer: superjson });

const appRouter = t.router({
echoQuery: t.procedure
.input(z.object({ payload: z.string(), date: z.date() }))
.query(({ input }) => input),
echoMutation: t.procedure
.input(z.object({ payload: z.string(), date: z.date() }))
.mutation(({ input }) => input),
echoSubscription: t.procedure
.input(z.object({ payload: z.string(), date: z.date() }))
.subscription(({ input }) =>
observable<typeof input>((emit) => {
emit.next(input);
}),
),

echoTransformerQuery: t.procedure
.input(z.object({ payload: z.date() }))
.query(({ input }) => input),

nestedRouter: t.router({
echoQuery: t.procedure
.input(z.object({ payload: z.string(), date: z.date() }))
.query(({ input }) => input),
echoMutation: t.procedure
.input(z.object({ payload: z.string(), date: z.date() }))
.mutation(({ input }) => input),
echoSubscription: t.procedure
.input(z.object({ payload: z.string(), date: z.date() }))
.subscription(({ input }) =>
observable((emit) => {
emit.next(input);
}),
),

echoTransformerQuery: t.procedure
.input(z.object({ payload: z.date() }))
.query(({ input }) => input),
}),
});

test('with query', async () => {
// background
createChromeHandler({ router: appRouter });
expect(chrome.runtime.onConnect.addListener).toHaveBeenCalledTimes(1);

// content
const port = chrome.runtime.connect();
const trpc = createTRPCProxyClient<typeof appRouter>({
links: [chromeLink({ port })],
transformer: superjson,
});

// 2023-11-17 08:00:00 utc
const date1 = new Date(1700208000000);
const data1 = await trpc.echoQuery.query({ payload: 'query1', date: date1 });
expect(data1).toEqual({ payload: 'query1', date: date1 });

// 2023-11-20 08:00:00 utc
const date2 = new Date(1700467200000);
const data2 = await trpc.nestedRouter.echoQuery.query({ payload: 'query2', date: date2 });
expect(data2).toEqual({ payload: 'query2', date: date2 });

// 2022-11-20 08:00:00 utc
const date3 = new Date(1668931200000);
// 2021-11-20 08:00:00 utc
const date4 = new Date(1637395200000);
const [data3, data4] = await Promise.all([
trpc.echoQuery.query({ payload: 'query3', date: date3 }),
trpc.echoQuery.query({ payload: 'query4', date: date4 }),
]);
expect(data3).toEqual({ payload: 'query3', date: date3 });
expect(data4).toEqual({ payload: 'query4', date: date4 });
});

test('with mutation', async () => {
// background
createChromeHandler({ router: appRouter });
expect(chrome.runtime.onConnect.addListener).toHaveBeenCalledTimes(1);

// content
const port = chrome.runtime.connect();
const trpc = createTRPCProxyClient<typeof appRouter>({
links: [chromeLink({ port })],
transformer: superjson,
});

// 2023-11-17 08:00:00 utc
const date1 = new Date(1700208000000);
const data1 = await trpc.echoMutation.mutate({ payload: 'mutation1', date: date1 });
expect(data1).toEqual({ payload: 'mutation1', date: date1 });

// 2023-11-20 08:00:00 utc
const date2 = new Date(1700467200000);
const data2 = await trpc.nestedRouter.echoMutation.mutate({ payload: 'mutation2', date: date2 });
expect(data2).toEqual({ payload: 'mutation2', date: date2 });

// 2022-11-20 08:00:00 utc
const date3 = new Date(1668931200000);
// 2021-11-20 08:00:00 utc
const date4 = new Date(1637395200000);
const [data3, data4] = await Promise.all([
trpc.echoMutation.mutate({ payload: 'mutation3', date: date3 }),
trpc.echoMutation.mutate({ payload: 'mutation4', date: date4 }),
]);
expect(data3).toEqual({ payload: 'mutation3', date: date3 });
expect(data4).toEqual({ payload: 'mutation4', date: date4 });
});

test('with subscription', async () => {
// background
createChromeHandler({ router: appRouter });
expect(chrome.runtime.onConnect.addListener).toHaveBeenCalledTimes(1);

// content
const port = chrome.runtime.connect();
const trpc = createTRPCProxyClient<typeof appRouter>({
links: [chromeLink({ port })],
transformer: superjson,
});

const onDataMock = jest.fn();
const onCompleteMock = jest.fn();
const onErrorMock = jest.fn();
const onStartedMock = jest.fn();
const onStoppedMock = jest.fn();

// 2023-11-17 08:00:00 utc
const date1 = new Date(1700208000000);
const subscription = await new Promise<Unsubscribable>((resolve) => {
const subscription = trpc.echoSubscription.subscribe(
{ payload: 'subscription1', date: date1 },
{
onData: (data) => {
onDataMock(data);
resolve(subscription);
},
onComplete: onCompleteMock,
onError: onErrorMock,
onStarted: onStartedMock,
onStopped: onStoppedMock,
},
);
});
expect(onDataMock).toHaveBeenCalledTimes(1);
expect(onDataMock).toHaveBeenNthCalledWith(1, { payload: 'subscription1', date: date1 });
expect(onCompleteMock).toHaveBeenCalledTimes(0);
expect(onErrorMock).toHaveBeenCalledTimes(0);
expect(onStartedMock).toHaveBeenCalledTimes(1);
expect(onStoppedMock).toHaveBeenCalledTimes(0);
subscription.unsubscribe();
expect(onDataMock).toHaveBeenCalledTimes(1);
expect(onCompleteMock).toHaveBeenCalledTimes(1);
expect(onErrorMock).toHaveBeenCalledTimes(0);
expect(onStartedMock).toHaveBeenCalledTimes(1);
expect(onStoppedMock).toHaveBeenCalledTimes(1);
});

test('with nested subscription', async () => {
// background
createChromeHandler({ router: appRouter });
expect(chrome.runtime.onConnect.addListener).toHaveBeenCalledTimes(1);

// content
const port = chrome.runtime.connect();
const trpc = createTRPCProxyClient<typeof appRouter>({
links: [chromeLink({ port })],
transformer: superjson,
});

const onDataMock = jest.fn();
const onCompleteMock = jest.fn();
const onErrorMock = jest.fn();
const onStartedMock = jest.fn();
const onStoppedMock = jest.fn();

// 2023-11-20 08:00:00 utc
const date1 = new Date(1700467200000);
const subscription = await new Promise<Unsubscribable>((resolve) => {
const subscription = trpc.nestedRouter.echoSubscription.subscribe(
{ payload: 'subscription1', date: date1 },
{
onData: (data) => {
onDataMock(data);
resolve(subscription);
},
onComplete: onCompleteMock,
onError: onErrorMock,
onStarted: onStartedMock,
onStopped: onStoppedMock,
},
);
});
expect(onDataMock).toHaveBeenCalledTimes(1);
expect(onDataMock).toHaveBeenNthCalledWith(1, { payload: 'subscription1', date: date1 });
expect(onCompleteMock).toHaveBeenCalledTimes(0);
expect(onErrorMock).toHaveBeenCalledTimes(0);
expect(onStartedMock).toHaveBeenCalledTimes(1);
expect(onStoppedMock).toHaveBeenCalledTimes(0);
subscription.unsubscribe();
expect(onDataMock).toHaveBeenCalledTimes(1);
expect(onCompleteMock).toHaveBeenCalledTimes(1);
expect(onErrorMock).toHaveBeenCalledTimes(0);
expect(onStartedMock).toHaveBeenCalledTimes(1);
expect(onStoppedMock).toHaveBeenCalledTimes(1);
});

// with subscription
// with error
// with createcontext
// with output
// with multiport

0 comments on commit 5c472d6

Please sign in to comment.