Skip to content

Commit

Permalink
test → val (28 October 2024) (#11899)
Browse files Browse the repository at this point in the history
  • Loading branch information
karla-vm authored Oct 29, 2024
2 parents c4e2d64 + 26e7fb4 commit d5836dc
Show file tree
Hide file tree
Showing 100 changed files with 10,785 additions and 5,574 deletions.
5 changes: 2 additions & 3 deletions .github/workflows/scan_security-hub-jira-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,12 @@ jobs:
aws-region: ${{ secrets.AWS_DEFAULT_REGION }}
role-to-assume: ${{ secrets.PRODUCTION_SYNC_OIDC_ROLE }}
- name: Sync Security Hub and Jira
uses: Enterprise-CMCS/mac-fc-security-hub-visibility@v1.0.7
uses: Enterprise-CMCS/mac-fc-security-hub-visibility@v2.0.9
with:
jira-username: "mdct_github_service_account"
jira-token: ${{ secrets.JIRA_ENT_USER_TOKEN }}
jira-host: jiraent.cms.gov
jira-project-key: CMDCT
jira-ignore-statuses: Done, Closed, Canceled
jira-custom-fields: '{ "customfield_10100": "CMDCT-2280", "customfield_26700" : [{"id": "40104", "value": "MCR"}] }'
aws-severities: CRITICAL, HIGH, MEDIUM
assign-jira-ticket-to: "MWTW"
jira-assignee: "MWTW"
502 changes: 446 additions & 56 deletions services/app-api/forms/mcpar.json

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions services/app-api/forms/mlr.json
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@
},
{
"type": "externalLink",
"content": "\"Managed Care Enrollment by Program and Plan\"",
"content": "Managed Care Enrollment by Program and Plan",
"props": {
"href": "https://www.medicaid.gov/medicaid/managed-care/enrollment-report/index.html",
"target": "_blank",
Expand Down Expand Up @@ -287,7 +287,7 @@
"hint": [
{
"type": "p",
"content": "Enter the eligibility group for this MLR report. Most states provide MLR reports for all populations. In this case, select \"All Populations.\" If the state is providing additional detail for specific eligibility groups, see below for instructions related to each group."
"content": "Enter the eligibility group for this MLR report. Most states provide MLR reports for all populations. In this case, select All Populations”. If the state is providing additional detail for specific eligibility groups, see below for instructions related to each group."
},
{
"type": "ol",
Expand All @@ -305,7 +305,7 @@
"children": [
{
"type": "html",
"content": "<i>For separate CHIP reporting:</i> States that intend to report MLRs for separate CHIP-only programs should select \"Standalone CHIP\". These separate child health assistance programs are defined in "
"content": "<i>For separate CHIP reporting:</i> States that intend to report MLRs for separate CHIP-only programs should select Standalone CHIP. These separate child health assistance programs are defined in "
},
{
"type": "externalLink",
Expand All @@ -330,7 +330,7 @@
"children": [
{
"type": "p",
"content": "<i>For SUPPORT Act reporting:</i> States that intend to qualify for the SUPPORT Act Section 4001 MLR provision must provide an MLR for the eligibility group described in section 1902(a)(10)(A)(i)(VIII) (referred to here as \"the Expansion Group\"). Select \"Group VIII Expansion Adult Only\"."
"content": "<i>For SUPPORT Act reporting:</i> States that intend to qualify for the SUPPORT Act Section 4001 MLR provision must provide an MLR for the eligibility group described in section 1902(a)(10)(A)(i)(VIII) (referred to here as the Expansion Group). Select Group VIII Expansion Adult Only."
}
]
},
Expand All @@ -344,7 +344,7 @@
"children": [
{
"type": "p",
"content": "For States that intend to report separate MLRs for elibility groups that are served under the same program, select \"Other, specify\"."
"content": "For States that intend to report separate MLRs for elibility groups that are served under the same program, select Other, specify."
}
]
}
Expand Down
36 changes: 23 additions & 13 deletions services/app-api/handlers/banners/create.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@ import { createBanner } from "./create";
import { DynamoDBDocumentClient, PutCommand } from "@aws-sdk/lib-dynamodb";
import { mockClient } from "aws-sdk-client-mock";
// types
import { APIGatewayProxyEvent, StatusCodes } from "../../utils/types";
import { APIGatewayProxyEvent } from "../../utils/types";
// utils
import { error } from "../../utils/constants/constants";
import { proxyEvent } from "../../utils/testing/proxyEvent";
import { StatusCodes } from "../../utils/responses/response-lib";
import { hasPermissions } from "../../utils/auth/authorization";

const dynamoClientMock = mockClient(DynamoDBDocumentClient);

jest.mock("../../utils/auth/authorization", () => ({
isAuthorized: jest.fn().mockReturnValue(true),
hasPermissions: jest.fn().mockReturnValueOnce(false).mockReturnValue(true),
isAuthenticated: jest.fn().mockReturnValue(true),
hasPermissions: jest.fn().mockReturnValue(true),
}));

const testEvent: APIGatewayProxyEvent = {
Expand All @@ -37,10 +39,14 @@ const consoleSpy: {
};

describe("Test createBanner API method", () => {
beforeEach(() => {
dynamoClientMock.reset();
});
test("Test unauthorized banner creation throws 403 error", async () => {
(hasPermissions as jest.Mock).mockReturnValueOnce(false);
const res = await createBanner(testEvent, null);
expect(consoleSpy.debug).toHaveBeenCalled();
expect(res.statusCode).toBe(403);
expect(res.statusCode).toBe(StatusCodes.Forbidden);
expect(res.body).toContain(error.UNAUTHORIZED);
});

Expand All @@ -49,37 +55,41 @@ describe("Test createBanner API method", () => {
dynamoClientMock.on(PutCommand).callsFake(mockPut);
const res = await createBanner(testEvent, null);
expect(consoleSpy.debug).toHaveBeenCalled();
expect(res.statusCode).toBe(StatusCodes.CREATED);
expect(res.statusCode).toBe(StatusCodes.Created);
expect(res.body).toContain("test banner");
expect(res.body).toContain("test description");
expect(mockPut).toHaveBeenCalled();
});

test("Test dynamo issue throws error", async () => {
dynamoClientMock.on(PutCommand).rejectsOnce("error with dynamo");
const res = await createBanner(testEvent, null);
expect(res.statusCode).toBe(StatusCodes.InternalServerError);
expect(res.body).toContain(error.DYNAMO_CREATION_ERROR);
});

test("Test invalid data causes failure", async () => {
const res = await createBanner(testEventWithInvalidData, null);
expect(consoleSpy.error).toHaveBeenCalled();
expect(res.statusCode).toBe(StatusCodes.SERVER_ERROR);
expect(res.statusCode).toBe(StatusCodes.BadRequest);
});

test("Test bannerKey not provided throws 500 error", async () => {
test("Test bannerKey not provided throws 400 error", async () => {
const noKeyEvent: APIGatewayProxyEvent = {
...testEvent,
pathParameters: {},
};
const res = await createBanner(noKeyEvent, null);
expect(consoleSpy.error).toHaveBeenCalled();
expect(res.statusCode).toBe(500);
expect(res.statusCode).toBe(StatusCodes.BadRequest);
expect(res.body).toContain(error.NO_KEY);
});

test("Test bannerKey empty throws 500 error", async () => {
test("Test bannerKey empty throws 400 error", async () => {
const noKeyEvent: APIGatewayProxyEvent = {
...testEvent,
pathParameters: { bannerId: "" },
};
const res = await createBanner(noKeyEvent, null);
expect(consoleSpy.error).toHaveBeenCalled();
expect(res.statusCode).toBe(500);
expect(res.statusCode).toBe(StatusCodes.BadRequest);
expect(res.body).toContain(error.NO_KEY);
});
});
88 changes: 49 additions & 39 deletions services/app-api/handlers/banners/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,51 +5,61 @@ import dynamoDb from "../../utils/dynamo/dynamodb-lib";
import { hasPermissions } from "../../utils/auth/authorization";
import { validateData } from "../../utils/validation/validation";
import { error } from "../../utils/constants/constants";
import {
badRequest,
created,
forbidden,
internalServerError,
} from "../../utils/responses/response-lib";
// types
import { StatusCodes, UserRoles } from "../../utils/types";
import { UserRoles } from "../../utils/types";

const validationSchema = yup.object().shape({
key: yup.string().required(),
title: yup.string().required(),
description: yup.string().required(),
link: yup.string().url().notRequired(),
startDate: yup.number().required(),
endDate: yup.number().required(),
});

export const createBanner = handler(async (event, _context) => {
if (!hasPermissions(event, [UserRoles.ADMIN])) {
return {
status: StatusCodes.UNAUTHORIZED,
body: error.UNAUTHORIZED,
};
} else if (!event?.pathParameters?.bannerId!) {
throw new Error(error.NO_KEY);
} else {
const unvalidatedPayload = JSON.parse(event!.body!);
return forbidden(error.UNAUTHORIZED);
}
if (!event?.pathParameters?.bannerId!) {
return badRequest(error.NO_KEY);
}
const unvalidatedPayload = JSON.parse(event.body!);

const validationSchema = yup.object().shape({
key: yup.string().required(),
title: yup.string().required(),
description: yup.string().required(),
link: yup.string().url().notRequired(),
startDate: yup.number().required(),
endDate: yup.number().required(),
});
let validatedPayload;
try {
validatedPayload = await validateData(validationSchema, unvalidatedPayload);
} catch {
return badRequest(error.INVALID_DATA);
}

const validatedPayload = await validateData(
validationSchema,
unvalidatedPayload
);
const { title, description, link, startDate, endDate } = validatedPayload;
const currentTime = Date.now();

if (validatedPayload) {
const params = {
TableName: process.env.BANNER_TABLE_NAME!,
Item: {
key: event.pathParameters.bannerId,
createdAt: Date.now(),
lastAltered: Date.now(),
lastAlteredBy: event?.headers["cognito-identity-id"],
title: validatedPayload.title,
description: validatedPayload.description,
link: validatedPayload.link,
startDate: validatedPayload.startDate,
endDate: validatedPayload.endDate,
},
};
await dynamoDb.put(params);
return { status: StatusCodes.CREATED, body: params };
}
const params = {
TableName: process.env.BANNER_TABLE_NAME!,
Item: {
key: event.pathParameters.bannerId,
createdAt: currentTime,
lastAltered: currentTime,
lastAlteredBy: event?.headers["cognito-identity-id"],
title,
description,
link,
startDate,
endDate,
},
};
try {
await dynamoDb.put(params);
} catch {
return internalServerError(error.DYNAMO_CREATION_ERROR);
}
return created(params);
});
24 changes: 12 additions & 12 deletions services/app-api/handlers/banners/delete.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ import { mockClient } from "aws-sdk-client-mock";
// utils
import { proxyEvent } from "../../utils/testing/proxyEvent";
import { error } from "../../utils/constants/constants";
import { hasPermissions } from "../../utils/auth/authorization";
// types
import { APIGatewayProxyEvent, StatusCodes } from "../../utils/types";
import { APIGatewayProxyEvent } from "../../utils/types";
import { StatusCodes } from "../../utils/responses/response-lib";

const dynamoClientMock = mockClient(DynamoDBDocumentClient);

jest.mock("../../utils/auth/authorization", () => ({
isAuthorized: jest.fn().mockReturnValue(true),
hasPermissions: jest.fn().mockReturnValueOnce(false).mockReturnValue(true),
isAuthenticated: jest.fn().mockReturnValue(true),
hasPermissions: jest.fn().mockReturnValue(true),
}));

const testEvent: APIGatewayProxyEvent = {
Expand All @@ -30,10 +32,11 @@ const consoleSpy: {

describe("Test deleteBanner API method", () => {
test("Test not authorized to delete banner throws 403 error", async () => {
(hasPermissions as jest.Mock).mockReturnValueOnce(false);
const res = await deleteBanner(testEvent, null);

expect(consoleSpy.debug).toHaveBeenCalled();
expect(res.statusCode).toBe(403);
expect(res.statusCode).toBe(StatusCodes.Forbidden);
expect(res.body).toContain(error.UNAUTHORIZED);
});

Expand All @@ -43,32 +46,29 @@ describe("Test deleteBanner API method", () => {
const res = await deleteBanner(testEvent, null);

expect(consoleSpy.debug).toHaveBeenCalled();
expect(res.statusCode).toBe(StatusCodes.SUCCESS);
expect(res.body).toContain("testKey");
expect(res.statusCode).toBe(StatusCodes.Ok);
expect(mockDelete).toHaveBeenCalled();
});

test("Test bannerKey not provided throws 500 error", async () => {
test("Test bannerKey not provided throws 400 error", async () => {
const noKeyEvent: APIGatewayProxyEvent = {
...testEvent,
pathParameters: {},
};
const res = await deleteBanner(noKeyEvent, null);

expect(consoleSpy.error).toHaveBeenCalled();
expect(res.statusCode).toBe(500);
expect(res.statusCode).toBe(StatusCodes.BadRequest);
expect(res.body).toContain(error.NO_KEY);
});

test("Test bannerKey empty throws 500 error", async () => {
test("Test bannerKey empty throws 400 error", async () => {
const noKeyEvent: APIGatewayProxyEvent = {
...testEvent,
pathParameters: { bannerId: "" },
};
const res = await deleteBanner(noKeyEvent, null);

expect(consoleSpy.error).toHaveBeenCalled();
expect(res.statusCode).toBe(500);
expect(res.statusCode).toBe(StatusCodes.BadRequest);
expect(res.body).toContain(error.NO_KEY);
});
});
30 changes: 14 additions & 16 deletions services/app-api/handlers/banners/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,23 @@ import handler from "../handler-lib";
import dynamoDb from "../../utils/dynamo/dynamodb-lib";
import { hasPermissions } from "../../utils/auth/authorization";
import { error } from "../../utils/constants/constants";
import { badRequest, forbidden, ok } from "../../utils/responses/response-lib";
// types
import { StatusCodes, UserRoles } from "../../utils/types";
import { UserRoles } from "../../utils/types";

export const deleteBanner = handler(async (event, _context) => {
if (!hasPermissions(event, [UserRoles.ADMIN])) {
return {
status: StatusCodes.UNAUTHORIZED,
body: error.UNAUTHORIZED,
};
} else if (!event?.pathParameters?.bannerId!) {
throw new Error(error.NO_KEY);
} else {
const params = {
TableName: process.env.BANNER_TABLE_NAME!,
Key: {
key: event?.pathParameters?.bannerId!,
},
};
await dynamoDb.delete(params);
return { status: StatusCodes.SUCCESS, body: params };
return forbidden(error.UNAUTHORIZED);
}
if (!event?.pathParameters?.bannerId!) {
return badRequest(error.NO_KEY);
}
const params = {
TableName: process.env.BANNER_TABLE_NAME!,
Key: {
key: event.pathParameters.bannerId,
},
};
await dynamoDb.delete(params);
return ok();
});
Loading

0 comments on commit d5836dc

Please sign in to comment.