From badb704fba4a598b1a2f5bf68e855d1809058128 Mon Sep 17 00:00:00 2001 From: Mike Roberts Date: Fri, 13 Sep 2024 14:55:33 -0400 Subject: [PATCH] More functional test refactoring --- .../domain/github/crawler/crawlUsers.test.ts | 126 ++++-------------- .../webPush/webPushSubscriptions.test.ts | 33 ++--- ...githubWebhookInstallationProcessor.test.ts | 17 +-- .../webhook/githubWebhookProcessor.test.ts | 63 +++++++++ .../github/webhook/githubWebhookProcessor.ts | 83 ------------ .../githubWebhookRepoPushProcessor.test.ts | 75 ++--------- .../githubWebhookWorkflowRunProcessor.test.ts | 102 +++----------- .../fakeDynamoDBInterfaceExpectations.ts | 31 ++++- .../fakes/tableRecordExpectedWrites.ts | 63 ++++++++- 9 files changed, 234 insertions(+), 359 deletions(-) create mode 100644 test/local/functional/domain/github/webhook/githubWebhookProcessor.test.ts delete mode 100644 test/local/functional/domain/github/webhook/githubWebhookProcessor.ts diff --git a/test/local/functional/domain/github/crawler/crawlUsers.test.ts b/test/local/functional/domain/github/crawler/crawlUsers.test.ts index d385ade..8811518 100644 --- a/test/local/functional/domain/github/crawler/crawlUsers.test.ts +++ b/test/local/functional/domain/github/crawler/crawlUsers.test.ts @@ -1,4 +1,4 @@ -import { expect, test } from 'vitest' +import { test } from 'vitest' import { FakeAppState } from '../../../../../testSupport/fakes/fakeAppState' import { FakeGithubInstallationClient } from '../../../../../testSupport/fakes/fakeGithubInstallationClient' import { @@ -15,6 +15,15 @@ import example_personal_account_user from '../../../../../examples/github/person import example_org_users from '../../../../../examples/github/org/api/users.json' import { crawlUsers } from '../../../../../../src/app/domain/github/crawler/crawlUsers' import { stubQueryAccountMembershipsByAccount } from '../../../../../testSupport/fakes/tableRecordReadStubs' +import { + expectBatchWrites, + expectBatchWritesLength +} from '../../../../../testSupport/fakes/dynamoDB/fakeDynamoDBInterfaceExpectations' +import { + expectedBatchDeleteGithubMemberships, + expectedBatchWriteGithubMemberships, + expectedBatchWriteGithubUsers +} from '../../../../../testSupport/fakes/tableRecordExpectedWrites' test('user-crawler-for-personal-account-installation', async () => { // A @@ -27,42 +36,11 @@ test('user-crawler-for-personal-account-installation', async () => { await crawlUsers(appState, testPersonalInstallation) // A - expect(appState.dynamoDB.batchWrites.length).toEqual(2) - expect(appState.dynamoDB.batchWrites[0]).toEqual({ - RequestItems: { - fakeGithubUsersTable: [ - { - PutRequest: { - Item: { - PK: 'USER#162360409', - _et: 'githubUser', - _lastUpdated: '2024-02-02T19:00:00.000Z', - ...testTestUser - } - } - } - ] - } - }) - expect(appState.dynamoDB.batchWrites[1]).toEqual({ - RequestItems: { - fakeGithubAccountMemberships: [ - { - PutRequest: { - Item: { - GSI1PK: 'USER#162360409', - GSI1SK: 'ACCOUNT#162360409', - PK: 'ACCOUNT#162360409', - SK: 'USER#162360409', - _et: 'githubAccountMembership', - _lastUpdated: '2024-02-02T19:00:00.000Z', - ...testTestUserMembershipOfPersonalInstallation - } - } - } - ] - } - }) + expectBatchWritesLength(appState).toEqual(2) + expectBatchWrites(appState, 0).toEqual(expectedBatchWriteGithubUsers([testTestUser])) + expectBatchWrites(appState, 1).toEqual( + expectedBatchWriteGithubMemberships([testTestUserMembershipOfPersonalInstallation]) + ) }) test('user-crawler-for-org-installation', async () => { @@ -82,66 +60,18 @@ test('user-crawler-for-org-installation', async () => { await crawlUsers(appState, testOrgInstallation) // A - expect(appState.dynamoDB.batchWrites.length).toEqual(3) - expect(appState.dynamoDB.batchWrites[0]).toEqual({ - RequestItems: { - fakeGithubUsersTable: [ - { - PutRequest: { - Item: { - PK: 'USER#162360409', - _et: 'githubUser', - _lastUpdated: '2024-02-02T19:00:00.000Z', - ...testTestUser - } - } - }, - { - PutRequest: { - Item: { - PK: 'USER#49635', - _et: 'githubUser', - _lastUpdated: '2024-02-02T19:00:00.000Z', - ...testMikeRobertsUser - } - } - } - ] - } - }) - // Previous membership for testTestUserMembershipOfOrg can remain unchanged - expect(appState.dynamoDB.batchWrites[1]).toEqual({ - RequestItems: { - fakeGithubAccountMemberships: [ - { - PutRequest: { - Item: { - GSI1PK: 'USER#49635', - GSI1SK: 'ACCOUNT#162483619', - PK: 'ACCOUNT#162483619', - SK: 'USER#49635', - _et: 'githubAccountMembership', - _lastUpdated: '2024-02-02T19:00:00.000Z', - ...testMikeRobertsUserMembershipOfOrg - } - } - } - ] - } - }) + expectBatchWritesLength(appState).toEqual(3) + expectBatchWrites(appState, 0).toEqual(expectedBatchWriteGithubUsers([testTestUser, testMikeRobertsUser])) + expectBatchWrites(appState, 1).toEqual( + expectedBatchWriteGithubMemberships([testMikeRobertsUserMembershipOfOrg]) + ) // No longer a member - expect(appState.dynamoDB.batchWrites[2]).toEqual({ - RequestItems: { - fakeGithubAccountMemberships: [ - { - DeleteRequest: { - Key: { - PK: 'ACCOUNT#162483619', - SK: 'USER#9786' - } - } - } - ] - } - }) + expectBatchWrites(appState, 2).toEqual( + expectedBatchDeleteGithubMemberships([ + { + accountId: 162483619, + userId: 9786 + } + ]) + ) }) diff --git a/test/local/functional/domain/github/webPush/webPushSubscriptions.test.ts b/test/local/functional/domain/github/webPush/webPushSubscriptions.test.ts index 0ab2873..bda4937 100644 --- a/test/local/functional/domain/github/webPush/webPushSubscriptions.test.ts +++ b/test/local/functional/domain/github/webPush/webPushSubscriptions.test.ts @@ -4,6 +4,16 @@ import { testTestUserPushSubscription } from '../../../../../examples/cicada/web import { handleApiMessage } from '../../../../../../src/app/lambdaFunctions/authenticatedApi/lambda' import { createAPIGatewayProxyWithLambdaAuthorizerEvent } from '../../../../../testSupport/fakes/awsStubs' import { HttpMethod } from 'aws-cdk-lib/aws-apigatewayv2' +import { + expectDelete, + expectDeletesLength, + expectPut, + expectPutsLength +} from '../../../../../testSupport/fakes/dynamoDB/fakeDynamoDBInterfaceExpectations' +import { + expectedDeleteWebPushSubscription, + expectedPutWebPushSubscription +} from '../../../../../testSupport/fakes/tableRecordExpectedWrites' test('web push test', async () => { const appState = new FakeAppState() @@ -55,17 +65,8 @@ test('web push subscribe', async () => { }, statusCode: 200 }) - expect(appState.dynamoDB.puts.length).toEqual(1) - expect(appState.dynamoDB.puts[0]).toEqual({ - Item: { - PK: 'USER#162360409', - SK: 'ENDPOINT#https://web.push.apple.com/TestOne', - _et: 'webPushSubscription', - _lastUpdated: '2024-02-02T19:00:00.000Z', - ...testTestUserPushSubscription - }, - TableName: 'fakeWebPushSubscriptions' - }) + expectPutsLength(appState).toEqual(1) + expectPut(appState).toEqual(expectedPutWebPushSubscription(testTestUserPushSubscription)) }) test('web push unsubscribe', async () => { @@ -93,12 +94,6 @@ test('web push unsubscribe', async () => { }, statusCode: 200 }) - expect(appState.dynamoDB.deletes.length).toEqual(1) - expect(appState.dynamoDB.deletes[0]).toEqual({ - Key: { - PK: 'USER#162360409', - SK: 'ENDPOINT#https://web.push.apple.com/TestOne' - }, - TableName: 'fakeWebPushSubscriptions' - }) + expectDeletesLength(appState).toEqual(1) + expectDelete(appState).toEqual(expectedDeleteWebPushSubscription(testTestUserPushSubscription)) }) diff --git a/test/local/functional/domain/github/webhook/githubWebhookInstallationProcessor.test.ts b/test/local/functional/domain/github/webhook/githubWebhookInstallationProcessor.test.ts index 469d439..e15f8f1 100644 --- a/test/local/functional/domain/github/webhook/githubWebhookInstallationProcessor.test.ts +++ b/test/local/functional/domain/github/webhook/githubWebhookInstallationProcessor.test.ts @@ -4,6 +4,11 @@ import { githubWebhookInstallationProcessor } from '../../../../../../src/app/do import example_installation_created from '../../../../../examples/github/org/webhook/installationCreated.json' import { testOrgInstallation } from '../../../../../examples/cicada/githubDomainObjects' +import { + expectPut, + expectPutsLength +} from '../../../../../testSupport/fakes/dynamoDB/fakeDynamoDBInterfaceExpectations' +import { expectedPutGithubInstallation } from '../../../../../testSupport/fakes/tableRecordExpectedWrites' test('installation-webhook-for-org-account-installation', async () => { // A @@ -17,16 +22,8 @@ test('installation-webhook-for-org-account-installation', async () => { await githubWebhookInstallationProcessor(appState, JSON.stringify(example_installation_created)) // A - expect(appState.dynamoDB.puts.length).toEqual(1) - expect(appState.dynamoDB.puts[0]).toEqual({ - Item: { - PK: 'ACCOUNT#162483619', - _et: 'githubInstallation', - _lastUpdated: '2024-02-02T19:00:00.000Z', - ...testOrgInstallation - }, - TableName: 'fakeGithubInstallationsTable' - }) + expectPutsLength(appState).toEqual(1) + expectPut(appState).toEqual(expectedPutGithubInstallation(testOrgInstallation)) expect(appState.eventBridgeBus.sentEvents.length).toEqual(1) expect(appState.eventBridgeBus.sentEvents[0]).toEqual({ detailType: 'InstallationUpdated', diff --git a/test/local/functional/domain/github/webhook/githubWebhookProcessor.test.ts b/test/local/functional/domain/github/webhook/githubWebhookProcessor.test.ts new file mode 100644 index 0000000..2cdc1c3 --- /dev/null +++ b/test/local/functional/domain/github/webhook/githubWebhookProcessor.test.ts @@ -0,0 +1,63 @@ +import { expect, test } from 'vitest' +import { FakeAppState } from '../../../../../testSupport/fakes/fakeAppState' +import example_workflow_run from '../../../../../examples/github/org/webhook/workflowRunCompleted.json' +import { testOrgTestRepoOneWorkflowRunThree } from '../../../../../examples/cicada/githubDomainObjects' +import { + createSignatureHeader, + processWebhookFromS3Event +} from '../../../../../../src/app/domain/github/webhookProcessor/githubWebhookProcessor' +import { + expectPut, + expectPutsLength +} from '../../../../../testSupport/fakes/dynamoDB/fakeDynamoDBInterfaceExpectations' +import { + expectedPutGithubWorkflowRun, + expectedPutGithubWorkflowRunEvent, + expectedPutLatestGithubWorkflowRunEvent +} from '../../../../../testSupport/fakes/tableRecordExpectedWrites' + +test('run-event', async () => { + // Arrange + const appState = new FakeAppState() + const rawBody = JSON.stringify(example_workflow_run) + appState.s3.getObjectsAsString.addResponse( + { bucket: 'fake-bucket', key: 'fake-key' }, + JSON.stringify({ + 'X-Hub-Signature-256': createSignatureHeader(rawBody, appState.config.fakeGithubConfig.webhookSecret), + 'X-GitHub-Event': 'workflow_run', + body: rawBody + }) + ) + + // Act + await processWebhookFromS3Event(appState, { + detail: { + bucket: { + name: 'fake-bucket' + }, + object: { + key: 'fake-key' + } + }, + 'detail-type': '', + account: '', + id: '', + region: '', + resources: [], + source: '', + time: '', + version: '' + }) + + // Assert + expectPutsLength(appState).toEqual(3) + expectPut(appState, 0).toEqual(expectedPutGithubWorkflowRunEvent(testOrgTestRepoOneWorkflowRunThree)) + expectPut(appState, 1).toEqual(expectedPutGithubWorkflowRun(testOrgTestRepoOneWorkflowRunThree)) + expectPut(appState, 2).toEqual(expectedPutLatestGithubWorkflowRunEvent(testOrgTestRepoOneWorkflowRunThree)) + + expect(appState.eventBridgeBus.sentEvents.length).toEqual(1) + expect(appState.eventBridgeBus.sentEvents[0].detailType).toEqual('GithubNewWorkflowRunEvent') + expect(JSON.parse(appState.eventBridgeBus.sentEvents[0].detail)).toEqual({ + data: testOrgTestRepoOneWorkflowRunThree + }) +}) diff --git a/test/local/functional/domain/github/webhook/githubWebhookProcessor.ts b/test/local/functional/domain/github/webhook/githubWebhookProcessor.ts deleted file mode 100644 index 92b7596..0000000 --- a/test/local/functional/domain/github/webhook/githubWebhookProcessor.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { expect, test } from 'vitest' -import { FakeAppState } from '../../../../../testSupport/fakes/fakeAppState' -import example_workflow_run from '../../../../../examples/github/org/webhook/workflowRunCompleted.json' -import { testOrgTestRepoOneWorkflowRunThree } from '../../../../../examples/cicada/githubDomainObjects' -import { - createSignatureHeader, - processWebhookFromS3Event -} from '../../../../../../src/app/domain/github/webhookProcessor/githubWebhookProcessor' - -test('run-event', async () => { - // Arrange - const appState = new FakeAppState() - const rawBody = JSON.stringify(example_workflow_run) - appState.s3.getObjectsAsString.addResponse( - { bucket: 'fake-bucket', key: 'fake-key' }, - JSON.stringify({ - 'X-Hub-Signature-256': createSignatureHeader(rawBody, appState.config.fakeGithubConfig.webhookSecret), - 'X-GitHub-Event': 'workflow_run', - body: rawBody - }) - ) - - // Act - await processWebhookFromS3Event(appState, { - detail: { - bucket: { - name: 'fake-bucket' - }, - object: { - key: 'fake-key' - } - }, - 'detail-type': '', - account: '', - id: '', - region: '', - resources: [], - source: '', - time: '', - version: '' - }) - - // Assert - expect(appState.dynamoDB.puts.length).toEqual(2) - expect(appState.dynamoDB.puts[0]).toEqual({ - ConditionExpression: 'attribute_not_exists(PK)', - Item: { - PK: 'ACCOUNT#162483619', - SK: 'REPO#768206479#WORKFLOW_ID#88647110#RUN_ID#8177622236#UPDATED_AT#2024-03-06T19:25:42Z#STATUS#completed', - GSI1PK: 'ACCOUNT#162483619', - GSI1SK: 'REPO#768206479#DATETIME#2024-03-06T19:25:42Z', - _et: 'githubWorkflowRunEvent', - _lastUpdated: '2024-02-02T19:00:00.000Z', - ...testOrgTestRepoOneWorkflowRunThree - }, - TableName: 'fakeGithubRepoActivityTable' - }) - expect(appState.dynamoDB.puts[1]).toEqual({ - ConditionExpression: 'attribute_not_exists(PK) OR #updatedAt < :newUpdatedAt', - ExpressionAttributeNames: { - '#updatedAt': 'updatedAt' - }, - ExpressionAttributeValues: { - ':newUpdatedAt': '2024-03-06T19:25:42Z' - }, - Item: { - PK: 'ACCOUNT#162483619', - SK: 'REPO#768206479#WORKFLOW#88647110', - GSI1PK: 'ACCOUNT#162483619', - GSI1SK: 'DATETIME#2024-03-06T19:25:42Z', - _et: 'githubLatestWorkflowRunEvent', - _lastUpdated: '2024-02-02T19:00:00.000Z', - ...testOrgTestRepoOneWorkflowRunThree - }, - TableName: 'fakeGithubLatestWorkflowRunsTable' - }) - - expect(appState.eventBridgeBus.sentEvents.length).toEqual(1) - expect(appState.eventBridgeBus.sentEvents[0]).toEqual({ - detailType: 'newWorkflowRunEvent', - detail: `{"ownerId":162483619,"ownerName":"cicada-test-org","ownerType":"organization","repoId":768206479,"repoName":"org-test-repo-one","workflowId":88647110,"id":8177622236,"runNumber":3,"displayTitle":"Test Repo One Workflow","createdAt":"2024-03-06T19:25:32Z","updatedAt":"2024-03-06T19:25:42Z","status":"completed","workflowName":"Test Repo One Workflow","conclusion":"success","headBranch":"main","htmlUrl":"https://github.com/cicada-test-org/org-test-repo-one/actions/runs/8177622236","actor":{"login":"mikebroberts"}}` - }) -}) diff --git a/test/local/functional/domain/github/webhook/githubWebhookRepoPushProcessor.test.ts b/test/local/functional/domain/github/webhook/githubWebhookRepoPushProcessor.test.ts index 32694f6..be69acb 100644 --- a/test/local/functional/domain/github/webhook/githubWebhookRepoPushProcessor.test.ts +++ b/test/local/functional/domain/github/webhook/githubWebhookRepoPushProcessor.test.ts @@ -4,74 +4,27 @@ import { FakeAppState } from '../../../../../testSupport/fakes/fakeAppState' import example_push from '../../../../../examples/github/org/webhook/push.json' import { githubWebhookRepoPushProcessor } from '../../../../../../src/app/domain/github/webhookProcessor/processors/githubWebhookRepoPushProcessor' import { testOrgTestRepoOnePushFC94 } from '../../../../../examples/cicada/githubDomainObjects' +import { + expectPut, + expectPutsLength +} from '../../../../../testSupport/fakes/dynamoDB/fakeDynamoDBInterfaceExpectations' +import { + expectedPutGithubPush, + expectedPutLatestGithubPush +} from '../../../../../testSupport/fakes/tableRecordExpectedWrites' test('push-webhook', async () => { const appState = new FakeAppState() await githubWebhookRepoPushProcessor(appState, JSON.stringify(example_push)) - expect(appState.dynamoDB.puts.length).toEqual(2) - expect(appState.dynamoDB.puts[0]).toEqual({ - ConditionExpression: 'attribute_not_exists(PK)', - Item: { - PK: 'ACCOUNT#162483619', - SK: 'REPO#768206479#REF#refs/heads/main#PUSH#COMMIT#fc94eb2b6feab026673ee6e740f3dd7fafd7c130', - GSI1PK: 'ACCOUNT#162483619', - GSI1SK: 'REPO#768206479#DATETIME#2024-03-06T21:26:18.000Z', - _et: 'githubPush', - _lastUpdated: '2024-02-02T19:00:00.000Z', - ...testOrgTestRepoOnePushFC94 - }, - TableName: 'fakeGithubRepoActivityTable' - }) - expect(appState.dynamoDB.puts[1]).toEqual({ - ConditionExpression: 'attribute_not_exists(PK) OR #dateTime < :newDateTime', - ExpressionAttributeNames: { - '#dateTime': 'dateTime' - }, - ExpressionAttributeValues: { - ':newDateTime': '2024-03-06T21:26:18.000Z' - }, - Item: { - PK: 'ACCOUNT#162483619', - SK: 'REPO#768206479#REF#refs/heads/main', - GSI1PK: 'ACCOUNT#162483619', - GSI1SK: 'DATETIME#2024-03-06T21:26:18.000Z', - _et: 'githubLatestPushPerRef', - _lastUpdated: '2024-02-02T19:00:00.000Z', - ...testOrgTestRepoOnePushFC94 - }, - TableName: 'fakeGithubLatestPushesPerRefTable' - }) + expectPutsLength(appState).toEqual(2) + expectPut(appState, 0).toEqual(expectedPutGithubPush(testOrgTestRepoOnePushFC94)) + expectPut(appState, 1).toEqual(expectedPutLatestGithubPush(testOrgTestRepoOnePushFC94)) expect(appState.eventBridgeBus.sentEvents.length).toEqual(1) - expect(appState.eventBridgeBus.sentEvents[0]).toEqual({ - detailType: 'GithubNewPush', - detail: JSON.stringify({ - data: { - ownerId: 162483619, - ownerName: 'cicada-test-org', - ownerType: 'organization', - repoId: 768206479, - repoName: 'org-test-repo-one', - repoUrl: 'https://github.com/cicada-test-org/org-test-repo-one', - actor: { - id: 49635, - login: 'mikebroberts', - avatarUrl: 'https://avatars.githubusercontent.com/u/49635?v=4' - }, - dateTime: '2024-03-06T21:26:18.000Z', - ref: 'refs/heads/main', - before: '8c3aa1cb0316ea23abeb2612457edb80868f53c8', - commits: [ - { - sha: 'fc94eb2b6feab026673ee6e740f3dd7fafd7c130', - message: 'Update README.md', - distinct: true, - author: { name: 'Mike Roberts', email: 'mike@symphonia.io' } - } - ] - } - }) + expect(appState.eventBridgeBus.sentEvents[0].detailType).toEqual('GithubNewPush') + expect(JSON.parse(appState.eventBridgeBus.sentEvents[0].detail)).toEqual({ + data: testOrgTestRepoOnePushFC94 }) }) diff --git a/test/local/functional/domain/github/webhook/githubWebhookWorkflowRunProcessor.test.ts b/test/local/functional/domain/github/webhook/githubWebhookWorkflowRunProcessor.test.ts index 726f788..fd02824 100644 --- a/test/local/functional/domain/github/webhook/githubWebhookWorkflowRunProcessor.test.ts +++ b/test/local/functional/domain/github/webhook/githubWebhookWorkflowRunProcessor.test.ts @@ -4,99 +4,29 @@ import { githubWebhookWorkflowRunProcessor } from '../../../../../../src/app/dom import example_workflow_run_complete from '../../../../../examples/github/org/webhook/workflowRunCompleted.json' import { testOrgTestRepoOneWorkflowRunThree } from '../../../../../examples/cicada/githubDomainObjects' +import { + expectPut, + expectPutsLength +} from '../../../../../testSupport/fakes/dynamoDB/fakeDynamoDBInterfaceExpectations' +import { + expectedPutGithubWorkflowRun, + expectedPutGithubWorkflowRunEvent, + expectedPutLatestGithubWorkflowRunEvent +} from '../../../../../testSupport/fakes/tableRecordExpectedWrites' test('workflow-run-completed-webhook', async () => { const appState = new FakeAppState() await githubWebhookWorkflowRunProcessor(appState, JSON.stringify(example_workflow_run_complete)) - expect(appState.dynamoDB.puts.length).toEqual(3) - expect(appState.dynamoDB.puts[0]).toEqual({ - ConditionExpression: 'attribute_not_exists(PK)', - Item: { - PK: 'ACCOUNT#162483619', - SK: 'REPO#768206479#WORKFLOW#88647110#WORKFLOW_RUN_EVENT#UPDATED_AT#2024-03-06T19:25:42Z#RUN#8177622236#STATUS#completed', - GSI1PK: 'ACCOUNT#162483619', - GSI1SK: 'REPO#768206479#DATETIME#2024-03-06T19:25:42Z', - _et: 'githubWorkflowRunEvent', - _lastUpdated: '2024-02-02T19:00:00.000Z', - ...testOrgTestRepoOneWorkflowRunThree - }, - TableName: 'fakeGithubRepoActivityTable' - }) - expect(appState.dynamoDB.puts[1]).toEqual({ - ConditionExpression: 'attribute_not_exists(PK) OR #updatedAt < :newUpdatedAt', - ExpressionAttributeNames: { - '#updatedAt': 'updatedAt' - }, - ExpressionAttributeValues: { - ':newUpdatedAt': '2024-03-06T19:25:42Z' - }, - Item: { - PK: 'ACCOUNT#162483619', - SK: 'REPO#768206479#WORKFLOW#88647110#WORKFLOW_RUN#RUN#8177622236', - GSI1PK: 'ACCOUNT#162483619', - GSI1SK: 'REPO#768206479#DATETIME#2024-03-06T19:25:42Z', - _et: 'githubWorkflowRun', - _lastUpdated: '2024-02-02T19:00:00.000Z', - ...testOrgTestRepoOneWorkflowRunThree - }, - TableName: 'fakeGithubRepoActivityTable' - }) - expect(appState.dynamoDB.puts[2]).toEqual({ - ConditionExpression: 'attribute_not_exists(PK) OR #updatedAt < :newUpdatedAt', - ExpressionAttributeNames: { - '#updatedAt': 'updatedAt' - }, - ExpressionAttributeValues: { - ':newUpdatedAt': '2024-03-06T19:25:42Z' - }, - Item: { - GSI1PK: 'ACCOUNT#162483619', - GSI1SK: 'DATETIME#2024-03-06T19:25:42Z', - PK: 'ACCOUNT#162483619', - SK: 'REPO#768206479#WORKFLOW#88647110', - _et: 'githubLatestWorkflowRunEvent', - _lastUpdated: '2024-02-02T19:00:00.000Z', - ...testOrgTestRepoOneWorkflowRunThree - }, - TableName: 'fakeGithubLatestWorkflowRunsTable' - }) + expectPutsLength(appState).toEqual(3) + expectPut(appState, 0).toEqual(expectedPutGithubWorkflowRunEvent(testOrgTestRepoOneWorkflowRunThree)) + expectPut(appState, 1).toEqual(expectedPutGithubWorkflowRun(testOrgTestRepoOneWorkflowRunThree)) + expectPut(appState, 2).toEqual(expectedPutLatestGithubWorkflowRunEvent(testOrgTestRepoOneWorkflowRunThree)) expect(appState.eventBridgeBus.sentEvents.length).toEqual(1) - expect(appState.eventBridgeBus.sentEvents[0]).toEqual({ - detailType: 'GithubNewWorkflowRunEvent', - detail: JSON.stringify({ - data: { - ownerId: 162483619, - ownerName: 'cicada-test-org', - ownerType: 'organization', - repoId: 768206479, - repoName: 'org-test-repo-one', - repoHtmlUrl: 'https://github.com/cicada-test-org/org-test-repo-one', - workflowId: 88647110, - id: 8177622236, - runNumber: 3, - runAttempt: 1, - event: 'workflow_dispatch', - path: '.github/workflows/test.yml', - displayTitle: 'Test Repo One Workflow', - createdAt: '2024-03-06T19:25:32Z', - updatedAt: '2024-03-06T19:25:42Z', - runStartedAt: '2024-03-06T19:25:32Z', - status: 'completed', - workflowName: 'Test Repo One Workflow', - conclusion: 'success', - headBranch: 'main', - htmlUrl: 'https://github.com/cicada-test-org/org-test-repo-one/actions/runs/8177622236', - headSha: '8c3aa1cb0316ea23abeb2612457edb80868f53c8', - actor: { - login: 'mikebroberts', - id: 49635, - avatarUrl: 'https://avatars.githubusercontent.com/u/49635?v=4', - htmlUrl: 'https://github.com/mikebroberts' - } - } - }) + expect(appState.eventBridgeBus.sentEvents[0].detailType).toEqual('GithubNewWorkflowRunEvent') + expect(JSON.parse(appState.eventBridgeBus.sentEvents[0].detail)).toEqual({ + data: testOrgTestRepoOneWorkflowRunThree }) }) diff --git a/test/testSupport/fakes/dynamoDB/fakeDynamoDBInterfaceExpectations.ts b/test/testSupport/fakes/dynamoDB/fakeDynamoDBInterfaceExpectations.ts index 6548db5..e70dda4 100644 --- a/test/testSupport/fakes/dynamoDB/fakeDynamoDBInterfaceExpectations.ts +++ b/test/testSupport/fakes/dynamoDB/fakeDynamoDBInterfaceExpectations.ts @@ -11,7 +11,15 @@ export function expectPut(appState: FakeAppState, index?: number) { return expect(appState.dynamoDB.puts[index ?? 0]) } -// TODO - use similar metadata object from stubber +export function expectDeletesLength(appState: FakeAppState) { + return expect(appState.dynamoDB.deletes.length) +} + +export function expectDelete(appState: FakeAppState, index?: number) { + return expect(appState.dynamoDB.deletes[index ?? 0]) +} + +// TODO - use similar metadata object from stubber? export function buildPut( tableName: string, entityType: string, @@ -29,6 +37,13 @@ export function buildPut( } } +export function buildDelete(tableName: string, key: Record) { + return { + Key: key, + TableName: tableName + } +} + export function expectBatchWritesLength(appState: FakeAppState) { return expect(appState.dynamoDB.batchWrites.length) } @@ -56,3 +71,17 @@ export function buildBatchWriteForEntity( } } } + +export function buildBatchDelete(tableName: string, keys: Record[]) { + return { + RequestItems: { + [tableName]: keys.map((key) => ({ + DeleteRequest: { + Key: { + ...key + } + } + })) + } + } +} diff --git a/test/testSupport/fakes/tableRecordExpectedWrites.ts b/test/testSupport/fakes/tableRecordExpectedWrites.ts index caf4936..15ab9f3 100644 --- a/test/testSupport/fakes/tableRecordExpectedWrites.ts +++ b/test/testSupport/fakes/tableRecordExpectedWrites.ts @@ -1,8 +1,17 @@ -import { buildBatchWriteForEntity, buildPut } from './dynamoDB/fakeDynamoDBInterfaceExpectations' +import { + buildBatchDelete, + buildBatchWriteForEntity, + buildDelete, + buildPut +} from './dynamoDB/fakeDynamoDBInterfaceExpectations' import { GithubInstallation } from '../../../src/app/domain/types/GithubInstallation' import { GithubPush } from '../../../src/app/domain/types/GithubPush' import { GithubRepository } from '../../../src/app/domain/types/GithubRepository' import { GithubWorkflowRunEvent } from '../../../src/app/domain/types/GithubWorkflowRunEvent' +import { GithubUser } from '../../../src/app/domain/types/GithubUser' +import { GithubAccountMembership } from '../../../src/app/domain/types/GithubAccountMembership' +import { GithubAccountId, GithubUserId } from '../../../src/app/domain/types/GithubKeys' +import { WebPushSubscription } from '../../../src/app/domain/types/WebPushSubscription' export function expectedPutGithubInstallation(installation: GithubInstallation) { return buildPut('fakeGithubInstallationsTable', 'githubInstallation', { @@ -125,3 +134,55 @@ export function expectedBatchWriteGithubRepositories(repos: GithubRepository[]) })) ) } + +export function expectedBatchWriteGithubUsers(users: GithubUser[]) { + return buildBatchWriteForEntity( + 'fakeGithubUsersTable', + 'githubUser', + users.map((user) => ({ + PK: `USER#${user.id}`, + ...user + })) + ) +} + +export function expectedBatchWriteGithubMemberships(memberships: GithubAccountMembership[]) { + return buildBatchWriteForEntity( + 'fakeGithubAccountMemberships', + 'githubAccountMembership', + memberships.map((membership) => ({ + PK: `ACCOUNT#${membership.accountId}`, + SK: `USER#${membership.userId}`, + GSI1PK: `USER#${membership.userId}`, + GSI1SK: `ACCOUNT#${membership.accountId}`, + ...membership + })) + ) +} + +export function expectedBatchDeleteGithubMemberships( + memberships: { accountId: GithubAccountId; userId: GithubUserId }[] +) { + return buildBatchDelete( + 'fakeGithubAccountMemberships', + memberships.map(({ accountId, userId }) => ({ + PK: `ACCOUNT#${accountId}`, + SK: `USER#${userId}` + })) + ) +} + +export function expectedPutWebPushSubscription(subscription: WebPushSubscription) { + return buildPut('fakeWebPushSubscriptions', 'webPushSubscription', { + PK: `USER#${subscription.userId}`, + SK: `ENDPOINT#${subscription.endpoint}`, + ...subscription + }) +} + +export function expectedDeleteWebPushSubscription(subscription: WebPushSubscription) { + return buildDelete('fakeWebPushSubscriptions', { + PK: `USER#${subscription.userId}`, + SK: `ENDPOINT#${subscription.endpoint}` + }) +}