-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[TS migration] Migrate GithubUtilsTest to typescript #36427
Changes from 3 commits
a9c81c3
eb8a2cd
ed6b6b2
5ce94eb
c37bbba
a6cf95a
4535da7
960ebb7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,69 @@ | ||
/** | ||
* @jest-environment node | ||
*/ | ||
const core = require('@actions/core'); | ||
const GithubUtils = require('../../.github/libs/GithubUtils'); | ||
import * as core from '@actions/core'; | ||
import GithubUtils from '../../.github/libs/GithubUtils'; | ||
|
||
const mockGetInput = jest.fn(); | ||
const mockListIssues = jest.fn(); | ||
|
||
type DeployBlockers = { | ||
url: string; | ||
number: number; | ||
isResolved: boolean; | ||
}; | ||
|
||
type PR = { | ||
url: string; | ||
number: number; | ||
isVerified: boolean; | ||
}; | ||
|
||
type Label = { | ||
id: number; | ||
number?: number; | ||
isVerified?: boolean; | ||
// eslint-disable-next-line @typescript-eslint/naming-convention | ||
node_id: string; | ||
url: string; | ||
name: string; | ||
color: string; | ||
default: boolean; | ||
description: string; | ||
}; | ||
|
||
type ExpectedReponse = { | ||
PRList: PR[]; | ||
labels: Label[]; | ||
tag: string; | ||
title: string; | ||
url: string; | ||
number: number; | ||
deployBlockers: DeployBlockers[]; | ||
internalQAPRList: string[]; | ||
isTimingDashboardChecked: boolean; | ||
isFirebaseChecked: boolean; | ||
isGHStatusChecked: boolean; | ||
}; | ||
|
||
type Issue = { | ||
url: string; | ||
title: string; | ||
labels: Label[]; | ||
body: string; | ||
}; | ||
|
||
type ObjectMethodData<T> = { | ||
data: T; | ||
}; | ||
|
||
type Mutable<T> = {-readonly [P in keyof T]: T[P]}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe you can reuse |
||
|
||
const asMutable = <T>(value: T): Mutable<T> => value as Mutable<T>; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice usage ❤️ |
||
|
||
beforeAll(() => { | ||
// Mock core module | ||
core.getInput = mockGetInput; | ||
asMutable(core).getInput = mockGetInput; | ||
|
||
// Mock octokit module | ||
const moctokit = { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is possible to use a type from GitHub library here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I couldn't find a way to make the mock complaint with the GitHub lib typing. |
||
|
@@ -19,16 +73,18 @@ | |
Promise.resolve({ | ||
data: { | ||
...arg, | ||
// eslint-disable-next-line @typescript-eslint/naming-convention | ||
html_url: 'https://github.com/Expensify/App/issues/29', | ||
}, | ||
}), | ||
), | ||
listForRepo: mockListIssues, | ||
}, | ||
}, | ||
paginate: jest.fn().mockImplementation((objectMethod) => objectMethod().then(({data}) => data)), | ||
paginate: jest.fn().mockImplementation(<T>(objectMethod: () => Promise<ObjectMethodData<T>>) => objectMethod().then(({data}) => data)), | ||
}; | ||
|
||
GithubUtils.internalOctokit = moctokit; | ||
Check failure on line 87 in tests/unit/GithubUtilsTest.ts GitHub Actions / typecheck
|
||
}); | ||
|
||
afterEach(() => { | ||
|
@@ -38,12 +94,13 @@ | |
|
||
describe('GithubUtils', () => { | ||
describe('getStagingDeployCash', () => { | ||
const baseIssue = { | ||
const baseIssue: Issue = { | ||
url: 'https://api.github.com/repos/Andrew-Test-Org/Public-Test-Repo/issues/29', | ||
title: 'Andrew Test Issue', | ||
labels: [ | ||
{ | ||
id: 2783847782, | ||
// eslint-disable-next-line @typescript-eslint/naming-convention | ||
node_id: 'MDU6TGFiZWwyNzgzODQ3Nzgy', | ||
url: 'https://api.github.com/repos/Andrew-Test-Org/Public-Test-Repo/labels/StagingDeployCash', | ||
name: 'StagingDeployCash', | ||
|
@@ -60,7 +117,7 @@ | |
issueWithDeployBlockers.body += | ||
'\r\n**Deploy Blockers:**\r\n- [ ] https://github.com/Expensify/App/issues/1\r\n- [x] https://github.com/Expensify/App/issues/2\r\n- [ ] https://github.com/Expensify/App/pull/1234\r\n'; | ||
|
||
const baseExpectedResponse = { | ||
const baseExpectedResponse: ExpectedReponse = { | ||
PRList: [ | ||
{ | ||
url: 'https://github.com/Expensify/App/pull/21', | ||
|
@@ -85,6 +142,7 @@ | |
description: '', | ||
id: 2783847782, | ||
name: 'StagingDeployCash', | ||
// eslint-disable-next-line @typescript-eslint/naming-convention | ||
node_id: 'MDU6TGFiZWwyNzgzODQ3Nzgy', | ||
url: 'https://api.github.com/repos/Andrew-Test-Org/Public-Test-Repo/labels/StagingDeployCash', | ||
}, | ||
|
@@ -119,13 +177,13 @@ | |
]; | ||
|
||
test('Test finding an open issue with no PRs successfully', () => { | ||
const bareIssue = { | ||
const bareIssue: Issue = { | ||
...baseIssue, | ||
// eslint-disable-next-line max-len | ||
body: '**Release Version:** `1.0.1-47`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n\r\ncc @Expensify/applauseleads\n', | ||
}; | ||
|
||
const bareExpectedResponse = { | ||
const bareExpectedResponse: ExpectedReponse = { | ||
...baseExpectedResponse, | ||
PRList: [], | ||
}; | ||
|
@@ -193,7 +251,9 @@ | |
['https://github.com/Expensify/Expensify/issues/156481'], | ||
['https://docs.google.com/document/d/1mMFh-m1seOES48r3zNqcvfuTvr3qOAsY6n5rP4ejdXE/edit?ts=602420d2#'], | ||
])('getPullRequestNumberFromURL("%s")', (input) => { | ||
expect(() => GithubUtils.getPullRequestNumberFromURL(input)).toThrow(new Error(`Provided URL ${input} is not a Github Pull Request!`)); | ||
expect(() => { | ||
GithubUtils.getPullRequestNumberFromURL(input); | ||
}).toThrow(new Error(`Provided URL ${input} is not a Github Pull Request!`)); | ||
}); | ||
}); | ||
}); | ||
|
@@ -218,7 +278,9 @@ | |
['https://github.com/Expensify/Expensify/pull/156481'], | ||
['https://docs.google.com/document/d/1mMFh-m1seOES48r3zNqcvfuTvr3qOAsY6n5rP4ejdXE/edit?ts=602420d2#'], | ||
])('getIssueNumberFromURL("%s")', (input) => { | ||
expect(() => GithubUtils.getIssueNumberFromURL(input)).toThrow(new Error(`Provided URL ${input} is not a Github Issue!`)); | ||
expect(() => { | ||
GithubUtils.getIssueNumberFromURL(input); | ||
}).toThrow(new Error(`Provided URL ${input} is not a Github Issue!`)); | ||
}); | ||
}); | ||
}); | ||
|
@@ -247,7 +309,9 @@ | |
test.each([['https://www.google.com/'], ['https://docs.google.com/document/d/1mMFh-m1seOES48r3zNqcvfuTvr3qOAsY6n5rP4ejdXE/edit?ts=602420d2#']])( | ||
'getIssueOrPullRequestNumberFromURL("%s")', | ||
(input) => { | ||
expect(() => GithubUtils.getIssueOrPullRequestNumberFromURL(input)).toThrow(new Error(`Provided URL ${input} is not a valid Github Issue or Pull Request!`)); | ||
expect(() => { | ||
GithubUtils.getIssueOrPullRequestNumberFromURL(input); | ||
}).toThrow(new Error(`Provided URL ${input} is not a valid Github Issue or Pull Request!`)); | ||
}, | ||
); | ||
}); | ||
|
@@ -259,46 +323,53 @@ | |
{ | ||
number: 1, | ||
title: 'Test PR 1', | ||
// eslint-disable-next-line @typescript-eslint/naming-convention | ||
html_url: 'https://github.com/Expensify/App/pull/1', | ||
user: {login: 'testUser'}, | ||
labels: [], | ||
}, | ||
{ | ||
number: 2, | ||
title: 'Test PR 2', | ||
// eslint-disable-next-line @typescript-eslint/naming-convention | ||
html_url: 'https://github.com/Expensify/App/pull/2', | ||
user: {login: 'testUser'}, | ||
labels: [], | ||
}, | ||
{ | ||
number: 3, | ||
title: 'Test PR 3', | ||
// eslint-disable-next-line @typescript-eslint/naming-convention | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about disabling it in whole file? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree |
||
html_url: 'https://github.com/Expensify/App/pull/3', | ||
user: {login: 'testUser'}, | ||
labels: [], | ||
}, | ||
{ | ||
number: 4, | ||
title: '[NO QA] Test No QA PR uppercase', | ||
// eslint-disable-next-line @typescript-eslint/naming-convention | ||
html_url: 'https://github.com/Expensify/App/pull/4', | ||
user: {login: 'testUser'}, | ||
labels: [], | ||
}, | ||
{ | ||
number: 5, | ||
title: '[NoQa] Test No QA PR Title Case', | ||
// eslint-disable-next-line @typescript-eslint/naming-convention | ||
html_url: 'https://github.com/Expensify/App/pull/5', | ||
user: {login: 'testUser'}, | ||
labels: [], | ||
}, | ||
{ | ||
number: 6, | ||
title: '[Internal QA] Test Internal QA PR', | ||
// eslint-disable-next-line @typescript-eslint/naming-convention | ||
html_url: 'https://github.com/Expensify/App/pull/6', | ||
user: {login: 'testUser'}, | ||
labels: [ | ||
{ | ||
id: 1234, | ||
// eslint-disable-next-line @typescript-eslint/naming-convention | ||
node_id: 'MDU6TGFiZWwyMDgwNDU5NDY=', | ||
url: 'https://api.github.com/Expensify/App/labels/InternalQA', | ||
name: 'InternalQA', | ||
|
@@ -318,11 +389,13 @@ | |
{ | ||
number: 7, | ||
title: '[Internal QA] Another Test Internal QA PR', | ||
// eslint-disable-next-line @typescript-eslint/naming-convention | ||
html_url: 'https://github.com/Expensify/App/pull/7', | ||
user: {login: 'testUser'}, | ||
labels: [ | ||
{ | ||
id: 1234, | ||
// eslint-disable-next-line @typescript-eslint/naming-convention | ||
node_id: 'MDU6TGFiZWwyMDgwNDU5NDY=', | ||
url: 'https://api.github.com/Expensify/App/labels/InternalQA', | ||
name: 'InternalQA', | ||
|
@@ -350,12 +423,13 @@ | |
list: jest.fn().mockResolvedValue({data: mockPRs}), | ||
}, | ||
}, | ||
paginate: jest.fn().mockImplementation((objectMethod) => objectMethod().then(({data}) => data)), | ||
paginate: jest.fn().mockImplementation(<T>(objectMethod: () => Promise<ObjectMethodData<T>>) => objectMethod().then(({data}) => data)), | ||
}), | ||
})); | ||
|
||
const octokit = mockGithub().getOctokit(); | ||
const githubUtils = class extends GithubUtils {}; | ||
// @ts-expect-error TODO: Remove this once GithubUtils (https://github.com/Expensify/App/issues/25382) is migrated to TypeScript. | ||
githubUtils.internalOctokit = octokit; | ||
const tag = '1.0.2-12'; | ||
const basePRList = [ | ||
|
@@ -404,8 +478,8 @@ | |
`${lineBreak}${closedCheckbox}${basePRList[5]}` + | ||
`${lineBreak}`; | ||
|
||
test('Test no verified PRs', () => | ||
githubUtils.generateStagingDeployCashBody(tag, basePRList).then((issueBody) => { | ||
test('Test no verified PRs', () => { | ||
githubUtils.generateStagingDeployCashBody(tag, basePRList).then((issueBody: string) => { | ||
expect(issueBody).toBe( | ||
`${baseExpectedOutput}` + | ||
`${openCheckbox}${basePRList[2]}` + | ||
|
@@ -419,10 +493,11 @@ | |
`${lineBreak}${openCheckbox}${ghVerification}` + | ||
`${lineBreakDouble}${ccApplauseLeads}`, | ||
); | ||
})); | ||
}); | ||
}); | ||
|
||
test('Test some verified PRs', () => | ||
githubUtils.generateStagingDeployCashBody(tag, basePRList, [basePRList[0]]).then((issueBody) => { | ||
test('Test some verified PRs', () => { | ||
githubUtils.generateStagingDeployCashBody(tag, basePRList, [basePRList[0]]).then((issueBody: string) => { | ||
expect(issueBody).toBe( | ||
`${baseExpectedOutput}` + | ||
`${openCheckbox}${basePRList[2]}` + | ||
|
@@ -436,10 +511,11 @@ | |
`${lineBreak}${openCheckbox}${ghVerification}` + | ||
`${lineBreakDouble}${ccApplauseLeads}`, | ||
); | ||
})); | ||
}); | ||
}); | ||
|
||
test('Test all verified PRs', () => | ||
githubUtils.generateStagingDeployCashBody(tag, basePRList, basePRList).then((issueBody) => { | ||
test('Test all verified PRs', () => { | ||
githubUtils.generateStagingDeployCashBody(tag, basePRList, basePRList).then((issueBody: string) => { | ||
expect(issueBody).toBe( | ||
`${allVerifiedExpectedOutput}` + | ||
`${lineBreak}${deployerVerificationsHeader}` + | ||
|
@@ -448,10 +524,11 @@ | |
`${lineBreak}${openCheckbox}${ghVerification}` + | ||
`${lineBreakDouble}${ccApplauseLeads}`, | ||
); | ||
})); | ||
}); | ||
}); | ||
|
||
test('Test no resolved deploy blockers', () => | ||
githubUtils.generateStagingDeployCashBody(tag, basePRList, basePRList, baseDeployBlockerList).then((issueBody) => { | ||
test('Test no resolved deploy blockers', () => { | ||
githubUtils.generateStagingDeployCashBody(tag, basePRList, basePRList, baseDeployBlockerList).then((issueBody: string) => { | ||
expect(issueBody).toBe( | ||
`${allVerifiedExpectedOutput}` + | ||
`${lineBreak}${deployBlockerHeader}` + | ||
|
@@ -463,10 +540,11 @@ | |
`${lineBreak}${openCheckbox}${ghVerification}${lineBreak}` + | ||
`${lineBreak}${ccApplauseLeads}`, | ||
); | ||
})); | ||
}); | ||
}); | ||
|
||
test('Test some resolved deploy blockers', () => | ||
githubUtils.generateStagingDeployCashBody(tag, basePRList, basePRList, baseDeployBlockerList, [baseDeployBlockerList[0]]).then((issueBody) => { | ||
test('Test some resolved deploy blockers', () => { | ||
githubUtils.generateStagingDeployCashBody(tag, basePRList, basePRList, baseDeployBlockerList, [baseDeployBlockerList[0]]).then((issueBody: string) => { | ||
expect(issueBody).toBe( | ||
`${allVerifiedExpectedOutput}` + | ||
`${lineBreak}${deployBlockerHeader}` + | ||
|
@@ -478,10 +556,11 @@ | |
`${lineBreak}${openCheckbox}${ghVerification}` + | ||
`${lineBreakDouble}${ccApplauseLeads}`, | ||
); | ||
})); | ||
}); | ||
}); | ||
|
||
test('Test all resolved deploy blockers', () => | ||
githubUtils.generateStagingDeployCashBody(tag, basePRList, basePRList, baseDeployBlockerList, baseDeployBlockerList).then((issueBody) => { | ||
test('Test all resolved deploy blockers', () => { | ||
githubUtils.generateStagingDeployCashBody(tag, basePRList, basePRList, baseDeployBlockerList, baseDeployBlockerList).then((issueBody: string) => { | ||
expect(issueBody).toBe( | ||
`${baseExpectedOutput}` + | ||
`${closedCheckbox}${basePRList[2]}` + | ||
|
@@ -498,10 +577,11 @@ | |
`${lineBreak}${openCheckbox}${ghVerification}` + | ||
`${lineBreakDouble}${ccApplauseLeads}`, | ||
); | ||
})); | ||
}); | ||
}); | ||
|
||
test('Test internalQA PRs', () => | ||
githubUtils.generateStagingDeployCashBody(tag, [...basePRList, ...internalQAPRList]).then((issueBody) => { | ||
test('Test internalQA PRs', () => { | ||
githubUtils.generateStagingDeployCashBody(tag, [...basePRList, ...internalQAPRList]).then((issueBody: string) => { | ||
expect(issueBody).toBe( | ||
`${baseExpectedOutput}` + | ||
`${openCheckbox}${basePRList[2]}` + | ||
|
@@ -518,10 +598,11 @@ | |
`${lineBreak}${openCheckbox}${ghVerification}` + | ||
`${lineBreakDouble}${ccApplauseLeads}`, | ||
); | ||
})); | ||
}); | ||
}); | ||
|
||
test('Test some verified internalQA PRs', () => | ||
githubUtils.generateStagingDeployCashBody(tag, [...basePRList, ...internalQAPRList], [], [], [], [internalQAPRList[0]]).then((issueBody) => { | ||
test('Test some verified internalQA PRs', () => { | ||
githubUtils.generateStagingDeployCashBody(tag, [...basePRList, ...internalQAPRList], [], [], [], [internalQAPRList[0]]).then((issueBody: string) => { | ||
expect(issueBody).toBe( | ||
`${baseExpectedOutput}` + | ||
`${openCheckbox}${basePRList[2]}` + | ||
|
@@ -538,7 +619,8 @@ | |
`${lineBreak}${openCheckbox}${ghVerification}` + | ||
`${lineBreakDouble}${ccApplauseLeads}`, | ||
); | ||
})); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('getPullRequestURLFromNumber', () => { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.