diff --git a/src/helpers/task-deadline.ts b/src/helpers/task-deadline.ts index c7449af..7a01c9e 100644 --- a/src/helpers/task-deadline.ts +++ b/src/helpers/task-deadline.ts @@ -2,6 +2,7 @@ import { DateTime } from "luxon"; import { Context } from "../types/context"; import { ListIssueForRepo } from "../types/github-types"; import { getAssigneesActivityForIssue } from "./get-assignee-activity"; +import { TimelineEvents } from "../types/plugin-inputs"; /** * Retrieves the deadline with the threshold for the issue. @@ -52,7 +53,7 @@ export async function getDeadlineWithThreshold( if (!o.event) { return false; } - return eventWhitelist.includes(o.event); + return eventWhitelist.includes(o.event as TimelineEvents); }); // adding the buffer onto the already established issueStart + timeLabelDuration diff --git a/src/types/plugin-inputs.ts b/src/types/plugin-inputs.ts index 85c35a4..1c78ac5 100644 --- a/src/types/plugin-inputs.ts +++ b/src/types/plugin-inputs.ts @@ -37,12 +37,18 @@ const eventWhitelist = [ "pull_request_review_comment.created", "issue_comment.created", "push", -] +]; -type WhitelistEvents = typeof eventWhitelist[number]; -type TimelineEvents = "review_requested" | "ready_for_review" | "commented" | "committed"; +type WhitelistEvents = + | "push" + | "pull_request.review_requested" + | "pull_request.ready_for_review" + | "pull_request_review_comment.created" + | "issue_comment.created"; -function mapWebhookToEvent(webhook: string) { +export type TimelineEvents = "review_requested" | "ready_for_review" | "commented" | "committed"; + +function mapWebhookToEvent(webhook: WhitelistEvents) { const roleMap: Map = new Map([ ["pull_request.review_requested", "review_requested"], ["pull_request.ready_for_review", "ready_for_review"], @@ -76,30 +82,41 @@ export const userActivityWatcherSettingsSchema = T.Object( /** * List of events to consider as valid activity on a task */ - eventWhitelist: T.Transform(T.Array(T.String(), { default: eventWhitelist })).Decode((value) => { - const validEvents = Object.values(eventWhitelist); - let eventsStripped = [] - for (const event of value) { - if (!validEvents.includes(event)) { - throw new TypeBoxError(`Invalid event [${event}]`); - } + eventWhitelist: T.Transform(T.Array(T.String(), { default: eventWhitelist })) + .Decode((value) => { + const validEvents = Object.values(eventWhitelist); + let eventsStripped: TimelineEvents[] = []; + for (const event of value) { + if (!validEvents.includes(event)) { + throw new TypeBoxError(`Invalid event [${event}]`); + } - eventsStripped.push(mapWebhookToEvent(event)); - } + const mappedEvent = mapWebhookToEvent(event as WhitelistEvents); - return eventsStripped as TimelineEvents[]; - }) - .Encode((value) => value.map((event) => { - const roleMap: Map = new Map([ - ["review_requested", "pull_request.review_requested"], - ["ready_for_review", "pull_request.ready_for_review"], - ["commented", "pull_request_review_comment.created"], - ["commented", "issue_comment.created"], - ["committed", "push"], - ]); + if (!mappedEvent) { + throw new TypeBoxError(`Invalid event [${event}]`); + } + + if (!eventsStripped.includes(mappedEvent)) { + eventsStripped.push(mappedEvent); + } + } + + return eventsStripped as TimelineEvents[]; + }) + .Encode((value) => + value.map((event) => { + const roleMap: Map = new Map([ + ["review_requested", "pull_request.review_requested"], + ["ready_for_review", "pull_request.ready_for_review"], + ["commented", "pull_request_review_comment.created"], + ["commented", "issue_comment.created"], + ["committed", "push"], + ]); - return roleMap.get(event as TimelineEvents) as WhitelistEvents; - })), + return roleMap.get(event as TimelineEvents) as WhitelistEvents; + }) + ), }, { default: {} } ); diff --git a/tests/__mocks__/results/valid-configuration.json b/tests/__mocks__/results/valid-configuration.json index 8d2cf8c..b094dc1 100644 --- a/tests/__mocks__/results/valid-configuration.json +++ b/tests/__mocks__/results/valid-configuration.json @@ -4,5 +4,5 @@ "watch": { "optOut": ["private-repo"] }, - "eventWhitelist": ["review_requested", "ready_for_review", "commented", "committed"] + "eventWhitelist": ["pull_request.review_requested", "pull_request.ready_for_review", "pull_request_review_comment.created", "issue_comment.created", "push"] } diff --git a/tests/main.test.ts b/tests/main.test.ts index 77b018c..841e4d3 100644 --- a/tests/main.test.ts +++ b/tests/main.test.ts @@ -14,6 +14,7 @@ import { botAssignmentComment, getIssueHtmlUrl, STRINGS } from "./__mocks__/stri import { createComment, createEvent, createIssue, createRepo, ONE_DAY } from "./__mocks__/helpers"; import { collectLinkedPullRequests } from "../src/handlers/collect-linked-pulls"; import ms from "ms"; +import { TypeBoxError } from "@sinclair/typebox"; dotenv.config(); const octokit = jest.requireActual("@octokit/rest"); @@ -31,7 +32,19 @@ describe("User start/stop", () => { beforeEach(async () => { await setupTests(); }); - + it("should throw an error if the whitelist events are incorrect", () => { + expect(() => + Value.Decode( + userActivityWatcherSettingsSchema, + Value.Default(userActivityWatcherSettingsSchema, { + warning: "12 days", + disqualification: "2 days", + watch: { optOut: [STRINGS.PRIVATE_REPO_NAME] }, + eventWhitelist: ["review_requested", "ready_for_review", "commented", "committed"], + }) + ) + ).toThrow(TypeBoxError); + }); it("Should parse thresholds", async () => { const settings = Value.Decode(userActivityWatcherSettingsSchema, Value.Default(userActivityWatcherSettingsSchema, cfg)); expect(settings).toEqual({ @@ -47,11 +60,26 @@ describe("User start/stop", () => { warning: "12 foobars", disqualification: "2 days", watch: { optOut: [STRINGS.PRIVATE_REPO_NAME] }, - eventWhitelist: ["review_requested", "ready_for_review", "commented", "committed"], }) ) ).toThrow(TransformDecodeError); }); + it("Should correctly transform the eventWhitelist", () => { + const settings = Value.Default(userActivityWatcherSettingsSchema, { + warning: "12 days", + disqualification: "2 days", + watch: { optOut: [STRINGS.PRIVATE_REPO_NAME] }, + eventWhitelist: [ + "pull_request.review_requested", + "pull_request.ready_for_review", + "pull_request_review_comment.created", + "issue_comment.created", + "push", + ], + }); + const decodedSettings = Value.Decode(userActivityWatcherSettingsSchema, settings); + expect(decodedSettings.eventWhitelist).toEqual(["review_requested", "ready_for_review", "commented", "committed"]); + }); it("Should define eventWhitelist defaults if omitted", () => { const settings = Value.Default(userActivityWatcherSettingsSchema, { warning: "12 days", @@ -68,6 +96,8 @@ describe("User start/stop", () => { const decodedSettings = Value.Decode(userActivityWatcherSettingsSchema, settings); + console.log("decodedSettings", decodedSettings); + expect(decodedSettings).toEqual({ warning: ms("3.5 days"), disqualification: ms("7 days"),