From 097d9339230d058de9168f4f629eeec4ba815bbb Mon Sep 17 00:00:00 2001 From: Tiffany Forkner Date: Tue, 7 Jan 2025 11:30:52 -0500 Subject: [PATCH 1/4] fix(test): Create mock for calling lambdas (#973) * Added msw endpoints for Lambda, Step Functions, Secure Token Services, and other related services * Added/updated test data to support new endpoints * Updated tests to use the new endpoints instead of mocking individually --- lib/lambda/cfnNotify.test.ts | 53 ++--- lib/lambda/cfnNotify.ts | 1 + lib/lambda/checkConsumerLag.test.ts | 202 ++++++------------ lib/lambda/checkConsumerLag.ts | 36 ++-- lib/lambda/createTriggers.test.ts | 74 ++++--- lib/lambda/createTriggers.ts | 4 +- lib/lambda/deleteIndex.test.ts | 46 ++-- lib/lambda/deleteTriggers.test.ts | 105 +++++---- lib/lambda/deleteTriggers.ts | 8 +- lib/lambda/mapRole.test.ts | 84 +++----- lib/lambda/mapRole.ts | 19 +- lib/lambda/runReindex.test.ts | 120 +++++------ lib/lambda/runReindex.ts | 16 +- lib/lambda/setupIndex.test.ts | 87 ++++---- lib/libs/sink-lib.test.ts | 20 +- lib/libs/sink-lib.ts | 3 +- .../manage-users/src/cognito-lib.ts | 31 +-- .../manage-users/src/manageUsers.test.ts | 171 ++++++--------- .../manage-users/src/manageUsers.ts | 17 +- lib/vitest.setup.ts | 2 - mocks/consts.ts | 1 + mocks/data/index.ts | 1 + mocks/data/lambdas.ts | 59 +++++ mocks/data/secrets.ts | 9 + mocks/data/users/stateSubmitters.ts | 35 +++ mocks/handlers/aws/cloudFormation.ts | 48 +++-- mocks/handlers/aws/cognito.ts | 39 +++- mocks/handlers/aws/credentials.ts | 49 ++++- mocks/handlers/aws/index.ts | 6 +- mocks/handlers/aws/lambda.ts | 112 ++++++++++ mocks/handlers/aws/stepFunctions.ts | 25 +++ mocks/handlers/opensearch/index.ts | 17 +- mocks/handlers/opensearch/indices.ts | 55 +++++ mocks/handlers/opensearch/security.ts | 13 ++ mocks/index.d.ts | 68 ++++-- 35 files changed, 971 insertions(+), 665 deletions(-) create mode 100644 mocks/data/lambdas.ts create mode 100644 mocks/handlers/aws/lambda.ts create mode 100644 mocks/handlers/aws/stepFunctions.ts create mode 100644 mocks/handlers/opensearch/indices.ts create mode 100644 mocks/handlers/opensearch/security.ts diff --git a/lib/lambda/cfnNotify.test.ts b/lib/lambda/cfnNotify.test.ts index f436e0c3d2..b6cdd45763 100644 --- a/lib/lambda/cfnNotify.test.ts +++ b/lib/lambda/cfnNotify.test.ts @@ -1,17 +1,14 @@ -import { describe, it, expect, vi, beforeEach } from "vitest"; +import { afterEach, describe, expect, it, vi } from "vitest"; import { handler } from "./cfnNotify"; -import { send, SUCCESS, FAILED } from "cfn-response-async"; - -vi.mock("cfn-response-async", () => ({ - send: vi.fn(), - SUCCESS: "SUCCESS", - FAILED: "FAILED", -})); +import { Context } from "aws-lambda"; +import { CLOUDFORMATION_NOTIFICATION_DOMAIN } from "mocks"; +import * as cfn from "cfn-response-async"; describe("Lambda Handler", () => { + const cfnSpy = vi.spyOn(cfn, "send"); const callback = vi.fn(); - beforeEach(() => { + afterEach(() => { vi.clearAllMocks(); }); @@ -21,19 +18,21 @@ describe("Lambda Handler", () => { Context: { Execution: { Input: { - cfnEvent: {}, + cfnEvent: { + ResponseURL: CLOUDFORMATION_NOTIFICATION_DOMAIN, + }, cfnContext: {}, }, }, }, }; - await handler(event, null, callback); + await handler(event, {} as Context, callback); - expect(send).toHaveBeenCalledWith( + expect(cfnSpy).toHaveBeenCalledWith( event.Context.Execution.Input.cfnEvent, event.Context.Execution.Input.cfnContext, - SUCCESS, + cfn.SUCCESS, {}, "static", ); @@ -46,19 +45,21 @@ describe("Lambda Handler", () => { Context: { Execution: { Input: { - cfnEvent: {}, + cfnEvent: { + ResponseURL: CLOUDFORMATION_NOTIFICATION_DOMAIN, + }, cfnContext: {}, }, }, }, }; - await handler(event, null, callback); + await handler(event, {} as Context, callback); - expect(send).toHaveBeenCalledWith( + expect(cfnSpy).toHaveBeenCalledWith( event.Context.Execution.Input.cfnEvent, event.Context.Execution.Input.cfnContext, - FAILED, + cfn.FAILED, {}, "static", ); @@ -78,29 +79,19 @@ describe("Lambda Handler", () => { }, }; - await handler(event, null, callback); + await handler(event, {} as Context, callback); - expect(send).not.toHaveBeenCalled(); + expect(cfnSpy).not.toHaveBeenCalled(); expect(callback).toHaveBeenCalledWith(null, { statusCode: 200 }); }); it("should handle errors and return statusCode 500", async () => { const event = { Success: true, - Context: { - Execution: { - Input: { - cfnEvent: {}, - cfnContext: {}, - }, - }, - }, + Context: {}, }; - // Simulate an error in send function - (send as vi.Mock).mockRejectedValue(new Error("Test error")); - - await handler(event, null, callback); + await handler(event, {} as Context, callback); expect(callback).toHaveBeenCalledWith(expect.any(Error), { statusCode: 500, diff --git a/lib/lambda/cfnNotify.ts b/lib/lambda/cfnNotify.ts index ef53387018..e3d9678dc4 100644 --- a/lib/lambda/cfnNotify.ts +++ b/lib/lambda/cfnNotify.ts @@ -18,6 +18,7 @@ export const handler: Handler = async (event, _, callback) => { await send(cfnEvent, cfnContext, result, responseData, "static"); } } catch (error: any) { + console.log({ error }); response.statusCode = 500; errorResponse = error; } finally { diff --git a/lib/lambda/checkConsumerLag.test.ts b/lib/lambda/checkConsumerLag.test.ts index 3c4a684ab3..2402eb5c48 100644 --- a/lib/lambda/checkConsumerLag.test.ts +++ b/lib/lambda/checkConsumerLag.test.ts @@ -1,6 +1,16 @@ -import { describe, it, expect, vi, beforeEach } from "vitest"; +import { describe, it, expect, vi, afterEach } from "vitest"; import { handler } from "./checkConsumerLag"; -import { Kafka } from "kafkajs"; +import { Context } from "aws-lambda"; +import { + TEST_FUNCTION_NAME, + TEST_TOPIC_NAME, + TEST_NONEXISTENT_TOPIC_NAME, + TEST_NONEXISTENT_FUNCTION_NAME, + TEST_MULTIPLE_TOPICS_FUNCTION_NAME, + TEST_MULTIPLE_TOPICS_TOPIC_NAME, + TEST_MISSING_CONSUMER_FUNCTION_NAME, + TEST_MISSING_CONSUMER_TOPIC_NAME, +} from "mocks"; const mockKafkaAdmin = { connect: vi.fn(), @@ -8,9 +18,7 @@ const mockKafkaAdmin = { groups: [{ state: "Stable" }], }), fetchTopicOffsets: vi.fn().mockResolvedValue([{ offset: "100" }]), - fetchOffsets: vi - .fn() - .mockResolvedValue([{ partitions: [{ offset: "100" }] }]), + fetchOffsets: vi.fn().mockResolvedValue([{ partitions: [{ offset: "100" }] }]), disconnect: vi.fn(), }; @@ -20,19 +28,10 @@ vi.mock("kafkajs", () => ({ })), })); -const mockLambdaClient = { - send: vi.fn(), -}; - -vi.mock("@aws-sdk/client-lambda", () => ({ - LambdaClient: vi.fn().mockImplementation(() => mockLambdaClient), - ListEventSourceMappingsCommand: vi.fn(), -})); - describe("Lambda Handler", () => { const callback = vi.fn(); - beforeEach(() => { + afterEach(() => { vi.clearAllMocks(); }); @@ -40,23 +39,14 @@ describe("Lambda Handler", () => { const event = { triggers: [ { - function: "test-function", - topics: ["test-topic"], + function: TEST_FUNCTION_NAME, + topics: [TEST_TOPIC_NAME], }, ], brokerString: "broker1,broker2", }; - mockLambdaClient.send.mockResolvedValueOnce({ - EventSourceMappings: [ - { - Topics: ["test-topic"], - SelfManagedKafkaEventSourceConfig: { ConsumerGroupId: "test-group" }, - }, - ], - }); - - await handler(event, null, callback); + await handler(event, {} as Context, callback); expect(callback).toHaveBeenCalledWith(null, { statusCode: 200, @@ -66,144 +56,72 @@ describe("Lambda Handler", () => { }); }); - it("should handle missing event source mappings", async () => { + it.each([ + [ + "should handle missing function", + TEST_NONEXISTENT_FUNCTION_NAME, + TEST_TOPIC_NAME, + `ERROR: No event source mapping found for function ${TEST_NONEXISTENT_FUNCTION_NAME} and topic ${TEST_TOPIC_NAME}`, + ], + [ + "should handle missing topic", + TEST_FUNCTION_NAME, + TEST_NONEXISTENT_TOPIC_NAME, + `ERROR: No event source mapping found for function ${TEST_FUNCTION_NAME} and topic ${TEST_NONEXISTENT_TOPIC_NAME}`, + ], + [ + "should handle multiple event source mappings", + TEST_MULTIPLE_TOPICS_FUNCTION_NAME, + TEST_MULTIPLE_TOPICS_TOPIC_NAME, + `ERROR: Multiple event source mappings found for function ${TEST_MULTIPLE_TOPICS_FUNCTION_NAME} and topic ${TEST_MULTIPLE_TOPICS_TOPIC_NAME}`, + ], + [ + "should handle missing ConsumerGroupId", + TEST_MISSING_CONSUMER_FUNCTION_NAME, + TEST_MISSING_CONSUMER_TOPIC_NAME, + `ERROR: No ConsumerGroupId found for function ${TEST_MISSING_CONSUMER_FUNCTION_NAME} and topic ${TEST_MISSING_CONSUMER_TOPIC_NAME}`, + ], + ])("%s", async (_, funcName, topicName, errorMessage) => { const event = { triggers: [ { - function: "test-function", - topics: ["nonexistent-topic"], + function: funcName, + topics: [topicName], }, ], brokerString: "broker1,broker2", }; - mockLambdaClient.send.mockResolvedValueOnce({ - EventSourceMappings: [], - }); - - await handler(event, null, callback); + await handler(event, {} as Context, callback); - expect(callback).toHaveBeenCalledWith( - new Error( - "ERROR: No event source mapping found for function test-function and topic nonexistent-topic", - ), - { - statusCode: 500, - stable: false, - current: false, - ready: false, - }, - ); - }); - - it("should handle multiple event source mappings", async () => { - const event = { - triggers: [ - { - function: "test-function", - topics: ["test-topic"], - }, - ], - brokerString: "broker1,broker2", - }; - - mockLambdaClient.send.mockResolvedValueOnce({ - EventSourceMappings: [ - { - Topics: ["test-topic"], - SelfManagedKafkaEventSourceConfig: { ConsumerGroupId: "test-group" }, - }, - { - Topics: ["test-topic"], - SelfManagedKafkaEventSourceConfig: { - ConsumerGroupId: "test-group-2", - }, - }, - ], + expect(callback).toHaveBeenCalledWith(new Error(errorMessage), { + statusCode: 500, + stable: false, + current: false, + ready: false, }); - - await handler(event, null, callback); - - expect(callback).toHaveBeenCalledWith( - new Error( - "ERROR: Multiple event source mappings found for function test-function and topic test-topic", - ), - { - statusCode: 500, - stable: false, - current: false, - ready: false, - }, - ); }); it("should handle kafka admin errors", async () => { const event = { triggers: [ { - function: "test-function", - topics: ["test-topic"], + function: TEST_FUNCTION_NAME, + topics: [TEST_TOPIC_NAME], }, ], brokerString: "broker1,broker2", }; - const kafka = new Kafka({ - clientId: "consumerGroupResetter", - brokers: event.brokerString?.split(",") || [], - ssl: true, - }); - - kafka.admin = vi.fn().mockReturnValueOnce({ - connect: vi.fn(), - describeGroups: vi.fn().mockRejectedValue(new Error("Kafka admin error")), - fetchTopicOffsets: vi.fn(), - fetchOffsets: vi.fn(), - disconnect: vi.fn(), - }); - - await handler(event, null, callback); + mockKafkaAdmin.describeGroups.mockRejectedValueOnce(new Error("Kafka admin error")); - expect(callback).toHaveBeenCalledWith( - expect.any(Error), - expect.objectContaining({ - statusCode: 500, - }), - ); - }); + await handler(event, {} as Context, callback); - it("should handle missing ConsumerGroupId", async () => { - const event = { - triggers: [ - { - function: "test-function", - topics: ["test-topic"], - }, - ], - brokerString: "broker1,broker2", - }; - - mockLambdaClient.send.mockResolvedValueOnce({ - EventSourceMappings: [ - { - Topics: ["test-topic"], - SelfManagedKafkaEventSourceConfig: null, - }, - ], + expect(callback).toHaveBeenCalledWith(new Error(`Kafka admin error`), { + statusCode: 500, + stable: false, + current: false, + ready: false, }); - - await handler(event, null, callback); - - expect(callback).toHaveBeenCalledWith( - new Error( - "ERROR: No ConsumerGroupId found for function test-function and topic test-topic", - ), - { - statusCode: 500, - stable: false, - current: false, - ready: false, - }, - ); }); }); diff --git a/lib/lambda/checkConsumerLag.ts b/lib/lambda/checkConsumerLag.ts index 7cda293361..20ff64482a 100644 --- a/lib/lambda/checkConsumerLag.ts +++ b/lib/lambda/checkConsumerLag.ts @@ -1,9 +1,6 @@ import { Handler } from "aws-lambda"; import { Kafka } from "kafkajs"; -import { - LambdaClient, - ListEventSourceMappingsCommand, -} from "@aws-sdk/client-lambda"; +import { LambdaClient, ListEventSourceMappingsCommand } from "@aws-sdk/client-lambda"; export const handler: Handler = async (event, _, callback) => { const response = { @@ -15,22 +12,17 @@ export const handler: Handler = async (event, _, callback) => { let errorResponse = null; try { const triggerInfo: any[] = []; - const lambdaClient = new LambdaClient({}); + const lambdaClient = new LambdaClient({ + region: process.env.region, + }); for (const trigger of event.triggers) { for (const topic of [...new Set(trigger.topics)]) { - console.log( - `Getting consumer groups for function: ${trigger.function} and topic ${topic}`, - ); + console.log(`Getting consumer groups for function: ${trigger.function} and topic ${topic}`); const lambdaResponse = await lambdaClient.send( new ListEventSourceMappingsCommand({ FunctionName: trigger.function, }), ); - if (!lambdaResponse.EventSourceMappings) { - throw new Error( - `ERROR: No event source mapping found for function ${trigger.function} and topic ${topic}`, - ); - } if ( !lambdaResponse.EventSourceMappings || lambdaResponse.EventSourceMappings.length === 0 @@ -39,19 +31,21 @@ export const handler: Handler = async (event, _, callback) => { `ERROR: No event source mapping found for function ${trigger.function} and topic ${topic}`, ); } - const mappingForCurrentTopic = - lambdaResponse.EventSourceMappings.filter( - (mapping) => - mapping.Topics && mapping.Topics.includes(topic as string), + const mappingForCurrentTopic = lambdaResponse.EventSourceMappings.filter( + (mapping) => mapping.Topics && mapping.Topics.includes(topic as string), + ); + if (!mappingForCurrentTopic || mappingForCurrentTopic.length === 0) { + throw new Error( + `ERROR: No event source mapping found for function ${trigger.function} and topic ${topic}`, ); + } if (mappingForCurrentTopic.length > 1) { throw new Error( `ERROR: Multiple event source mappings found for function ${trigger.function} and topic ${topic}`, ); } const groupId = - mappingForCurrentTopic[0]?.SelfManagedKafkaEventSourceConfig - ?.ConsumerGroupId; + mappingForCurrentTopic[0]?.SelfManagedKafkaEventSourceConfig?.ConsumerGroupId; if (!groupId) { throw new Error( `ERROR: No ConsumerGroupId found for function ${trigger.function} and topic ${topic}`, @@ -98,9 +92,7 @@ export const handler: Handler = async (event, _, callback) => { } await admin.disconnect(); response.stable = statuses.every((status) => status === "Stable"); - response.current = Object.values(offsets).every( - (o) => o.latestOffset === o.currentOffset, - ); + response.current = Object.values(offsets).every((o) => o.latestOffset === o.currentOffset); response.ready = response.stable && response.current; } catch (error: any) { response.statusCode = 500; diff --git a/lib/lambda/createTriggers.test.ts b/lib/lambda/createTriggers.test.ts index 2742df1bec..62f9b71c47 100644 --- a/lib/lambda/createTriggers.test.ts +++ b/lib/lambda/createTriggers.test.ts @@ -1,36 +1,32 @@ -import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { handler } from "./createTriggers"; +import { Context } from "aws-lambda"; +import { + TEST_ERROR_EVENT_SOURCE_FUNCTION_NAME, + TEST_FUNCTION_NAME, + TEST_TOPIC_NAME, + TEST_FUNCTION_TEST_TOPIC_UUID, +} from "mocks"; import { LambdaClient, CreateEventSourceMappingCommand, GetEventSourceMappingCommand, } from "@aws-sdk/client-lambda"; -vi.mock("@aws-sdk/client-lambda", () => ({ - LambdaClient: vi.fn().mockImplementation(() => ({ - send: vi.fn(), - })), - CreateEventSourceMappingCommand: vi.fn(), - GetEventSourceMappingCommand: vi.fn(), -})); - vi.mock("crypto", () => ({ randomUUID: vi.fn().mockReturnValue("test-uuid"), })); describe("Lambda Handler", () => { + const lambdaSpy = vi.spyOn(LambdaClient.prototype, "send"); const callback = vi.fn(); - const mockLambdaClientSend = vi.fn(); beforeEach(() => { - vi.clearAllMocks(); vi.useFakeTimers(); - (LambdaClient as any).mockImplementation(() => ({ - send: mockLambdaClientSend, - })); }); afterEach(() => { + vi.clearAllMocks(); vi.useRealTimers(); }); @@ -38,8 +34,8 @@ describe("Lambda Handler", () => { const event = { triggers: [ { - function: "test-function", - topics: ["test-topic"], + function: TEST_FUNCTION_NAME, + topics: [TEST_TOPIC_NAME], }, ], consumerGroupPrefix: "cg-", @@ -49,18 +45,26 @@ describe("Lambda Handler", () => { startingPosition: "TRIM_HORIZON", }; - mockLambdaClientSend - .mockResolvedValueOnce({ UUID: "uuid-1" }) // Response for CreateEventSourceMappingCommand - .mockResolvedValueOnce({ State: "Enabled" }); // Response for GetEventSourceMappingCommand - - await handler(event, null, callback); + await handler(event, {} as Context, callback); - expect(mockLambdaClientSend).toHaveBeenCalledWith( - expect.any(CreateEventSourceMappingCommand), + expect(lambdaSpy).toHaveBeenCalledWith( + expect.objectContaining({ + input: expect.objectContaining({ + BatchSize: 1000, + Enabled: true, + FunctionName: TEST_FUNCTION_NAME, + Topics: [TEST_TOPIC_NAME], + }), + } as CreateEventSourceMappingCommand), ); - expect(mockLambdaClientSend).toHaveBeenCalledWith( - expect.any(GetEventSourceMappingCommand), + expect(lambdaSpy).toHaveBeenCalledWith( + expect.objectContaining({ + input: { + UUID: TEST_FUNCTION_TEST_TOPIC_UUID, + }, + } as GetEventSourceMappingCommand), ); + expect(lambdaSpy).toHaveBeenCalledTimes(2); expect(callback).toHaveBeenCalledWith(null, { statusCode: 200 }); }); @@ -68,8 +72,8 @@ describe("Lambda Handler", () => { const event = { triggers: [ { - function: "test-function", - topics: ["test-topic"], + function: TEST_ERROR_EVENT_SOURCE_FUNCTION_NAME, + topics: [TEST_TOPIC_NAME], }, ], consumerGroupPrefix: "cg-", @@ -79,13 +83,19 @@ describe("Lambda Handler", () => { startingPosition: "TRIM_HORIZON", }; - mockLambdaClientSend.mockRejectedValueOnce(new Error("Test error")); - - await handler(event, null, callback); + await handler(event, {} as Context, callback); - expect(mockLambdaClientSend).toHaveBeenCalledWith( - expect.any(CreateEventSourceMappingCommand), + expect(lambdaSpy).toHaveBeenCalledWith( + expect.objectContaining({ + input: expect.objectContaining({ + BatchSize: 1000, + Enabled: true, + FunctionName: TEST_ERROR_EVENT_SOURCE_FUNCTION_NAME, + Topics: [TEST_TOPIC_NAME], + }), + } as CreateEventSourceMappingCommand), ); + expect(lambdaSpy).toHaveBeenCalledTimes(1); expect(callback).toHaveBeenCalledWith(expect.any(Error), { statusCode: 500, }); diff --git a/lib/lambda/createTriggers.ts b/lib/lambda/createTriggers.ts index e728627a83..47aebb4af2 100644 --- a/lib/lambda/createTriggers.ts +++ b/lib/lambda/createTriggers.ts @@ -14,7 +14,9 @@ export const handler: Handler = async (event, _, callback) => { }; let errorResponse = null; try { - const lambdaClient = new LambdaClient({}); + const lambdaClient = new LambdaClient({ + region: process.env.region, + }); const uuidsToCheck = []; for (const trigger of event.triggers) { for (const topic of [...new Set(trigger.topics)]) { diff --git a/lib/lambda/deleteIndex.test.ts b/lib/lambda/deleteIndex.test.ts index 45b9123c2d..43feb819d0 100644 --- a/lib/lambda/deleteIndex.test.ts +++ b/lib/lambda/deleteIndex.test.ts @@ -1,40 +1,38 @@ -import { describe, it, expect, vi, beforeEach } from "vitest"; +import { describe, it, expect, vi, afterEach } from "vitest"; import { handler } from "./deleteIndex"; +import { Context } from "aws-lambda"; +import { OPENSEARCH_DOMAIN, OPENSEARCH_INDEX_NAMESPACE, errorDeleteIndexHandler } from "mocks"; +import { mockedServiceServer as mockedServer } from "mocks/server"; import * as os from "libs/opensearch-lib"; -vi.mock("libs/opensearch-lib", () => ({ - deleteIndex: vi.fn(), -})); - describe("Lambda Handler", () => { + const deleteIndexSpy = vi.spyOn(os, "deleteIndex"); const callback = vi.fn(); - beforeEach(() => { + afterEach(() => { vi.clearAllMocks(); }); it("should successfully delete all indices", async () => { const event = { - osDomain: "test-domain", - indexNamespace: "test-namespace-", + osDomain: OPENSEARCH_DOMAIN, + indexNamespace: OPENSEARCH_INDEX_NAMESPACE, }; - (os.deleteIndex as vi.Mock).mockResolvedValueOnce(null); - - await handler(event, null, callback); + await handler(event, {} as Context, callback); const expectedIndices = [ - "test-namespace-main", - "test-namespace-changelog", - "test-namespace-insights", - "test-namespace-types", - "test-namespace-subtypes", - "test-namespace-legacyinsights", - "test-namespace-cpocs", + `${OPENSEARCH_INDEX_NAMESPACE}main`, + `${OPENSEARCH_INDEX_NAMESPACE}changelog`, + `${OPENSEARCH_INDEX_NAMESPACE}insights`, + `${OPENSEARCH_INDEX_NAMESPACE}types`, + `${OPENSEARCH_INDEX_NAMESPACE}subtypes`, + `${OPENSEARCH_INDEX_NAMESPACE}legacyinsights`, + `${OPENSEARCH_INDEX_NAMESPACE}cpocs`, ]; expectedIndices.forEach((index) => { - expect(os.deleteIndex).toHaveBeenCalledWith("test-domain", index); + expect(deleteIndexSpy).toHaveBeenCalledWith(OPENSEARCH_DOMAIN, index); }); expect(callback).toHaveBeenCalledWith(null, { statusCode: 200 }); @@ -42,10 +40,10 @@ describe("Lambda Handler", () => { it("should handle missing osDomain", async () => { const event = { - indexNamespace: "test-namespace-", + indexNamespace: OPENSEARCH_INDEX_NAMESPACE, }; - await handler(event, null, callback); + await handler(event, {} as Context, callback); expect(callback).toHaveBeenCalledWith(expect.any(String), { statusCode: 500, @@ -53,14 +51,14 @@ describe("Lambda Handler", () => { }); it("should handle errors during index deletion", async () => { + mockedServer.use(errorDeleteIndexHandler); + const event = { osDomain: "test-domain", indexNamespace: "test-namespace-", }; - (os.deleteIndex as vi.Mock).mockRejectedValueOnce(new Error("Test error")); - - await handler(event, null, callback); + await handler(event, {} as Context, callback); expect(callback).toHaveBeenCalledWith(expect.any(Error), { statusCode: 500, diff --git a/lib/lambda/deleteTriggers.test.ts b/lib/lambda/deleteTriggers.test.ts index 28125ed84d..315b359cbf 100644 --- a/lib/lambda/deleteTriggers.test.ts +++ b/lib/lambda/deleteTriggers.test.ts @@ -1,57 +1,77 @@ -import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; +import { afterEach, describe, expect, it, vi } from "vitest"; import { handler } from "./deleteTriggers"; +import { Context } from "aws-lambda"; import { + TEST_DELETE_TRIGGER_FUNCTION_NAME, + TEST_DELETE_TRIGGER_UUID, + TEST_ERROR_EVENT_SOURCE_FUNCTION_NAME, + TEST_NO_TRIGGERS_FUNCTION_NAME, +} from "mocks"; +import { + DeleteEventSourceMappingCommand, + GetEventSourceMappingCommand, LambdaClient, ListEventSourceMappingsCommand, - DeleteEventSourceMappingCommand, } from "@aws-sdk/client-lambda"; -vi.mock("@aws-sdk/client-lambda", () => ({ - LambdaClient: vi.fn().mockImplementation(() => ({ - send: vi.fn(), - })), - ListEventSourceMappingsCommand: vi.fn(), - DeleteEventSourceMappingCommand: vi.fn(), - GetEventSourceMappingCommand: vi.fn(), -})); - describe("Lambda Handler", () => { + const lambdaSpy = vi.spyOn(LambdaClient.prototype, "send"); const callback = vi.fn(); - const mockLambdaClientSend = vi.fn(); - beforeEach(() => { + afterEach(() => { vi.clearAllMocks(); - vi.useFakeTimers(); - (LambdaClient as any).mockImplementation(() => ({ - send: mockLambdaClientSend, - })); + vi.useRealTimers(); }); - afterEach(() => { - vi.useRealTimers(); + it("should handle deleting a trigger", async () => { + const event = { + functions: [TEST_DELETE_TRIGGER_FUNCTION_NAME], + }; + + await handler(event, {} as Context, callback); + + expect(lambdaSpy).toHaveBeenCalledWith( + expect.objectContaining({ + input: { + FunctionName: TEST_DELETE_TRIGGER_FUNCTION_NAME, + }, + } as ListEventSourceMappingsCommand), + ); + expect(lambdaSpy).toHaveBeenCalledWith( + expect.objectContaining({ + input: { + UUID: TEST_DELETE_TRIGGER_UUID, + }, + } as DeleteEventSourceMappingCommand), + ); + expect(lambdaSpy).toHaveBeenCalledWith( + expect.objectContaining({ + input: { + UUID: TEST_DELETE_TRIGGER_UUID, + }, + } as GetEventSourceMappingCommand), + ); + expect(lambdaSpy).toHaveBeenCalledTimes(3); + expect(callback).toHaveBeenCalledWith(null, { + statusCode: 200, + }); }); it("should handle errors during trigger deletion", async () => { const event = { - functions: ["function1"], + functions: [TEST_ERROR_EVENT_SOURCE_FUNCTION_NAME], }; - mockLambdaClientSend - .mockResolvedValueOnce({ - EventSourceMappings: [ - { UUID: "uuid-1", SelfManagedKafkaEventSourceConfig: {} }, - ], - }) - .mockRejectedValueOnce(new Error("Test error")); - - await handler(event, null, callback); + await handler(event, {} as Context, callback); - expect(mockLambdaClientSend).toHaveBeenCalledWith( - expect.any(ListEventSourceMappingsCommand), - ); - expect(mockLambdaClientSend).toHaveBeenCalledWith( - expect.any(DeleteEventSourceMappingCommand), + expect(lambdaSpy).toHaveBeenCalledWith( + expect.objectContaining({ + input: { + FunctionName: TEST_ERROR_EVENT_SOURCE_FUNCTION_NAME, + }, + } as ListEventSourceMappingsCommand), ); + expect(lambdaSpy).toHaveBeenCalledTimes(1); expect(callback).toHaveBeenCalledWith(expect.any(Error), { statusCode: 500, }); @@ -59,18 +79,19 @@ describe("Lambda Handler", () => { it("should handle no Kafka triggers found for the provided functions", async () => { const event = { - functions: ["function1"], + functions: [TEST_NO_TRIGGERS_FUNCTION_NAME], }; - mockLambdaClientSend.mockResolvedValueOnce({ - EventSourceMappings: [], - }); - - await handler(event, null, callback); + await handler(event, {} as Context, callback); - expect(mockLambdaClientSend).toHaveBeenCalledWith( - expect.any(ListEventSourceMappingsCommand), + expect(lambdaSpy).toHaveBeenCalledWith( + expect.objectContaining({ + input: { + FunctionName: TEST_NO_TRIGGERS_FUNCTION_NAME, + }, + } as ListEventSourceMappingsCommand), ); + expect(lambdaSpy).toHaveBeenCalledTimes(1); expect(callback).toHaveBeenCalledWith(null, { statusCode: 200 }); }); }); diff --git a/lib/lambda/deleteTriggers.ts b/lib/lambda/deleteTriggers.ts index 22d9be6599..c0f4a18c01 100644 --- a/lib/lambda/deleteTriggers.ts +++ b/lib/lambda/deleteTriggers.ts @@ -23,7 +23,9 @@ export const handler: Handler = async (event, _, callback) => { }; export const deleteAllTriggersForFunctions = async (functions: string[]) => { - const lambdaClient = new LambdaClient({}); + const lambdaClient = new LambdaClient({ + region: process.env.region, + }); const uuidsToCheck = []; for (const functionName of functions) { const response = await lambdaClient.send( @@ -31,9 +33,7 @@ export const deleteAllTriggersForFunctions = async (functions: string[]) => { ); for (const eventSourceMapping of response.EventSourceMappings || []) { if (eventSourceMapping.SelfManagedKafkaEventSourceConfig) { - console.log( - `Disabling all Kafka triggers for function: ${functionName}`, - ); + console.log(`Disabling all Kafka triggers for function: ${functionName}`); await lambdaClient.send( new DeleteEventSourceMappingCommand({ UUID: eventSourceMapping.UUID, diff --git a/lib/lambda/mapRole.test.ts b/lib/lambda/mapRole.test.ts index 4bff81432b..34477b81df 100644 --- a/lib/lambda/mapRole.test.ts +++ b/lib/lambda/mapRole.test.ts @@ -1,30 +1,28 @@ -import { describe, it, expect, vi, beforeEach } from "vitest"; -import { send, SUCCESS, FAILED } from "cfn-response-async"; +import { afterEach, describe, expect, it, vi } from "vitest"; import { handler } from "./mapRole"; +import { Context } from "aws-lambda"; +import { + CLOUDFORMATION_NOTIFICATION_DOMAIN, + OPENSEARCH_DOMAIN, + errorSecurityRolesMappingHandler, +} from "mocks"; +import { mockedServiceServer as mockedServer } from "mocks/server"; import * as os from "../libs/opensearch-lib"; -vi.mock("cfn-response-async", () => ({ - send: vi.fn(), - SUCCESS: "SUCCESS", - FAILED: "FAILED", -})); - -vi.mock("../libs/opensearch-lib", () => ({ - mapRole: vi.fn(), -})); - describe("CloudFormation Custom Resource Handler", () => { - const mockContext = {}; const mockEventBase = { + ResponseURL: CLOUDFORMATION_NOTIFICATION_DOMAIN, ResourceProperties: { - OsDomain: "test-domain", + OsDomain: OPENSEARCH_DOMAIN, MasterRoleToAssume: "master-role", OsRoleName: "os-role", IamRoleName: "iam-role", }, }; + const mapRoleSpy = vi.spyOn(os, "mapRole"); + const callback = vi.fn(); - beforeEach(() => { + afterEach(() => { vi.clearAllMocks(); }); @@ -34,23 +32,15 @@ describe("CloudFormation Custom Resource Handler", () => { RequestType: "Create", }; - (os.mapRole as vi.Mock).mockResolvedValueOnce("Role mapped successfully"); - - await handler(mockEvent, mockContext); + await handler(mockEvent, {} as Context, callback); - expect(os.mapRole).toHaveBeenCalledWith( + expect(mapRoleSpy).toHaveBeenCalledWith( mockEvent.ResourceProperties.OsDomain, mockEvent.ResourceProperties.MasterRoleToAssume, mockEvent.ResourceProperties.OsRoleName, mockEvent.ResourceProperties.IamRoleName, ); - expect(send).toHaveBeenCalledWith( - mockEvent, - mockContext, - SUCCESS, - {}, - "static", - ); + expect(callback).toHaveBeenCalledWith(null, { statusCode: 200 }); }); it("should call os.mapRole on Update request type", async () => { @@ -59,23 +49,15 @@ describe("CloudFormation Custom Resource Handler", () => { RequestType: "Update", }; - (os.mapRole as vi.Mock).mockResolvedValueOnce("Role mapped successfully"); - - await handler(mockEvent, mockContext); + await handler(mockEvent, {} as Context, callback); - expect(os.mapRole).toHaveBeenCalledWith( + expect(mapRoleSpy).toHaveBeenCalledWith( mockEvent.ResourceProperties.OsDomain, mockEvent.ResourceProperties.MasterRoleToAssume, mockEvent.ResourceProperties.OsRoleName, mockEvent.ResourceProperties.IamRoleName, ); - expect(send).toHaveBeenCalledWith( - mockEvent, - mockContext, - SUCCESS, - {}, - "static", - ); + expect(callback).toHaveBeenCalledWith(null, { statusCode: 200 }); }); it("should do nothing on Delete request type", async () => { @@ -84,34 +66,22 @@ describe("CloudFormation Custom Resource Handler", () => { RequestType: "Delete", }; - await handler(mockEvent, mockContext); + await handler(mockEvent, {} as Context, callback); - expect(os.mapRole).not.toHaveBeenCalled(); - expect(send).toHaveBeenCalledWith( - mockEvent, - mockContext, - SUCCESS, - {}, - "static", - ); + expect(mapRoleSpy).not.toHaveBeenCalled(); + expect(callback).toHaveBeenCalledWith(null, { statusCode: 200 }); }); it("should send FAILED status on error", async () => { + mockedServer.use(errorSecurityRolesMappingHandler); + const mockEvent = { ...mockEventBase, RequestType: "Create", }; - (os.mapRole as vi.Mock).mockRejectedValueOnce(new Error("Test error")); - - await handler(mockEvent, mockContext); - - expect(send).toHaveBeenCalledWith( - mockEvent, - mockContext, - FAILED, - {}, - "static", - ); + await handler(mockEvent, {} as Context, callback); + expect(mapRoleSpy).toHaveBeenCalled(); + expect(callback).toHaveBeenCalledWith(expect.any(Error), { statusCode: 500 }); }); }); diff --git a/lib/lambda/mapRole.ts b/lib/lambda/mapRole.ts index 82cba51d44..06f8937867 100644 --- a/lib/lambda/mapRole.ts +++ b/lib/lambda/mapRole.ts @@ -3,17 +3,21 @@ import { send, SUCCESS, FAILED } from "cfn-response-async"; type ResponseStatus = typeof SUCCESS | typeof FAILED; import * as os from "./../libs/opensearch-lib"; -export const handler: Handler = async (event, context) => { +export const handler: Handler = async (event, context, callback) => { console.log("request:", JSON.stringify(event, undefined, 2)); const responseData: any = {}; let responseStatus: ResponseStatus = SUCCESS; + const response = { + statusCode: 200, + }; + let errorResponse = null; try { if (event.RequestType == "Create" || event.RequestType == "Update") { const reply = await os.mapRole( event.ResourceProperties.OsDomain, event.ResourceProperties.MasterRoleToAssume, event.ResourceProperties.OsRoleName, - event.ResourceProperties.IamRoleName + event.ResourceProperties.IamRoleName, ); console.log(reply); } else if (event.RequestType == "Delete") { @@ -22,7 +26,16 @@ export const handler: Handler = async (event, context) => { } catch (error) { console.log(error); responseStatus = FAILED; - } finally { + response.statusCode = 500; + errorResponse = error; + } + + try { await send(event, context, responseStatus, responseData, "static"); + } catch (error) { + response.statusCode = 500; + errorResponse = error; + } finally { + callback(errorResponse, response); } }; diff --git a/lib/lambda/runReindex.test.ts b/lib/lambda/runReindex.test.ts index b4f1695b29..f21626aeec 100644 --- a/lib/lambda/runReindex.test.ts +++ b/lib/lambda/runReindex.test.ts @@ -1,30 +1,22 @@ -import { describe, it, expect, vi, beforeEach } from "vitest"; -import { send, SUCCESS, FAILED } from "cfn-response-async"; -import { SFNClient, StartExecutionCommand } from "@aws-sdk/client-sfn"; +import { describe, it, expect, vi, afterEach } from "vitest"; import { handler } from "./runReindex"; - -vi.mock("cfn-response-async", () => ({ - send: vi.fn(), - SUCCESS: "SUCCESS", - FAILED: "FAILED", -})); - -vi.mock("@aws-sdk/client-sfn", () => ({ - SFNClient: vi.fn().mockImplementation(() => ({ - send: vi.fn(), - })), - StartExecutionCommand: vi.fn(), -})); +import { Context } from "aws-lambda"; +import { CLOUDFORMATION_NOTIFICATION_DOMAIN } from "mocks"; +import { SFNClient } from "@aws-sdk/client-sfn"; +import * as cfn from "cfn-response-async"; describe("CloudFormation Custom Resource Handler", () => { - const mockContext = {}; const mockEventBase = { + ResponseURL: CLOUDFORMATION_NOTIFICATION_DOMAIN, ResourceProperties: { stateMachine: "test-state-machine-arn", }, }; + const stepFunctionSpy = vi.spyOn(SFNClient.prototype, "send"); + const cfnSpy = vi.spyOn(cfn, "send"); + const callback = vi.fn(); - beforeEach(() => { + afterEach(() => { vi.clearAllMocks(); }); @@ -34,33 +26,21 @@ describe("CloudFormation Custom Resource Handler", () => { RequestType: "Create", }; - const startExecutionResponse = { - executionArn: "test-execution-arn", - }; - - const sendMock = vi.fn().mockResolvedValue(startExecutionResponse); - (SFNClient as any).mockImplementationOnce(() => ({ - send: sendMock, - })); - - await handler(mockEvent, mockContext); - - expect(SFNClient).toHaveBeenCalled(); - expect(StartExecutionCommand).toHaveBeenCalledWith({ - stateMachineArn: "test-state-machine-arn", - input: JSON.stringify({ - cfnEvent: mockEvent, - cfnContext: mockContext, + await handler(mockEvent, {} as Context, callback); + + expect(stepFunctionSpy).toHaveBeenCalledWith( + expect.objectContaining({ + input: { + input: JSON.stringify({ + cfnEvent: mockEvent, + cfnContext: {}, + }), + stateMachineArn: "test-state-machine-arn", + }, }), - }); - expect(sendMock).toHaveBeenCalled(); - expect(send).not.toHaveBeenCalledWith( - mockEvent, - mockContext, - SUCCESS, - {}, - "static", ); + expect(cfnSpy).not.toHaveBeenCalled(); + expect(callback).toHaveBeenCalledWith(null, { statusCode: 200 }); }); it("should send a SUCCESS response on Update request type", async () => { @@ -69,15 +49,11 @@ describe("CloudFormation Custom Resource Handler", () => { RequestType: "Update", }; - await handler(mockEvent, mockContext); + await handler(mockEvent, {} as Context, callback); - expect(send).toHaveBeenCalledWith( - mockEvent, - mockContext, - SUCCESS, - {}, - "static", - ); + expect(stepFunctionSpy).not.toHaveBeenCalled(); + expect(cfnSpy).toHaveBeenCalledWith(mockEvent, {}, cfn.SUCCESS, {}, "static"); + expect(callback).toHaveBeenCalledWith(null, { statusCode: 200 }); }); it("should send a SUCCESS response on Delete request type", async () => { @@ -86,36 +62,36 @@ describe("CloudFormation Custom Resource Handler", () => { RequestType: "Delete", }; - await handler(mockEvent, mockContext); + await handler(mockEvent, {} as Context, callback); - expect(send).toHaveBeenCalledWith( - mockEvent, - mockContext, - SUCCESS, - {}, - "static", - ); + expect(stepFunctionSpy).not.toHaveBeenCalled(); + expect(cfnSpy).toHaveBeenCalledWith(mockEvent, {}, cfn.SUCCESS, {}, "static"); + expect(callback).toHaveBeenCalledWith(null, { statusCode: 200 }); }); it("should send a FAILED response on error", async () => { const mockEvent = { ...mockEventBase, RequestType: "Create", + ResourceProperties: { + stateMachine: "error-test-state-machine-arn", + }, }; - const sendMock = vi.fn().mockRejectedValue(new Error("Test error")); - (SFNClient as any).mockImplementationOnce(() => ({ - send: sendMock, - })); - - await handler(mockEvent, mockContext); - - expect(send).toHaveBeenCalledWith( - mockEvent, - mockContext, - FAILED, - {}, - "static", + await handler(mockEvent, {} as Context, callback); + + expect(stepFunctionSpy).toHaveBeenCalledWith( + expect.objectContaining({ + input: { + input: JSON.stringify({ + cfnEvent: mockEvent, + cfnContext: {}, + }), + stateMachineArn: "error-test-state-machine-arn", + }, + }), ); + expect(cfnSpy).toHaveBeenCalledWith(mockEvent, {}, cfn.FAILED, {}, "static"); + expect(callback).toHaveBeenCalledWith(expect.any(Error), { statusCode: 500 }); }); }); diff --git a/lib/lambda/runReindex.ts b/lib/lambda/runReindex.ts index 33fc568177..1dfecee5ef 100644 --- a/lib/lambda/runReindex.ts +++ b/lib/lambda/runReindex.ts @@ -2,11 +2,17 @@ import { Handler } from "aws-lambda"; import { send, SUCCESS, FAILED } from "cfn-response-async"; import { SFNClient, StartExecutionCommand } from "@aws-sdk/client-sfn"; -export const handler: Handler = async (event, context) => { +export const handler: Handler = async (event, context, callback) => { console.log("request:", JSON.stringify(event, undefined, 2)); + const response = { + statusCode: 200, + }; + let errorResponse = null; try { if (event.RequestType == "Create") { - const stepFunctionsClient = new SFNClient({}); + const stepFunctionsClient = new SFNClient({ + region: process.env.region, + }); const stateMachineArn = event.ResourceProperties.stateMachine; const startExecutionCommand = new StartExecutionCommand({ @@ -20,7 +26,7 @@ export const handler: Handler = async (event, context) => { const execution = await stepFunctionsClient.send(startExecutionCommand); console.log(`State machine execution started: ${execution.executionArn}`); console.log( - "The state machine is now in charge of this resource, and will notify of success or failure upon completion." + "The state machine is now in charge of this resource, and will notify of success or failure upon completion.", ); } else if (event.RequestType == "Update") { await send(event, context, SUCCESS, {}, "static"); @@ -30,6 +36,10 @@ export const handler: Handler = async (event, context) => { } } catch (error) { console.log(error); + response.statusCode = 500; + errorResponse = error; await send(event, context, FAILED, {}, "static"); + } finally { + callback(errorResponse, response); } }; diff --git a/lib/lambda/setupIndex.test.ts b/lib/lambda/setupIndex.test.ts index 3f05c9b4e5..45e4c39f5a 100644 --- a/lib/lambda/setupIndex.test.ts +++ b/lib/lambda/setupIndex.test.ts @@ -1,67 +1,66 @@ -import { describe, it, expect, vi, beforeEach } from "vitest"; +import { describe, it, expect, vi, afterEach } from "vitest"; import { handler } from "./setupIndex"; -import * as opensearchLib from "libs/opensearch-lib"; - -const MOCK_EVENT = { - osDomain: "test-domain", - indexNamespace: "test-namespace-", -}; -const MOCK_CALLBACK = vi.fn(); +import { Context } from "aws-lambda"; +import { OPENSEARCH_DOMAIN, OPENSEARCH_INDEX_NAMESPACE, errorCreateIndexHandler } from "mocks"; +import { mockedServiceServer as mockedServer } from "mocks/server"; +import * as os from "libs/opensearch-lib"; describe("handler", () => { - const spiedOnUpdateFieldMapping = vi.spyOn(opensearchLib, "updateFieldMapping"); + const baseEvent = { + osDomain: OPENSEARCH_DOMAIN, + indexNamespace: OPENSEARCH_INDEX_NAMESPACE, + }; + const createIndexSpy = vi.spyOn(os, "createIndex"); + const updateMappingSpy = vi.spyOn(os, "updateFieldMapping"); + const callback = vi.fn(); - beforeEach(() => { - vi.resetAllMocks(); - MOCK_CALLBACK.mockClear(); + afterEach(() => { + vi.clearAllMocks(); }); it("should create and update indices without errors", async () => { - const spiedOnCreateIndex = vi - .spyOn(opensearchLib, "createIndex") - .mockImplementation(() => Promise.resolve()); - - await handler(MOCK_EVENT, expect.anything(), MOCK_CALLBACK); - - expect(spiedOnCreateIndex).toHaveBeenCalledTimes(7); + await handler(baseEvent, {} as Context, callback); const expectedIndices = [ - "test-namespace-main", - "test-namespace-changelog", - "test-namespace-types", - "test-namespace-subtypes", - "test-namespace-cpocs", - "test-namespace-insights", - "test-namespace-legacyinsights", + `${OPENSEARCH_INDEX_NAMESPACE}main`, + `${OPENSEARCH_INDEX_NAMESPACE}changelog`, + `${OPENSEARCH_INDEX_NAMESPACE}types`, + `${OPENSEARCH_INDEX_NAMESPACE}subtypes`, + `${OPENSEARCH_INDEX_NAMESPACE}cpocs`, + `${OPENSEARCH_INDEX_NAMESPACE}insights`, + `${OPENSEARCH_INDEX_NAMESPACE}legacyinsights`, ]; for (const index of expectedIndices) { - expect(opensearchLib.createIndex).toHaveBeenCalledWith("test-domain", index); + expect(createIndexSpy).toHaveBeenCalledWith(OPENSEARCH_DOMAIN, index); } + expect(createIndexSpy).toHaveBeenCalledTimes(7); - expect(spiedOnUpdateFieldMapping).toHaveBeenCalledTimes(1); - expect(spiedOnUpdateFieldMapping).toHaveBeenCalledWith("test-domain", "test-namespace-main", { - approvedEffectiveDate: { type: "date" }, - changedDate: { type: "date" }, - finalDispositionDate: { type: "date" }, - proposedDate: { type: "date" }, - statusDate: { type: "date" }, - submissionDate: { type: "date" }, - }); + expect(updateMappingSpy).toHaveBeenCalledWith( + OPENSEARCH_DOMAIN, + `${OPENSEARCH_INDEX_NAMESPACE}main`, + { + approvedEffectiveDate: { type: "date" }, + changedDate: { type: "date" }, + finalDispositionDate: { type: "date" }, + proposedDate: { type: "date" }, + statusDate: { type: "date" }, + submissionDate: { type: "date" }, + }, + ); + expect(updateMappingSpy).toHaveBeenCalledTimes(1); - expect(MOCK_CALLBACK).toHaveBeenCalledWith(null, { statusCode: 200 }); + expect(callback).toHaveBeenCalledWith(null, { statusCode: 200 }); }); it("should handle errors and return status 500", async () => { - const spiedOnCreateIndex = vi - .spyOn(opensearchLib, "createIndex") - .mockRejectedValueOnce(new Error("Test error")); + mockedServer.use(errorCreateIndexHandler); - await handler(MOCK_EVENT, expect.anything(), MOCK_CALLBACK); + await handler(baseEvent, {} as Context, callback); - expect(spiedOnCreateIndex).toHaveBeenCalledTimes(1); - expect(spiedOnUpdateFieldMapping).not.toHaveBeenCalled(); - expect(MOCK_CALLBACK).toHaveBeenCalledWith(expect.any(Error), { + expect(createIndexSpy).toHaveBeenCalledTimes(1); + expect(updateMappingSpy).not.toHaveBeenCalled(); + expect(callback).toHaveBeenCalledWith(expect.any(Error), { statusCode: 500, }); }); diff --git a/lib/libs/sink-lib.test.ts b/lib/libs/sink-lib.test.ts index 85dc75da25..a725086a4c 100644 --- a/lib/libs/sink-lib.test.ts +++ b/lib/libs/sink-lib.test.ts @@ -1,25 +1,20 @@ import { afterEach, describe, expect, it, vi } from "vitest"; -import * as os from "./opensearch-lib"; import { bulkUpdateDataWrapper } from "./sink-lib"; import { OPENSEARCH_DOMAIN, OPENSEARCH_INDEX_NAMESPACE } from "mocks"; +import * as os from "./opensearch-lib"; describe("bulkUpdateDataWrapper", () => { + const bulkUpdateDataSpy = vi.spyOn(os, "bulkUpdateData"); const DOCS = [{ id: "1" }]; afterEach(() => { vi.restoreAllMocks(); - vi.resetModules(); }); it("calls bulkUpdateData with correct arguments when env vars are defined", async () => { - const mockBulkUpdateData = vi.spyOn(os, "bulkUpdateData").mockImplementation(vi.fn()); - - vi.stubEnv("osDomain", OPENSEARCH_DOMAIN); - vi.stubEnv("indexNamespace", OPENSEARCH_INDEX_NAMESPACE); - await bulkUpdateDataWrapper(DOCS, "main"); - expect(mockBulkUpdateData).toHaveBeenCalledWith( + expect(bulkUpdateDataSpy).toHaveBeenCalledWith( OPENSEARCH_DOMAIN, `${OPENSEARCH_INDEX_NAMESPACE}main`, DOCS, @@ -27,14 +22,15 @@ describe("bulkUpdateDataWrapper", () => { }); it("throws an Error when env vars are missing", async () => { - vi.stubEnv("osDomain", undefined); - vi.stubEnv("indexNamespace", undefined); + delete process.env.osDomain; + delete process.env.indexNamespace; await expect(bulkUpdateDataWrapper(DOCS, "main")).rejects.toThrow(); - vi.stubEnv("osDomain", OPENSEARCH_DOMAIN); - vi.stubEnv("indexNamespace", undefined); + process.env.osDomain = OPENSEARCH_DOMAIN; await expect(bulkUpdateDataWrapper(DOCS, "main")).rejects.toThrow(); + + process.env.indexNamespace = OPENSEARCH_INDEX_NAMESPACE; }); }); diff --git a/lib/libs/sink-lib.ts b/lib/libs/sink-lib.ts index 9a9c730a46..491387ff01 100644 --- a/lib/libs/sink-lib.ts +++ b/lib/libs/sink-lib.ts @@ -99,7 +99,7 @@ export function getDomainAndNamespace(baseIndex?: BaseIndex) { throw new Error("osDomain is undefined in environment variables"); } - if (indexNamespace === undefined) { + if (indexNamespace == "" && process.env.isDev == "true") { throw new Error("indexName is undefined in environment variables"); } @@ -117,6 +117,7 @@ export async function bulkUpdateDataWrapper( await os.bulkUpdateData(domain, index, docs); } catch (error) { + console.log({ error }); logError({ type: ErrorType.BULKUPDATE, error, diff --git a/lib/local-constructs/manage-users/src/cognito-lib.ts b/lib/local-constructs/manage-users/src/cognito-lib.ts index 902a1ac64d..d876bb82a9 100644 --- a/lib/local-constructs/manage-users/src/cognito-lib.ts +++ b/lib/local-constructs/manage-users/src/cognito-lib.ts @@ -5,8 +5,9 @@ import { AdminUpdateUserAttributesCommand, AdminGetUserCommand, } from "@aws-sdk/client-cognito-identity-provider"; + const client = new CognitoIdentityProviderClient({ - region: process.env.region, + region: process.env.region || process.env.REGION_A || "us-east-1", }); export async function createUser(params: any): Promise { @@ -41,22 +42,14 @@ export async function updateUserAttributes(params: any): Promise { const user = await client.send(getUserCommand); // Check for existing "custom:cms-roles" - const cmsRolesAttribute = user.UserAttributes?.find( - (attr) => attr.Name === "custom:cms-roles", - ); + const cmsRolesAttribute = user.UserAttributes?.find((attr) => attr.Name === "custom:cms-roles"); const existingRoles = - cmsRolesAttribute && cmsRolesAttribute.Value - ? cmsRolesAttribute.Value.split(",") - : []; + cmsRolesAttribute && cmsRolesAttribute.Value ? cmsRolesAttribute.Value.split(",") : []; // Check for existing "custom:state" - const stateAttribute = user.UserAttributes?.find( - (attr) => attr.Name === "custom:state", - ); + const stateAttribute = user.UserAttributes?.find((attr) => attr.Name === "custom:state"); const existingStates = - stateAttribute && stateAttribute.Value - ? stateAttribute.Value.split(",") - : []; + stateAttribute && stateAttribute.Value ? stateAttribute.Value.split(",") : []; // Prepare for updating user attributes const attributeData: any = { @@ -79,8 +72,7 @@ export async function updateUserAttributes(params: any): Promise { ), ) : new Set(["onemac-micro-super"]); // Ensure "onemac-micro-super" is always included - attributeData.UserAttributes[rolesIndex].Value = - Array.from(newRoles).join(","); + attributeData.UserAttributes[rolesIndex].Value = Array.from(newRoles).join(","); } else { // Add "custom:cms-roles" with "onemac-micro-super" attributeData.UserAttributes.push({ @@ -98,14 +90,9 @@ export async function updateUserAttributes(params: any): Promise { if (stateIndex !== -1) { // Only merge if new states are not empty const newStates = attributeData.UserAttributes[stateIndex].Value - ? new Set( - attributeData.UserAttributes[stateIndex].Value.split(",").concat( - "ZZ", - ), - ) + ? new Set(attributeData.UserAttributes[stateIndex].Value.split(",").concat("ZZ")) : new Set(["ZZ"]); // Ensure "ZZ" is always included - attributeData.UserAttributes[stateIndex].Value = - Array.from(newStates).join(","); + attributeData.UserAttributes[stateIndex].Value = Array.from(newStates).join(","); } else { // Add "custom:state" with "ZZ" attributeData.UserAttributes.push({ diff --git a/lib/local-constructs/manage-users/src/manageUsers.test.ts b/lib/local-constructs/manage-users/src/manageUsers.test.ts index 890aa240b0..f84dd7edf0 100644 --- a/lib/local-constructs/manage-users/src/manageUsers.test.ts +++ b/lib/local-constructs/manage-users/src/manageUsers.test.ts @@ -1,140 +1,111 @@ import { describe, it, expect, vi, beforeEach } from "vitest"; import { handler } from "./manageUsers"; // Adjust the path as necessary -import * as cfnResponse from "cfn-response-async"; -import * as cognitolib from "./cognito-lib"; -import { getSecret } from "shared-utils"; - -vi.mock("cfn-response-async"); -vi.mock("./cognito-lib"); -vi.mock("shared-utils"); +import { Context } from "aws-lambda"; +import { + CognitoIdentityProviderClient, + AdminCreateUserCommand, + AdminSetUserPasswordCommand, + AdminUpdateUserAttributesCommand, + AdminGetUserCommand, +} from "@aws-sdk/client-cognito-identity-provider"; +import { + CLOUDFORMATION_NOTIFICATION_DOMAIN, + TEST_PW_ARN, + TEST_SECRET_ERROR_ID, + USER_POOL_ID, + testNewStateSubmitter, +} from "mocks"; +import * as cfn from "cfn-response-async"; describe("Cognito User Lambda Handler", () => { - const mockSend = vi.fn(); - const mockGetSecret = vi.fn(); - const mockCreateUser = vi.fn(); - const mockSetPassword = vi.fn(); - const mockUpdateUserAttributes = vi.fn(); + const cognitoSpy = vi.spyOn(CognitoIdentityProviderClient.prototype, "send"); + const cfnSpy = vi.spyOn(cfn, "send"); + const callback = vi.fn(); beforeEach(() => { vi.clearAllMocks(); - (cfnResponse.send as unknown as typeof mockSend).mockImplementation( - mockSend, - ); - (getSecret as unknown as typeof mockGetSecret).mockImplementation( - mockGetSecret, - ); - ( - cognitolib.createUser as unknown as typeof mockCreateUser - ).mockImplementation(mockCreateUser); - ( - cognitolib.setPassword as unknown as typeof mockSetPassword - ).mockImplementation(mockSetPassword); - ( - cognitolib.updateUserAttributes as unknown as typeof mockUpdateUserAttributes - ).mockImplementation(mockUpdateUserAttributes); }); it("should create, set password, and update attributes for each user on Create or Update", async () => { const event = { + ResponseURL: CLOUDFORMATION_NOTIFICATION_DOMAIN, RequestType: "Create", ResourceProperties: { - userPoolId: "userPoolId", + userPoolId: USER_POOL_ID, users: [ { - username: "user1", - attributes: [ - { - Name: "email", - Value: "user1@example.com", - }, - ], + username: testNewStateSubmitter.Username, + attributes: testNewStateSubmitter.UserAttributes, }, ], - passwordSecretArn: "passwordSecretArn", // pragma: allowlist secret + passwordSecretArn: TEST_PW_ARN, }, }; - const context = {}; - - mockGetSecret.mockResolvedValue("devUserPassword"); - mockSend.mockResolvedValue(undefined); - mockCreateUser.mockResolvedValue(undefined); - mockSetPassword.mockResolvedValue(undefined); - mockUpdateUserAttributes.mockResolvedValue(undefined); + await handler(event, {} as Context, callback); - await handler(event, context); - - expect(mockGetSecret).toHaveBeenCalledWith("passwordSecretArn"); - expect(mockCreateUser).toHaveBeenCalledWith({ - UserPoolId: "userPoolId", - Username: "user1", - UserAttributes: [ - { - Name: "email", - Value: "user1@example.com", + expect(cognitoSpy).toHaveBeenCalledWith( + expect.objectContaining({ + input: { + UserPoolId: USER_POOL_ID, + Username: testNewStateSubmitter.Username, + UserAttributes: testNewStateSubmitter.UserAttributes, + MessageAction: "SUPPRESS", }, - ], - MessageAction: "SUPPRESS", - }); - expect(mockSetPassword).toHaveBeenCalledWith({ - Password: "devUserPassword", // pragma: allowlist secret - UserPoolId: "userPoolId", - Username: "user1", - Permanent: true, - }); - expect(mockUpdateUserAttributes).toHaveBeenCalledWith({ - Username: "user1", - UserPoolId: "userPoolId", - UserAttributes: [ - { - Name: "email", - Value: "user1@example.com", + } as AdminCreateUserCommand), + ); + expect(cognitoSpy).toHaveBeenCalledWith( + expect.objectContaining({ + input: { + Password: "devUserPassword", // pragma: allowlist secret + UserPoolId: USER_POOL_ID, + Username: testNewStateSubmitter.Username, + Permanent: true, }, - ], - }); - expect(mockSend).toHaveBeenCalledWith( - event, - context, - "SUCCESS", - {}, - "static", + } as AdminSetUserPasswordCommand), ); + expect(cognitoSpy).toHaveBeenCalledWith( + expect.objectContaining({ + input: { + UserPoolId: USER_POOL_ID, + Username: testNewStateSubmitter.Username, + }, + } as AdminGetUserCommand), + ); + expect(cognitoSpy).toHaveBeenCalledWith( + expect.objectContaining({ + input: { + Username: testNewStateSubmitter.Username, + UserPoolId: USER_POOL_ID, + UserAttributes: testNewStateSubmitter.UserAttributes, + }, + } as AdminUpdateUserAttributesCommand), + ); + expect(cognitoSpy).toHaveBeenCalledTimes(4); + expect(cfnSpy).toHaveBeenCalledWith(event, {}, cfn.SUCCESS, {}, "static"); + expect(callback).toHaveBeenCalledWith(null, { statusCode: 200 }); }); it("should handle errors and send FAILED response", async () => { const event = { + ResponseURL: CLOUDFORMATION_NOTIFICATION_DOMAIN, RequestType: "Create", ResourceProperties: { - userPoolId: "userPoolId", + userPoolId: USER_POOL_ID, users: [ { - username: "user1", - attributes: [ - { - Name: "email", - Value: "user1@example.com", - }, - ], + username: testNewStateSubmitter.Username, + attributes: testNewStateSubmitter.UserAttributes, }, ], - passwordSecretArn: "passwordSecretArn", // pragma: allowlist secret + passwordSecretArn: TEST_SECRET_ERROR_ID, }, }; - const context = {}; + await handler(event, {} as Context, callback); - mockGetSecret.mockRejectedValue(new Error("Failed to get secret")); - mockSend.mockResolvedValue(undefined); - - await handler(event, context); - - expect(mockGetSecret).toHaveBeenCalledWith("passwordSecretArn"); // pragma: allowlist secret - expect(mockSend).toHaveBeenCalledWith( - event, - context, - "FAILED", - {}, - "static", - ); + expect(cognitoSpy).not.toHaveBeenCalled(); + expect(cfnSpy).toHaveBeenCalledWith(event, {}, cfn.FAILED, {}, "static"); + expect(callback).toHaveBeenCalledWith(expect.any(Error), { statusCode: 500 }); }); }); diff --git a/lib/local-constructs/manage-users/src/manageUsers.ts b/lib/local-constructs/manage-users/src/manageUsers.ts index 6865018ff0..b36ab8b1f7 100644 --- a/lib/local-constructs/manage-users/src/manageUsers.ts +++ b/lib/local-constructs/manage-users/src/manageUsers.ts @@ -4,10 +4,14 @@ type ResponseStatus = typeof SUCCESS | typeof FAILED; import * as cognitolib from "./cognito-lib"; import { getSecret } from "shared-utils"; -export const handler: Handler = async (event, context) => { +export const handler: Handler = async (event, context, callback) => { console.log("request:", JSON.stringify(event, undefined, 2)); const responseData: any = {}; let responseStatus: ResponseStatus = SUCCESS; + const response = { + statusCode: 200, + }; + let errorResponse = null; try { if (event.RequestType == "Create" || event.RequestType == "Update") { const { userPoolId, users, passwordSecretArn } = event.ResourceProperties; @@ -43,7 +47,16 @@ export const handler: Handler = async (event, context) => { } catch (error) { console.log(error); responseStatus = FAILED; - } finally { + response.statusCode = 500; + errorResponse = error; + } + + try { await send(event, context, responseStatus, responseData, "static"); + } catch (error) { + response.statusCode = 500; + errorResponse = error; + } finally { + callback(errorResponse, response); } }; diff --git a/lib/vitest.setup.ts b/lib/vitest.setup.ts index 9fa5507433..0253f06766 100644 --- a/lib/vitest.setup.ts +++ b/lib/vitest.setup.ts @@ -57,8 +57,6 @@ Amplify.configure({ beforeAll(() => { setDefaultStateSubmitter(); - vi.spyOn(console, "error").mockImplementation(() => {}); - console.log("starting MSW listener for lib tests"); mockedServer.listen({ onUnhandledRequest: "warn", diff --git a/mocks/consts.ts b/mocks/consts.ts index 9023b452fa..976633c77c 100644 --- a/mocks/consts.ts +++ b/mocks/consts.ts @@ -9,6 +9,7 @@ export const USER_POOL_CLIENT_DOMAIN = `mocked-tests-login-${USER_POOL_CLIENT_ID export const COGNITO_IDP_DOMAIN = `https://cognito-idp.${REGION}.amazonaws.com/${USER_POOL_ID}`; export const OPENSEARCH_DOMAIN = `https://vpc-opensearchdomain-mock-domain.${REGION}.es.amazonaws.com`; export const OPENSEARCH_INDEX_NAMESPACE = "test-namespace-"; +export const CLOUDFORMATION_NOTIFICATION_DOMAIN = "https://test-cfn.amazonaws.com"; export const ACCESS_KEY_ID = "ASIAZHXA3XOU7XZ53M36"; // pragma: allowlist secret export const SECRET_KEY = "UWKCFxhrgbPnixgLnL1JKwFEwiK9ZKvTAtpk8cGa"; // pragma: allowlist secret diff --git a/mocks/data/index.ts b/mocks/data/index.ts index ddcb36eb91..34dfabcde0 100644 --- a/mocks/data/index.ts +++ b/mocks/data/index.ts @@ -1,6 +1,7 @@ export * from "./cloudFormationsExports"; export * from "./counties"; export * from "./items"; +export * from "./lambdas"; export * from "./secrets"; export * from "./types"; export * from "./users"; diff --git a/mocks/data/lambdas.ts b/mocks/data/lambdas.ts new file mode 100644 index 0000000000..0680443cae --- /dev/null +++ b/mocks/data/lambdas.ts @@ -0,0 +1,59 @@ +import { TestEventSourceMapping } from "../index.d"; + +export const TEST_FUNCTION_NAME = "test-function"; +export const TEST_TOPIC_NAME = "test-topic"; +export const TEST_FUNCTION_TEST_TOPIC_UUID = "38c1c0a1-096c-4cfd-845b-4237d3c888f0"; +export const TEST_NONEXISTENT_FUNCTION_NAME = "nonexistent-function"; +export const TEST_NONEXISTENT_TOPIC_NAME = "nonexistent-topic"; +export const TEST_MULTIPLE_TOPICS_FUNCTION_NAME = "multiple-topic-function"; +export const TEST_MULTIPLE_TOPICS_TOPIC_NAME = "multiple-topics-topic"; +export const TEST_NO_TRIGGERS_FUNCTION_NAME = "no-triggers-function"; +export const TEST_MISSING_CONSUMER_FUNCTION_NAME = "missing-consumer-function"; +export const TEST_MISSING_CONSUMER_TOPIC_NAME = "missing-consumer-topic"; +export const TEST_DELETE_TRIGGER_FUNCTION_NAME = "delete-function"; +export const TEST_DELETE_TRIGGER_TOPIC_NAME = "delete-topic"; +export const TEST_DELETE_TRIGGER_UUID = "fc51f7f4-f678-46d5-83c3-d26418be2a5a"; +export const TEST_ERROR_EVENT_SOURCE_FUNCTION_NAME = "error-function"; +export const TEST_ERROR_EVENT_SOURCE_UUID = "3f01f676-75e9-4f6d-b274-4b817072cfbc"; + +export const consumerGroups: Record = { + [TEST_FUNCTION_NAME]: [ + { + Topics: [TEST_TOPIC_NAME], + SelfManagedKafkaEventSourceConfig: { ConsumerGroupId: "test-group" }, + State: "Enabled", + UUID: TEST_FUNCTION_TEST_TOPIC_UUID, + }, + ], + [TEST_MULTIPLE_TOPICS_FUNCTION_NAME]: [ + { + Topics: [TEST_MULTIPLE_TOPICS_TOPIC_NAME], + SelfManagedKafkaEventSourceConfig: { ConsumerGroupId: "test-group" }, + State: "Enabled", + UUID: "772f9cc6-f8f7-46e5-a58c-6b89ce147d0c", + }, + { + Topics: [TEST_MULTIPLE_TOPICS_TOPIC_NAME], + SelfManagedKafkaEventSourceConfig: { ConsumerGroupId: "test-group-2" }, + State: "Enabled", + UUID: "83aa8994-5520-472e-961c-d9f44abb64d9", + }, + ], + [TEST_NO_TRIGGERS_FUNCTION_NAME]: [], + [TEST_MISSING_CONSUMER_FUNCTION_NAME]: [ + { + Topics: [TEST_MISSING_CONSUMER_TOPIC_NAME], + SelfManagedKafkaEventSourceConfig: null, + State: "Enabled", + UUID: "2cb32df8-2ff5-41ba-a773-b0f4de8b27b1", + }, + ], + [TEST_DELETE_TRIGGER_FUNCTION_NAME]: [ + { + Topics: [TEST_DELETE_TRIGGER_TOPIC_NAME], + SelfManagedKafkaEventSourceConfig: { ConsumerGroupId: "test-group-3" }, + State: "Enabled", + UUID: TEST_DELETE_TRIGGER_UUID, + }, + ], +}; diff --git a/mocks/data/secrets.ts b/mocks/data/secrets.ts index badc8d4170..1889504ad4 100644 --- a/mocks/data/secrets.ts +++ b/mocks/data/secrets.ts @@ -4,6 +4,7 @@ export const TEST_SECRET_ID = "test-secret"; // pragma: allowlist secret export const TEST_SECRET_TO_DELETE_ID = "test-secret-to-delete"; // pragma: allowlist secret export const TEST_SECRET_NO_VALUE_ID = "test-secret-no-value"; // pragma: allowlist secret export const TEST_SECRET_ERROR_ID = "Throw Get Secret Error"; // pragma: allowlist secret +export const TEST_PW_ARN = "test-arn-create-update-user"; // pragma: allowlist secret const secrets: Record = { [TEST_SECRET_ID]: { @@ -30,6 +31,14 @@ const secrets: Record = { VersionId: "1.0", VersionStages: ["prod"], }, + [TEST_PW_ARN]: { + ARN: `arn://${TEST_PW_ARN}`, + CreatedDate: Date.now(), + Name: TEST_PW_ARN, + SecretString: "devUserPassword", // pragma: allowlist secret + VersionId: "1.0", + VersionStages: ["prod"], + }, }; export default secrets; diff --git a/mocks/data/users/stateSubmitters.ts b/mocks/data/users/stateSubmitters.ts index 7590f30296..f391b9fcf3 100644 --- a/mocks/data/users/stateSubmitters.ts +++ b/mocks/data/users/stateSubmitters.ts @@ -238,6 +238,40 @@ export const automatedStateSubmitter: TestUserData = { Username: "f3a1b6d6-3bc9-498d-ac22-41a6d46982c9", }; +export const testNewStateSubmitter: TestUserData = { + UserAttributes: [ + { + Name: "email", + Value: "new-state-submitter@example.com", + }, + { + Name: "email_verified", + Value: "true", + }, + { + Name: "given_name", + Value: "Test", + }, + { + Name: "family_name", + Value: "Submitter", + }, + { + Name: "custom:state", + Value: "VA", + }, + { + Name: "custom:cms-roles", + Value: "onemac-micro-statesubmitter", + }, + { + Name: "sub", + Value: "f8e64f73-d121-4252-b9e3-1f4df902a1c1", + }, + ], + Username: "f8e64f73-d121-4252-b9e3-1f4df902a1c1", +}; + export const stateSubmitters: TestUserData[] = [ makoStateSubmitter, stateSubmitter, @@ -246,4 +280,5 @@ export const stateSubmitters: TestUserData[] = [ multiStateSubmitter, noStateSubmitter, automatedStateSubmitter, + testNewStateSubmitter, ]; diff --git a/mocks/handlers/aws/cloudFormation.ts b/mocks/handlers/aws/cloudFormation.ts index 69f17a4865..ba87334946 100644 --- a/mocks/handlers/aws/cloudFormation.ts +++ b/mocks/handlers/aws/cloudFormation.ts @@ -1,23 +1,7 @@ import { http, HttpResponse } from "msw"; +import { CLOUDFORMATION_NOTIFICATION_DOMAIN } from "../../consts"; import exports from "../../data/cloudFormationsExports"; -export const errorCloudFormationHandler = http.post( - `https://cloudformation.us-east-1.amazonaws.com/`, - async () => - HttpResponse.xml( - ` - - ServiceUnavailable - Service is unable to handle request. - - `, - { - status: 503, - statusText: "ServiceUnavailable", - }, - ) -); - const defaultCloudFormationHandler = http.post( `https://cloudformation.us-east-1.amazonaws.com/`, async () => { @@ -51,4 +35,32 @@ const defaultCloudFormationHandler = http.post( }, ); -export const cloudFormationHandlers = [defaultCloudFormationHandler]; +export const errorCloudFormationHandler = http.post( + `https://cloudformation.us-east-1.amazonaws.com/`, + async () => + HttpResponse.xml( + ` + + ServiceUnavailable + Service is unable to handle request. + + `, + { + status: 503, + statusText: "ServiceUnavailable", + }, + ), +); + +const defaultCloudFormationResponseHandler = http.put( + CLOUDFORMATION_NOTIFICATION_DOMAIN, + async ({ request }) => { + console.log("notify", { request }); + return new HttpResponse(null, { status: 200 }); + }, +); + +export const cloudFormationHandlers = [ + defaultCloudFormationHandler, + defaultCloudFormationResponseHandler, +]; diff --git a/mocks/handlers/aws/cognito.ts b/mocks/handlers/aws/cognito.ts index 6f1888c9c0..4cd07fb707 100644 --- a/mocks/handlers/aws/cognito.ts +++ b/mocks/handlers/aws/cognito.ts @@ -5,14 +5,15 @@ import { IDENTITY_POOL_ID, SECRET_KEY, USER_POOL_CLIENT_ID, - COGNITO_IDP_DOMAIN + COGNITO_IDP_DOMAIN, } from "../../consts"; import type { IdentityRequest, IdpListUsersRequestBody, IdpRefreshRequestBody, IdpRequestSessionBody, - TestUserData + AdminGetUserRequestBody, + TestUserData, } from "../../index.d"; import { findUserByUsername } from "../authUtils"; import { APIGatewayEventRequestContext } from "shared-types"; @@ -162,6 +163,10 @@ export const signInHandler = http.post(/amazoncognito.com\/oauth2\/token/, async export const identityServiceHandler = http.post( /cognito-identity/, async ({ request }) => { + console.log("identityServiceHandler", { + request, + headers: request.headers, + }); const target = request.headers.get("x-amz-target"); if (target) { if (target == "AWSCognitoIdentityService.GetId") { @@ -231,8 +236,12 @@ export const identityServiceHandler = http.post( export const identityProviderServiceHandler = http.post< PathParams, - IdpRequestSessionBody | IdpRefreshRequestBody | IdpListUsersRequestBody + IdpRequestSessionBody | IdpRefreshRequestBody | IdpListUsersRequestBody | AdminGetUserRequestBody >(/https:\/\/cognito-idp.\S*.amazonaws.com\//, async ({ request }) => { + console.log("identityProviderServiceHandler", { + request, + headers: request.headers, + }); const target = request.headers.get("x-amz-target"); if (target) { if (target == "AWSCognitoIdentityProviderService.InitiateAuth") { @@ -311,6 +320,28 @@ export const identityProviderServiceHandler = http.post< return new HttpResponse("User not set", { status: 401 }); } + if (target == "AWSCognitoIdentityProviderService.AdminCreateUser") { + return new HttpResponse(null, { status: 200 }); + } + + if (target == "AWSCognitoIdentityProviderService.AdminSetUserPassword") { + return new HttpResponse(null, { status: 200 }); + } + + if (target == "AWSCognitoIdentityProviderService.AdminGetUser") { + const { Username } = (await request.json()) as AdminGetUserRequestBody; + const username = Username || process.env.MOCK_USER_USERNAME; + + if (username) { + const user = findUserByUsername(username); + if (user) { + return HttpResponse.json(user); + } + return new HttpResponse("No user found with this sub", { status: 404 }); + } + return new HttpResponse("User not set", { status: 401 }); + } + if (target == "AWSCognitoIdentityProviderService.ListUsers") { const { Filter } = (await request.json()) as IdpListUsersRequestBody; const username = @@ -336,7 +367,7 @@ export const identityProviderServiceHandler = http.post< }); } - console.error(`x-amz-target ${target} not mocked`); + console.log(`x-amz-target ${target} not mocked`); return passthrough(); } diff --git a/mocks/handlers/aws/credentials.ts b/mocks/handlers/aws/credentials.ts index e62255bef1..0ea1feed75 100644 --- a/mocks/handlers/aws/credentials.ts +++ b/mocks/handlers/aws/credentials.ts @@ -26,4 +26,51 @@ const defaultSecurityCredentialsHandler = http.get(/\/meta-data\/iam\/security-c }); }); -export const credentialHandlers = [defaultApiTokenHandler, defaultSecurityCredentialsHandler]; +const defaultSecurityTokenServiceHandler = http.post("https://sts.us-east-1.amazonaws.com/", () => { + const xmlResponse = ` + + + DevUser123 + + ${generateSessionToken()} + ${SECRET_KEY} + 2019-07-15T23:28:33.359Z + ${ACCESS_KEY_ID} + + + arn:aws:sts::123456789012:assumed-role/demo/John + ARO123EXAMPLE123:John + + 8 + + + c6104cbe-af31-11e0-8154-cbc7ccf896c7 + + +`; + + return HttpResponse.xml(xmlResponse); +}); + +export const errorSecurityTokenServiceHandler = http.post( + "https://sts.us-east-1.amazonaws.com/", + async () => + HttpResponse.xml( + ` + + ServiceUnavailable + Service is unable to handle request. + + `, + { + status: 503, + statusText: "ServiceUnavailable", + }, + ), +); + +export const credentialHandlers = [ + defaultApiTokenHandler, + defaultSecurityCredentialsHandler, + defaultSecurityTokenServiceHandler, +]; diff --git a/mocks/handlers/aws/index.ts b/mocks/handlers/aws/index.ts index 4197aafa7d..7856eff9c6 100644 --- a/mocks/handlers/aws/index.ts +++ b/mocks/handlers/aws/index.ts @@ -1,13 +1,17 @@ import { cloudFormationHandlers } from "./cloudFormation"; import { cognitoHandlers } from "./cognito"; import { credentialHandlers } from "./credentials"; +import { lambdaHandlers } from "./lambda"; import { secretsManagerHandlers } from "./secretsManager"; +import { stepFunctionHandlers } from "./stepFunctions"; export const awsHandlers = [ ...cloudFormationHandlers, ...cognitoHandlers, ...credentialHandlers, - ...secretsManagerHandlers + ...lambdaHandlers, + ...secretsManagerHandlers, + ...stepFunctionHandlers, ]; export { errorCloudFormationHandler } from "./cloudFormation"; diff --git a/mocks/handlers/aws/lambda.ts b/mocks/handlers/aws/lambda.ts new file mode 100644 index 0000000000..9eeea91e58 --- /dev/null +++ b/mocks/handlers/aws/lambda.ts @@ -0,0 +1,112 @@ +import { http, HttpResponse, PathParams } from "msw"; +import { + consumerGroups, + TEST_DELETE_TRIGGER_UUID, + TEST_ERROR_EVENT_SOURCE_FUNCTION_NAME, + TEST_ERROR_EVENT_SOURCE_UUID, +} from "../../data/lambdas"; +import { TestEventSourceMappingRequestBody } from "../../index.d"; + +const defaultListEventSourceMappingsHandler = http.get( + "https://lambda.us-east-1.amazonaws.com/2015-03-31/event-source-mappings", + async ({ request }) => { + console.log("get: ", { request }); + const requestUrl = new URL(request.url); + const functionName = requestUrl.searchParams.get("FunctionName") || ""; + + if (!functionName) { + return new HttpResponse("InvalidParameterValueException", { status: 400 }); + } + + if (functionName == TEST_ERROR_EVENT_SOURCE_FUNCTION_NAME) { + return new HttpResponse(null, { status: 500 }); + } + + return HttpResponse.json({ + EventSourceMappings: consumerGroups[functionName], + }); + }, +); + +const defaultCreateEventSourceMappingsHandler = http.post< + PathParams, + TestEventSourceMappingRequestBody +>( + "https://lambda.us-east-1.amazonaws.com/2015-03-31/event-source-mappings", + async ({ request }) => { + const { FunctionName, Topics } = await request.json(); + + if (!FunctionName) { + return new HttpResponse("InvalidParameterValueException", { status: 400 }); + } + + if (FunctionName == TEST_ERROR_EVENT_SOURCE_FUNCTION_NAME) { + return new HttpResponse("ServerError", { status: 500 }); + } + + if (!Topics || Topics.length === 0 || Topics.length > 1 || !Topics[0]) { + return new HttpResponse("InvalidParameterValueException", { status: 400 }); + } + const topic = Topics[0]; + if (!topic) { + return new HttpResponse("InvalidParameterValueException", { status: 400 }); + } + + const mapping = consumerGroups[FunctionName]; + + if (!mapping) { + return new HttpResponse("ResourceNotFoundException", { status: 404 }); + } + + const topicMapping = mapping.find((obj) => obj.Topics && obj.Topics.includes(topic)); + + return topicMapping + ? HttpResponse.json(topicMapping) + : new HttpResponse("Mapping not found", { status: 404 }); + }, +); + +const defaultGetEventSourceMappingHandler = http.get( + "https://lambda.us-east-1.amazonaws.com/2015-03-31/event-source-mappings/:uuid", + async ({ params }) => { + const { uuid } = params; + + if (!uuid) { + return new HttpResponse("InvalidParameterValueException", { status: 400 }); + } + + if (uuid == TEST_ERROR_EVENT_SOURCE_UUID || uuid == TEST_DELETE_TRIGGER_UUID) { + return new HttpResponse(null, { status: 500 }); + } + + const [mapping] = Object.values(consumerGroups).reduce((acc, curr) => { + return acc.concat(curr.filter((currItem) => currItem.UUID == uuid)); + }, []); + + return mapping ? HttpResponse.json(mapping) : new HttpResponse(null, { status: 404 }); + }, +); + +const defaultDeleteEventSourceMappingHandler = http.delete( + "https://lambda.us-east-1.amazonaws.com/2015-03-31/event-source-mappings/:uuid", + async ({ params }) => { + const { uuid } = params; + + if (!uuid) { + return new HttpResponse("InvalidParameterValueException", { status: 400 }); + } + + if (uuid == TEST_ERROR_EVENT_SOURCE_UUID) { + return new HttpResponse(null, { status: 500 }); + } + + return new HttpResponse(null, { status: 200 }); + }, +); + +export const lambdaHandlers = [ + defaultListEventSourceMappingsHandler, + defaultCreateEventSourceMappingsHandler, + defaultGetEventSourceMappingHandler, + defaultDeleteEventSourceMappingHandler, +]; diff --git a/mocks/handlers/aws/stepFunctions.ts b/mocks/handlers/aws/stepFunctions.ts new file mode 100644 index 0000000000..a41d8adf5e --- /dev/null +++ b/mocks/handlers/aws/stepFunctions.ts @@ -0,0 +1,25 @@ +import { http, HttpResponse, PathParams } from "msw"; +import { TestStepFunctionRequestBody } from "../../index.d"; + +const defaultStepFunctionHandler = http.post( + "https://states.us-east-1.amazonaws.com/", + async ({ request }) => { + const { input } = await request.json(); + const { + cfnEvent: { + ResourceProperties: { stateMachine }, + }, + } = JSON.parse(input); + + if (stateMachine.includes("error")) { + return new HttpResponse(null, { status: 500 }); + } + + return HttpResponse.json({ + executionArn: "arn://fakearnvalue", + startDate: Date.now(), + }); + }, +); + +export const stepFunctionHandlers = [defaultStepFunctionHandler]; diff --git a/mocks/handlers/opensearch/index.ts b/mocks/handlers/opensearch/index.ts index 2ced771efb..bf9cf4fff8 100644 --- a/mocks/handlers/opensearch/index.ts +++ b/mocks/handlers/opensearch/index.ts @@ -1,15 +1,26 @@ import { changelogSearchHandlers } from "./changelog"; import { cpocSearchHandlers } from "./cpocs"; +import { indexHandlers } from "./indices"; import { mainSearchHandlers } from "./main"; -import { typeSearchHandlers } from "./types" +import { securityHandlers } from "./security"; import { subtypeSearchHandlers } from "./subtypes"; +import { typeSearchHandlers } from "./types"; export const opensearchHandlers = [ ...changelogSearchHandlers, ...cpocSearchHandlers, + ...indexHandlers, ...mainSearchHandlers, - ...typeSearchHandlers, + ...securityHandlers, ...subtypeSearchHandlers, + ...typeSearchHandlers, ]; -export { emptyCpocSearchHandler, errorCpocSearchHandler } from "./cpocs" +export { emptyCpocSearchHandler, errorCpocSearchHandler } from "./cpocs"; +export { + errorCreateIndexHandler, + errorUpdateFieldMappingHandler, + errorBulkUpdateDataHandler, + errorDeleteIndexHandler, +} from "./indices"; +export { errorSecurityRolesMappingHandler } from "./security"; diff --git a/mocks/handlers/opensearch/indices.ts b/mocks/handlers/opensearch/indices.ts new file mode 100644 index 0000000000..6a40734f8b --- /dev/null +++ b/mocks/handlers/opensearch/indices.ts @@ -0,0 +1,55 @@ +import { http, HttpResponse } from "msw"; + +const defaultCreateIndexHandler = http.head( + "https://vpc-opensearchdomain-mock-domain.us-east-1.es.amazonaws.com/:index", + async () => { + return new HttpResponse(null, { status: 200 }); + }, +); + +export const errorCreateIndexHandler = http.head( + "https://vpc-opensearchdomain-mock-domain.us-east-1.es.amazonaws.com/:index", + () => new HttpResponse("Internal server error", { status: 500 }), +); + +// updateFieldMapping +const defaultUpdateFieldMappingHandler = http.put( + "https://vpc-opensearchdomain-mock-domain.us-east-1.es.amazonaws.com/:index/_mapping", + async () => { + return new HttpResponse(null, { status: 200 }); + }, +); + +export const errorUpdateFieldMappingHandler = http.put( + "https://vpc-opensearchdomain-mock-domain.us-east-1.es.amazonaws.com/:index/_mapping", + () => new HttpResponse("Internal server error", { status: 500 }), +); + +const defaultBulkUpdateDataHandler = http.post( + "https://vpc-opensearchdomain-mock-domain.us-east-1.es.amazonaws.com/_bulk", + () => new HttpResponse(null, { status: 200 }), +); + +export const errorBulkUpdateDataHandler = http.post( + "https://vpc-opensearchdomain-mock-domain.us-east-1.es.amazonaws.com/_bulk", + () => new HttpResponse("Internal server error", { status: 500 }), +); + +const defaultDeleteIndexHandler = http.delete( + "https://vpc-opensearchdomain-mock-domain.us-east-1.es.amazonaws.com/:index", + async () => { + return new HttpResponse(null, { status: 200 }); + }, +); + +export const errorDeleteIndexHandler = http.delete( + "https://vpc-opensearchdomain-mock-domain.us-east-1.es.amazonaws.com/:index", + () => new HttpResponse("Internal server error", { status: 500 }), +); + +export const indexHandlers = [ + defaultCreateIndexHandler, + defaultUpdateFieldMappingHandler, + defaultBulkUpdateDataHandler, + defaultDeleteIndexHandler, +]; diff --git a/mocks/handlers/opensearch/security.ts b/mocks/handlers/opensearch/security.ts new file mode 100644 index 0000000000..442faaa550 --- /dev/null +++ b/mocks/handlers/opensearch/security.ts @@ -0,0 +1,13 @@ +import { http, HttpResponse } from "msw"; + +const defaultSecurityRolesMappingHandler = http.patch( + "https://vpc-opensearchdomain-mock-domain.us-east-1.es.amazonaws.com/_plugins/_security/api/rolesmapping/os-role", + () => new HttpResponse(null, { status: 200 }), +); + +export const errorSecurityRolesMappingHandler = http.patch( + "https://vpc-opensearchdomain-mock-domain.us-east-1.es.amazonaws.com/_plugins/_security/api/rolesmapping/os-role", + () => new HttpResponse("Internal server error", { status: 500 }), +); + +export const securityHandlers = [defaultSecurityRolesMappingHandler]; diff --git a/mocks/index.d.ts b/mocks/index.d.ts index 5486c8e1b8..6764d1eecb 100644 --- a/mocks/index.d.ts +++ b/mocks/index.d.ts @@ -1,6 +1,7 @@ -import type { APIGatewayEventRequestContext, UserData, opensearch } from "shared-types"; import type { Export } from "@aws-sdk/client-cloudformation"; +import { CreateEventSourceMappingCommandInput } from "@aws-sdk/client-lambda"; import type { GetSecretValueCommandOutput } from "@aws-sdk/client-secrets-manager"; +import type { APIGatewayEventRequestContext, UserData, opensearch } from "shared-types"; // code borrowed from https://stackoverflow.com/questions/47914536/use-partial-in-nested-property-with-typescript export type DeepPartial = { @@ -38,7 +39,6 @@ export type TestSecretData = Partial; - export type IdentityRequest = { IdentityPoolId: string; Logins: Record; @@ -62,40 +62,48 @@ export type IdpListUsersRequestBody = { Filter: string; }; +export type AdminGetUserRequestBody = { + UserPoolId: string; + Username: string; +}; + export type SecretManagerRequestBody = { SecretId: string; }; - -type FieldValue = boolean | undefined | number | string -type MinimumShouldMatch = number | string +type FieldValue = boolean | undefined | number | string; +type MinimumShouldMatch = number | string; type TermsLookup = { id?: string; index?: string; path?: string; routing?: string; -} -type TermsQueryField = FieldValue[] | TermsLookup +}; +type TermsQueryField = FieldValue[] | TermsLookup; type QueryBase = { _name?: string; boost?: number; -} -type MatchQuery = FieldValue | (QueryBase & { - analyzer?: string; - auto_generate_synonyms_phrase_query?: boolean; - cutoff_frequency?: number; - query: FieldValue; -}) +}; +type MatchQuery = + | FieldValue + | (QueryBase & { + analyzer?: string; + auto_generate_synonyms_phrase_query?: boolean; + cutoff_frequency?: number; + query: FieldValue; + }); type MatchAllQuery = QueryBase & Record; -export type TermQuery = FieldValue | (QueryBase & { - case_insensitive?: boolean; - value: FieldValue; -}); +export type TermQuery = + | FieldValue + | (QueryBase & { + case_insensitive?: boolean; + value: FieldValue; + }); export type TermsQuery = QueryBase & { _name?: any; boost?: any; [key: string]: any | TermsQueryField; -} +}; type QueryContainer = { match?: Record; match_all?: MatchAllQuery; @@ -109,22 +117,38 @@ type BoolQuery = QueryBase & { must?: QueryContainer | QueryContainer[]; must_not?: QueryContainer | QueryContainer[]; should?: QueryContainer | QueryContainer[]; -} +}; export type SearchQueryBody = { from?: number; search?: string; query?: { - bool: BoolQuery + bool: BoolQuery; match_all?: MatchAllQuery; }; size?: number; sortDirection?: string; sortField?: string; -} +}; export type GetItemBody = { id: string }; export type EventRequestContext = Partial; +export type TestEventSourceMapping = { + Topics: [string]; + SelfManagedKafkaEventSourceConfig?: { + ConsumerGroupId?: string; + } | null; + State?: "Creating" | "Enabling" | "Enabled" | "Disabling" | "Disabled" | "Updating" | "Deleting"; + UUID?: string; +}; + +export type TestEventSourceMappingRequestBody = DeepPartial; + +export type TestStepFunctionRequestBody = { + stateMachineArn: string; + input: string; +}; + export type TestCounty = [string, string, string]; From ba4f3a63712059888acc0a426308aeceff34f324 Mon Sep 17 00:00:00 2001 From: Ty Bolt Date: Tue, 7 Jan 2025 14:31:16 -0500 Subject: [PATCH 2/4] fix(email): switch email logo back to using url --- lib/libs/email/content/email-components.tsx | 3 +- lib/libs/email/content/onemac-logo-base64.ts | 2 - .../InitialSubmissionCMS.test.tsx.snap | 40 +++++++------- .../InitialSubmissionState.test.tsx.snap | 54 +++++++++---------- .../__snapshots__/ResToRaiCMS.test.tsx.snap | 28 +++++----- .../__snapshots__/ResToRaiState.test.tsx.snap | 28 +++++----- .../__snapshots__/UpSubDocCMS.test.tsx.snap | 28 +++++----- .../__snapshots__/UpSubDocState.test.tsx.snap | 28 +++++----- .../WithdrawPackageCMS.test.tsx.snap | 28 +++++----- .../WithdrawPackageState.test.tsx.snap | 28 +++++----- .../__snapshots__/WithdrwRaiCMS.test.tsx.snap | 10 ++-- .../WithdrawRaiState.test.tsx.snap | 14 ++--- .../WithdrawConfirmationState.test.tsx.snap | 28 +++++----- 13 files changed, 158 insertions(+), 161 deletions(-) delete mode 100644 lib/libs/email/content/onemac-logo-base64.ts diff --git a/lib/libs/email/content/email-components.tsx b/lib/libs/email/content/email-components.tsx index 04e74fb5d4..7f070719c6 100644 --- a/lib/libs/email/content/email-components.tsx +++ b/lib/libs/email/content/email-components.tsx @@ -2,7 +2,6 @@ import { Column, Heading, Hr, Link, Row, Section, Text } from "@react-email/comp import { ReactNode } from "react"; import { Attachment, AttachmentKey, AttachmentTitle } from "shared-types"; import { styles } from "./email-styles"; -import { ONEMAC_LOGO_BASE64 } from "./onemac-logo-base64"; export const EMAIL_CONFIG = { DEV_EMAIL: "mako.stateuser+dev-to@gmail.com", @@ -52,7 +51,7 @@ const EmailNav = ({ appEndpointUrl }: { appEndpointUrl: string }) => ( height={40} width={112} style={{ maxWidth: "112px" }} - src={`data:image/png;base64,${ONEMAC_LOGO_BASE64}`} + src={`${appEndpointUrl}onemac-logo.png`} alt="OneMAC Logo" /> diff --git a/lib/libs/email/content/onemac-logo-base64.ts b/lib/libs/email/content/onemac-logo-base64.ts deleted file mode 100644 index 96798cba2e..0000000000 --- a/lib/libs/email/content/onemac-logo-base64.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const ONEMAC_LOGO_BASE64 = - "iVBORw0KGgoAAAANSUhEUgAAAVsAAACDCAYAAAAj1bgbAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAFzJJREFUeJztnXmUFdWdxz/dNAKy0xIUREQicUNU3EXjHpQxEkXFMVEnLjPJiR7Nok5ixqiTieaMJmbzRI1xQowLE6NGRRQFNWhAibgGxd24byyCotA9f/zem653e6u6S92qfr/POe/0u/Wq7r2v+/X33frd39LQ2tqKoiiKEpbG2BNQFEWpB5piT0BRUtAINAODgCGVn63ASmA5sAJ4L9rsFCUFTcArsSeh5M5WwJrYk+iCkcBUYBIwEZgA9O/mmveBJcBjwEPA7RT7PSp1RkOrGm3rkYHAh7EnYTAI+DJwNLA37iauNcBtwExEePVzrkRFxbY+KZLYbgCcCFwAjAg0xhPAhcCsQP0rSreo2NYnRRHbLwBXAqM7eX09sAx4FHgSeBex0a4C1iH22w2BccBngV0qPztjNvAvwFse5q4omVCxrU9ii20TcD5wDu3NBeuAucB1wM3IJlgWNgaOQEwSe3Tw+pvA8cDdGftVFCdUbOuTmGLbH7gFOMA43gL8Afge/jZt90JEvaOx/hW4ytM4itItKrb1SSyx7YdsWu1vHH8KWW3+LdC4JwA/RcwOVVqAU4CrA42pKDWo2NYnMcS2NyK0BxvHZwFfzWE+WyI223GJYy2I98MfA4+tKBpBpuTGBbQX2p8Cx5CP8C9DbLh/TxxrREwJY3IYX6lzdGVbn+S9sj0QmEPtl/s1yIo278/fGCToYZPEsQXAvsjmnKIEQVe2SmgGAP9D7WftAcReGuOL/mXEU6ElcWwv4OQIc1HqCBVbJTRnIOG3VT5EghhiriLvBS4zjp2LbOApShBszAiLgUdCTEaxYiKwe8Zr8jIjNAPPA4MTx74B/DKHsbtjEGLH/Uzi2LeBS+JMR+np2GT9uh04z/dEFGu+Q3axzYszqRXal4ErIs3FZCXwn8DPEsfORDbt1keZkdKj0RSLSigaEd/ZJBcBn0aYS2f8BvgBMKzSHoUEQNxl2d8ooE/l+dt0f/fQFzgIsRlvB4xFgj4GIFnMPqj8fBT4C7KRt8Jybr7YCdgTCY3eEvFdHoKYhVYgIdWPIne/dyDh1Qoqtko4DqY258FyxAOhSKxBNu/OTBw7EXuxvQnYtfL8ZETMO2IkcHZlrEGdnNOceD6l8vMTJMruv5FAkLwYgETcfRXYpovzqn/vfSs/P0ZCri8Eng41ubKgG2RKKE4w2jch/3xF43qjPQ0/G2XNHRzrC1yK2LFPp3Oh7YxqhrQngN9aXG/DscBSROC7EtqO6AvMQHIM/4S2VX9doitbJQSNtA9guCHGRFLwMJKLYbNKux9iA5/n2O9GRnsM8oWzk3G8FRHPpcgt+HvILfnQSh+7AuONaxoQ0d0FWfX+w3GuHdEXCfg4roPXWpDf22LgncqjATEnbIuYGTZLnN+EeKXshiQJejPAfAuPiq0Sggm02UEBViPuVkWkFbgHSb1YZR/cxTa5sv0c4ls8PDHmHOB3lbHf7qavkYhf8mlGv9sCdyI2X5+23KGVfnc1jr8I/BC4FRHYzmhAEsB/F0mjWWUP5P3ujdii6wo1Iygh2NdoL6TY0VkPGO19PPRZFcXhiAdPVWgfQ0TnECSNZHdCC/A6kr1sHPBn47VtEQ8KX/RDxDQptGsRt7itETt0V0IL8mVyP7LqPp5a89E2SNa3ulvoqdgqITBd0R6KMov0LDLakzz0WTUj/J625Dczkd/NQss+VyA2ZTM15AnAzpZ9mvwWmJxov4+YhC5BRDcrM5Fw7WQ9uMmIy2JdoWKrhGBLo704yizSs4zalfdgOt7gykIzYp+s2q5nInZW103CFiQwJJmOsgE/4jUDSQxUZQVyy3+/Y78LkPee5Dxq7bo9HhVbJQRmaZoXo8wiPZ8ALxjHtnDsczPaAiaWAKdSm4/BhbXUuqsBHI64aNkyFPhFot0KnIQ/l61ZwI2Jdh/qbHWrYqv4Zji1UWNQfLEFeM1ou4rthkiQQyvio+rb7e1+xP5bpQ/tN7SycAa1q/kr8J/n9xxqo/NOov1npceiYqv4ZpTRXk78qKc0mO5IG3vq9zba24R9YVYL7qjmWhoGI36/VdYigQi+eREJcqjSD7FB1wUqtopv+hvtMggtiI9rEvN92HK5p346wtxo28Wyn6OpLRl0De1X+r64zmgfFWicwqFiq/jGtBuu6fCs4vGR0fYhtiuRSsGhMGu2jbDs55+N9q8s+0nDHGrzY0wGegUcrzCo2Cq+2dBol0VsTbcmH2L7MGET77xv9D+ksxO7YDi1fsWvAo+7TKobPkQi5qoMRpLw9HhUbBXfbGC0i5TlqyvMoAsfcfwPe+ijO5JmmqEW10+mVgfucJtOKkxXQBVbRbHgE6PdN8ossmMmn/HhPfCohz66Y1Xiuc1qfG+j7epTm4aXjfbYHMaMjoqt4htTpEyzQlEx5+lDbF/30Ed3uPru7mC0n3XsLw1m4py6CG5QsVV8s9po+9rVD425svVhay6DJ8Y4o70shzHNz8jAHMaMTt0lg1CCY/qrDke+1H1FT4ViuNF+w0OfRRfbPsCmifYa2qfGDIGZZrIsX8hOqNgqvjFvnTdAAgTyuKV2YYzR9iG2eRTVdGEotXe3G1IbUpsXdZFUXM0Iim8+pH3dqc0jzCMrptj6cOrPWrk6b+piRVkUVGyVEJj1scwsYEVjKLXJztcDz0SaS56o2OaIiq0SAlNsd4syi/SYCVyeo31EWU/EXHkvRtI15v1IVnPosajYKiEwndZtE6TkhSm2efjHFgHTK8AmAk1JiYqtEoL5Rns7ip1Kz/wymB9jEhEw3duK/DcqPSq2Sgiepdb7oAk4LNJcumMgsJ9xbH6EecTgXdxzKygpUbFVQnGr0S5qKr3DqA0pXkp9bI6B5IN4JdFuor1XhuIJFVslFNcb7YNxr+sVAvNLwJx3T+c5o22bE1fpBhVbJRQPUJtwpC9SqLBIbEmteaMFuDbSXGJhZiZTsQ2Eiq0SihbaCh5WOZ1ixcGfRW3i6ltpv9Lr6dxntPeKMos6QMVWCcmV1EaTDUMErghsBRxvHLs0xkQi8yC1PsV70L6OnOIBFVslJKuA/zKOnQPsHGEuSRqRL4JkovM/I6aPemMN8KdEuxE4JdJcejQqtkpoLqM2bV8TcDXta5XlybeRCgVV1gLfijSXInCN0f4G6nPrHRVbJTSfACch+QaqTABuIU62p2m0X21/n3zyuBaVe4AliXYzcH6kufRYVGyVPHgA+JFxbH9kRWXWLAvJwYhrV3JTbA5wSY5zKCItiHknyWnAlAhz6bGo2Cp58QNglnFsBjAP2CSH8U8FbqN2Nf0UcBzFT2yeB3OAmxPtRuAPwI5xptPzULFV8mI98BXkljXJnoiv5xGBxh2JiMavgd6J4y8gK933Ao1bRk6iNqJsKDAXOCjQeL2pIw2qmzeqFIK1wFRE/JKMAv6I5CTY09NYw5DV9LPAscZrixB/0qJXj8ib95EvPdNdbzbwE2CQp3HGAxcDr1KegqDOqNgqebMW+DJiI1xrvPZ5YAGSm+A/kMqvvUnPJsDRyO3wG8B5tE+QfTWSeMaslaYIi4EDEeGt0gs4A4kIvAjYPmOfDcAk4Fzgr0j+ibOAEa6TLRNag0yJQSuysrkduIr2ycXHI7vh5yOC/CTwNFJAcTlSeqc34p40CEmeMhGpddYZLwFfA+709B56MouRHL/XURu+OwQ4u/J4A3gIibh7nbbAiD7IanUw8ncZj4RF170rmYqtEpMnkYilaYiwTujgnD7IqmiS5RhvIK5eVyBuaEo6nkdMLf8OfJP2YrkJbnb2lcANtL+76bGoGUGJTSsSwTQRCTS4EvdNqzWIKWEasrr6BSq0NnwKXACMRUwyrqknVyGReiciG5enUptPt0ejK1ulKLQi9toFwL8B2wL7Vn6OQyr0NiO3qH0Qd60VSGmXl5Hb2WcQn95FxBHX06jdRMqjlPkJQL/K8/VdnejAB4joXoD8PQ5E7kK2R1a4A2lb+a5CTAorkL/LMmSTclHlsS7QHAuPiq1SRFqAJyqPMrEowpgLch7vKdoX9FRSoGYERVGUHFCxVRRFyQEVW0VRlBxQsVUURckBFVtFUZQcULFVFEXJARVbRVGUHFCxVRRFyQENalCUcrMv/v+P5xEuGs0nTUhmuO2ALSqPEUhEXV8kWdEqJA/DSiQM/HkkKOPv1ObuzWWyihKCd5HwWl+0AqOB1zz2maSh0rfvqhFb4Z5ToDPGI8Lom/0D9euDkcAxwKHA7rgVDl2F1F77C3Afkk85WGIcNSMoZaEB+QcLxSTyKc/jk+kl69eWBiTp/F3IavRSJD+Da4XmgcDeSGazO5EFwv8CXyJAbTwVW6VMTA3Yd0ghD8WRAfvt1e1Z+fBF4FGkftxBhJ3XAOS934Tk6L0Y2NRX5yq2Spk4ELHFheCQQP2GYnPCFWMcgeSyjcloJE3mLUj6zbxpRqpJPI+nihIqtkqZ6I+UzvHNRtRWJCgD05Hb65D9x+JQ4DHg8IhzqPIg8JaPjlRslbIRwpQwheLcNqcllAmhylHE0YdzkQTjQyOM3RG/8dWRiq1SNv4pQJ9lMyGMon3dNt9sjJQsypMfAhdSHF1agdhvvVCUN6UoaRkLbO2xv17AFzz2lwdHEtaEUCVPU8L5wHdzHC8Nv0dKLHlBxVYpIz5NCbvi1x84D0KbEKqEtgtXORL4fg7jZMWbCQFUbJVy4lNsy2ZCsPUUsAkG2RQJHAjJ9sDvyEfUs7AYcTnzhoqtUkYmA0M89VU2/9ojsNvM+5XleCFNCU3A1UgRz6Jxle8OVWyVMtIEHOyhn42BnTz0kye2JoTbgRcsrjuKcKvObyKRe0VjDXCd705VbJWy4sOUcAjFu33timbs/IzXIMlXHrK4djRhfJCH49dOuwq4HPlcjEaS0GyAfKFuA+wDnAHMQqLDumIW4ongFU1Eo5SVQ5HbaZfsVGWz107D7n92MbAOWAgcZ3H9dPyXaT8L99wGIGXvf454M3zQwetv0RaU8ABwWeX5DsjvYgbtQ3K9boxV0ZWtUlZco76akFj7MnGE5XULKz8ftLzet922Gfi6h34+Ag5DVqwdCW1XLAG+A4xBglruQIT7GSQLmHdUbJUy42JK2At/m2x5MBjJDWHDgsrPJcByi+vH4te2+hXcN8VagOMRkXTtZw7yWdoa+RJodeyzQ1RslSJxbcbzXaLJspgQ3qZNsGLxRezS/rXStqJdj9xK2+BzdXuShz7OQ9Ih+uRZ4F7Pff4/KrZKkci6SpmIfQq8LGI7h4BJpVNi64XwDPJlUcU2KfjRlteZTEAqK7jwHPBjD3PJFRVbpUisAJZlON82ofimyD99WuYQ1+QwAHtXN3Mlayu2W+AnpaMPv+azgU889JMrKrZKkWgGZme8xsZueyjpXb5agLuJK7aHInW1bDA3xR5HanHZ4MOUMMXx+heBP3mYR+4U1fXrAMrnlhOLsuVh7YphiNienuGaA5CE4h9nuCbLZ2sxchs+OMM1vnHJhXCf0W6pHLPxbJgOfM9hLr2QXBQuXE+gDazQFFVs9wC+FXsSSu4MQYRgDel3q/sjFWbvTHn+BohAp6Xarw+fUBv6YX/r/SqyEjS5FzuxHY/kMnjccj5b4e6FcKPj9dFQM4JSJAYjvpP3Z7wuiylhH6TQX1rmICuyPplm5I8p2At9Zzvr91j2B26mBFeb73LEfa2UqNgqRaJ6q57VbntYhnOzmBCWIwEBMROluJgQ5ndyfCnwD8s+XbwSPutwLdivqAuBiq1SJKqbUFnFdgwS/56GLLfkdyNhrrHEdgPcfInnd/GarT/p54BtLa8dbXldlSccr4+Kiq1SJKor22VIVdMspBGlsYjdMC1Ve23/jHPxxUHYb8y9ALzUxesupoSjLK8b5TAmZHMLLBwqtkqRGJR4nnV1m2bFmmVV24rYa8He7coVFxNCd2I616Fv23m5FnG0CTUuDCq2SpHom3ie1rugymTEdawrsthrn6CtukHvjHPxQRPZbNEm3Ynt64jt1obtsKsD5/qltcrx+qio2CpFIhn7fy/imZCWXnQdZdUX2C9Df0mxj+EiuR+S2cyGVtLZZPP2SlCxVZSCkHSv+ojsSVO6cgHbj2wbXXMSz23K0LjiYkJ4HHgnxXmxXMBs+TTCmN5QsVWKhJnVysZu25kwZjEhrKY2y1feYtsIHO5wfVp77Dzsk69vT7bNRnAvCx7L19kLKrZKkTD/mbLabYcBu3XyWhaxvYfaLF95mxH2Rsq52JJ2xboc+JvDOFmj0FY7jAXxNiq9oGKrFAlzZbuUjsNNu6IjU8J4sjnU32W08/4/cTEhfEo280uepgTXle1nHK+PioqtUiQ6+jxmXd12JLZZM4OZY+ZZFLIBqTVmy1+BDzOc7yK2O5LtS8zVdcvVTzcqRU1EoyhVZgNfy3D+RCSi7OXEsSwmhGfJHlDhk91wi7TaGngkw/mubm1HAhenPPclx7HGOV4fFRVbpejci9hPs2yOTAF+XXneH0k+k5asK2nfuO7yb4S9y5gN00kvtllNQiY+66DljpoRlKKzGjcXsAPIJtRzuj8lKF+KPH5Wdib9itP1jmE83QeuFBYVW6UMZF1tHkibT20WE8Ja2ifbzpNJSPmZspHWK+EZx3Ea8VNWJwoqtkoZyOpv2w/4fOV5FrG9D3f3JBdcvBBiktb08SISJuzCMY7XR0PFVikDT1O74ZWGqUgM/5gM18Q2IdhUTygCu5D+9+xaEn4q2YMpCoGKrVIWspoSDiP7LWfMzbHtkVyxZaSB9KvyrPb3jsb6gWMfUVCxVcpCVlPCZsCFGc5/FVlBx6KsJoQqaU0Js3Ev2HgMbuHMUVCxVcrCXGpDaNNgRqR1RVYx903ZxXZ35AuuO55DSg25MhPYyUM/JtXUlmf47ljFVikLZnIY38S0147HvtRMUWggvdvatR7GG4j4YLuUDUoyEfEXfgW4lWwVmFOhYquUiVA21XW4ha26YltmpmikNSXcAHzsYbzBiDBeR3Z7dxMSrXcRUm5nCXAWsImHeXU6YFamAiN8T8QgxO2BUn5mAz8O0O+DwIoA/aal7CaEKnsi+Qte6+a8d4DLgTM9jNkAzKg8FiJJhB5DvFdWIOkxhyUeExCTx07kXMjTRmwnUfKwOaW0PInc5qWxDWYhpglhLLBDxPF90oi4r/08xbk/Ak5GzAG+2I3OU2xGR80IStkIIYwxXb6m455VbFKlDx+P2xznktaU8A7wM8exSoWKrVI2fHsNvIPY62LhakJ4F7/zd7VdTwZGpjz3QuL+7nNFxVYpG3PxW4tqNtDisb8sbArs6tjHXPzO31VsG0mfj3ctcDTZ8u+WFhVbpWysQja0fBHTXnsk7iaEu31MJMGTwJuOfWRJE7kM+DrxvvByQ8VWKSO+TAktpC+OGAIfXgi+xbYVKQTpwj5kK2EzEziFHi64KrZKGfElto8Ab3vqKysjEFcpF5YiYca+cTUl9CJ7Xt6rkYocPVZwVWyVMvI4fkQmphfCEbiXSPe9qvXZr03FiSuQXMSuaRgLiYqtUlbMCrg2xLbXuhJKbF/BvarCfthVw52HBBz4+PsWChVbpay4rko/ABb5mIgFzbQlN7dlHWGrSrjasnthn5nrLaSO3LHAC47zsOENAtz1qNgqZeUu3FzA7kYEKwbTcC+2+hCw0sNcOsNHrgiX1XsrcD2S82AG8vfy6fJn8jFwI5KOYDTwS98DNBHGwK4Umzw2Iaqx6Vn4KMO5K5EkJDtmHKPKzRnO/Qj7FVZHArGLQ39VbnK8vjvm4T7HzYEBuPnRrkMS19wADEWyfB2OFJrMUoXDZDXwMDC/8liIn+Q4ndLQ2uqax1dRFCUKg4BtkOQyzcAQJNfCAKQO3UokcGIVIvivIrbo5xFTQa6o2CqKouSA2mwVRVFy4P8AK6n0HmV9e0MAAAAASUVORK5CYII="; // pragma: allowlist secret diff --git a/lib/libs/email/preview/Initial Submissions/CMS/__snapshots__/InitialSubmissionCMS.test.tsx.snap b/lib/libs/email/preview/Initial Submissions/CMS/__snapshots__/InitialSubmissionCMS.test.tsx.snap index 71f0b0723b..e7b53f37b2 100644 --- a/lib/libs/email/preview/Initial Submissions/CMS/__snapshots__/InitialSubmissionCMS.test.tsx.snap +++ b/lib/libs/email/preview/Initial Submissions/CMS/__snapshots__/InitialSubmissionCMS.test.tsx.snap @@ -63,7 +63,7 @@ exports[`Initial Submission CMS Email Snapshot Test > renders a AppkCMSEmail Pre OneMAC Logo @@ -641,7 +641,7 @@ exports[`Initial Submission CMS Email Snapshot Test > renders a AppkCMSEmail Pre OneMAC Logo @@ -1276,7 +1276,7 @@ exports[`Initial Submission CMS Email Snapshot Test > renders a Chipspa Preview OneMAC Logo @@ -1853,7 +1853,7 @@ exports[`Initial Submission CMS Email Snapshot Test > renders a Chipspa Preview OneMAC Logo @@ -2554,7 +2554,7 @@ exports[`Initial Submission CMS Email Snapshot Test > renders a Chipspa Preview OneMAC Logo @@ -3312,7 +3312,7 @@ exports[`Initial Submission CMS Email Snapshot Test > renders a Medicaid Spa Pre OneMAC Logo @@ -3889,7 +3889,7 @@ exports[`Initial Submission CMS Email Snapshot Test > renders a Medicaid Spa Pre OneMAC Logo @@ -4589,7 +4589,7 @@ exports[`Initial Submission CMS Email Snapshot Test > renders a Medicaid Spa Pre OneMAC Logo @@ -5428,7 +5428,7 @@ exports[`Initial Submission CMS Email Snapshot Test > renders a Medicaid Spa Pre OneMAC Logo @@ -6324,7 +6324,7 @@ exports[`Initial Submission CMS Email Snapshot Test > renders a TempExt Preview OneMAC Logo @@ -6901,7 +6901,7 @@ exports[`Initial Submission CMS Email Snapshot Test > renders a TempExt Preview OneMAC Logo @@ -7601,7 +7601,7 @@ exports[`Initial Submission CMS Email Snapshot Test > renders a TempExt Preview OneMAC Logo @@ -8439,7 +8439,7 @@ exports[`Initial Submission CMS Email Snapshot Test > renders a TempExt Preview OneMAC Logo @@ -8952,7 +8952,7 @@ exports[`Initial Submission CMS Email Snapshot Test > renders a TempExt Preview OneMAC Logo @@ -9522,7 +9522,7 @@ exports[`Initial Submission CMS Email Snapshot Test > renders a Waiver Capitated OneMAC Logo @@ -10099,7 +10099,7 @@ exports[`Initial Submission CMS Email Snapshot Test > renders a Waiver Capitated OneMAC Logo @@ -10799,7 +10799,7 @@ exports[`Initial Submission CMS Email Snapshot Test > renders a Waiver Capitated OneMAC Logo @@ -11637,7 +11637,7 @@ exports[`Initial Submission CMS Email Snapshot Test > renders a Waiver Capitated OneMAC Logo @@ -12149,7 +12149,7 @@ exports[`Initial Submission CMS Email Snapshot Test > renders a Waiver Capitated OneMAC Logo @@ -12696,7 +12696,7 @@ exports[`Initial Submission CMS Email Snapshot Test > renders a Waiver Capitated OneMAC Logo diff --git a/lib/libs/email/preview/Initial Submissions/State/__snapshots__/InitialSubmissionState.test.tsx.snap b/lib/libs/email/preview/Initial Submissions/State/__snapshots__/InitialSubmissionState.test.tsx.snap index 1cd1ec1104..0701eaa32c 100644 --- a/lib/libs/email/preview/Initial Submissions/State/__snapshots__/InitialSubmissionState.test.tsx.snap +++ b/lib/libs/email/preview/Initial Submissions/State/__snapshots__/InitialSubmissionState.test.tsx.snap @@ -63,7 +63,7 @@ exports[`Initial Submission State Email Snapshot Test > renders a AppKCMSEmailPr OneMAC Logo @@ -564,7 +564,7 @@ exports[`Initial Submission State Email Snapshot Test > renders a AppKCMSEmailPr OneMAC Logo @@ -1122,7 +1122,7 @@ exports[`Initial Submission State Email Snapshot Test > renders a Chipspa Previe OneMAC Logo @@ -1622,7 +1622,7 @@ exports[`Initial Submission State Email Snapshot Test > renders a Chipspa Previe OneMAC Logo @@ -1982,7 +1982,7 @@ exports[`Initial Submission State Email Snapshot Test > renders a Chipspa Previe OneMAC Logo @@ -2399,7 +2399,7 @@ exports[`Initial Submission State Email Snapshot Test > renders a Medicaid Spa P OneMAC Logo @@ -2899,7 +2899,7 @@ exports[`Initial Submission State Email Snapshot Test > renders a Medicaid Spa P OneMAC Logo @@ -3258,7 +3258,7 @@ exports[`Initial Submission State Email Snapshot Test > renders a Medicaid Spa P OneMAC Logo @@ -3696,7 +3696,7 @@ exports[`Initial Submission State Email Snapshot Test > renders a Medicaid Spa P OneMAC Logo @@ -4191,7 +4191,7 @@ exports[`Initial Submission State Email Snapshot Test > renders a TempExt Previe OneMAC Logo @@ -4691,7 +4691,7 @@ exports[`Initial Submission State Email Snapshot Test > renders a TempExt Previe OneMAC Logo @@ -5050,7 +5050,7 @@ exports[`Initial Submission State Email Snapshot Test > renders a TempExt Previe OneMAC Logo @@ -5487,7 +5487,7 @@ exports[`Initial Submission State Email Snapshot Test > renders a TempExt Previe OneMAC Logo @@ -5966,7 +5966,7 @@ exports[`Initial Submission State Email Snapshot Test > renders a TempExt Previe OneMAC Logo @@ -6502,7 +6502,7 @@ exports[`Initial Submission State Email Snapshot Test > renders a Waiver Capitat OneMAC Logo @@ -7002,7 +7002,7 @@ exports[`Initial Submission State Email Snapshot Test > renders a Waiver Capitat OneMAC Logo @@ -7361,7 +7361,7 @@ exports[`Initial Submission State Email Snapshot Test > renders a Waiver Capitat OneMAC Logo @@ -7798,7 +7798,7 @@ exports[`Initial Submission State Email Snapshot Test > renders a Waiver Capitat OneMAC Logo @@ -8276,7 +8276,7 @@ exports[`Initial Submission State Email Snapshot Test > renders a Waiver Capitat OneMAC Logo @@ -8850,7 +8850,7 @@ exports[`Initial Submission State Email Snapshot Test > renders a Waiver Capitat OneMAC Logo @@ -9481,7 +9481,7 @@ exports[`renders a Waiver Contracting Preview Template 1`] = ` OneMAC Logo @@ -9981,7 +9981,7 @@ exports[`renders a Waiver Contracting Preview Template 1`] = ` OneMAC Logo @@ -10340,7 +10340,7 @@ exports[`renders a Waiver Contracting Preview Template 1`] = ` OneMAC Logo @@ -10777,7 +10777,7 @@ exports[`renders a Waiver Contracting Preview Template 1`] = ` OneMAC Logo @@ -11255,7 +11255,7 @@ exports[`renders a Waiver Contracting Preview Template 1`] = ` OneMAC Logo @@ -11828,7 +11828,7 @@ exports[`renders a Waiver Contracting Preview Template 1`] = ` OneMAC Logo @@ -12360,7 +12360,7 @@ exports[`renders a Waiver Contracting Preview Template 1`] = ` OneMAC Logo diff --git a/lib/libs/email/preview/Respond to Rai/CMS/__snapshots__/ResToRaiCMS.test.tsx.snap b/lib/libs/email/preview/Respond to Rai/CMS/__snapshots__/ResToRaiCMS.test.tsx.snap index 2dc8db56d8..985c7609a1 100644 --- a/lib/libs/email/preview/Respond to Rai/CMS/__snapshots__/ResToRaiCMS.test.tsx.snap +++ b/lib/libs/email/preview/Respond to Rai/CMS/__snapshots__/ResToRaiCMS.test.tsx.snap @@ -63,7 +63,7 @@ exports[`Respond To RAI CMS Email Snapshot Test > renders a AppKCMSEmailPreview OneMAC Logo @@ -526,7 +526,7 @@ exports[`Respond To RAI CMS Email Snapshot Test > renders a AppKCMSEmailPreview OneMAC Logo @@ -1046,7 +1046,7 @@ exports[`Respond To RAI CMS Email Snapshot Test > renders a ChipSPA Preview Temp OneMAC Logo @@ -1508,7 +1508,7 @@ exports[`Respond To RAI CMS Email Snapshot Test > renders a ChipSPA Preview Temp OneMAC Logo @@ -2155,7 +2155,7 @@ exports[`Respond To RAI CMS Email Snapshot Test > renders a ChipSPA Preview Temp OneMAC Logo @@ -2859,7 +2859,7 @@ exports[`Respond To RAI CMS Email Snapshot Test > renders a Medicaid_SPA Preview OneMAC Logo @@ -3321,7 +3321,7 @@ exports[`Respond To RAI CMS Email Snapshot Test > renders a Medicaid_SPA Preview OneMAC Logo @@ -3967,7 +3967,7 @@ exports[`Respond To RAI CMS Email Snapshot Test > renders a Medicaid_SPA Preview OneMAC Logo @@ -4604,7 +4604,7 @@ exports[`Respond To RAI CMS Email Snapshot Test > renders a Medicaid_SPA Preview OneMAC Logo @@ -5298,7 +5298,7 @@ exports[`Respond To RAI CMS Email Snapshot Test > renders a Waiver Capitated Pre OneMAC Logo @@ -5760,7 +5760,7 @@ exports[`Respond To RAI CMS Email Snapshot Test > renders a Waiver Capitated Pre OneMAC Logo @@ -6406,7 +6406,7 @@ exports[`Respond To RAI CMS Email Snapshot Test > renders a Waiver Capitated Pre OneMAC Logo @@ -7042,7 +7042,7 @@ exports[`Respond To RAI CMS Email Snapshot Test > renders a Waiver Capitated Pre OneMAC Logo @@ -7681,7 +7681,7 @@ exports[`Respond To RAI CMS Email Snapshot Test > renders a Waiver Capitated Pre OneMAC Logo diff --git a/lib/libs/email/preview/Respond to Rai/State/__snapshots__/ResToRaiState.test.tsx.snap b/lib/libs/email/preview/Respond to Rai/State/__snapshots__/ResToRaiState.test.tsx.snap index 22ab79cb12..a3220ba431 100644 --- a/lib/libs/email/preview/Respond to Rai/State/__snapshots__/ResToRaiState.test.tsx.snap +++ b/lib/libs/email/preview/Respond to Rai/State/__snapshots__/ResToRaiState.test.tsx.snap @@ -63,7 +63,7 @@ exports[`Respond To Rai State Email Snapshot Test > renders a AppKStateEmailPrev OneMAC Logo @@ -523,7 +523,7 @@ exports[`Respond To Rai State Email Snapshot Test > renders a AppKStateEmailPrev OneMAC Logo @@ -1040,7 +1040,7 @@ exports[`Respond To Rai State Email Snapshot Test > renders a ChipSPA Preview Te OneMAC Logo @@ -1499,7 +1499,7 @@ exports[`Respond To Rai State Email Snapshot Test > renders a ChipSPA Preview Te OneMAC Logo @@ -1880,7 +1880,7 @@ exports[`Respond To Rai State Email Snapshot Test > renders a ChipSPA Preview Te OneMAC Logo @@ -2318,7 +2318,7 @@ exports[`Respond To Rai State Email Snapshot Test > renders a Medicaid_SPA Previ OneMAC Logo @@ -2777,7 +2777,7 @@ exports[`Respond To Rai State Email Snapshot Test > renders a Medicaid_SPA Previ OneMAC Logo @@ -3157,7 +3157,7 @@ exports[`Respond To Rai State Email Snapshot Test > renders a Medicaid_SPA Previ OneMAC Logo @@ -3547,7 +3547,7 @@ exports[`Respond To Rai State Email Snapshot Test > renders a Medicaid_SPA Previ OneMAC Logo @@ -3994,7 +3994,7 @@ exports[`Respond To Rai State Email Snapshot Test > renders a Waiver Capitated P OneMAC Logo @@ -4453,7 +4453,7 @@ exports[`Respond To Rai State Email Snapshot Test > renders a Waiver Capitated P OneMAC Logo @@ -4833,7 +4833,7 @@ exports[`Respond To Rai State Email Snapshot Test > renders a Waiver Capitated P OneMAC Logo @@ -5222,7 +5222,7 @@ exports[`Respond To Rai State Email Snapshot Test > renders a Waiver Capitated P OneMAC Logo @@ -5682,7 +5682,7 @@ exports[`Respond To Rai State Email Snapshot Test > renders a Waiver Capitated P OneMAC Logo diff --git a/lib/libs/email/preview/Upload Subsequent Documents/CMS/__snapshots__/UpSubDocCMS.test.tsx.snap b/lib/libs/email/preview/Upload Subsequent Documents/CMS/__snapshots__/UpSubDocCMS.test.tsx.snap index 06908c7d32..0c148148e6 100644 --- a/lib/libs/email/preview/Upload Subsequent Documents/CMS/__snapshots__/UpSubDocCMS.test.tsx.snap +++ b/lib/libs/email/preview/Upload Subsequent Documents/CMS/__snapshots__/UpSubDocCMS.test.tsx.snap @@ -63,7 +63,7 @@ exports[`Upload Subsequent Document CMS Email Snapshot Test > renders a AppKCMSE OneMAC Logo @@ -454,7 +454,7 @@ exports[`Upload Subsequent Document CMS Email Snapshot Test > renders a AppKCMSE OneMAC Logo @@ -902,7 +902,7 @@ exports[`Upload Subsequent Document CMS Email Snapshot Test > renders a ChipSPA OneMAC Logo @@ -1292,7 +1292,7 @@ exports[`Upload Subsequent Document CMS Email Snapshot Test > renders a ChipSPA OneMAC Logo @@ -1913,7 +1913,7 @@ exports[`Upload Subsequent Document CMS Email Snapshot Test > renders a ChipSPA OneMAC Logo @@ -2591,7 +2591,7 @@ exports[`Upload Subsequent Document CMS Email Snapshot Test > renders a Medicaid OneMAC Logo @@ -2981,7 +2981,7 @@ exports[`Upload Subsequent Document CMS Email Snapshot Test > renders a Medicaid OneMAC Logo @@ -3601,7 +3601,7 @@ exports[`Upload Subsequent Document CMS Email Snapshot Test > renders a Medicaid OneMAC Logo @@ -4222,7 +4222,7 @@ exports[`Upload Subsequent Document CMS Email Snapshot Test > renders a Medicaid OneMAC Logo @@ -4900,7 +4900,7 @@ exports[`Upload Subsequent Document CMS Email Snapshot Test > renders a Waiver C OneMAC Logo @@ -5290,7 +5290,7 @@ exports[`Upload Subsequent Document CMS Email Snapshot Test > renders a Waiver C OneMAC Logo @@ -5910,7 +5910,7 @@ exports[`Upload Subsequent Document CMS Email Snapshot Test > renders a Waiver C OneMAC Logo @@ -6530,7 +6530,7 @@ exports[`Upload Subsequent Document CMS Email Snapshot Test > renders a Waiver C OneMAC Logo @@ -7151,7 +7151,7 @@ exports[`Upload Subsequent Document CMS Email Snapshot Test > renders a Waiver C OneMAC Logo diff --git a/lib/libs/email/preview/Upload Subsequent Documents/State/__snapshots__/UpSubDocState.test.tsx.snap b/lib/libs/email/preview/Upload Subsequent Documents/State/__snapshots__/UpSubDocState.test.tsx.snap index 84f22167d1..85f479a589 100644 --- a/lib/libs/email/preview/Upload Subsequent Documents/State/__snapshots__/UpSubDocState.test.tsx.snap +++ b/lib/libs/email/preview/Upload Subsequent Documents/State/__snapshots__/UpSubDocState.test.tsx.snap @@ -63,7 +63,7 @@ exports[`Upload Subsequent Document CMS Email Snapshot Test > renders a AppKCMSE OneMAC Logo @@ -498,7 +498,7 @@ exports[`Upload Subsequent Document CMS Email Snapshot Test > renders a AppKCMSE OneMAC Logo @@ -990,7 +990,7 @@ exports[`Upload Subsequent Document CMS Email Snapshot Test > renders a ChipSPA OneMAC Logo @@ -1424,7 +1424,7 @@ exports[`Upload Subsequent Document CMS Email Snapshot Test > renders a ChipSPA OneMAC Logo @@ -2089,7 +2089,7 @@ exports[`Upload Subsequent Document CMS Email Snapshot Test > renders a ChipSPA OneMAC Logo @@ -2811,7 +2811,7 @@ exports[`Upload Subsequent Document CMS Email Snapshot Test > renders a Medicaid OneMAC Logo @@ -3245,7 +3245,7 @@ exports[`Upload Subsequent Document CMS Email Snapshot Test > renders a Medicaid OneMAC Logo @@ -3909,7 +3909,7 @@ exports[`Upload Subsequent Document CMS Email Snapshot Test > renders a Medicaid OneMAC Logo @@ -4571,7 +4571,7 @@ exports[`Upload Subsequent Document CMS Email Snapshot Test > renders a Medicaid OneMAC Logo @@ -5290,7 +5290,7 @@ exports[`Upload Subsequent Document CMS Email Snapshot Test > renders a Waiver C OneMAC Logo @@ -5724,7 +5724,7 @@ exports[`Upload Subsequent Document CMS Email Snapshot Test > renders a Waiver C OneMAC Logo @@ -6388,7 +6388,7 @@ exports[`Upload Subsequent Document CMS Email Snapshot Test > renders a Waiver C OneMAC Logo @@ -7049,7 +7049,7 @@ exports[`Upload Subsequent Document CMS Email Snapshot Test > renders a Waiver C OneMAC Logo @@ -7714,7 +7714,7 @@ exports[`Upload Subsequent Document CMS Email Snapshot Test > renders a Waiver C OneMAC Logo diff --git a/lib/libs/email/preview/Withdraw Package/CMS/__snapshots__/WithdrawPackageCMS.test.tsx.snap b/lib/libs/email/preview/Withdraw Package/CMS/__snapshots__/WithdrawPackageCMS.test.tsx.snap index a4af943300..24318dfa80 100644 --- a/lib/libs/email/preview/Withdraw Package/CMS/__snapshots__/WithdrawPackageCMS.test.tsx.snap +++ b/lib/libs/email/preview/Withdraw Package/CMS/__snapshots__/WithdrawPackageCMS.test.tsx.snap @@ -63,7 +63,7 @@ exports[`Withdraw Package CMS Email Snapshot Test > renders a Appk Preview Templ OneMAC Logo @@ -398,7 +398,7 @@ exports[`Withdraw Package CMS Email Snapshot Test > renders a Appk Preview Templ OneMAC Logo @@ -790,7 +790,7 @@ exports[`Withdraw Package CMS Email Snapshot Test > renders a ChipSPA Preview Te OneMAC Logo @@ -1124,7 +1124,7 @@ exports[`Withdraw Package CMS Email Snapshot Test > renders a ChipSPA Preview Te OneMAC Logo @@ -1462,7 +1462,7 @@ exports[`Withdraw Package CMS Email Snapshot Test > renders a ChipSPA Preview Te OneMAC Logo @@ -1857,7 +1857,7 @@ exports[`Withdraw Package CMS Email Snapshot Test > renders a Medicaid_SPA Previ OneMAC Logo @@ -2191,7 +2191,7 @@ exports[`Withdraw Package CMS Email Snapshot Test > renders a Medicaid_SPA Previ OneMAC Logo @@ -2528,7 +2528,7 @@ exports[`Withdraw Package CMS Email Snapshot Test > renders a Medicaid_SPA Previ OneMAC Logo @@ -2866,7 +2866,7 @@ exports[`Withdraw Package CMS Email Snapshot Test > renders a Medicaid_SPA Previ OneMAC Logo @@ -3261,7 +3261,7 @@ exports[`Withdraw Package CMS Email Snapshot Test > renders a Waiver Capitated P OneMAC Logo @@ -3595,7 +3595,7 @@ exports[`Withdraw Package CMS Email Snapshot Test > renders a Waiver Capitated P OneMAC Logo @@ -3932,7 +3932,7 @@ exports[`Withdraw Package CMS Email Snapshot Test > renders a Waiver Capitated P OneMAC Logo @@ -4269,7 +4269,7 @@ exports[`Withdraw Package CMS Email Snapshot Test > renders a Waiver Capitated P OneMAC Logo @@ -4604,7 +4604,7 @@ exports[`Withdraw Package CMS Email Snapshot Test > renders a Waiver Capitated P OneMAC Logo diff --git a/lib/libs/email/preview/Withdraw Package/State/__snapshots__/WithdrawPackageState.test.tsx.snap b/lib/libs/email/preview/Withdraw Package/State/__snapshots__/WithdrawPackageState.test.tsx.snap index af6c97956e..fba5d287a2 100644 --- a/lib/libs/email/preview/Withdraw Package/State/__snapshots__/WithdrawPackageState.test.tsx.snap +++ b/lib/libs/email/preview/Withdraw Package/State/__snapshots__/WithdrawPackageState.test.tsx.snap @@ -63,7 +63,7 @@ exports[`Withdraw Package State Email Snapshot Test > renders a Appk Preview Tem OneMAC Logo @@ -439,7 +439,7 @@ exports[`Withdraw Package State Email Snapshot Test > renders a Appk Preview Tem OneMAC Logo @@ -872,7 +872,7 @@ exports[`Withdraw Package State Email Snapshot Test > renders a ChipSPA Preview OneMAC Logo @@ -1247,7 +1247,7 @@ exports[`Withdraw Package State Email Snapshot Test > renders a ChipSPA Preview OneMAC Logo @@ -1617,7 +1617,7 @@ exports[`Withdraw Package State Email Snapshot Test > renders a ChipSPA Preview OneMAC Logo @@ -2044,7 +2044,7 @@ exports[`Withdraw Package State Email Snapshot Test > renders a Medicaid_SPA Pre OneMAC Logo @@ -2419,7 +2419,7 @@ exports[`Withdraw Package State Email Snapshot Test > renders a Medicaid_SPA Pre OneMAC Logo @@ -2788,7 +2788,7 @@ exports[`Withdraw Package State Email Snapshot Test > renders a Medicaid_SPA Pre OneMAC Logo @@ -3158,7 +3158,7 @@ exports[`Withdraw Package State Email Snapshot Test > renders a Medicaid_SPA Pre OneMAC Logo @@ -3585,7 +3585,7 @@ exports[`Withdraw Package State Email Snapshot Test > renders a Waiver Capitated OneMAC Logo @@ -3960,7 +3960,7 @@ exports[`Withdraw Package State Email Snapshot Test > renders a Waiver Capitated OneMAC Logo @@ -4329,7 +4329,7 @@ exports[`Withdraw Package State Email Snapshot Test > renders a Waiver Capitated OneMAC Logo @@ -4698,7 +4698,7 @@ exports[`Withdraw Package State Email Snapshot Test > renders a Waiver Capitated OneMAC Logo @@ -5074,7 +5074,7 @@ exports[`Withdraw Package State Email Snapshot Test > renders a Waiver Capitated OneMAC Logo diff --git a/lib/libs/email/preview/Withdraw Rai/CMS/__snapshots__/WithdrwRaiCMS.test.tsx.snap b/lib/libs/email/preview/Withdraw Rai/CMS/__snapshots__/WithdrwRaiCMS.test.tsx.snap index e5da1a10c0..043b39ed70 100644 --- a/lib/libs/email/preview/Withdraw Rai/CMS/__snapshots__/WithdrwRaiCMS.test.tsx.snap +++ b/lib/libs/email/preview/Withdraw Rai/CMS/__snapshots__/WithdrwRaiCMS.test.tsx.snap @@ -63,7 +63,7 @@ exports[`Withdraw RAI CMS Email Snapshot Test > renders a Appk Preview Template OneMAC Logo @@ -666,7 +666,7 @@ exports[`Withdraw RAI CMS Email Snapshot Test > renders a Appk Preview Template OneMAC Logo @@ -1326,7 +1326,7 @@ exports[`Withdraw RAI CMS Email Snapshot Test > renders a ChipSPA Preview Templa OneMAC Logo @@ -2543,7 +2543,7 @@ exports[`Withdraw RAI CMS Email Snapshot Test > renders a Medicaid_SPA Preview T OneMAC Logo @@ -4038,7 +4038,7 @@ exports[`Withdraw RAI CMS Email Snapshot Test > renders a Waiver Capitated Previ OneMAC Logo diff --git a/lib/libs/email/preview/Withdraw Rai/State/__snapshots__/WithdrawRaiState.test.tsx.snap b/lib/libs/email/preview/Withdraw Rai/State/__snapshots__/WithdrawRaiState.test.tsx.snap index bef4a90675..bbcfe84ac3 100644 --- a/lib/libs/email/preview/Withdraw Rai/State/__snapshots__/WithdrawRaiState.test.tsx.snap +++ b/lib/libs/email/preview/Withdraw Rai/State/__snapshots__/WithdrawRaiState.test.tsx.snap @@ -63,7 +63,7 @@ exports[`Withdraw RAI State Email Snapshot Test > renders a Appk Preview Templat OneMAC Logo @@ -439,7 +439,7 @@ exports[`Withdraw RAI State Email Snapshot Test > renders a Appk Preview Templat OneMAC Logo @@ -872,7 +872,7 @@ exports[`Withdraw RAI State Email Snapshot Test > renders a ChipSPA Preview Temp OneMAC Logo @@ -1870,7 +1870,7 @@ exports[`Withdraw RAI State Email Snapshot Test > renders a Medicaid_SPA Preview OneMAC Logo @@ -3150,7 +3150,7 @@ exports[`Withdraw RAI State Email Snapshot Test > renders a Waiver Capitated Pre OneMAC Logo @@ -4089,7 +4089,7 @@ exports[`Withdraw RAI State Email Snapshot Test > renders a Waiver Capitated Pre OneMAC Logo @@ -4726,7 +4726,7 @@ exports[`Withdraw RAI State Email Snapshot Test > renders a Waiver Capitated Pre OneMAC Logo diff --git a/lib/libs/email/preview/WithdrawConfirmation/State/__snapshots__/WithdrawConfirmationState.test.tsx.snap b/lib/libs/email/preview/WithdrawConfirmation/State/__snapshots__/WithdrawConfirmationState.test.tsx.snap index 011c4e16f3..59b198dfb2 100644 --- a/lib/libs/email/preview/WithdrawConfirmation/State/__snapshots__/WithdrawConfirmationState.test.tsx.snap +++ b/lib/libs/email/preview/WithdrawConfirmation/State/__snapshots__/WithdrawConfirmationState.test.tsx.snap @@ -63,7 +63,7 @@ exports[`Withdraw Confirmation State Email Snapshot Test > renders a Appk Previe OneMAC Logo @@ -229,7 +229,7 @@ exports[`Withdraw Confirmation State Email Snapshot Test > renders a Appk Previe OneMAC Logo @@ -452,7 +452,7 @@ exports[`Withdraw Confirmation State Email Snapshot Test > renders a ChipSPA Pre OneMAC Logo @@ -617,7 +617,7 @@ exports[`Withdraw Confirmation State Email Snapshot Test > renders a ChipSPA Pre OneMAC Logo @@ -783,7 +783,7 @@ exports[`Withdraw Confirmation State Email Snapshot Test > renders a ChipSPA Pre OneMAC Logo @@ -1006,7 +1006,7 @@ exports[`Withdraw Confirmation State Email Snapshot Test > renders a Medicaid_SP OneMAC Logo @@ -1171,7 +1171,7 @@ exports[`Withdraw Confirmation State Email Snapshot Test > renders a Medicaid_SP OneMAC Logo @@ -1336,7 +1336,7 @@ exports[`Withdraw Confirmation State Email Snapshot Test > renders a Medicaid_SP OneMAC Logo @@ -1502,7 +1502,7 @@ exports[`Withdraw Confirmation State Email Snapshot Test > renders a Medicaid_SP OneMAC Logo @@ -1725,7 +1725,7 @@ exports[`Withdraw Confirmation State Email Snapshot Test > renders a Waiver Prev OneMAC Logo @@ -1890,7 +1890,7 @@ exports[`Withdraw Confirmation State Email Snapshot Test > renders a Waiver Prev OneMAC Logo @@ -2055,7 +2055,7 @@ exports[`Withdraw Confirmation State Email Snapshot Test > renders a Waiver Prev OneMAC Logo @@ -2220,7 +2220,7 @@ exports[`Withdraw Confirmation State Email Snapshot Test > renders a Waiver Prev OneMAC Logo @@ -2386,7 +2386,7 @@ exports[`Withdraw Confirmation State Email Snapshot Test > renders a Waiver Prev OneMAC Logo From 281a9dc71dd1fbbac861b0eaf7f0f52f5551515e Mon Sep 17 00:00:00 2001 From: asharonbaltazar <58940073+asharonbaltazar@users.noreply.github.com> Date: Wed, 8 Jan 2025 10:33:59 -0500 Subject: [PATCH 3/4] fix(schema): remove logic for determining next business day for `submissionDate` (#980) * fix: remove logic for determining next business day for `submissionDate` * fix: update `submissionDate` value --- lib/lambda/sinkMainProcessors.test.ts | 2 +- .../opensearch/main/transforms/app-k.ts | 16 ++++++---------- .../main/transforms/capitated-amendment.ts | 17 ++++++----------- .../main/transforms/capitated-initial.ts | 17 ++++++----------- .../main/transforms/capitated-renewal.ts | 17 ++++++----------- .../main/transforms/contracting-amendment.ts | 17 ++++++----------- .../main/transforms/contracting-initial.ts | 17 ++++++----------- .../main/transforms/contracting-renewal.ts | 17 ++++++----------- .../main/transforms/new-chip-submission.ts | 17 ++++++----------- .../main/transforms/new-medicaid-submission.ts | 17 ++++++----------- .../main/transforms/temporary-extension.ts | 17 ++++++----------- 11 files changed, 61 insertions(+), 110 deletions(-) diff --git a/lib/lambda/sinkMainProcessors.test.ts b/lib/lambda/sinkMainProcessors.test.ts index 4b289f4f07..4e4f31f5ee 100644 --- a/lib/lambda/sinkMainProcessors.test.ts +++ b/lib/lambda/sinkMainProcessors.test.ts @@ -115,7 +115,7 @@ describe("insertOneMacRecordsFromKafkaIntoMako", () => { statusDate: offsetToUtc(new Date(1732645041526)).toISOString(), proposedDate: 1732597200000, subject: null, - submissionDate: "2024-11-26T00:00:00.000Z", + submissionDate: "2024-11-26T18:17:21.526Z", submitterEmail: "george@example.com", submitterName: "George Harrison", initialIntakeNeeded: true, diff --git a/lib/packages/shared-types/opensearch/main/transforms/app-k.ts b/lib/packages/shared-types/opensearch/main/transforms/app-k.ts index f057d73e49..b5863849f7 100644 --- a/lib/packages/shared-types/opensearch/main/transforms/app-k.ts +++ b/lib/packages/shared-types/opensearch/main/transforms/app-k.ts @@ -1,34 +1,30 @@ import { events, getStatus, SEATOOL_STATUS } from "shared-types"; -import { - getNextBusinessDayTimestamp, - seaToolFriendlyTimestamp, -} from "../../../../shared-utils/seatool-date-helper"; +import { seaToolFriendlyTimestamp } from "../../../../shared-utils/seatool-date-helper"; export const transform = () => { return events["app-k"].schema.transform((data) => { const { stateStatus, cmsStatus } = getStatus(SEATOOL_STATUS.PENDING); - const timestampDate = data.timestamp ? new Date(data.timestamp) : undefined; + const timestampDate = new Date(data.timestamp); const todayEpoch = seaToolFriendlyTimestamp(timestampDate); - const nextBusinessDayEpoch = getNextBusinessDayTimestamp(timestampDate); return { title: data.title, additionalInformation: data.additionalInformation, authority: data.authority, - changedDate: timestampDate?.toISOString() || null, + changedDate: timestampDate.toISOString(), cmsStatus, description: null, id: data.id, - makoChangedDate: timestampDate?.toISOString() || null, + makoChangedDate: timestampDate.toISOString(), origin: "OneMAC", raiWithdrawEnabled: false, // Set to false for new submissions seatoolStatus: SEATOOL_STATUS.PENDING, state: data.id?.split("-")?.[0], stateStatus, - statusDate: new Date(todayEpoch).toISOString() || null, + statusDate: new Date(todayEpoch).toISOString(), proposedDate: data.proposedEffectiveDate, subject: null, - submissionDate: new Date(nextBusinessDayEpoch).toISOString() || null, + submissionDate: timestampDate.toISOString(), submitterEmail: data.submitterEmail, submitterName: data.submitterName, actionType: data.actionType, diff --git a/lib/packages/shared-types/opensearch/main/transforms/capitated-amendment.ts b/lib/packages/shared-types/opensearch/main/transforms/capitated-amendment.ts index 8e71ee3842..8b42a5adbd 100644 --- a/lib/packages/shared-types/opensearch/main/transforms/capitated-amendment.ts +++ b/lib/packages/shared-types/opensearch/main/transforms/capitated-amendment.ts @@ -1,34 +1,29 @@ import { events, getStatus, SEATOOL_STATUS } from "shared-types"; -import { - getNextBusinessDayTimestamp, - seaToolFriendlyTimestamp, -} from "../../../../shared-utils/seatool-date-helper"; +import { seaToolFriendlyTimestamp } from "../../../../shared-utils/seatool-date-helper"; export const transform = () => { - // any adhoc logic return events["capitated-amendment"].schema.transform((data) => { const { stateStatus, cmsStatus } = getStatus(SEATOOL_STATUS.PENDING); - const timestampDate = data.timestamp ? new Date(data.timestamp) : undefined; + const timestampDate = new Date(data.timestamp); const todayEpoch = seaToolFriendlyTimestamp(timestampDate); - const nextBusinessDayEpoch = getNextBusinessDayTimestamp(timestampDate); return { additionalInformation: data.additionalInformation, authority: data.authority, - changedDate: timestampDate?.toISOString() || null, + changedDate: timestampDate.toISOString(), cmsStatus, description: null, id: data.id, - makoChangedDate: timestampDate?.toISOString() || null, + makoChangedDate: timestampDate.toISOString(), origin: "OneMAC", raiWithdrawEnabled: false, // Set to false for new submissions seatoolStatus: SEATOOL_STATUS.PENDING, state: data.id?.split("-")?.[0], stateStatus, - statusDate: new Date(todayEpoch).toISOString() || null, + statusDate: new Date(todayEpoch).toISOString(), proposedDate: data.proposedEffectiveDate, // wish this was proposedEffectiveDate subject: null, - submissionDate: new Date(nextBusinessDayEpoch).toISOString() || null, + submissionDate: timestampDate.toISOString(), submitterEmail: data.submitterEmail, submitterName: data.submitterName, actionType: data.actionType, diff --git a/lib/packages/shared-types/opensearch/main/transforms/capitated-initial.ts b/lib/packages/shared-types/opensearch/main/transforms/capitated-initial.ts index 0bdf7e9f1e..38b66e7737 100644 --- a/lib/packages/shared-types/opensearch/main/transforms/capitated-initial.ts +++ b/lib/packages/shared-types/opensearch/main/transforms/capitated-initial.ts @@ -1,34 +1,29 @@ import { events, getStatus, SEATOOL_STATUS } from "shared-types"; -import { - getNextBusinessDayTimestamp, - seaToolFriendlyTimestamp, -} from "../../../../shared-utils/seatool-date-helper"; +import { seaToolFriendlyTimestamp } from "../../../../shared-utils/seatool-date-helper"; export const transform = () => { - // any adhoc logic return events["capitated-initial"].schema.transform((data) => { const { stateStatus, cmsStatus } = getStatus(SEATOOL_STATUS.PENDING); - const timestampDate = data.timestamp ? new Date(data.timestamp) : undefined; + const timestampDate = new Date(data.timestamp); const todayEpoch = seaToolFriendlyTimestamp(timestampDate); - const nextBusinessDayEpoch = getNextBusinessDayTimestamp(timestampDate); return { additionalInformation: data.additionalInformation, authority: data.authority, - changedDate: timestampDate?.toISOString() || null, + changedDate: timestampDate.toISOString(), cmsStatus, description: null, id: data.id, - makoChangedDate: timestampDate?.toISOString() || null, + makoChangedDate: timestampDate.toISOString(), origin: "OneMAC", raiWithdrawEnabled: false, // Set to false for new submissions seatoolStatus: SEATOOL_STATUS.PENDING, state: data.id?.split("-")?.[0], stateStatus, - statusDate: new Date(todayEpoch).toISOString() || null, + statusDate: new Date(todayEpoch).toISOString(), proposedDate: data.proposedEffectiveDate, // wish this was proposedEffectiveDate subject: null, - submissionDate: new Date(nextBusinessDayEpoch).toISOString() || null, + submissionDate: timestampDate.toISOString(), submitterEmail: data.submitterEmail, submitterName: data.submitterName, actionType: data.actionType, diff --git a/lib/packages/shared-types/opensearch/main/transforms/capitated-renewal.ts b/lib/packages/shared-types/opensearch/main/transforms/capitated-renewal.ts index 683db73b51..4a9b4d7fdb 100644 --- a/lib/packages/shared-types/opensearch/main/transforms/capitated-renewal.ts +++ b/lib/packages/shared-types/opensearch/main/transforms/capitated-renewal.ts @@ -1,34 +1,29 @@ import { events, getStatus, SEATOOL_STATUS } from "shared-types"; -import { - getNextBusinessDayTimestamp, - seaToolFriendlyTimestamp, -} from "../../../../shared-utils/seatool-date-helper"; +import { seaToolFriendlyTimestamp } from "../../../../shared-utils/seatool-date-helper"; export const transform = () => { - // any adhoc logic return events["capitated-renewal"].schema.transform((data) => { const { stateStatus, cmsStatus } = getStatus(SEATOOL_STATUS.PENDING); - const timestampDate = data.timestamp ? new Date(data.timestamp) : undefined; + const timestampDate = new Date(data.timestamp); const todayEpoch = seaToolFriendlyTimestamp(timestampDate); - const nextBusinessDayEpoch = getNextBusinessDayTimestamp(timestampDate); return { additionalInformation: data.additionalInformation, authority: data.authority, - changedDate: timestampDate?.toISOString() || null, + changedDate: timestampDate.toISOString(), cmsStatus, description: null, id: data.id, - makoChangedDate: timestampDate?.toISOString() || null, + makoChangedDate: timestampDate.toISOString(), origin: "OneMAC", raiWithdrawEnabled: false, // Set to false for new submissions seatoolStatus: SEATOOL_STATUS.PENDING, state: data.id?.split("-")?.[0], stateStatus, - statusDate: new Date(todayEpoch).toISOString() || null, + statusDate: new Date(todayEpoch).toISOString(), proposedDate: data.proposedEffectiveDate, // wish this was proposedEffectiveDate subject: null, - submissionDate: new Date(nextBusinessDayEpoch).toISOString() || null, + submissionDate: timestampDate.toISOString(), submitterEmail: data.submitterEmail, submitterName: data.submitterName, actionType: data.actionType, diff --git a/lib/packages/shared-types/opensearch/main/transforms/contracting-amendment.ts b/lib/packages/shared-types/opensearch/main/transforms/contracting-amendment.ts index 9305fb6daa..577f91da6a 100644 --- a/lib/packages/shared-types/opensearch/main/transforms/contracting-amendment.ts +++ b/lib/packages/shared-types/opensearch/main/transforms/contracting-amendment.ts @@ -1,34 +1,29 @@ import { events, getStatus, SEATOOL_STATUS } from "shared-types"; -import { - getNextBusinessDayTimestamp, - seaToolFriendlyTimestamp, -} from "../../../../shared-utils/seatool-date-helper"; +import { seaToolFriendlyTimestamp } from "../../../../shared-utils/seatool-date-helper"; export const transform = () => { - // any adhoc logic return events["contracting-amendment"].schema.transform((data) => { const { stateStatus, cmsStatus } = getStatus(SEATOOL_STATUS.PENDING); - const timestampDate = data.timestamp ? new Date(data.timestamp) : undefined; + const timestampDate = new Date(data.timestamp); const todayEpoch = seaToolFriendlyTimestamp(timestampDate); - const nextBusinessDayEpoch = getNextBusinessDayTimestamp(timestampDate); return { additionalInformation: data.additionalInformation, authority: data.authority, - changedDate: timestampDate?.toISOString() || null, + changedDate: timestampDate.toISOString(), cmsStatus, description: null, id: data.id, - makoChangedDate: timestampDate?.toISOString() || null, + makoChangedDate: timestampDate.toISOString(), origin: "OneMAC", raiWithdrawEnabled: false, // Set to false for new submissions seatoolStatus: SEATOOL_STATUS.PENDING, state: data.id?.split("-")?.[0], stateStatus, - statusDate: new Date(todayEpoch).toISOString() || null, + statusDate: new Date(todayEpoch).toISOString(), proposedDate: data.proposedEffectiveDate, // wish this was proposedEffectiveDate subject: null, - submissionDate: new Date(nextBusinessDayEpoch).toISOString() || null, + submissionDate: timestampDate.toISOString(), submitterEmail: data.submitterEmail, submitterName: data.submitterName, actionType: data.actionType, diff --git a/lib/packages/shared-types/opensearch/main/transforms/contracting-initial.ts b/lib/packages/shared-types/opensearch/main/transforms/contracting-initial.ts index 795732cbae..6448c395dd 100644 --- a/lib/packages/shared-types/opensearch/main/transforms/contracting-initial.ts +++ b/lib/packages/shared-types/opensearch/main/transforms/contracting-initial.ts @@ -1,34 +1,29 @@ import { events, getStatus, SEATOOL_STATUS } from "shared-types"; -import { - getNextBusinessDayTimestamp, - seaToolFriendlyTimestamp, -} from "../../../../shared-utils/seatool-date-helper"; +import { seaToolFriendlyTimestamp } from "../../../../shared-utils/seatool-date-helper"; export const transform = () => { - // any adhoc logic return events["contracting-initial"].schema.transform((data) => { const { stateStatus, cmsStatus } = getStatus(SEATOOL_STATUS.PENDING); - const timestampDate = data.timestamp ? new Date(data.timestamp) : undefined; + const timestampDate = new Date(data.timestamp); const todayEpoch = seaToolFriendlyTimestamp(timestampDate); - const nextBusinessDayEpoch = getNextBusinessDayTimestamp(timestampDate); return { additionalInformation: data.additionalInformation, authority: data.authority, - changedDate: timestampDate?.toISOString() || null, + changedDate: timestampDate.toISOString(), cmsStatus, description: null, id: data.id, - makoChangedDate: timestampDate?.toISOString() || null, + makoChangedDate: timestampDate.toISOString(), origin: "OneMAC", raiWithdrawEnabled: false, // Set to false for new submissions seatoolStatus: SEATOOL_STATUS.PENDING, state: data.id?.split("-")?.[0], stateStatus, - statusDate: new Date(todayEpoch).toISOString() || null, + statusDate: new Date(todayEpoch).toISOString(), proposedDate: data.proposedEffectiveDate, // wish this was proposedEffectiveDate subject: null, - submissionDate: new Date(nextBusinessDayEpoch).toISOString() || null, + submissionDate: timestampDate.toISOString(), submitterEmail: data.submitterEmail, submitterName: data.submitterName, actionType: data.actionType, diff --git a/lib/packages/shared-types/opensearch/main/transforms/contracting-renewal.ts b/lib/packages/shared-types/opensearch/main/transforms/contracting-renewal.ts index e3257de90f..05fb371dcc 100644 --- a/lib/packages/shared-types/opensearch/main/transforms/contracting-renewal.ts +++ b/lib/packages/shared-types/opensearch/main/transforms/contracting-renewal.ts @@ -1,34 +1,29 @@ import { events, getStatus, SEATOOL_STATUS } from "shared-types"; -import { - getNextBusinessDayTimestamp, - seaToolFriendlyTimestamp, -} from "../../../../shared-utils/seatool-date-helper"; +import { seaToolFriendlyTimestamp } from "../../../../shared-utils/seatool-date-helper"; export const transform = () => { - // any adhoc logic return events["contracting-renewal"].schema.transform((data) => { const { stateStatus, cmsStatus } = getStatus(SEATOOL_STATUS.PENDING); - const timestampDate = data.timestamp ? new Date(data.timestamp) : undefined; + const timestampDate = new Date(data.timestamp); const todayEpoch = seaToolFriendlyTimestamp(timestampDate); - const nextBusinessDayEpoch = getNextBusinessDayTimestamp(timestampDate); return { additionalInformation: data.additionalInformation, authority: data.authority, - changedDate: timestampDate?.toISOString() || null, + changedDate: timestampDate?.toISOString(), cmsStatus, description: null, id: data.id, - makoChangedDate: timestampDate?.toISOString() || null, + makoChangedDate: timestampDate?.toISOString(), origin: "OneMAC", raiWithdrawEnabled: false, // Set to false for new submissions seatoolStatus: SEATOOL_STATUS.PENDING, state: data.id?.split("-")?.[0], stateStatus, - statusDate: new Date(todayEpoch).toISOString() || null, + statusDate: new Date(todayEpoch).toISOString(), proposedDate: data.proposedEffectiveDate, // wish this was proposedEffectiveDate subject: null, - submissionDate: new Date(nextBusinessDayEpoch).toISOString() || null, + submissionDate: timestampDate.toISOString(), submitterEmail: data.submitterEmail, submitterName: data.submitterName, actionType: data.actionType, diff --git a/lib/packages/shared-types/opensearch/main/transforms/new-chip-submission.ts b/lib/packages/shared-types/opensearch/main/transforms/new-chip-submission.ts index 2e71269e91..0c3255b92d 100644 --- a/lib/packages/shared-types/opensearch/main/transforms/new-chip-submission.ts +++ b/lib/packages/shared-types/opensearch/main/transforms/new-chip-submission.ts @@ -1,34 +1,29 @@ import { events, getStatus, SEATOOL_STATUS } from "shared-types"; -import { - getNextBusinessDayTimestamp, - seaToolFriendlyTimestamp, -} from "../../../../shared-utils/seatool-date-helper"; +import { seaToolFriendlyTimestamp } from "../../../../shared-utils/seatool-date-helper"; export const transform = () => { - // any adhoc logic return events["new-chip-submission"].schema.transform((data) => { const { stateStatus, cmsStatus } = getStatus(SEATOOL_STATUS.PENDING); - const timestampDate = data.timestamp ? new Date(data.timestamp) : undefined; + const timestampDate = new Date(data.timestamp); const todayEpoch = seaToolFriendlyTimestamp(timestampDate); - const nextBusinessDayEpoch = getNextBusinessDayTimestamp(timestampDate); return { additionalInformation: data.additionalInformation, authority: data.authority, - changedDate: timestampDate?.toISOString() || null, + changedDate: timestampDate.toISOString(), cmsStatus, description: null, id: data.id, - makoChangedDate: timestampDate?.toISOString() || null, + makoChangedDate: timestampDate.toISOString(), origin: "OneMAC", raiWithdrawEnabled: false, // Set to false for new submissions seatoolStatus: SEATOOL_STATUS.PENDING, state: data.id?.split("-")?.[0], stateStatus, - statusDate: new Date(todayEpoch).toISOString() || null, + statusDate: new Date(todayEpoch).toISOString(), proposedDate: data.proposedEffectiveDate, // wish this was proposedEffectiveDate subject: null, - submissionDate: new Date(nextBusinessDayEpoch).toISOString() || null, + submissionDate: timestampDate.toISOString(), submitterEmail: data.submitterEmail, submitterName: data.submitterName, actionType: data.actionType, diff --git a/lib/packages/shared-types/opensearch/main/transforms/new-medicaid-submission.ts b/lib/packages/shared-types/opensearch/main/transforms/new-medicaid-submission.ts index bdb6d3922f..d75fcd61d1 100644 --- a/lib/packages/shared-types/opensearch/main/transforms/new-medicaid-submission.ts +++ b/lib/packages/shared-types/opensearch/main/transforms/new-medicaid-submission.ts @@ -1,34 +1,29 @@ import { events, getStatus, SEATOOL_STATUS } from "shared-types"; -import { - getNextBusinessDayTimestamp, - seaToolFriendlyTimestamp, -} from "../../../../shared-utils/seatool-date-helper"; +import { seaToolFriendlyTimestamp } from "../../../../shared-utils/seatool-date-helper"; export const transform = () => { - // any adhoc logic return events["new-medicaid-submission"].schema.transform((data) => { const { stateStatus, cmsStatus } = getStatus(SEATOOL_STATUS.PENDING); - const timestampDate = data.timestamp ? new Date(data.timestamp) : undefined; + const timestampDate = new Date(data.timestamp); const todayEpoch = seaToolFriendlyTimestamp(timestampDate); - const nextBusinessDayEpoch = getNextBusinessDayTimestamp(timestampDate); return { additionalInformation: data.additionalInformation, authority: data.authority, - changedDate: timestampDate?.toISOString() || null, + changedDate: timestampDate.toISOString(), cmsStatus, description: null, id: data.id, - makoChangedDate: timestampDate?.toISOString() || null, + makoChangedDate: timestampDate.toISOString(), origin: "OneMAC", raiWithdrawEnabled: false, // Set to false for new submissions seatoolStatus: SEATOOL_STATUS.PENDING, state: data.id?.split("-")?.[0], stateStatus, - statusDate: new Date(todayEpoch).toISOString() || null, + statusDate: new Date(todayEpoch).toISOString(), proposedDate: data.proposedEffectiveDate, // wish this was proposedEffectiveDate subject: null, - submissionDate: new Date(nextBusinessDayEpoch).toISOString() || null, + submissionDate: timestampDate.toISOString(), submitterEmail: data.submitterEmail, submitterName: data.submitterName, initialIntakeNeeded: true, diff --git a/lib/packages/shared-types/opensearch/main/transforms/temporary-extension.ts b/lib/packages/shared-types/opensearch/main/transforms/temporary-extension.ts index d252337301..4f20fb4715 100644 --- a/lib/packages/shared-types/opensearch/main/transforms/temporary-extension.ts +++ b/lib/packages/shared-types/opensearch/main/transforms/temporary-extension.ts @@ -1,33 +1,28 @@ import { events, SEATOOL_STATUS } from "shared-types"; -import { - getNextBusinessDayTimestamp, - seaToolFriendlyTimestamp, -} from "../../../../shared-utils/seatool-date-helper"; +import { seaToolFriendlyTimestamp } from "../../../../shared-utils/seatool-date-helper"; export const transform = () => { - // any adhoc logic return events["temporary-extension"].schema.transform((data) => { - const timestampDate = data.timestamp ? new Date(data.timestamp) : undefined; + const timestampDate = new Date(data.timestamp); const todayEpoch = seaToolFriendlyTimestamp(timestampDate); - const nextBusinessDayEpoch = getNextBusinessDayTimestamp(timestampDate); return { additionalInformation: data.additionalInformation, authority: data.authority, - changedDate: timestampDate?.toISOString() || null, + changedDate: timestampDate?.toISOString(), cmsStatus: "Requested", description: null, id: data.id, - makoChangedDate: timestampDate?.toISOString() || null, + makoChangedDate: timestampDate?.toISOString(), origin: "OneMAC", originalWaiverNumber: data.waiverNumber, raiWithdrawEnabled: false, // Set to false for new submissions seatoolStatus: SEATOOL_STATUS.PENDING, state: data.id?.split("-")?.[0], stateStatus: "Submitted", - statusDate: new Date(todayEpoch).toISOString() || null, + statusDate: new Date(todayEpoch).toISOString(), subject: null, - submissionDate: new Date(nextBusinessDayEpoch).toISOString() || null, + submissionDate: timestampDate.toISOString(), submitterEmail: data.submitterEmail, submitterName: data.submitterName, actionType: data.actionType, From 02ca4c5f7019ec0ba02c8183d4a06facfa097c5a Mon Sep 17 00:00:00 2001 From: Ty Bolt Date: Wed, 8 Jan 2025 11:02:50 -0500 Subject: [PATCH 4/4] feat(ui): Remove status date from package details pages for all users (#965) --- react-app/src/features/package/package-details/hooks.tsx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/react-app/src/features/package/package-details/hooks.tsx b/react-app/src/features/package/package-details/hooks.tsx index 247f7d9fe3..15fadab519 100644 --- a/react-app/src/features/package/package-details/hooks.tsx +++ b/react-app/src/features/package/package-details/hooks.tsx @@ -1,4 +1,4 @@ -import { isCmsUser, isStateUser, formatSeatoolDate } from "shared-utils"; +import { formatSeatoolDate, isCmsUser, isStateUser } from "shared-utils"; import { OneMacUser } from "@/api/useGetUser"; import { BLANK_VALUE } from "@/consts"; @@ -122,11 +122,6 @@ export const recordDetails = (data: opensearch.main.Document): DetailSectionItem return !(data.actionType === "Extend"); }, }, - { - label: "Status Date", - value: data.statusDate ? formatSeatoolDate(data.statusDate) : BLANK_VALUE, - canView: (u) => (!u || !u.user ? false : isCmsUser(u.user)), - }, ]; export const approvedAndAEffectiveDetails = (