From 890422739bf8b16de1d0f5df885d5a06b575f7a9 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Fri, 25 Oct 2024 17:21:08 -0400 Subject: [PATCH] Add more tests Signed-off-by: Peter Zhu --- src/call/add-issue-to-github-project-v2.ts | 63 ++++++++++--------- .../add-issue-to-github-project-v2.test.ts | 63 ++++++++++++++++--- 2 files changed, 87 insertions(+), 39 deletions(-) diff --git a/src/call/add-issue-to-github-project-v2.ts b/src/call/add-issue-to-github-project-v2.ts index d4c4e04..b93f79e 100644 --- a/src/call/add-issue-to-github-project-v2.ts +++ b/src/call/add-issue-to-github-project-v2.ts @@ -15,7 +15,7 @@ // : Ex: `opensearch-project/206` which is the OpenSearch Roadmap Project // Requirements : ADDITIONAL_RESOURCE_CONTEXT=true -import crypto from 'crypto'; +import * as crypto from 'crypto'; import { Probot } from 'probot'; import { Resource } from '../service/resource/resource'; import { validateResourceConfig } from '../utility/verification/verify-resource'; @@ -45,49 +45,54 @@ export default async function addIssueToGitHubProjectV2( context: any, resource: Resource, { labels, projects }: AddIssueToGitHubProjectV2Params, -): Promise> { - if (!(await validateResourceConfig(app, context, resource))) return 'none'; - if (!(await validateProjects(app, resource, projects))) return 'none'; +): Promise> { + if (!(await validateResourceConfig(app, context, resource))) return; + if (!(await validateProjects(app, resource, projects))) return; // Verify triggered label const label = context.payload.label.name.trim(); if (!labels.includes(label)) { app.log.error(`"${label}" is not defined in call paramter "labels": ${labels}.`); - return 'none'; + return; } const orgName = context.payload.organization.login; const repoName = context.payload.repository.name; const issueNumber = context.payload.issue.number; const issueNodeId = context.payload.issue.node_id; - const itemIdMap = new Map(); + const itemIdMap = new Map(); // Add to project - await Promise.all( - projects.map(async (project) => { - app.log.info(`Attempt to add ${orgName}/${repoName}/${issueNumber} to project ${project}`); - const mutationId = await crypto.randomBytes(20).toString('hex'); - const projectSplit = project.split('/'); - const projectNodeId = resource.organizations.get(projectSplit[0])?.projects.get(Number(projectSplit[1]))?.nodeId; - const addToProjectMutation = ` - mutation { - addProjectV2ItemById(input: { - clientMutationId: "${mutationId}", - contentId: "${issueNodeId}", - projectId: "${projectNodeId}", - }) { - item { - id + try { + await Promise.all( + projects.map(async (project) => { + app.log.info(`Attempt to add ${orgName}/${repoName}/${issueNumber} to project ${project}`); + const mutationId = await crypto.randomBytes(20).toString('hex'); + const projectSplit = project.split('/'); + const projectNodeId = resource.organizations.get(projectSplit[0])?.projects.get(Number(projectSplit[1]))?.nodeId; + const addToProjectMutation = ` + mutation { + addProjectV2ItemById(input: { + clientMutationId: "${mutationId}", + contentId: "${issueNodeId}", + projectId: "${projectNodeId}", + }) { + item { + id + } } } - } - `; - const responseAddToProject = await context.octokit.graphql(addToProjectMutation); - app.log.info(responseAddToProject); - const itemId = responseAddToProject.addProjectV2ItemById.item.id; - itemIdMap.set(project, itemId); - }), - ); + `; + const responseAddToProject = await context.octokit.graphql(addToProjectMutation); + app.log.info(responseAddToProject); + const itemId = responseAddToProject.addProjectV2ItemById.item.id; + itemIdMap.set(project, [itemId, label]); + }), + ); + } catch (e) { + app.log.error(`ERROR: ${e}`); + return; + } return itemIdMap; } diff --git a/test/call/add-issue-to-github-project-v2.test.ts b/test/call/add-issue-to-github-project-v2.test.ts index 4fde167..aaebdcb 100644 --- a/test/call/add-issue-to-github-project-v2.test.ts +++ b/test/call/add-issue-to-github-project-v2.test.ts @@ -1,8 +1,16 @@ -//import * as crypto from 'crypto'; import addIssueToGitHubProjectV2, { AddIssueToGitHubProjectV2Params } from '../../src/call/add-issue-to-github-project-v2'; import { validateProjects } from '../../src/call/add-issue-to-github-project-v2'; import { Probot, Logger } from 'probot'; +// Mock mutationId return +jest.mock('crypto', () => ({ + randomBytes: jest.fn(() => { + return { + toString: jest.fn().mockReturnValue('mutation-id'), + }; + }), +})); + describe('addIssueToGitHubProjectV2Functions', () => { let app: Probot; let context: any; @@ -44,12 +52,6 @@ describe('addIssueToGitHubProjectV2Functions', () => { labels: ['Meta', 'RFC'], projects: ['test-org/222'], }; - - jest.mock('crypto', () => ({ - randomBytes: jest.fn().mockReturnValue({ - toString: jest.fn().mockReturnValue('mocked-mutation-id'), - }), - })); }); afterEach(() => { @@ -71,12 +73,53 @@ describe('addIssueToGitHubProjectV2Functions', () => { describe('addIssueToGitHubProjectV2', () => { it('should print error if context label does not match the ones in resource config', async () => { context.payload.label.name = 'enhancement'; - + const result = await addIssueToGitHubProjectV2(app, context, resource, params); - + expect(app.log.error).toHaveBeenCalledWith('"enhancement" is not defined in call paramter "labels": Meta,RFC.'); - expect(result).toBe('none'); + expect(result).toBe(undefined); expect(context.octokit.graphql).not.toHaveBeenCalled(); }); + + it('should add context issue to project when conditions are met', async () => { + const graphQLResponse = { + addProjectV2ItemById: { item: { id: 'new-item-id' } }, + }; + + context.octokit.graphql.mockResolvedValue(graphQLResponse); + + const result = await addIssueToGitHubProjectV2(app, context, resource, params); + + /* prettier-ignore-start */ + const graphQLCallStack = ` + mutation { + addProjectV2ItemById(input: { + clientMutationId: "mutation-id", + contentId: "issue-111-nodeid", + projectId: "project-222-nodeid", + }) { + item { + id + } + } + } + `; + /* prettier-ignore-end */ + + expect(context.octokit.graphql).toHaveBeenCalledWith(graphQLCallStack); + expect(JSON.stringify((result as Map).get('test-org/222'))).toBe('["new-item-id","Meta"]'); + expect(app.log.info).toHaveBeenCalledWith(graphQLResponse); + }); + + it('should print log error when GraphQL call fails', async () => { + context.octokit.graphql.mockRejectedValue(new Error('GraphQL request failed')); + + const result = await addIssueToGitHubProjectV2(app, context, resource, params) + + expect(context.octokit.graphql).rejects.toThrow('GraphQL request failed') + expect(context.octokit.graphql).toHaveBeenCalled(); + expect(result).toBe(undefined); + expect(app.log.error).toHaveBeenCalledWith('ERROR: Error: GraphQL request failed'); + }); }); });