Skip to content

Commit

Permalink
Force UTC timezone to make some tests (e.g. typeorm-query-service.spe…
Browse files Browse the repository at this point in the history
…c) deterministic

Filter registration on module initialization
Add tests at the query service level to test the e2e pipeline, with and without relations
  • Loading branch information
luca-nardelli committed Nov 12, 2021
1 parent a6a5ec3 commit b1f7566
Show file tree
Hide file tree
Showing 23 changed files with 54,879 additions and 23,623 deletions.
78,200 changes: 54,656 additions & 23,544 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
"lint": "eslint --cache --ext=.ts .",
"lint:no-cache": "eslint --ext=.ts .",
"lint:fix": "eslint --fix --ext=.ts .",
"jest": "jest --runInBand --coverage",
"jest:e2e": "jest --runInBand --config=./jest.e2e.config.js",
"jest:unit": "jest --coverage --config=./jest.unit.config.js",
"jest": "TZ=UTC jest --runInBand --coverage",
"jest:e2e": "TZ=UTC jest --runInBand --config=./jest.e2e.config.js",
"jest:unit": "TZ=UTC jest --coverage --config=./jest.unit.config.js",
"coverage": "cat ./coverage/lcov.info | coveralls",
"prepare": "husky install"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,27 @@ type IsMultipleOfOpType = 'isMultipleOf';

@Injectable()
export class IsMultipleOfCustomFilter implements CustomFilter<IsMultipleOfOpType> {
constructor() {}

readonly operations: IsMultipleOfOpType[] = ['isMultipleOf'];

apply(field: string, cmp: IsMultipleOfOpType, val: unknown, alias?: string): CustomFilterResult {
alias = alias ? alias : '';
const pname = `param${randomString()}`;
return {
sql: `("${alias}"."${field}" % :${pname}) == 0`,
sql: `(${alias}.${field} % :${pname}) == 0`,
params: { [pname]: val },
};
}
}

