import { ViewerContext } from '@expo/entity' ; import { RedisCacheAdapterContext } from '@expo/entity-cache-adapter-redis' ; import Redis from 'ioredis' ; import { knex , Knex } from 'knex' ; import nullthrows from 'nullthrows' ; import { URL } from 'url' ; import { createFullIntegrationTestEntityCompanionProvider } from '../testfixtures/createFullIntegrationTestEntityCompanionProvider' ; import ChildEntity from './entities/ChildEntity' ; import ParentEntity from './entities/ParentEntity' ; async function createOrTruncatePostgresTables ( knex ) { await knex . raw ( 'CREATE EXTENSION IF NOT EXISTS "uuid-ossp"' ) ; await knex . schema . createTable ( 'parents' , ( table ) => { table . uuid ( 'id' ) . defaultTo ( knex . raw ( 'uuid_generate_v4()' ) ) . primary ( ) ; } ) ; await knex . into ( 'parents' ) . truncate ( ) ; await knex . schema . createTable ( 'children' , ( table ) => { table . uuid ( 'id' ) . defaultTo ( knex . raw ( 'uuid_generate_v4()' ) ) . primary ( ) ; table . uuid ( 'parent_id' ) . references ( 'id' ) . inTable ( 'parents' ) . onDelete ( 'cascade' ) . unique ( ) ; } ) ; await knex . into ( 'children' ) . truncate ( ) ; } async function dropPostgresTable ( knex ) { if ( await knex . schema . hasTable ( 'children' ) ) { await knex . schema . dropTable ( 'children' ) ; } if ( await knex . schema . hasTable ( 'parents' ) ) { await knex . schema . dropTable ( 'parents' ) ; } } describe ( 'EntityMutator.processEntityDeletionForInboundEdgesAsync' , ( ) => { let knexInstance ; let redisCacheAdapterContext ; beforeAll ( ( ) => { knexInstance = knex ( { client : 'pg' , connection : { user : nullthrows ( process . env [ 'PGUSER' ] ) , password : nullthrows ( process . env [ 'PGPASSWORD' ] ) , host : 'localhost' , port : parseInt ( nullthrows ( process . env [ 'PGPORT' ] ) , 10 ) , database : nullthrows ( process . env [ 'PGDATABASE' ] ) , } , } ) ; redisCacheAdapterContext = { redisClient : new Redis ( new URL ( process . env [ 'REDIS_URL' ] ! ) . toString ( ) ) , makeKeyFn ( ... parts ) { const delimiter = ':' ; const escapedParts = parts . map ( ( part ) => part . replace ( '\\' , '\\\\' ) . replace ( delimiter , `\\${ delimiter }` ) ) ; return escapedParts . join ( delimiter ) ; } , cacheKeyPrefix : 'test-' , cacheKeyVersion : 1 , ttlSecondsPositive : 86400 , ttlSecondsNegative : 600 , } ; } ) ; beforeEach ( async ( ) => { await createOrTruncatePostgresTables ( knexInstance ) ; await redisCacheAdapterContext . redisClient . flushdb ( ) ; } ) ; afterAll ( async ( ) => { await dropPostgresTable ( knexInstance ) ; await knexInstance . destroy ( ) ; redisCacheAdapterContext . redisClient . disconnect ( ) ; } ) ; describe ( 'EntityEdgeDeletionBehavior.INVALIDATE_CACHE' , ( ) => { it ( 'invalidates the cache' , async ( ) => { const viewerContext = new ViewerContext ( createFullIntegrationTestEntityCompanionProvider ( knexInstance , redisCacheAdapterContext ) ) ; const parent = await ParentEntity . creator ( viewerContext ) . enforceCreateAsync ( ) ; const child = await ChildEntity . creator ( viewerContext ) . setField ( 'parent_id' , parent . getID ( ) ) . enforceCreateAsync ( ) ; await expect ( ParentEntity . loader ( viewerContext ) . enforcing ( ) . loadByIDNullableAsync ( parent . getID ( ) ) ) . resolves . not . toBeNull ( ) ; await expect ( ChildEntity . loader ( viewerContext ) . enforcing ( ) . loadByFieldEqualingAsync ( 'parent_id' , parent . getID ( ) ) ) . resolves . not . toBeNull ( ) ; await ParentEntity . enforceDeleteAsync ( parent ) ; await expect ( ParentEntity . loader ( viewerContext ) . enforcing ( ) . loadByIDNullableAsync ( parent . getID ( ) ) ) . resolves . toBeNull ( ) ; await expect ( ChildEntity . loader ( viewerContext ) . enforcing ( ) . loadByIDNullableAsync ( child . getID ( ) ) ) . resolves . toBeNull ( ) ; } ) ; } ) ; } ) ;