From 5b36355537311048851478449c4c4e91c5cbe6e0 Mon Sep 17 00:00:00 2001 From: Gao Sun Date: Mon, 6 Sep 2021 10:39:39 +0800 Subject: [PATCH] test(core): add unit tests for database insert into factory (#109) --- .../core/src/database/insert-into.test.ts | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 packages/core/src/database/insert-into.test.ts diff --git a/packages/core/src/database/insert-into.test.ts b/packages/core/src/database/insert-into.test.ts new file mode 100644 index 000000000..62e14a83a --- /dev/null +++ b/packages/core/src/database/insert-into.test.ts @@ -0,0 +1,72 @@ +import { UserDBEntry, Users } from '@logto/schemas'; +import decamelize from 'decamelize'; + +import RequestError from '@/errors/RequestError'; +import { createTestPool } from '@/utils/test-utils'; + +import { buildInsertInto } from './insert-into'; +import { convertToIdentifiers, excludeAutoSetFields } from './utils'; + +describe('buildInsertInto()', () => { + const keys = excludeAutoSetFields(Users.fieldKeys); + const expectInsertIntoSql = [ + `insert into "users" (${keys.map((key) => `"${decamelize(key)}"`).join(', ')})`, + `values (${keys.map((_, index) => `$${index + 1}`).join(', ')})`, + ]; + + it('resolves a promise with `undefined` when `returning` is false', async () => { + const pool = createTestPool(expectInsertIntoSql.join('\n')); + const insertInto = buildInsertInto(pool, Users); + await expect(insertInto({ id: 'foo', username: '456' })).resolves.toBe(undefined); + }); + + it('resolves a promise with `undefined` when `returning` is false and `onConflict` is enabled', async () => { + const pool = createTestPool( + [ + ...expectInsertIntoSql, + 'on conflict ("id", "username") do update', + 'set "primary_email"=excluded."primary_email"', + ].join('\n') + ); + const { fields } = convertToIdentifiers(Users); + const insertInto = buildInsertInto(pool, Users, { + onConflict: { + fields: [fields.id, fields.username], + setExcludedFields: [fields.primaryEmail], + }, + }); + await expect( + insertInto({ id: 'foo', username: '456', primaryEmail: 'foo@bar.com' }) + ).resolves.toBe(undefined); + }); + + it('resolves a promise with single entity when `returning` is true', async () => { + const user: UserDBEntry = { id: 'foo', username: '123', primaryEmail: 'foo@bar.com' }; + const pool = createTestPool( + [...expectInsertIntoSql, 'returning *'].join('\n'), + (_, [id, username, primaryEmail]) => ({ + id: String(id), + username: String(username), + primaryEmail: String(primaryEmail), + }) + ); + const insertInto = buildInsertInto(pool, Users, { returning: true }); + await expect( + insertInto({ id: 'foo', username: '123', primaryEmail: 'foo@bar.com' }) + ).resolves.toStrictEqual(user); + }); + + it('throws `entity.create_failed` error with `undefined` when `returning` is true', async () => { + const pool = createTestPool([...expectInsertIntoSql, 'returning *'].join('\n')); + const insertInto = buildInsertInto(pool, Users, { returning: true }); + + await expect( + insertInto({ id: 'foo', username: '123', primaryEmail: 'foo@bar.com' }) + ).rejects.toMatchError( + new RequestError({ + code: 'entity.create_failed', + name: Users.tableSingular, + }) + ); + }); +});