From 864a9e3ab248f3533ab2b172af3ae32ad6b779eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Santiago=20Mart=C3=ADn=20Agra?= Date: Sun, 3 May 2020 18:58:37 +0200 Subject: [PATCH 1/2] test: new 'PullRequestPayloadBuilder' --- package.json | 5 ++- src/schemas/github/pull-request-payload.ts | 17 ++++++++- .../github/pull-request-payload-builder.ts | 37 +++++++++++++++++++ yarn.lock | 5 +++ 4 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 test/builders/github/pull-request-payload-builder.ts diff --git a/package.json b/package.json index ddcae28..1b29f2f 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,6 @@ "tmi.js": "^1.5.0" }, "devDependencies": { - "lodash": "^4.17.15", "@types/faker": "^4.1.11", "@types/hapi__hapi": "^19.0.2", "@types/hapi__joi": "^16.0.12", @@ -36,10 +35,12 @@ "husky": "^4.2.5", "jest": "^25.2.7", "lint-staged": ">=10", + "lodash": "^4.17.15", "nock": "^12.0.3", "nodemon": "^2.0.3", "prettier": "^2.0.4", "ts-jest": "^25.4.0", - "typescript": "^3.8.3" + "typescript": "^3.8.3", + "utility-types": "^3.10.0" } } diff --git a/src/schemas/github/pull-request-payload.ts b/src/schemas/github/pull-request-payload.ts index 0d8f3dd..f495ae6 100644 --- a/src/schemas/github/pull-request-payload.ts +++ b/src/schemas/github/pull-request-payload.ts @@ -1,6 +1,19 @@ import { RepositoryWebhookPayload } from './repository-webhook-payload'; export interface PullRequestPayload extends RepositoryWebhookPayload { - action: string; - pull_request: { user: { login: string }; merged?: boolean }; + action: + | 'assigned' + | 'unassigned' + | 'review_requested' + | 'review_request_removed' + | 'labeled' + | 'unlabeled' + | 'opened' + | 'edited' + | 'closed' + | 'ready_for_review' + | 'locked' + | 'unlocked' + | 'reopened'; + pull_request: { user: { login: string }; merged?: boolean; html_url: string }; } diff --git a/test/builders/github/pull-request-payload-builder.ts b/test/builders/github/pull-request-payload-builder.ts new file mode 100644 index 0000000..fdd83fa --- /dev/null +++ b/test/builders/github/pull-request-payload-builder.ts @@ -0,0 +1,37 @@ +import { internet, random } from 'faker'; +import { merge } from 'lodash'; +import { PullRequestPayload } from '../../../src/schemas/github/pull-request-payload'; +import { DeepPartial } from 'utility-types'; + +export class PullRequestPayloadBuilder { + private payload: PullRequestPayload = { + action: random.arrayElement([ + 'assigned', + 'unassigned', + 'review_requested', + 'review_request_removed', + 'labeled', + 'unlabeled', + 'opened', + 'edited', + 'closed', + 'ready_for_review', + 'locked', + 'unlocked', + 'reopened', + ]), + pull_request: { user: { login: internet.userName() }, html_url: internet.url() }, + repository: { html_url: internet.url(), full_name: 'streamdevs/webhook' }, + sender: { login: internet.userName() }, + }; + + public with(payload: DeepPartial): PullRequestPayloadBuilder { + merge(this.payload, payload); + + return this; + } + + public getInstance(): PullRequestPayload { + return this.payload; + } +} diff --git a/yarn.lock b/yarn.lock index f796d97..eae0c96 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5190,6 +5190,11 @@ util-deprecate@^1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= +utility-types@^3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/utility-types/-/utility-types-3.10.0.tgz#ea4148f9a741015f05ed74fd615e1d20e6bed82b" + integrity sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg== + uuid@^3.3.2: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" From a31469457abec3fc04406a76982d7de4d670773e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Santiago=20Mart=C3=ADn=20Agra?= Date: Sun, 3 May 2020 19:45:09 +0200 Subject: [PATCH 2/2] test: fix pull request payload types --- .../github/pull-request-merged.spec.ts | 21 +- .../github/pull-request-opened.spec.ts | 21 +- test/routes/github/pull_request.spec.ts | 230 +++++------------- 3 files changed, 81 insertions(+), 191 deletions(-) diff --git a/test/reactions/github/pull-request-merged.spec.ts b/test/reactions/github/pull-request-merged.spec.ts index 158eb3f..51b1c8c 100644 --- a/test/reactions/github/pull-request-merged.spec.ts +++ b/test/reactions/github/pull-request-merged.spec.ts @@ -2,6 +2,7 @@ import { PullRequestMerged } from '../../../src/reactions/github/pull-request-me import { PullRequestPayload } from '../../../src/schemas/github/pull-request-payload'; import { TwitchChatMock } from '../../__mocks__/TwitchChat'; import { StreamLabsMock } from '../../__mocks__/StreamLabs'; +import { PullRequestPayloadBuilder } from '../../builders/github/pull-request-payload-builder'; describe('PullRequestMerged', () => { let streamlabs: StreamLabsMock; @@ -16,15 +17,17 @@ describe('PullRequestMerged', () => { let payload: PullRequestPayload; beforeEach(() => { - payload = { - action: 'closed', - repository: { - full_name: 'streamdevs/webhook', - html_url: 'https://github.com/streamdevs/webhook', - }, - pull_request: { user: { login: 'SantiMA10' }, merged: true }, - sender: { login: 'pepe' }, - }; + payload = new PullRequestPayloadBuilder() + .with({ + action: 'closed', + repository: { + full_name: 'streamdevs/webhook', + html_url: 'https://github.com/streamdevs/webhook', + }, + pull_request: { user: { login: 'SantiMA10' }, merged: true }, + sender: { login: 'pepe' }, + }) + .getInstance(); }); it("returns 'twitchChat.notified' === false if something goes wrong with TwitchChat", async () => { diff --git a/test/reactions/github/pull-request-opened.spec.ts b/test/reactions/github/pull-request-opened.spec.ts index e1a7428..415d6cb 100644 --- a/test/reactions/github/pull-request-opened.spec.ts +++ b/test/reactions/github/pull-request-opened.spec.ts @@ -3,6 +3,7 @@ import { PullRequestPayload } from '../../../src/schemas/github/pull-request-pay import { StreamLabsMock } from '../../__mocks__/StreamLabs'; import { TwitchChatMock } from '../../__mocks__/TwitchChat'; import { Config } from '../../../src/config'; +import { PullRequestPayloadBuilder } from '../../builders/github/pull-request-payload-builder'; describe('PullRequestOpened', () => { let streamlabs: StreamLabsMock; @@ -17,15 +18,17 @@ describe('PullRequestOpened', () => { let payload: PullRequestPayload; beforeEach(() => { - payload = { - action: 'opened', - repository: { - full_name: 'streamdevs/webhook', - html_url: 'https://github.com/streamdevs/webhook', - }, - pull_request: { user: { login: 'SantiMA10' } }, - sender: { login: 'pepe' }, - }; + payload = new PullRequestPayloadBuilder() + .with({ + action: 'opened', + repository: { + full_name: 'streamdevs/webhook', + html_url: 'https://github.com/streamdevs/webhook', + }, + pull_request: { user: { login: 'SantiMA10' } }, + sender: { login: 'pepe' }, + }) + .getInstance(); }); it("returns 'twitchChat.notified' === false if something goes wrong with TwitchChat", async () => { diff --git a/test/routes/github/pull_request.spec.ts b/test/routes/github/pull_request.spec.ts index f175837..08a2444 100644 --- a/test/routes/github/pull_request.spec.ts +++ b/test/routes/github/pull_request.spec.ts @@ -2,6 +2,7 @@ import { initServer } from '../../../src/server'; import { getConfig } from '../../../src/config'; import { StreamLabs } from '../../../src/services/StreamLabs'; import { TwitchChat } from '../../../src/services/TwitchChat'; +import { PullRequestPayloadBuilder } from '../../builders/github/pull-request-payload-builder'; describe('POST /github', () => { describe("GitHub 'pull_request' event", () => { @@ -16,189 +17,72 @@ describe('POST /github', () => { spyTwitchChat.mockImplementationOnce(jest.fn()); }); - describe('StreamLabs alerts', () => { - it('sends the notification to StreamLabs when a pull request was opened', async () => { - const subject = await initServer(getConfig()); - const repositoryFullName = 'streamdevs/webhook'; - const pullRequestLogin = 'SantiMA10'; + it('handles the pull request opened event', async () => { + const subject = await initServer(getConfig()); + const payload = new PullRequestPayloadBuilder().with({ action: 'opened' }).getInstance(); - await subject.inject({ - method: 'POST', - url: '/github', - payload: { - action: 'opened', - repository: { full_name: repositoryFullName }, - pull_request: { user: { login: pullRequestLogin } }, - sender: { login: 'pepe' }, - }, - headers: { 'x-github-event': 'pull_request' }, - }); - - const expectedPayload = { - message: `*${pullRequestLogin}* just opened a pull request in *${repositoryFullName}*`, - }; - expect(spyStreamLabs).toHaveBeenCalledWith(expectedPayload); - }); - - it("ignores other 'pull_request' event", async () => { - const subject = await initServer(getConfig()); - const repositoryFullName = 'streamdevs/webhook'; - const pullRequestLogin = 'SantiMA10'; - - const { statusCode } = await subject.inject({ - method: 'POST', - url: '/github', - payload: { - action: 'assigned', - repository: { full_name: repositoryFullName }, - pull_request: { user: { login: pullRequestLogin } }, - sender: { login: 'pepe' }, - }, - headers: { 'x-github-event': 'pull_request' }, - }); - - expect(spyStreamLabs).not.toHaveBeenCalled(); - expect(statusCode).toBe(200); - }); - - it("ignores other 'closed' event when it is not merged", async () => { - const subject = await initServer(getConfig()); - const repositoryFullName = 'streamdevs/webhook'; - const pullRequestLogin = 'SantiMA10'; - - const { statusCode } = await subject.inject({ - method: 'POST', - url: '/github', - payload: { - action: 'closed', - repository: { full_name: repositoryFullName }, - pull_request: { user: { login: pullRequestLogin } }, - sender: { login: 'pepe' }, - }, - headers: { 'x-github-event': 'pull_request' }, - }); - - expect(spyStreamLabs).not.toHaveBeenCalled(); - expect(statusCode).toEqual(200); + const { result } = await subject.inject({ + method: 'POST', + url: '/github', + payload, + headers: { 'x-github-event': 'pull_request' }, }); - it('sends a notification to StreamLabs when a pull request was merged', async () => { - const subject = await initServer(getConfig()); - const repositoryFullName = 'streamdevs/webhook'; - const pullRequestLogin = 'SantiMA10'; - - await subject.inject({ - method: 'POST', - url: '/github', - payload: { - action: 'closed', - repository: { full_name: repositoryFullName }, - pull_request: { user: { login: pullRequestLogin }, merged: true }, - sender: { login: 'pepe' }, - }, - headers: { 'x-github-event': 'pull_request' }, - }); - - const expectedPayload = { - message: `The pull request from *${pullRequestLogin}* has been merged into *${repositoryFullName}*`, - }; - - expect(spyStreamLabs).toHaveBeenCalledWith(expectedPayload); - }); + expect(result).toEqual( + expect.objectContaining({ + messages: [ + expect.objectContaining({ + twitchChat: expect.anything(), + streamlabs: expect.anything(), + }), + ], + }), + ); }); - describe('TwitchChat send', () => { - it('sends the message to the Twitch chat when a pull request was opened', async () => { - const subject = await initServer(getConfig()); - const repositoryUrl = 'https://github.com/streamdevs/webhook'; - const pullRequestLogin = 'SantiMA10'; - - await subject.inject({ - method: 'POST', - url: '/github', - payload: { - action: 'opened', - repository: { - full_name: 'streamdevs/webhook', - html_url: repositoryUrl, - }, - pull_request: { user: { login: pullRequestLogin } }, - sender: { login: 'pepe' }, - }, - headers: { 'x-github-event': 'pull_request' }, - }); - - expect(spyTwitchChat).toHaveBeenCalledWith( - `${pullRequestLogin} just opened a pull request in ${repositoryUrl}`, - ); - }); - - it('sends the message to the Twitch chat when a pull request was merged', async () => { - const subject = await initServer(getConfig()); - const repositoryUrl = 'https://github.com/streamdevs/webhook'; - const pullRequestLogin = 'SantiMA10'; - - await subject.inject({ - method: 'POST', - url: '/github', - payload: { - action: 'closed', - repository: { - full_name: 'streamdevs/webhook', - html_url: repositoryUrl, - }, - pull_request: { user: { login: pullRequestLogin }, merged: true }, - sender: { login: 'pepe' }, - }, - headers: { 'x-github-event': 'pull_request' }, - }); - - expect(spyTwitchChat).toHaveBeenCalledWith( - `The pull request from ${pullRequestLogin} has been merged into ${repositoryUrl}`, - ); + it('handles the pull request merged event', async () => { + const subject = await initServer(getConfig()); + const payload = new PullRequestPayloadBuilder() + .with({ action: 'closed', pull_request: { merged: true } }) + .getInstance(); + + const { result } = await subject.inject({ + method: 'POST', + url: '/github', + payload, + headers: { 'x-github-event': 'pull_request' }, }); - it("ignores other 'pull_request' event", async () => { - const subject = await initServer(getConfig()); - const repositoryFullName = 'streamdevs/webhook'; - const pullRequestLogin = 'SantiMA10'; - - const { statusCode } = await subject.inject({ - method: 'POST', - url: '/github', - payload: { - action: 'assigned', - repository: { full_name: repositoryFullName }, - pull_request: { user: { login: pullRequestLogin } }, - sender: { login: 'pepe' }, - }, - headers: { 'x-github-event': 'pull_request' }, - }); + expect(result).toEqual( + expect.objectContaining({ + messages: [ + expect.objectContaining({ + twitchChat: expect.anything(), + streamlabs: expect.anything(), + }), + ], + }), + ); + }); - expect(spyTwitchChat).not.toHaveBeenCalled(); - expect(statusCode).toBe(200); + it('ignores other pull request events', async () => { + const subject = await initServer(getConfig()); + const payload = new PullRequestPayloadBuilder() + .with({ action: 'edited', pull_request: { merged: true } }) + .getInstance(); + + const { result } = await subject.inject({ + method: 'POST', + url: '/github', + payload, + headers: { 'x-github-event': 'pull_request' }, }); - it("ignores other 'closed' event when it is not merged", async () => { - const subject = await initServer(getConfig()); - const repositoryFullName = 'streamdevs/webhook'; - const pullRequestLogin = 'SantiMA10'; - - const { statusCode } = await subject.inject({ - method: 'POST', - url: '/github', - payload: { - action: 'closed', - repository: { full_name: repositoryFullName }, - pull_request: { user: { login: pullRequestLogin } }, - sender: { login: 'pepe' }, - }, - headers: { 'x-github-event': 'pull_request' }, - }); - - expect(spyTwitchChat).not.toHaveBeenCalled(); - expect(statusCode).toEqual(200); - }); + expect(result).toEqual( + expect.objectContaining({ + message: expect.anything(), + }), + ); }); }); });