mirror of
https://github.com/logto-io/logto.git
synced 2025-01-20 21:32:31 -05:00
test(core): add ut for application query (#282)
add ut for appliction query
This commit is contained in:
parent
409602beff
commit
2109b7be31
5 changed files with 196 additions and 11 deletions
|
@ -67,6 +67,7 @@
|
|||
"nock": "^13.2.2",
|
||||
"openapi-types": "^9.1.0",
|
||||
"prettier": "^2.3.2",
|
||||
"snake-case": "^3.0.4",
|
||||
"supertest": "^6.2.2",
|
||||
"ts-jest": "^27.0.5",
|
||||
"tsc-watch": "^4.4.0",
|
||||
|
|
176
packages/core/src/queries/application.test.ts
Normal file
176
packages/core/src/queries/application.test.ts
Normal file
|
@ -0,0 +1,176 @@
|
|||
import { Applications } from '@logto/schemas';
|
||||
import {
|
||||
createMockPool,
|
||||
createMockQueryResult,
|
||||
sql,
|
||||
QueryResultType,
|
||||
QueryResultRowType,
|
||||
} from 'slonik';
|
||||
import { PrimitiveValueExpressionType } from 'slonik/dist/src/types.d';
|
||||
import { snakeCase } from 'snake-case';
|
||||
|
||||
import {
|
||||
convertToIdentifiers,
|
||||
convertToPrimitiveOrSql,
|
||||
excludeAutoSetFields,
|
||||
} from '@/database/utils';
|
||||
import { DeletionError } from '@/errors/SlonikError';
|
||||
import { mockApplication } from '@/utils/mock';
|
||||
import { expectSqlAssert } from '@/utils/test-utils';
|
||||
|
||||
import {
|
||||
findTotalNumberOfApplications,
|
||||
findAllApplications,
|
||||
findApplicationById,
|
||||
insertApplication,
|
||||
updateApplicationById,
|
||||
deleteApplicationById,
|
||||
} from './application';
|
||||
|
||||
type MockQuery = (
|
||||
sql: string,
|
||||
values: PrimitiveValueExpressionType
|
||||
) => Promise<QueryResultType<QueryResultRowType>>;
|
||||
|
||||
const mockQuery: jest.MockedFunction<MockQuery> = jest.fn();
|
||||
|
||||
jest.mock('@/database/pool', () =>
|
||||
createMockPool({
|
||||
query: async (sql, values) => {
|
||||
return mockQuery(sql, values);
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
describe('appliaction query', () => {
|
||||
const { table, fields } = convertToIdentifiers(Applications);
|
||||
|
||||
it('findTotalNumberOfApplications', async () => {
|
||||
const expectSql = sql`
|
||||
select count(*)
|
||||
from ${table}
|
||||
`;
|
||||
|
||||
mockQuery.mockImplementationOnce(async (sql, values) => {
|
||||
expectSqlAssert(sql, expectSql.sql);
|
||||
expect(values).toEqual(expectSql.values);
|
||||
|
||||
return createMockQueryResult([{ count: 10 }]);
|
||||
});
|
||||
|
||||
await expect(findTotalNumberOfApplications()).resolves.toEqual({ count: 10 });
|
||||
});
|
||||
|
||||
it('findAllApplications', async () => {
|
||||
const limit = 10;
|
||||
const offset = 1;
|
||||
const rowData = { id: 'foo' };
|
||||
|
||||
const expectSql = sql`
|
||||
select ${sql.join(Object.values(fields), sql`, `)}
|
||||
from ${table}
|
||||
limit $1
|
||||
offset $2
|
||||
`;
|
||||
|
||||
mockQuery.mockImplementationOnce(async (sql, values) => {
|
||||
expectSqlAssert(sql, expectSql.sql);
|
||||
expect(values).toEqual([limit, offset]);
|
||||
|
||||
return createMockQueryResult([rowData]);
|
||||
});
|
||||
|
||||
await expect(findAllApplications(limit, offset)).resolves.toEqual([rowData]);
|
||||
});
|
||||
|
||||
it('findApplicationById', async () => {
|
||||
const id = 'foo';
|
||||
const rowData = { id };
|
||||
|
||||
const expectSql = sql`
|
||||
select ${sql.join(Object.values(fields), sql`, `)}
|
||||
from ${table}
|
||||
where ${fields.id}=$1
|
||||
`;
|
||||
|
||||
mockQuery.mockImplementationOnce(async (sql, values) => {
|
||||
expectSqlAssert(sql, expectSql.sql);
|
||||
expect(values).toEqual([id]);
|
||||
|
||||
return createMockQueryResult([rowData]);
|
||||
});
|
||||
|
||||
await findApplicationById(id);
|
||||
});
|
||||
|
||||
it('insertApplication', async () => {
|
||||
const keys = excludeAutoSetFields(Applications.fieldKeys);
|
||||
|
||||
const expectSql = `
|
||||
insert into "applications" (${keys.map((k) => `"${snakeCase(k)}"`).join(', ')})
|
||||
values (${keys.map((_, index) => `$${index + 1}`).join(', ')})
|
||||
returning *
|
||||
`;
|
||||
|
||||
mockQuery.mockImplementationOnce(async (sql, values) => {
|
||||
const rowData = { id: 'foo' };
|
||||
expectSqlAssert(sql, expectSql);
|
||||
|
||||
expect(values).toEqual(keys.map((k) => convertToPrimitiveOrSql(k, mockApplication[k])));
|
||||
|
||||
return createMockQueryResult([rowData]);
|
||||
});
|
||||
|
||||
await insertApplication(mockApplication);
|
||||
});
|
||||
|
||||
it('updateApplicationById', async () => {
|
||||
const id = 'foo';
|
||||
const description = 'des';
|
||||
|
||||
const expectSql = sql`
|
||||
update ${table}
|
||||
set ${fields.description}=$1
|
||||
where ${fields.id}=$2
|
||||
returning *
|
||||
`;
|
||||
|
||||
mockQuery.mockImplementationOnce(async (sql, values) => {
|
||||
expectSqlAssert(sql, expectSql.sql);
|
||||
expect(values).toEqual([description, id]);
|
||||
|
||||
return createMockQueryResult([{ id, description }]);
|
||||
});
|
||||
|
||||
await updateApplicationById(id, { description });
|
||||
});
|
||||
|
||||
it('deleteApplicationById', async () => {
|
||||
const id = 'foo';
|
||||
const expectSql = sql`
|
||||
delete from ${table}
|
||||
where ${fields.id}=$1
|
||||
`;
|
||||
|
||||
mockQuery.mockImplementationOnce(async (sql, values) => {
|
||||
expectSqlAssert(sql, expectSql.sql);
|
||||
expect(values).toEqual([id]);
|
||||
|
||||
return createMockQueryResult([{ id }]);
|
||||
});
|
||||
|
||||
await deleteApplicationById(id);
|
||||
});
|
||||
|
||||
it('deleteApplicationById throw error if return row count is 0', async () => {
|
||||
const id = 'foo';
|
||||
|
||||
mockQuery.mockImplementationOnce(async () => {
|
||||
return createMockQueryResult([]);
|
||||
});
|
||||
|
||||
await expect(deleteApplicationById(id)).rejects.toMatchError(
|
||||
new DeletionError(Applications.table, id)
|
||||
);
|
||||
});
|
||||
});
|
|
@ -46,7 +46,7 @@ export const updateApplicationById = async (
|
|||
export const deleteApplicationById = async (id: string) => {
|
||||
const { rowCount } = await pool.query(sql`
|
||||
delete from ${table}
|
||||
where id=${id}
|
||||
where ${fields.id}=${id}
|
||||
`);
|
||||
|
||||
if (rowCount < 1) {
|
||||
|
|
|
@ -8,6 +8,20 @@ import request from 'supertest';
|
|||
|
||||
import { AuthedRouter, AnonymousRouter } from '@/routes/types';
|
||||
|
||||
export const expectSqlAssert = (sql: string, expectSql: string) => {
|
||||
expect(
|
||||
sql
|
||||
.split('\n')
|
||||
.map((row) => row.trim())
|
||||
.filter((row) => row)
|
||||
).toEqual(
|
||||
expectSql
|
||||
.split('\n')
|
||||
.map((row) => row.trim())
|
||||
.filter((row) => row)
|
||||
);
|
||||
};
|
||||
|
||||
export const createTestPool = <T extends QueryResultRowType>(
|
||||
expectSql?: string,
|
||||
returning?: T | ((sql: string, values: readonly PrimitiveValueExpressionType[]) => T)
|
||||
|
@ -15,12 +29,7 @@ export const createTestPool = <T extends QueryResultRowType>(
|
|||
createMockPool({
|
||||
query: async (sql, values) => {
|
||||
if (expectSql) {
|
||||
expect(
|
||||
sql
|
||||
.split('\n')
|
||||
.map((row) => row.trim())
|
||||
.filter((row) => row)
|
||||
).toEqual(expectSql.split('\n'));
|
||||
expectSqlAssert(sql, expectSql);
|
||||
}
|
||||
|
||||
return createMockQueryResult(
|
||||
|
|
7
pnpm-lock.yaml
generated
7
pnpm-lock.yaml
generated
|
@ -110,6 +110,7 @@ importers:
|
|||
query-string: ^7.0.1
|
||||
slonik: ^23.8.3
|
||||
slonik-interceptor-preset: ^1.2.10
|
||||
snake-case: ^3.0.4
|
||||
snakecase-keys: ^5.1.0
|
||||
supertest: ^6.2.2
|
||||
ts-jest: ^27.0.5
|
||||
|
@ -165,6 +166,7 @@ importers:
|
|||
nock: 13.2.2
|
||||
openapi-types: 9.3.1
|
||||
prettier: 2.5.1
|
||||
snake-case: 3.0.4
|
||||
supertest: 6.2.2
|
||||
ts-jest: 27.1.1_0ef321b3552d50570980838f9f6677eb
|
||||
tsc-watch: 4.5.0_typescript@4.5.5
|
||||
|
@ -5066,7 +5068,6 @@ packages:
|
|||
dependencies:
|
||||
no-case: 3.0.4
|
||||
tslib: 2.3.1
|
||||
dev: false
|
||||
|
||||
/dot-prop/5.3.0:
|
||||
resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==}
|
||||
|
@ -6285,6 +6286,7 @@ packages:
|
|||
|
||||
/graceful-fs/4.2.9:
|
||||
resolution: {integrity: sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==}
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
|
||||
/handlebars/4.7.7:
|
||||
|
@ -8704,7 +8706,6 @@ packages:
|
|||
resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==}
|
||||
dependencies:
|
||||
tslib: 2.3.1
|
||||
dev: false
|
||||
|
||||
/lowercase-keys/1.0.1:
|
||||
resolution: {integrity: sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==}
|
||||
|
@ -9179,7 +9180,6 @@ packages:
|
|||
dependencies:
|
||||
lower-case: 2.0.2
|
||||
tslib: 2.3.1
|
||||
dev: false
|
||||
|
||||
/nock/13.2.2:
|
||||
resolution: {integrity: sha512-PcBHuvl9i6zfaJ50A7LS55oU+nFLv8htXIhffJO+FxyfibdZ4jEvd9kTuvkrJireBFIGMZ+oUIRpMK5gU9h//g==}
|
||||
|
@ -11588,7 +11588,6 @@ packages:
|
|||
dependencies:
|
||||
dot-case: 3.0.4
|
||||
tslib: 2.3.1
|
||||
dev: false
|
||||
|
||||
/snakecase-keys/5.1.2:
|
||||
resolution: {integrity: sha512-fvtDQZqPBqYb0dEY97TGuOMbN2NJ05Tj4MaoKwjTKkmjcG6mrd58JYGr23UWZRi6Aqv49Fk4HtjTIStOQenaug==}
|
||||
|
|
Loading…
Add table
Reference in a new issue