Skip to content

Commit

Permalink
fix: fixed tests
Browse files Browse the repository at this point in the history
Signed-off-by: Jim Ezesinachi <ezesinachijim@gmail.com>
  • Loading branch information
jimezesinachi committed May 8, 2024
1 parent e4b7b0d commit 4aab9c0
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 158 deletions.
6 changes: 6 additions & 0 deletions packages/backend/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
export { collectLast } from './util/generators/collectLast';
export {
type ExpressSynthqlHandler,
type ExpressSynthqlHandlerRequest,
type ExpressSynthqlHandlerResponse,
createExpressSynthqlHandler,
} from './util/handlers/createExpressSynthqlHandler';

export type * from './types/QueryPlan';
export * from './QueryEngine';
27 changes: 0 additions & 27 deletions packages/backend/src/tests/createHttpServer.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,102 +1,23 @@
import { afterAll, beforeAll, describe, expect, test } from 'vitest';
import {
type ExpressSynthqlHandler,
createExpressSynthqlHandler,
} from './createExpressSynthqlHandler';
import { queryEngine } from '../../tests/queryEngine';
import { getMockReq, getMockRes } from 'vitest-mock-express';
import { describe, test } from 'vitest';
import { query } from '@synthql/queries';

import { DB } from '../../tests/db';
const from = query<DB>().from;

import { HttpServer, createHttpServer } from '../../tests/createHttpServer';
import { query } from '@synthql/queries';

describe('createExpressSynthqlHandler', () => {
let httpServer: HttpServer;
let handler: ExpressSynthqlHandler;

beforeAll(async () => {
handler = await createExpressSynthqlHandler<DB>(queryEngine);

// httpServer = await createHttpServer(handler);
});

afterAll(() => {
// httpServer?.server.close();
});

test(`Query execution is successful`, async () => {
const q = from('actor')
.columns('actor_id', 'first_name', 'last_name')
.groupingId('actor_id')
.where({ actor_id: { in: [1] } })
.one();

// Mock Express request object
const request = {
method: 'POST',
url: '/synthql',
body: JSON.stringify(q),
};

const req = getMockReq(request);
const { res } = getMockRes();

handler(req, res);

expect(req.body).toEqual(request.body);

expect(res.status).toHaveBeenCalledWith(200);

expect(res.setHeader).toHaveBeenCalledWith(
'Content-Type',
'application/x-ndjson',
);

expect(res.write).toHaveBeenCalledWith(expect.stringContaining('\n'));

expect(res.end).toHaveBeenCalled();
});

test(`Query execution is successful with returnLastOnly passed`, async () => {
const handler = await createExpressSynthqlHandler<DB>(queryEngine);

const q = from('actor')
.columns('actor_id', 'first_name', 'last_name')
.groupingId('actor_id')
.where({ actor_id: { in: [1] } })
.maybe();

// Mock Express request object
const request = {
method: 'POST',
url: '/synthql',
body: JSON.stringify(q),
headers: {
'x-return-last-only': 'true',
},
};

const req = getMockReq(request);
const { res } = getMockRes();

handler(req, res);

expect(req.headers['x-return-last-only']).toEqual(
request.headers['x-return-last-only'],
);

expect(req.body).toEqual(request.body);

expect(res.status).toHaveBeenCalledWith(200);

expect(res.setHeader).toHaveBeenCalledWith(
'Content-Type',
'application/x-ndjson',
);

expect(res.write).toHaveBeenCalledWith(expect.stringContaining('\n'));

expect(res.end).toHaveBeenCalled();
});
});
36 changes: 22 additions & 14 deletions packages/backend/src/util/handlers/createExpressSynthqlHandler.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
import { QueryEngine, collectLast } from '../..';
import type { Request, Response } from 'express';

export type ExpressSynthqlHandler = (req: Request, res: Response) => void;
export type ExpressSynthqlHandlerRequest = Pick<Request, 'body' | 'headers'>;

