From 52c1172732eddaae399d12294ea819e92ca596d0 Mon Sep 17 00:00:00 2001 From: William Schurman Date: Wed, 4 Nov 2020 12:35:55 -0800 Subject: [PATCH 1/2] ensure integration tests fail when defined in multiple files --- .../EntityEdgesIntegration-test.ts | 102 +----------------- .../entities/ChildEntity.ts | 65 +++++++++++ .../entities/ParentEntity.ts | 56 ++++++++++ 3 files changed, 124 insertions(+), 99 deletions(-) create mode 100644 packages/entity-full-integration-tests/src/__integration-tests__/entities/ChildEntity.ts create mode 100644 packages/entity-full-integration-tests/src/__integration-tests__/entities/ParentEntity.ts diff --git a/packages/entity-full-integration-tests/src/__integration-tests__/EntityEdgesIntegration-test.ts b/packages/entity-full-integration-tests/src/__integration-tests__/EntityEdgesIntegration-test.ts index 8bc7aff8..c60b9058 100644 --- a/packages/entity-full-integration-tests/src/__integration-tests__/EntityEdgesIntegration-test.ts +++ b/packages/entity-full-integration-tests/src/__integration-tests__/EntityEdgesIntegration-test.ts @@ -1,108 +1,12 @@ -import { - EntityPrivacyPolicy, - ViewerContext, - AlwaysAllowPrivacyPolicyRule, - Entity, - EntityCompanionDefinition, - EntityConfiguration, - DatabaseAdapterFlavor, - CacheAdapterFlavor, - UUIDField, - EntityEdgeDeletionBehavior, -} from '@expo/entity'; +import { ViewerContext } from '@expo/entity'; import { RedisCacheAdapterContext } from '@expo/entity-cache-adapter-redis'; import Redis from 'ioredis'; import Knex from 'knex'; import { URL } from 'url'; import { createFullIntegrationTestEntityCompanionProvider } from '../testfixtures/createFullIntegrationTestEntityCompanionProvider'; - -interface ParentFields { - id: string; -} - -interface ChildFields { - id: string; - parent_id: string; -} - -class TestEntityPrivacyPolicy extends EntityPrivacyPolicy { - protected readonly readRules = [new AlwaysAllowPrivacyPolicyRule()]; - protected readonly createRules = [new AlwaysAllowPrivacyPolicyRule()]; - protected readonly updateRules = [new AlwaysAllowPrivacyPolicyRule()]; - protected readonly deleteRules = [new AlwaysAllowPrivacyPolicyRule()]; -} - -class ParentEntity extends Entity { - static getCompanionDefinition(): EntityCompanionDefinition< - ParentFields, - string, - ViewerContext, - ParentEntity, - TestEntityPrivacyPolicy - > { - return parentEntityCompanion; - } -} - -class ChildEntity extends Entity { - static getCompanionDefinition(): EntityCompanionDefinition< - ChildFields, - string, - ViewerContext, - ChildEntity, - TestEntityPrivacyPolicy - > { - return childEntityCompanion; - } -} - -const parentEntityConfiguration = new EntityConfiguration({ - idField: 'id', - tableName: 'parents', - inboundEdges: [ChildEntity], - schema: { - id: new UUIDField({ - columnName: 'id', - cache: true, - }), - }, - databaseAdapterFlavor: DatabaseAdapterFlavor.POSTGRES, - cacheAdapterFlavor: CacheAdapterFlavor.REDIS, -}); - -const childEntityConfiguration = new EntityConfiguration({ - idField: 'id', - tableName: 'children', - schema: { - id: new UUIDField({ - columnName: 'id', - cache: true, - }), - parent_id: new UUIDField({ - columnName: 'parent_id', - cache: true, - association: { - associatedEntityClass: ParentEntity, - edgeDeletionBehavior: EntityEdgeDeletionBehavior.CASCADE_DELETE_INVALIDATE_CACHE, - }, - }), - }, - databaseAdapterFlavor: DatabaseAdapterFlavor.POSTGRES, - cacheAdapterFlavor: CacheAdapterFlavor.REDIS, -}); - -const parentEntityCompanion = new EntityCompanionDefinition({ - entityClass: ParentEntity, - entityConfiguration: parentEntityConfiguration, - privacyPolicyClass: TestEntityPrivacyPolicy, -}); - -const childEntityCompanion = new EntityCompanionDefinition({ - entityClass: ChildEntity, - entityConfiguration: childEntityConfiguration, - privacyPolicyClass: TestEntityPrivacyPolicy, -}); +import ChildEntity from './entities/ChildEntity'; +import ParentEntity from './entities/ParentEntity'; async function createOrTruncatePostgresTables(knex: Knex): Promise { await knex.raw('CREATE EXTENSION IF NOT EXISTS "uuid-ossp"'); // for uuid_generate_v4() diff --git a/packages/entity-full-integration-tests/src/__integration-tests__/entities/ChildEntity.ts b/packages/entity-full-integration-tests/src/__integration-tests__/entities/ChildEntity.ts new file mode 100644 index 00000000..639e645a --- /dev/null +++ b/packages/entity-full-integration-tests/src/__integration-tests__/entities/ChildEntity.ts @@ -0,0 +1,65 @@ +import { + AlwaysAllowPrivacyPolicyRule, + CacheAdapterFlavor, + DatabaseAdapterFlavor, + Entity, + EntityCompanionDefinition, + EntityConfiguration, + EntityEdgeDeletionBehavior, + EntityPrivacyPolicy, + UUIDField, + ViewerContext, +} from '@expo/entity'; + +import ParentEntity from './ParentEntity'; + +interface ChildFields { + id: string; + parent_id: string; +} + +class TestEntityPrivacyPolicy extends EntityPrivacyPolicy { + protected readonly readRules = [new AlwaysAllowPrivacyPolicyRule()]; + protected readonly createRules = [new AlwaysAllowPrivacyPolicyRule()]; + protected readonly updateRules = [new AlwaysAllowPrivacyPolicyRule()]; + protected readonly deleteRules = [new AlwaysAllowPrivacyPolicyRule()]; +} + +export default class ChildEntity extends Entity { + static getCompanionDefinition(): EntityCompanionDefinition< + ChildFields, + string, + ViewerContext, + ChildEntity, + TestEntityPrivacyPolicy + > { + return childEntityCompanion; + } +} + +const childEntityConfiguration = new EntityConfiguration({ + idField: 'id', + tableName: 'children', + schema: { + id: new UUIDField({ + columnName: 'id', + cache: true, + }), + parent_id: new UUIDField({ + columnName: 'parent_id', + cache: true, + association: { + associatedEntityClass: ParentEntity, + edgeDeletionBehavior: EntityEdgeDeletionBehavior.CASCADE_DELETE_INVALIDATE_CACHE, + }, + }), + }, + databaseAdapterFlavor: DatabaseAdapterFlavor.POSTGRES, + cacheAdapterFlavor: CacheAdapterFlavor.REDIS, +}); + +const childEntityCompanion = new EntityCompanionDefinition({ + entityClass: ChildEntity, + entityConfiguration: childEntityConfiguration, + privacyPolicyClass: TestEntityPrivacyPolicy, +}); diff --git a/packages/entity-full-integration-tests/src/__integration-tests__/entities/ParentEntity.ts b/packages/entity-full-integration-tests/src/__integration-tests__/entities/ParentEntity.ts new file mode 100644 index 00000000..31a8661e --- /dev/null +++ b/packages/entity-full-integration-tests/src/__integration-tests__/entities/ParentEntity.ts @@ -0,0 +1,56 @@ +import { + AlwaysAllowPrivacyPolicyRule, + CacheAdapterFlavor, + DatabaseAdapterFlavor, + Entity, + EntityCompanionDefinition, + EntityConfiguration, + EntityPrivacyPolicy, + UUIDField, + ViewerContext, +} from '@expo/entity'; + +import ChildEntity from './ChildEntity'; + +interface ParentFields { + id: string; +} + +class TestEntityPrivacyPolicy extends EntityPrivacyPolicy { + protected readonly readRules = [new AlwaysAllowPrivacyPolicyRule()]; + protected readonly createRules = [new AlwaysAllowPrivacyPolicyRule()]; + protected readonly updateRules = [new AlwaysAllowPrivacyPolicyRule()]; + protected readonly deleteRules = [new AlwaysAllowPrivacyPolicyRule()]; +} + +export default class ParentEntity extends Entity { + static getCompanionDefinition(): EntityCompanionDefinition< + ParentFields, + string, + ViewerContext, + ParentEntity, + TestEntityPrivacyPolicy + > { + return parentEntityCompanion; + } +} + +const parentEntityConfiguration = new EntityConfiguration({ + idField: 'id', + tableName: 'parents', + inboundEdges: [ChildEntity], + schema: { + id: new UUIDField({ + columnName: 'id', + cache: true, + }), + }, + databaseAdapterFlavor: DatabaseAdapterFlavor.POSTGRES, + cacheAdapterFlavor: CacheAdapterFlavor.REDIS, +}); + +const parentEntityCompanion = new EntityCompanionDefinition({ + entityClass: ParentEntity, + entityConfiguration: parentEntityConfiguration, + privacyPolicyClass: TestEntityPrivacyPolicy, +}); From 65b90ebb4294fd03b23c8b4b427f18303648771c Mon Sep 17 00:00:00 2001 From: William Schurman Date: Wed, 4 Nov 2020 12:39:10 -0800 Subject: [PATCH 2/2] fix: edge definition cyclic imports --- .../EntitySelfReferentialEdgesIntegration-test.ts | 4 ++-- .../src/__integration-tests__/entities/ParentEntity.ts | 2 +- packages/entity/src/EntityConfiguration.ts | 6 +++--- packages/entity/src/EntityMutator.ts | 2 +- packages/entity/src/__tests__/EntityEdges-test.ts | 4 ++-- .../entity/src/__tests__/EntitySelfReferentialEdges-test.ts | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/entity-full-integration-tests/src/__integration-tests__/EntitySelfReferentialEdgesIntegration-test.ts b/packages/entity-full-integration-tests/src/__integration-tests__/EntitySelfReferentialEdgesIntegration-test.ts index 907b18b6..bd786663 100644 --- a/packages/entity-full-integration-tests/src/__integration-tests__/EntitySelfReferentialEdgesIntegration-test.ts +++ b/packages/entity-full-integration-tests/src/__integration-tests__/EntitySelfReferentialEdgesIntegration-test.ts @@ -67,7 +67,7 @@ const makeEntityClasses = async (knex: Knex, edgeDeletionBehavior: EntityEdgeDel const categoryEntityConfiguration = new EntityConfiguration({ idField: 'id', tableName: categoriesTableName, - inboundEdges: [OtherEntity], + inboundEdges: () => [OtherEntity], schema: { id: new UUIDField({ columnName: 'id', @@ -95,7 +95,7 @@ const makeEntityClasses = async (knex: Knex, edgeDeletionBehavior: EntityEdgeDel const otherEntityConfiguration = new EntityConfiguration({ idField: 'id', tableName: othersTableName, - inboundEdges: [CategoryEntity], + inboundEdges: () => [CategoryEntity], schema: { id: new UUIDField({ columnName: 'id', diff --git a/packages/entity-full-integration-tests/src/__integration-tests__/entities/ParentEntity.ts b/packages/entity-full-integration-tests/src/__integration-tests__/entities/ParentEntity.ts index 31a8661e..cf6d7e79 100644 --- a/packages/entity-full-integration-tests/src/__integration-tests__/entities/ParentEntity.ts +++ b/packages/entity-full-integration-tests/src/__integration-tests__/entities/ParentEntity.ts @@ -38,7 +38,7 @@ export default class ParentEntity extends Entity({ idField: 'id', tableName: 'parents', - inboundEdges: [ChildEntity], + inboundEdges: () => [ChildEntity], schema: { id: new UUIDField({ columnName: 'id', diff --git a/packages/entity/src/EntityConfiguration.ts b/packages/entity/src/EntityConfiguration.ts index 33dc0577..5c24b53d 100644 --- a/packages/entity/src/EntityConfiguration.ts +++ b/packages/entity/src/EntityConfiguration.ts @@ -13,7 +13,7 @@ export default class EntityConfiguration { readonly cacheableKeys: ReadonlySet; readonly cacheKeyVersion: number; - readonly inboundEdges: IEntityClass[]; + readonly inboundEdges: () => IEntityClass[]; readonly schema: ReadonlyMap; readonly entityToDBFieldsKeyMapping: ReadonlyMap; readonly dbToEntityFieldsKeyMapping: ReadonlyMap; @@ -25,7 +25,7 @@ export default class EntityConfiguration { idField, tableName, schema, - inboundEdges = [], + inboundEdges = () => [], cacheKeyVersion = 0, databaseAdapterFlavor, cacheAdapterFlavor, @@ -33,7 +33,7 @@ export default class EntityConfiguration { idField: keyof TFields; tableName: string; schema: Record; - inboundEdges?: IEntityClass[]; + inboundEdges?: () => IEntityClass[]; cacheKeyVersion?: number; databaseAdapterFlavor: DatabaseAdapterFlavor; cacheAdapterFlavor: CacheAdapterFlavor; diff --git a/packages/entity/src/EntityMutator.ts b/packages/entity/src/EntityMutator.ts index 606c31aa..f06b44fb 100644 --- a/packages/entity/src/EntityMutator.ts +++ b/packages/entity/src/EntityMutator.ts @@ -629,7 +629,7 @@ export class DeleteMutator< TMSelectedFields >; const entityConfiguration = companionDefinition.entityConfiguration; - const inboundEdges = entityConfiguration.inboundEdges; + const inboundEdges = entityConfiguration.inboundEdges(); await Promise.all( inboundEdges.map(async (entityClass) => { return await mapMapAsync( diff --git a/packages/entity/src/__tests__/EntityEdges-test.ts b/packages/entity/src/__tests__/EntityEdges-test.ts index 4611b844..f884ec84 100644 --- a/packages/entity/src/__tests__/EntityEdges-test.ts +++ b/packages/entity/src/__tests__/EntityEdges-test.ts @@ -81,7 +81,7 @@ const makeEntityClasses = (edgeDeletionBehavior: EntityEdgeDeletionBehavior) => const parentEntityConfiguration = new EntityConfiguration({ idField: 'id', tableName: 'parents', - inboundEdges: [ChildEntity], + inboundEdges: () => [ChildEntity], schema: { id: new UUIDField({ columnName: 'id', @@ -95,7 +95,7 @@ const makeEntityClasses = (edgeDeletionBehavior: EntityEdgeDeletionBehavior) => const childEntityConfiguration = new EntityConfiguration({ idField: 'id', tableName: 'children', - inboundEdges: [GrandChildEntity], + inboundEdges: () => [GrandChildEntity], schema: { id: new UUIDField({ columnName: 'id', diff --git a/packages/entity/src/__tests__/EntitySelfReferentialEdges-test.ts b/packages/entity/src/__tests__/EntitySelfReferentialEdges-test.ts index bc06d191..149f21e9 100644 --- a/packages/entity/src/__tests__/EntitySelfReferentialEdges-test.ts +++ b/packages/entity/src/__tests__/EntitySelfReferentialEdges-test.ts @@ -48,7 +48,7 @@ const makeEntityClass = (edgeDeletionBehavior: EntityEdgeDeletionBehavior) => { const categoryEntityConfiguration = new EntityConfiguration({ idField: 'id', tableName: 'categories', - inboundEdges: [CategoryEntity], + inboundEdges: () => [CategoryEntity], schema: { id: new UUIDField({ columnName: 'id',