@Injectable()
export class IsMultipleOfDateCustomFilter implements CustomFilter<IsMultipleOfOpType> {
constructor() {}

readonly operations: IsMultipleOfOpType[] = ['isMultipleOf'];

apply(field: string, cmp: IsMultipleOfOpType, val: unknown, alias?: string): CustomFilterResult {
alias = alias ? alias : '';
const pname = `param${randomString()}`;
return {
sql: `(EXTRACT(EPOCH FROM "${alias}"."${field}") / 3600 / 24) % :${pname}) == 0`,
sql: `(EXTRACT(EPOCH FROM ${alias}.${field}) / 3600 / 24) % :${pname}) == 0`,
params: { [pname]: val },
};
}
Expand All @@ -40,8 +36,6 @@ type RadiusCustomFilterOp = 'distanceFrom';

@Injectable()
export class RadiusCustomFilter implements CustomFilter<RadiusCustomFilterOp> {
constructor() {}

readonly operations: RadiusCustomFilterOp[] = ['distanceFrom'];

apply(
Expand All @@ -55,7 +49,7 @@ export class RadiusCustomFilter implements CustomFilter<RadiusCustomFilterOp> {
const plng = `param${randomString()}`;
const prad = `param${randomString()}`;
return {
sql: `ST_Distance("${alias}"."${field}", ST_MakePoint(:${plat},:${plng})) <= :${prad}`,
sql: `ST_Distance(${alias}.${field}, ST_MakePoint(:${plat},:${plng})) <= :${prad}`,
params: { [plat]: val.point.lat, [plng]: val.point.lng, [prad]: val.radius },
};
}
Expand Down
16 changes: 8 additions & 8 deletions packages/query-typeorm/__tests__/__fixtures__/seeds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,33 +23,33 @@ export const TEST_SOFT_DELETE_ENTITIES: TestSoftDeleteEntity[] = [1, 2, 3, 4, 5,
};
});

export const TEST_RELATIONS: TestRelation[] = TEST_ENTITIES.reduce(
(relations, te) => [
// Generate different numberTypes so we can use them for filters later on
export const TEST_RELATIONS: TestRelation[] = TEST_ENTITIES.reduce((relations, te) => {
return [
...relations,
{
testRelationPk: `test-relations-${te.testEntityPk}-1`,
relationName: `${te.stringType}-test-relation-one`,
testEntityId: te.testEntityPk,
uniDirectionalTestEntityId: te.testEntityPk,
numberType: 42,
numberType: te.numberType * 10 + 1,
},
{
testRelationPk: `test-relations-${te.testEntityPk}-2`,
relationName: `${te.stringType}-test-relation-two`,
testEntityId: te.testEntityPk,
uniDirectionalTestEntityId: te.testEntityPk,
numberType: 42,
numberType: te.numberType * 10 + 2,
},
{
testRelationPk: `test-relations-${te.testEntityPk}-3`,
relationName: `${te.stringType}-test-relation-three`,
testEntityId: te.testEntityPk,
uniDirectionalTestEntityId: te.testEntityPk,
numberType: 42,
numberType: te.numberType * 10 + 3,
},
],
[] as TestRelation[],
);
];
}, [] as TestRelation[]);

export const TEST_RELATIONS_OF_RELATION = TEST_RELATIONS.map<Partial<RelationOfTestRelationEntity>>((testRelation) => ({
relationName: `test-relation-of-${testRelation.relationName}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@ import { ManyToOne, Column, Entity, JoinColumn, ManyToMany, OneToOne, OneToMany,
import { TestEntityRelationEntity } from './test-entity-relation.entity';
import { TestEntity } from './test.entity';
import { RelationOfTestRelationEntity } from './relation-of-test-relation.entity';
import { TypeormQueryFilter } from '../../src/decorators/typeorm-query-filter.decorator';
import { IsMultipleOfCustomFilter } from './custom-filters.services';

@Entity()
@TypeormQueryFilter<TestRelation>({
filter: IsMultipleOfCustomFilter,
fields: ['numberType'], // Try the scoped registration
})
export class TestRelation {
@PrimaryColumn({ name: 'test_relation_pk' })
testRelationPk!: string;
Expand Down
10 changes: 7 additions & 3 deletions packages/query-typeorm/__tests__/__fixtures__/test.entity.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import { Column, Entity, OneToMany, ManyToMany, JoinTable, OneToOne, JoinColumn, PrimaryColumn } from 'typeorm';
import { TypeormQueryFilter, TypeormQueryFilterOpts } from '../../src/decorators/typeorm-query-filter.decorator';
import { IsMultipleOfCustomFilter } from './custom-filters.services';
import { TypeormQueryFilter } from '../../src/decorators/typeorm-query-filter.decorator';
import { IsMultipleOfCustomFilter, IsMultipleOfDateCustomFilter } from './custom-filters.services';
import { TestEntityRelationEntity } from './test-entity-relation.entity';
import { TestRelation } from './test-relation.entity';

@Entity()
@TypeormQueryFilter<TestEntity>({
filter: IsMultipleOfCustomFilter,
} as TypeormQueryFilterOpts<TestEntity>)
})
@TypeormQueryFilter<TestEntity>({
filter: IsMultipleOfDateCustomFilter,
fields: ['dateType'],
})
export class TestEntity {
@PrimaryColumn({ name: 'test_entity_pk' })
testEntityPk!: string;
Expand Down
2 changes: 1 addition & 1 deletion packages/query-typeorm/__tests__/module.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ describe('NestjsQueryTypeOrmModule', () => {
const typeOrmModule = NestjsQueryTypeOrmModule.forFeature([TestEntity]);
expect(typeOrmModule.imports).toHaveLength(1);
expect(typeOrmModule.module).toBe(NestjsQueryTypeOrmModule);
expect(typeOrmModule.providers).toHaveLength(2);
expect(typeOrmModule.providers).toHaveLength(3);
expect(typeOrmModule.exports).toHaveLength(2);
});
});
3 changes: 2 additions & 1 deletion packages/query-typeorm/__tests__/providers.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Repository } from 'typeorm';
import { mock, instance } from 'ts-mockito';
import { createTypeOrmQueryServiceProviders } from '../src/providers';
import { TypeOrmQueryService } from '../src/services';
import { CustomFilterRegistry } from '../src/query';

describe('createTypeOrmQueryServiceProviders', () => {
it('should create a provider for the entity', () => {
Expand All @@ -12,7 +13,7 @@ describe('createTypeOrmQueryServiceProviders', () => {
const providers = createTypeOrmQueryServiceProviders([TestEntity]);
expect(providers).toHaveLength(1);
expect(providers[0].provide).toBe(getQueryServiceToken(TestEntity));
expect(providers[0].inject).toEqual([getRepositoryToken(TestEntity)]);
expect(providers[0].inject).toEqual([getRepositoryToken(TestEntity), CustomFilterRegistry]);
expect(providers[0].useFactory(instance(mockRepo))).toBeInstanceOf(TypeOrmQueryService);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ exports[`FilterQueryBuilder #delete with sorting should ignore sorting 1`] = `DE

exports[`FilterQueryBuilder #delete with sorting should ignore sorting 2`] = `Array []`;

exports[`FilterQueryBuilder #select with custom filter should add custom filters 1`] = `SELECT "TestEntity"."test_entity_pk" AS "TestEntity_test_entity_pk", "TestEntity"."string_type" AS "TestEntity_string_type", "TestEntity"."bool_type" AS "TestEntity_bool_type", "TestEntity"."number_type" AS "TestEntity_number_type", "TestEntity"."date_type" AS "TestEntity_date_type", "TestEntity"."oneTestRelationTestRelationPk" AS "TestEntity_oneTestRelationTestRelationPk" FROM "test_entity" "TestEntity" WHERE ("TestEntity"."number_type" >= ? OR "TestEntity"."number_type" <= ? OR ("TestEntity"."numberType" % ?) == 0) AND ((EXTRACT(EPOCH FROM "TestEntity"."dateType") / 3600 / 24) % ?) == 0) AND (ST_Distance("TestEntity"."fakePointType", ST_MakePoint(?,?)) <= ?)`;
exports[`FilterQueryBuilder #select with custom filter should add custom filters 1`] = `SELECT "TestEntity"."test_entity_pk" AS "TestEntity_test_entity_pk", "TestEntity"."string_type" AS "TestEntity_string_type", "TestEntity"."bool_type" AS "TestEntity_bool_type", "TestEntity"."number_type" AS "TestEntity_number_type", "TestEntity"."date_type" AS "TestEntity_date_type", "TestEntity"."oneTestRelationTestRelationPk" AS "TestEntity_oneTestRelationTestRelationPk" FROM "test_entity" "TestEntity" WHERE ("TestEntity"."number_type" >= ? OR "TestEntity"."number_type" <= ? OR ("TestEntity"."number_type" % ?) == 0) AND ((EXTRACT(EPOCH FROM "TestEntity"."date_type") / 3600 / 24) % ?) == 0) AND (ST_Distance(TestEntity.fakePointType, ST_MakePoint(?,?)) <= ?)`;

exports[`FilterQueryBuilder #select with custom filter should add custom filters 2`] = `
Array [
Expand All @@ -26,7 +26,7 @@ Array [
]
`;

exports[`FilterQueryBuilder #select with custom filter should add custom filters with aggregate 1`] = `SELECT MAX("TestEntity"."number_type") AS "MAX_numberType" FROM "test_entity" "TestEntity" WHERE ("TestEntity"."number_type" >= ? OR "TestEntity"."number_type" <= ? OR ("TestEntity"."numberType" % ?) == 0) AND ((EXTRACT(EPOCH FROM "TestEntity"."dateType") / 3600 / 24) % ?) == 0) AND (ST_Distance("TestEntity"."fakePointType", ST_MakePoint(?,?)) <= ?)`;
exports[`FilterQueryBuilder #select with custom filter should add custom filters with aggregate 1`] = `SELECT MAX("TestEntity"."number_type") AS "MAX_numberType" FROM "test_entity" "TestEntity" WHERE ("TestEntity"."number_type" >= ? OR "TestEntity"."number_type" <= ? OR ("TestEntity"."number_type" % ?) == 0) AND ((EXTRACT(EPOCH FROM "TestEntity"."date_type") / 3600 / 24) % ?) == 0) AND (ST_Distance(TestEntity.fakePointType, ST_MakePoint(?,?)) <= ?)`;

exports[`FilterQueryBuilder #select with custom filter should add custom filters with aggregate 2`] = `
Array [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ Array [
]
`;

exports[`RelationQueryBuilder #select with custom filters should accept custom filters 1`] = `SELECT "testEntityRelation"."test_relation_id" AS "testEntityRelation_test_relation_id", "testEntityRelation"."test_entity_id" AS "testEntityRelation_test_entity_id" FROM "test_entity_relation_entity" "testEntityRelation" WHERE ("testEntityRelation"."test_entity_id" = ?) AND (testEntityRelation.numberType >= ? OR testEntityRelation.numberType <= ? OR ("testEntityRelation"."numberType" % ?) == 0) AND ((EXTRACT(EPOCH FROM "testEntityRelation"."dateType") / 3600 / 24) % ?) == 0) AND (ST_Distance("testEntityRelation"."fakePointType", ST_MakePoint(?,?)) <= ?)`;
exports[`RelationQueryBuilder #select with custom filters should accept custom filters 1`] = `SELECT "testRelations"."test_relation_pk" AS "testRelations_test_relation_pk", "testRelations"."relation_name" AS "testRelations_relation_name", "testRelations"."test_entity_id" AS "testRelations_test_entity_id", "testRelations"."uni_directional_test_entity_id" AS "testRelations_uni_directional_test_entity_id", "testRelations"."number_type" AS "testRelations_number_type", "testRelations"."uni_directional_relation_test_entity_id" AS "testRelations_uni_directional_relation_test_entity_id" FROM "test_relation" "testRelations" WHERE ("testRelations"."test_entity_id" = ?) AND ("testRelations"."number_type" >= ? OR "testRelations"."number_type" <= ? OR ("testRelations"."number_type" % ?) == 0) AND ((EXTRACT(EPOCH FROM testRelations.dateType) / 3600 / 24) % ?) == 0) AND (ST_Distance(testRelations.fakePointType, ST_MakePoint(?,?)) <= ?)`;

exports[`RelationQueryBuilder #select with custom filters should accept custom filters 2`] = `
Array [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Array [
]
`;

exports[`WhereBuilder and and multiple expressions together with custom filters 1`] = `SELECT "TestEntity"."test_entity_pk" AS "TestEntity_test_entity_pk", "TestEntity"."string_type" AS "TestEntity_string_type", "TestEntity"."bool_type" AS "TestEntity_bool_type", "TestEntity"."number_type" AS "TestEntity_number_type", "TestEntity"."date_type" AS "TestEntity_date_type", "TestEntity"."oneTestRelationTestRelationPk" AS "TestEntity_oneTestRelationTestRelationPk" FROM "test_entity" "TestEntity" WHERE ((("TestEntity"."number_type" > ?)) AND (("TestEntity"."number_type" < ?)) AND (("TestEntity"."number_type" >= ?)) AND (("TestEntity"."number_type" <= ?)) AND ((("TestEntity"."numberType" % ?) == 0)) AND (((EXTRACT(EPOCH FROM "TestEntity"."dateType") / 3600 / 24) % ?) == 0)) AND ((ST_Distance("TestEntity"."fakePointType", ST_MakePoint(?,?)) <= ?)))`;
exports[`WhereBuilder and and multiple expressions together with custom filters 1`] = `SELECT "TestEntity"."test_entity_pk" AS "TestEntity_test_entity_pk", "TestEntity"."string_type" AS "TestEntity_string_type", "TestEntity"."bool_type" AS "TestEntity_bool_type", "TestEntity"."number_type" AS "TestEntity_number_type", "TestEntity"."date_type" AS "TestEntity_date_type", "TestEntity"."oneTestRelationTestRelationPk" AS "TestEntity_oneTestRelationTestRelationPk" FROM "test_entity" "TestEntity" WHERE ((("TestEntity"."number_type" > ?)) AND (("TestEntity"."number_type" < ?)) AND (("TestEntity"."number_type" >= ?)) AND (("TestEntity"."number_type" <= ?)) AND ((("TestEntity"."number_type" % ?) == 0)) AND (((EXTRACT(EPOCH FROM "TestEntity"."date_type") / 3600 / 24) % ?) == 0)) AND ((ST_Distance(TestEntity.fakePointType, ST_MakePoint(?,?)) <= ?)))`;

exports[`WhereBuilder and and multiple expressions together with custom filters 2`] = `
Array [
Expand Down Expand Up @@ -101,7 +101,7 @@ Array [
]
`;

exports[`WhereBuilder or or multiple expressions together with custom filter 1`] = `SELECT "TestEntity"."test_entity_pk" AS "TestEntity_test_entity_pk", "TestEntity"."string_type" AS "TestEntity_string_type", "TestEntity"."bool_type" AS "TestEntity_bool_type", "TestEntity"."number_type" AS "TestEntity_number_type", "TestEntity"."date_type" AS "TestEntity_date_type", "TestEntity"."oneTestRelationTestRelationPk" AS "TestEntity_oneTestRelationTestRelationPk" FROM "test_entity" "TestEntity" WHERE ((("TestEntity"."number_type" > ?)) OR (("TestEntity"."number_type" < ?)) OR (("TestEntity"."number_type" >= ?)) OR (("TestEntity"."number_type" <= ?)) OR ((("TestEntity"."numberType" % ?) == 0)) OR (((EXTRACT(EPOCH FROM "TestEntity"."dateType") / 3600 / 24) % ?) == 0)) OR ((ST_Distance("TestEntity"."fakePointType", ST_MakePoint(?,?)) <= ?)))`;
exports[`WhereBuilder or or multiple expressions together with custom filter 1`] = `SELECT "TestEntity"."test_entity_pk" AS "TestEntity_test_entity_pk", "TestEntity"."string_type" AS "TestEntity_string_type", "TestEntity"."bool_type" AS "TestEntity_bool_type", "TestEntity"."number_type" AS "TestEntity_number_type", "TestEntity"."date_type" AS "TestEntity_date_type", "TestEntity"."oneTestRelationTestRelationPk" AS "TestEntity_oneTestRelationTestRelationPk" FROM "test_entity" "TestEntity" WHERE ((("TestEntity"."number_type" > ?)) OR (("TestEntity"."number_type" < ?)) OR (("TestEntity"."number_type" >= ?)) OR (("TestEntity"."number_type" <= ?)) OR ((("TestEntity"."number_type" % ?) == 0)) OR (((EXTRACT(EPOCH FROM "TestEntity"."date_type") / 3600 / 24) % ?) == 0)) OR ((ST_Distance(TestEntity.fakePointType, ST_MakePoint(?,?)) <= ?)))`;

exports[`WhereBuilder or or multiple expressions together with custom filter 2`] = `
Array [
Expand Down Expand Up @@ -142,7 +142,7 @@ exports[`WhereBuilder should accept a empty filter 1`] = `SELECT "TestEntity"."t

exports[`WhereBuilder should accept a empty filter 2`] = `Array []`;

exports[`WhereBuilder should accept custom filters alongside regular filters 1`] = `SELECT "TestEntity"."test_entity_pk" AS "TestEntity_test_entity_pk", "TestEntity"."string_type" AS "TestEntity_string_type", "TestEntity"."bool_type" AS "TestEntity_bool_type", "TestEntity"."number_type" AS "TestEntity_number_type", "TestEntity"."date_type" AS "TestEntity_date_type", "TestEntity"."oneTestRelationTestRelationPk" AS "TestEntity_oneTestRelationTestRelationPk" FROM "test_entity" "TestEntity" WHERE ("TestEntity"."number_type" >= ? OR "TestEntity"."number_type" <= ? OR ("TestEntity"."numberType" % ?) == 0) AND ((EXTRACT(EPOCH FROM "TestEntity"."dateType") / 3600 / 24) % ?) == 0) AND (ST_Distance("TestEntity"."fakePointType", ST_MakePoint(?,?)) <= ?)`;
exports[`WhereBuilder should accept custom filters alongside regular filters 1`] = `SELECT "TestEntity"."test_entity_pk" AS "TestEntity_test_entity_pk", "TestEntity"."string_type" AS "TestEntity_string_type", "TestEntity"."bool_type" AS "TestEntity_bool_type", "TestEntity"."number_type" AS "TestEntity_number_type", "TestEntity"."date_type" AS "TestEntity_date_type", "TestEntity"."oneTestRelationTestRelationPk" AS "TestEntity_oneTestRelationTestRelationPk" FROM "test_entity" "TestEntity" WHERE ("TestEntity"."number_type" >= ? OR "TestEntity"."number_type" <= ? OR ("TestEntity"."number_type" % ?) == 0) AND ((EXTRACT(EPOCH FROM "TestEntity"."date_type") / 3600 / 24) % ?) == 0) AND (ST_Distance(TestEntity.fakePointType, ST_MakePoint(?,?)) <= ?)`;

exports[`WhereBuilder should accept custom filters alongside regular filters 2`] = `
Array [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ describe('FilterQueryBuilder', (): void => {
);
});

// eslint-disable-next-line jest/expect-expect
it('should add custom filters with aggregate', () => {
expectAggregateSQLSnapshot(
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ describe('RelationQueryBuilder', (): void => {
fakePointType: { distanceFrom: { point: { lat: 45.3, lng: 9.5 }, radius: 50000 } },
} as any, // TODO Fix any typing
};
expectSQLSnapshot(TestEntity, testEntity, 'testEntityRelation', query);
expectSQLSnapshot(TestEntity, testEntity, 'testRelations', query);
});
});
});
Expand Down
Loading

0 comments on commit b1f7566

Please sign in to comment.