export async function createExpressSynthqlHandler<T>(
export type ExpressSynthqlHandlerResponse = Pick<
Response,
'statusCode' | 'write' | 'setHeader' | 'end'
>;

export type ExpressSynthqlHandler = (
req: ExpressSynthqlHandlerRequest,
res: ExpressSynthqlHandlerResponse,
) => void;

export function createExpressSynthqlHandler<T>(
queryEngine: QueryEngine<T>,
): Promise<ExpressSynthqlHandler> {
): ExpressSynthqlHandler {
return async (req, res) => {
try {
const headers = req.headers;
Expand All @@ -22,28 +32,24 @@ export async function createExpressSynthqlHandler<T>(
}),
);

res.status(200);
res.statusCode = 200;

res.setHeader('Content-Type', 'application/x-ndjson');
res.setHeader('Content-Type', 'application/json');

res.write(JSON.stringify(result));

res.write('\n');

res.end();
} catch (error) {
res.status(400);
res.statusCode = 500;

res.setHeader('Content-Type', 'application/x-ndjson');
res.setHeader('Content-Type', 'application/json');

res.write(JSON.stringify({ error: String(error) }));

res.write('\n');

res.end();
}
} else {
res.status(200);
res.statusCode = 200;

res.setHeader('Content-Type', 'application/x-ndjson');

Expand All @@ -58,9 +64,11 @@ export async function createExpressSynthqlHandler<T>(
res.end();
}
} catch (error) {
res.write(JSON.stringify({ error: String(error) }));
res.statusCode = 400;

res.setHeader('Content-Type', 'application/json');

res.write('\n');
res.write(JSON.stringify({ error: 'Invalid JSON body' }));

res.end();
}
Expand Down
2 changes: 1 addition & 1 deletion packages/docs/static/reference/assets/navigation.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/docs/static/reference/assets/search.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

46 changes: 46 additions & 0 deletions packages/react/src/test/appendBody.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { IncomingMessage, ServerResponse } from 'http';
import {
ExpressSynthqlHandler,
ExpressSynthqlHandlerRequest,
ExpressSynthqlHandlerResponse,
} from '@synthql/backend';

function readBody(req: IncomingMessage): Promise<string> {
return new Promise((resolve, reject) => {
let body = '';

req.on('data', (chunk) => {
body += chunk;
});

req.on('end', () => {
resolve(body);
});

req.on('error', (e) => {
reject(e);
});
});
}

export type IncomingMessageWithBody = IncomingMessage &
ExpressSynthqlHandlerRequest;

export type ServerResponseWithEnd = ServerResponse &
ExpressSynthqlHandlerResponse;

export function appendBody(expressHandler: ExpressSynthqlHandler) {
return async (req: IncomingMessage, res: ServerResponse) => {
const body = await readBody(req);

const newReq = {
...req,
headers: req.headers,
body: body,
} as IncomingMessageWithBody;

const newRes = res as ServerResponseWithEnd;

expressHandler(newReq, newRes);
};
}
41 changes: 8 additions & 33 deletions packages/react/src/test/createPagilaServer.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { QueryEngine } from '@synthql/backend';
import { DB } from './db';
import { QueryEngine, createExpressSynthqlHandler } from '@synthql/backend';
import http from 'http';

import { DB } from './db';
import { appendBody } from './appendBody';

export interface PagilaServer {
url: string;
server: http.Server;
Expand All @@ -13,42 +15,15 @@ export function createPagilaServer({
queryEngine: QueryEngine<DB>;
}): Promise<PagilaServer> {
return new Promise((resolve, reject) => {
const server = http.createServer((req, res) => {
let body = '';

req.on('data', (chunk) => {
body += chunk;
});

req.on('end', async () => {
const headers = req.headers;
const handler = createExpressSynthqlHandler<DB>(queryEngine);

const json = JSON.parse(body);
const nodeHandler = appendBody(handler);

res.writeHead(200, { 'Content-Type': 'application/json' });

try {
for await (const intermediateResult of queryEngine.execute(
json,
{
returnLastOnly:
headers['x-return-last-only'] === 'true',
},
)) {
res.write(JSON.stringify(intermediateResult) + '\n');
}

res.end();
} catch (error) {
res.write(JSON.stringify({ error: String(error) }) + '\n');

res.end();
}
});
});
const server = http.createServer(nodeHandler);

server.listen(() => {
const address = server.address();

if (typeof address === 'string' || address === null) {
reject('Failed to get server address: ' + address);
} else {
Expand Down

0 comments on commit 4aab9c0

Please sign in to comment.