From 9a8a70f63e93f54716c18f3fd9b1714b8a226091 Mon Sep 17 00:00:00 2001 From: Dinesh Sajwan Date: Wed, 18 Oct 2023 19:29:30 -0400 Subject: [PATCH] feat(construct): /cdk test cases (#40) * added rag test cases, updated summary test cases * added qa test cases * added qa test cases --------- Co-authored-by: Dinesh Sajwan --- .../aws-qa-appsync-opensearch.test.ts | 155 ++++++++++++++++++ .../aws-rag-appsync-stepfn-opensearch.test.ts | 33 ++-- .../aws-summarization-appsync-stepfn.test.ts | 21 ++- 3 files changed, 195 insertions(+), 14 deletions(-) create mode 100644 test/patterns/gen-ai/aws-qa-appsync-opensearch/aws-qa-appsync-opensearch.test.ts diff --git a/test/patterns/gen-ai/aws-qa-appsync-opensearch/aws-qa-appsync-opensearch.test.ts b/test/patterns/gen-ai/aws-qa-appsync-opensearch/aws-qa-appsync-opensearch.test.ts new file mode 100644 index 00000000..bf3f86aa --- /dev/null +++ b/test/patterns/gen-ai/aws-qa-appsync-opensearch/aws-qa-appsync-opensearch.test.ts @@ -0,0 +1,155 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance + * with the License. A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES + * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +import * as cdk from 'aws-cdk-lib'; +import { Template, Match } from 'aws-cdk-lib/assertions'; +import * as cognito from 'aws-cdk-lib/aws-cognito'; +import * as os from 'aws-cdk-lib/aws-opensearchservice'; +import * as secret from 'aws-cdk-lib/aws-secretsmanager'; +import { QaAppsyncOpensearch, QaAppsyncOpensearchProps } from '../../../../src/patterns/gen-ai/aws-qa-appsync-opensearch'; + + +describe('QA Appsync Open search construct', () => { + + let qaTestTemplate: Template; + let qaTestConstruct: QaAppsyncOpensearch; + const cognitoPoolId = 'region_XXXXX'; + + + afterAll(() => { + console.log('Test completed'); + }); + + beforeAll(() => { + + const qaTestStack = new cdk.Stack(undefined, undefined, { + env: { account: cdk.Aws.ACCOUNT_ID, region: cdk.Aws.REGION }, + }); + + const osDomain = os.Domain.fromDomainAttributes(qaTestStack, 'osdomain', { + domainArn: 'arn:aws:es:region:account:domain/', + domainEndpoint: 'https://osendppint.amazon.aws.com', + }); + + + const osSecret = secret.Secret.fromSecretNameV2(qaTestStack, 'ossecret', 'OSSecretId'); + const userPoolLoaded = cognito.UserPool.fromUserPoolId(qaTestStack, 'testUserPool', cognitoPoolId); + + + const qaTestProps: QaAppsyncOpensearchProps = + { + existingOpensearchDomain: osDomain, + openSearchIndexName: 'demoindex', + openSearchSecret: osSecret, + cognitoUserPool: userPoolLoaded, + }; + + qaTestConstruct = new QaAppsyncOpensearch(qaTestStack, 'test', qaTestProps); + qaTestTemplate = Template.fromStack(qaTestStack); + + }); + + test('Lambda properties', () => { + qaTestTemplate.hasResourceProperties('AWS::Lambda::Function', { + Handler: 'index.handler', + }); + + qaTestTemplate.hasResourceProperties('AWS::Lambda::Function', { + PackageType: 'Image', + FunctionName: Match.stringLikeRegexp('lambda_question_answering'), + Environment: { + Variables: { + GRAPHQL_URL: { + 'Fn::GetAtt': [ + Match.stringLikeRegexp('testquestionAnsweringGraphqlApi'), + 'GraphQLUrl', + ], + }, + INPUT_BUCKET: { Ref: Match.stringLikeRegexp('testinputAssetsBucketdev') }, + OPENSEARCH_DOMAIN_ENDPOINT: 'osendppint.amazon.aws.com', + OPENSEARCH_INDEX: 'demoindex', + OPENSEARCH_SECRET_ID: 'OSSecretId', + }, + }, + }); + }); + + + test('Lambda function count', () => { + qaTestTemplate.resourceCountIs('AWS::Lambda::Function', 2); + }); + + test('Appsync Graphql Properties', () => { + qaTestTemplate.hasResourceProperties('AWS::AppSync::GraphQLApi', { + UserPoolConfig: {}, + AuthenticationType: 'AMAZON_COGNITO_USER_POOLS', + }); + }); + + test('Appsync resolver Properties', () => { + qaTestTemplate.hasResourceProperties('AWS::AppSync::Resolver', { + DataSourceName: Match.stringLikeRegexp('questionAnsweringEventBridgeDataSource'), + FieldName: 'postQuestion', + TypeName: 'Mutation', + }); + + qaTestTemplate.hasResourceProperties('AWS::AppSync::Resolver', { + DataSourceName: Match.stringLikeRegexp('JobStatusDataSource'), + FieldName: 'updateQAJobStatus', + TypeName: 'Mutation', + }); + }); + + test('Appsync resolver Count', () => { + qaTestTemplate.resourceCountIs('AWS::AppSync::Resolver', 2); + }, + ); + + test('Appsync Graphql Count', () => { + qaTestTemplate.resourceCountIs('AWS::AppSync::GraphQLApi', 1); + expect(qaTestConstruct.graphqlApi.apiId).not.toBeNull; + }, + ); + + test('Event Bus rule Target', () => { + qaTestTemplate.hasResourceProperties('AWS::Events::Rule', + Match.objectEquals + ({ + Description: 'Rule to trigger question answering function', + EventBusName: { Ref: Match.stringLikeRegexp('testquestionAnsweringEventBus') }, + EventPattern: { source: ['questionanswering'] }, + State: 'ENABLED', + Targets: + [{ + Arn: + { + 'Fn::GetAtt': [Match.stringLikeRegexp('testlambdaquestionanswering'), 'Arn'], + }, + Id: 'Target0', + + }], + }, + )); + }); + + test('S3 Bucket Properties', () => { + qaTestTemplate.hasResourceProperties('AWS::S3::Bucket', { + BucketEncryption: { ServerSideEncryptionConfiguration: [{ ServerSideEncryptionByDefault: { SSEAlgorithm: 'AES256' } }] }, + }); + expect(qaTestConstruct.s3InputAssetsBucket).not.toBeNull; + }); + + test('S3 Bucket Count', () => { + qaTestTemplate.resourceCountIs('AWS::S3::Bucket', 1); + }); + +}); diff --git a/test/patterns/gen-ai/aws-rag-appsync-stepfn-opensearch/aws-rag-appsync-stepfn-opensearch.test.ts b/test/patterns/gen-ai/aws-rag-appsync-stepfn-opensearch/aws-rag-appsync-stepfn-opensearch.test.ts index 21eb3f70..1594dd49 100644 --- a/test/patterns/gen-ai/aws-rag-appsync-stepfn-opensearch/aws-rag-appsync-stepfn-opensearch.test.ts +++ b/test/patterns/gen-ai/aws-rag-appsync-stepfn-opensearch/aws-rag-appsync-stepfn-opensearch.test.ts @@ -22,9 +22,8 @@ import { RagAppsyncStepfnOpensearch, RagAppsyncStepfnOpensearchProps } from '../ describe('RAG Appsync Stepfn Open search construct', () => { let ragTestTemplate: Template; - let stage = '-dev'; let ragTestConstruct: RagAppsyncStepfnOpensearch; - const cognitoPoolId = 'us-east-1_1RVagE46n'; + const cognitoPoolId = 'region_XXXXX'; afterAll(() => { console.log('Test completed'); @@ -56,11 +55,11 @@ describe('RAG Appsync Stepfn Open search construct', () => { ); const osDomain = os.Domain.fromDomainAttributes(ragTestStack, 'osdomain', { - domainArn: 'arn:aws:es:us-east-1:383119320704:domain/whiskeyosmanagedcluster', - domainEndpoint: 'https://vpc-whiskeyosmanagedcluster-4pkv5sj6vhoz5lrxn35wfidrie.us-east-1.es.amazonaws.com', + domainArn: 'arn:aws:es:region:account:domain/', + domainEndpoint: 'https://osendppint.amazon.aws.com', }); - const osSecret = secret.Secret.fromSecretNameV2(ragTestStack, 'ossecret', 'OSSecret4A7B7484-NJb2Ppu2AmvJ'); + const osSecret = secret.Secret.fromSecretNameV2(ragTestStack, 'ossecret', 'OSSecretID'); const userPoolLoaded = cognito.UserPool.fromUserPoolId(ragTestStack, 'testUserPool', cognitoPoolId); @@ -79,12 +78,12 @@ describe('RAG Appsync Stepfn Open search construct', () => { test('Lambda properties', () => { ragTestTemplate.hasResourceProperties('AWS::Lambda::Function', { PackageType: 'Image', - FunctionName: 'embeddings_job_docker'+stage, + FunctionName: Match.stringLikeRegexp('embeddings_job_docker'), Environment: { Variables: { GRAPHQL_URL: { 'Fn::GetAtt': [Match.stringLikeRegexp('testingestionGraphqlApi'), 'GraphQLUrl'] }, INPUT_BUCKET: { Ref: Match.stringLikeRegexp('testinputAssetsBucket') }, - OPENSEARCH_DOMAIN_ENDPOINT: Match.stringLikeRegexp('vpc-whiskeyosmanagedcluster-'), + OPENSEARCH_DOMAIN_ENDPOINT: Match.stringLikeRegexp('osendppint.amazon.aws.com'), OPENSEARCH_INDEX: 'demoindex', OPENSEARCH_SECRET_ID: Match.stringLikeRegexp('OSSecret'), OUTPUT_BUCKET: { Ref: Match.stringLikeRegexp('testprocessedAssetsBucketdev') }, @@ -93,7 +92,7 @@ describe('RAG Appsync Stepfn Open search construct', () => { }); ragTestTemplate.hasResourceProperties('AWS::Lambda::Function', { PackageType: 'Image', - FunctionName: 's3_file_transformer_docker'+stage, + FunctionName: Match.stringLikeRegexp('s3_file_transformer_docker'), Environment: { Variables: { GRAPHQL_URL: { 'Fn::GetAtt': [Match.stringLikeRegexp('testingestionGraphqlApi'), 'GraphQLUrl'] }, @@ -104,7 +103,7 @@ describe('RAG Appsync Stepfn Open search construct', () => { }); ragTestTemplate.hasResourceProperties('AWS::Lambda::Function', { PackageType: 'Image', - FunctionName: 'ingestion_input_validation_docker'+stage, + FunctionName: Match.stringLikeRegexp('ingestion_input_validation_docker'), Environment: { Variables: { @@ -124,13 +123,27 @@ describe('RAG Appsync Stepfn Open search construct', () => { ragTestTemplate.resourceCountIs('AWS::Lambda::Function', 4); }); - test('Appsync Merge Graphql Properties', () => { + test('Appsync Graphql Properties', () => { ragTestTemplate.hasResourceProperties('AWS::AppSync::GraphQLApi', { UserPoolConfig: {}, AuthenticationType: 'AMAZON_COGNITO_USER_POOLS', }); }); + test('Appsync resolver Properties', () => { + ragTestTemplate.hasResourceProperties('AWS::AppSync::Resolver', { + DataSourceName: Match.stringLikeRegexp('ingestionEventBridgeDataSource'), + FieldName: 'ingestDocuments', + TypeName: 'Mutation', + }); + + ragTestTemplate.hasResourceProperties('AWS::AppSync::Resolver', { + DataSourceName: Match.stringLikeRegexp('JobStatusDataSource'), + FieldName: 'updateIngestionJobStatus', + TypeName: 'Mutation', + }); + }); + test('Appsync Graphql Count', () => { ragTestTemplate.resourceCountIs('AWS::AppSync::GraphQLApi', 1); }); diff --git a/test/patterns/gen-ai/aws-summarization-appsync-stepfn/aws-summarization-appsync-stepfn.test.ts b/test/patterns/gen-ai/aws-summarization-appsync-stepfn/aws-summarization-appsync-stepfn.test.ts index e1acd178..05bf1bcf 100644 --- a/test/patterns/gen-ai/aws-summarization-appsync-stepfn/aws-summarization-appsync-stepfn.test.ts +++ b/test/patterns/gen-ai/aws-summarization-appsync-stepfn/aws-summarization-appsync-stepfn.test.ts @@ -29,7 +29,7 @@ describe('Summarization Appsync Stepfn construct', () => { let summarizationTestTemplate: Template; let summarizationTestConstruct: SummarizationAppsyncStepfn; - const cognitoPoolId = 'us-east-1_1RVagE46n'; + const cognitoPoolId = 'region_XXXXX'; afterAll(() => { @@ -109,7 +109,7 @@ describe('Summarization Appsync Stepfn construct', () => { test('Lambda properties', () => { summarizationTestTemplate.hasResourceProperties('AWS::Lambda::Function', { PackageType: 'Image', - FunctionName: 'summary_input_validator-dev', + FunctionName: Match.stringLikeRegexp('summary_input_validator'), Environment: { Variables: { GRAPHQL_URL: { @@ -124,7 +124,7 @@ describe('Summarization Appsync Stepfn construct', () => { }); summarizationTestTemplate.hasResourceProperties('AWS::Lambda::Function', { PackageType: 'Image', - FunctionName: 'summary_document_reader-dev', + FunctionName: Match.stringLikeRegexp('summary_document_reader'), Environment: { Variables: { GRAPHQL_URL: { @@ -143,7 +143,7 @@ describe('Summarization Appsync Stepfn construct', () => { }); summarizationTestTemplate.hasResourceProperties('AWS::Lambda::Function', { PackageType: 'Image', - FunctionName: 'summary_generator-dev', + FunctionName: Match.stringLikeRegexp('summary_generator-dev'), Environment: { Variables: { ASSET_BUCKET_NAME: { Ref: 'testprocessedAssetsBucketdevF293824A' }, @@ -180,6 +180,19 @@ describe('Summarization Appsync Stepfn construct', () => { }); }); + test('Appsync resolver Properties', () => { + summarizationTestTemplate.hasResourceProperties('AWS::AppSync::Resolver', { + DataSourceName: Match.stringLikeRegexp('eventBridgeDataSource'), + FieldName: 'generateSummary', + TypeName: 'Mutation', + }); + + summarizationTestTemplate.hasResourceProperties('AWS::AppSync::Resolver', { + DataSourceName: Match.stringLikeRegexp('SummaryStatusDataSource'), + FieldName: 'updateSummaryJobStatus', + TypeName: 'Mutation', + }); + }); test('Appsync Graphql Count', () => { summarizationTestTemplate.resourceCountIs('AWS::AppSync::GraphQLApi', 2);