From 0788c44c0fa58f4175306bcfa73cdcb0815fb38c Mon Sep 17 00:00:00 2001 From: Simon Li Date: Thu, 29 Feb 2024 00:23:01 +0000 Subject: [PATCH] Replace nock with undici mocks --- __tests__/main.test.ts | 253 +++++++++++++++++++++++++++-------------- package-lock.json | 32 ++++-- package.json | 4 +- 3 files changed, 193 insertions(+), 96 deletions(-) diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts index 206bc39..c4a3529 100644 --- a/__tests__/main.test.ts +++ b/__tests__/main.test.ts @@ -1,17 +1,7 @@ import {addBinderComment, parseBoolean, __private} from '../src/binder' +import {MockAgent, MockClient, setGlobalDispatcher} from 'undici' import nock from 'nock' -beforeEach(() => { - nock.disableNetConnect() -}) - -afterEach(() => { - if (!nock.isDone()) { - nock.cleanAll() - throw new Error('Not all nock calls were made') - } -}) - // Check no other requests are made nock.emitter.on('no match', (req: any) => { throw new Error( @@ -181,18 +171,48 @@ const fullComment2 = `${fullComment1}\n\n${binderComment2}` const binderCommentBranch = '[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/owner/repo/ref-branch) :point_left: Launch a binder notebook on this branch ref-branch' +let mockAgent: MockAgent +let mockClient: MockClient +const defaultReplyHeaders = { + headers: {'Content-Type': 'application/json; charset=utf-8'} +} + +beforeEach(() => { + mockAgent = new MockAgent({connections: 1}) + mockAgent.disableNetConnect() + setGlobalDispatcher(mockAgent) + mockClient = mockAgent.get('https://api.github.com') +}) + +afterEach(() => { + mockAgent.assertNoPendingInterceptors() + mockAgent.close() +}) + test('add new comment', async () => { - nock('https://api.github.com') - .get('/repos/owner/repo/pulls/1') - .reply(200, mockPrResponse('owner', 'repo', 'abcdef1', 'branch', 1)) - nock('https://api.github.com') - .get('/repos/owner/repo/issues/1/comments') - .reply(200, [ - mockCommentResponse(12, 'github-actions[bot]', 'something else'), - mockCommentResponse(34, 'someone-else', 'something else') - ]) - nock('https://api.github.com') - .post('/repos/owner/repo/issues/1/comments', {body: fullComment1}) + mockClient + .intercept({path: '/repos/owner/repo/pulls/1'}) + .reply( + 200, + mockPrResponse('owner', 'repo', 'abcdef1', 'branch', 1), + defaultReplyHeaders + ) + mockClient + .intercept({path: '/repos/owner/repo/issues/1/comments'}) + .reply( + 200, + [ + mockCommentResponse(12, 'github-actions[bot]', 'something else'), + mockCommentResponse(34, 'someone-else', 'something else') + ], + defaultReplyHeaders + ) + mockClient + .intercept({ + method: 'POST', + path: '/repos/owner/repo/issues/1/comments', + body: JSON.stringify({body: fullComment1}) + }) .reply(200) const c = await addBinderComment({ @@ -203,17 +223,29 @@ test('add new comment', async () => { }) test('update existing comment', async () => { - nock('https://api.github.com') - .get('/repos/owner/repo/pulls/2') - .reply(200, mockPrResponse('owner', 'repo', '9876543', 'branch', 2)) - nock('https://api.github.com') - .get('/repos/owner/repo/issues/2/comments') - .reply(200, [ - mockCommentResponse(56, 'github-actions[bot]', fullComment1), - mockCommentResponse(78, 'someone-else', 'something else') - ]) - nock('https://api.github.com') - .patch('/repos/owner/repo/issues/comments/56', {body: fullComment2}) + mockClient + .intercept({path: '/repos/owner/repo/pulls/2'}) + .reply( + 200, + mockPrResponse('owner', 'repo', '9876543', 'branch', 2), + defaultReplyHeaders + ) + mockClient + .intercept({path: '/repos/owner/repo/issues/2/comments'}) + .reply( + 200, + [ + mockCommentResponse(56, 'github-actions[bot]', fullComment1), + mockCommentResponse(78, 'someone-else', 'something else') + ], + defaultReplyHeaders + ) + mockClient + .intercept({ + method: 'PATCH', + path: '/repos/owner/repo/issues/comments/56', + body: JSON.stringify({body: fullComment2}) + }) .reply(200) const c = await addBinderComment({ @@ -228,14 +260,26 @@ test('add new lab comment using query', async () => { '[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/owner/repo/a1b2c3d?urlpath=lab) :point_left: Launch a binder notebook on this branch for commit a1b2c3d' const fullLabComment = `${binderLabComment}\n\nI will automatically update this comment whenever this PR is modified` - nock('https://api.github.com') - .get('/repos/owner/repo/pulls/3') - .reply(200, mockPrResponse('owner', 'repo', 'a1b2c3d', 'branch', 3)) - nock('https://api.github.com') - .get('/repos/owner/repo/issues/3/comments') - .reply(200, [mockCommentResponse(90, 'someone-else', 'something else')]) - nock('https://api.github.com') - .post('/repos/owner/repo/issues/3/comments', {body: fullLabComment}) + mockClient + .intercept({path: '/repos/owner/repo/pulls/3'}) + .reply( + 200, + mockPrResponse('owner', 'repo', 'a1b2c3d', 'branch', 3), + defaultReplyHeaders + ) + mockClient + .intercept({path: '/repos/owner/repo/issues/3/comments'}) + .reply( + 200, + [mockCommentResponse(90, 'someone-else', 'something else')], + defaultReplyHeaders + ) + mockClient + .intercept({ + method: 'POST', + path: '/repos/owner/repo/issues/3/comments', + body: JSON.stringify({body: fullLabComment}) + }) .reply(200) const c = await addBinderComment({ @@ -251,14 +295,26 @@ test('add new lab comment using urlpath', async () => { '[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/owner/repo/a1b2c3d?urlpath=lab) :point_left: Launch a binder notebook on this branch for commit a1b2c3d' const fullLabComment = `${binderLabComment}\n\nI will automatically update this comment whenever this PR is modified` - nock('https://api.github.com') - .get('/repos/owner/repo/pulls/4') - .reply(200, mockPrResponse('owner', 'repo', 'a1b2c3d', 'branch', 4)) - nock('https://api.github.com') - .get('/repos/owner/repo/issues/4/comments') - .reply(200, [mockCommentResponse(91, 'someone-else', 'something else')]) - nock('https://api.github.com') - .post('/repos/owner/repo/issues/4/comments', {body: fullLabComment}) + mockClient + .intercept({path: '/repos/owner/repo/pulls/4'}) + .reply( + 200, + mockPrResponse('owner', 'repo', 'a1b2c3d', 'branch', 4), + defaultReplyHeaders + ) + mockClient + .intercept({path: '/repos/owner/repo/issues/4/comments'}) + .reply( + 200, + [mockCommentResponse(91, 'someone-else', 'something else')], + defaultReplyHeaders + ) + mockClient + .intercept({ + method: 'POST', + path: '/repos/owner/repo/issues/4/comments', + body: JSON.stringify({body: fullLabComment}) + }) .reply(200) const c = await addBinderComment({ @@ -275,14 +331,26 @@ test('add new lab comment with pullyMcPullface using branch', async () => { const binderLabComment = `[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/envowner/envrepo/branch${binderPullQuery}) :point_left: Launch a binder notebook on this branch ref-branch` const fullLabComment = `${binderLabComment}\n\nI will automatically update this comment whenever this PR is modified` - nock('https://api.github.com') - .get('/repos/owner/repo/pulls/5') - .reply(200, mockPrResponse('owner', 'repo', 'a1b2c3d', 'ref-branch', 5)) - nock('https://api.github.com') - .get('/repos/owner/repo/issues/5/comments') - .reply(200, [mockCommentResponse(101, 'someone-else', 'something else')]) - nock('https://api.github.com') - .post('/repos/owner/repo/issues/5/comments', {body: fullLabComment}) + mockClient + .intercept({path: '/repos/owner/repo/pulls/5'}) + .reply( + 200, + mockPrResponse('owner', 'repo', 'a1b2c3d', 'ref-branch', 5), + defaultReplyHeaders + ) + mockClient + .intercept({path: '/repos/owner/repo/issues/5/comments'}) + .reply( + 200, + [mockCommentResponse(101, 'someone-else', 'something else')], + defaultReplyHeaders + ) + mockClient + .intercept({ + method: 'POST', + path: '/repos/owner/repo/issues/5/comments', + body: JSON.stringify({body: fullLabComment}) + }) .reply(200) const c = await addBinderComment({ @@ -296,18 +364,26 @@ test('add new lab comment with pullyMcPullface using branch', async () => { }) test('avoid duplicating existing comment', async () => { - nock('https://api.github.com') - .get('/repos/owner/repo/pulls/6') - .reply(200, mockPrResponse('owner', 'repo', 'abcdef1', 'branch', 6)) - nock('https://api.github.com') - .get('/repos/owner/repo/issues/6/comments') - .reply(200, [ - mockCommentResponse( - 102, - 'github-actions[bot]', - `Prefix\n${fullComment1}\nSuffix` - ) - ]) + mockClient + .intercept({path: '/repos/owner/repo/pulls/6'}) + .reply( + 200, + mockPrResponse('owner', 'repo', 'abcdef1', 'branch', 6), + defaultReplyHeaders + ) + mockClient + .intercept({path: '/repos/owner/repo/issues/6/comments'}) + .reply( + 200, + [ + mockCommentResponse( + 102, + 'github-actions[bot]', + `Prefix\n${fullComment1}\nSuffix` + ) + ], + defaultReplyHeaders + ) // PATCH https://api.github.com/repos/owner/repo/issues/comments/102 // should not be called, if it is it will be caught by the earlier // nock.emitter.on('no match') handler @@ -321,8 +397,8 @@ test('avoid duplicating existing comment', async () => { test('add to pr description', async () => { const initialDescription = '# PR\n\ndescription' - nock('https://api.github.com') - .get('/repos/owner/repo/pulls/7') + mockClient + .intercept({path: '/repos/owner/repo/pulls/7'}) .reply( 200, mockPrResponse( @@ -332,11 +408,14 @@ test('add to pr description', async () => { 'branch', 6, initialDescription - ) + ), + defaultReplyHeaders ) - nock('https://api.github.com') - .patch('/repos/owner/repo/pulls/7', { - body: `${initialDescription}\n\n${binderComment1}` + mockClient + .intercept({ + path: '/repos/owner/repo/pulls/7', + method: 'PATCH', + body: JSON.stringify({body: `${initialDescription}\n\n${binderComment1}`}) }) .reply(200) @@ -350,8 +429,8 @@ test('add to pr description', async () => { test('add another to pr description', async () => { const initialDescription = `# PR\n\ndescription\n\n${binderComment1}` - nock('https://api.github.com') - .get('/repos/owner/repo/pulls/8') + mockClient + .intercept({path: '/repos/owner/repo/pulls/8'}) .reply( 200, mockPrResponse( @@ -361,11 +440,16 @@ test('add another to pr description', async () => { 'branch', 7, initialDescription - ) + ), + defaultReplyHeaders ) - nock('https://api.github.com') - .patch('/repos/owner/repo/pulls/8', { - body: `${initialDescription}\n\n${binderComment2}` + mockClient + .intercept({ + path: '/repos/owner/repo/pulls/8', + method: 'PATCH', + body: JSON.stringify({ + body: `${initialDescription}\n\n${binderComment2}` + }) }) .reply(200) @@ -379,8 +463,8 @@ test('add another to pr description', async () => { test('avoid duplicating pr description using branch', async () => { const initialDescription = `# PR\n\ndescription\n${binderCommentBranch}` - nock('https://api.github.com') - .get('/repos/owner/repo/pulls/9') + mockClient + .intercept({path: '/repos/owner/repo/pulls/9'}) .reply( 200, mockPrResponse( @@ -390,7 +474,8 @@ test('avoid duplicating pr description using branch', async () => { 'ref-branch', 9, initialDescription - ) + ), + defaultReplyHeaders ) // PATCH https://api.github.com/repos/owner/repo/pulls/9 // should not be called, if it is it will be caught by the earlier diff --git a/package-lock.json b/package-lock.json index d06a5f9..51468a8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,11 +26,11 @@ "jest": "^29.7.0", "jest-circus": "^29.7.0", "js-yaml": "^4.1.0", - "nock": "^13.5.4", "prettier": "3.2.5", "rimraf": "^5.0.5", "ts-jest": "^29.1.2", - "typescript": "^5.3.3" + "typescript": "^5.3.3", + "undici": "^6.6.2" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -172,6 +172,17 @@ "undici": "^5.25.4" } }, + "node_modules/@actions/http-client/node_modules/undici": { + "version": "5.28.3", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.3.tgz", + "integrity": "sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==", + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, "node_modules/@ampproject/remapping": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", @@ -6101,9 +6112,9 @@ "dev": true }, "node_modules/nock": { - "version": "13.5.4", - "resolved": "https://registry.npmjs.org/nock/-/nock-13.5.4.tgz", - "integrity": "sha512-yAyTfdeNJGGBFxWdzSKCBYxs5FxLbCg5X5Q4ets974hcQzG1+qCxvIyOo4j2Ry6MUlhWVMX4OoYDefAIIwupjw==", + "version": "14.0.0-beta.4", + "resolved": "https://registry.npmjs.org/nock/-/nock-14.0.0-beta.4.tgz", + "integrity": "sha512-N9GIOnNFas/TtdCQpavpi6A6SyVVInkD/vrUCF2u51vlE2wSnqfPifVli6xSX8l6Lz/3sdSwPusE9n3KPDDh0g==", "dev": true, "dependencies": { "debug": "^4.1.0", @@ -6111,7 +6122,7 @@ "propagate": "^2.0.0" }, "engines": { - "node": ">= 10.13" + "node": ">= 18" } }, "node_modules/node-int64": { @@ -7577,14 +7588,15 @@ } }, "node_modules/undici": { - "version": "5.28.3", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.3.tgz", - "integrity": "sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==", + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.6.2.tgz", + "integrity": "sha512-vSqvUE5skSxQJ5sztTZ/CdeJb1Wq0Hf44hlYMciqHghvz+K88U0l7D6u1VsndoFgskDcnU+nG3gYmMzJVzd9Qg==", + "dev": true, "dependencies": { "@fastify/busboy": "^2.0.0" }, "engines": { - "node": ">=14.0" + "node": ">=18.0" } }, "node_modules/undici-types": { diff --git a/package.json b/package.json index fd8c4c2..27ffb9f 100644 --- a/package.json +++ b/package.json @@ -43,10 +43,10 @@ "jest": "^29.7.0", "jest-circus": "^29.7.0", "js-yaml": "^4.1.0", - "nock": "^13.5.4", "prettier": "3.2.5", "rimraf": "^5.0.5", "ts-jest": "^29.1.2", - "typescript": "^5.3.3" + "typescript": "^5.3.3", + "undici": "^6.6.2" } }