From cc18e529bfcecdc6fe02707b4ff06fa71f117bf3 Mon Sep 17 00:00:00 2001 From: "James M. Greene" Date: Wed, 6 Dec 2023 01:05:59 -0600 Subject: [PATCH] Update tests to use undici mocking for latest Octokit --- src/__tests__/internal/deployment.test.js | 573 +++++++++++++++------- 1 file changed, 406 insertions(+), 167 deletions(-) diff --git a/src/__tests__/internal/deployment.test.js b/src/__tests__/internal/deployment.test.js index 173ba0c..88a2a24 100644 --- a/src/__tests__/internal/deployment.test.js +++ b/src/__tests__/internal/deployment.test.js @@ -1,5 +1,8 @@ const core = require('@actions/core') +// For mocking network calls with core http (http-client) const nock = require('nock') +// For mocking network calls with native Fetch (octokit) +const { MockAgent, setGlobalDispatcher } = require('undici') const { Deployment, MAX_TIMEOUT, ONE_GIGABYTE, SIZE_LIMIT_DESCRIPTION } = require('../../internal/deployment') @@ -7,6 +10,8 @@ const fakeJwt = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJiNjllMWIxOC1jOGFiLTRhZGQtOGYxOC03MzVlMzVjZGJhZjAiLCJzdWIiOiJyZXBvOnBhcGVyLXNwYS9taW55aTplbnZpcm9ubWVudDpQcm9kdWN0aW9uIiwiYXVkIjoiaHR0cHM6Ly9naXRodWIuY29tL3BhcGVyLXNwYSIsInJlZiI6InJlZnMvaGVhZHMvbWFpbiIsInNoYSI6ImEyODU1MWJmODdiZDk3NTFiMzdiMmM0YjM3M2MxZjU3NjFmYWM2MjYiLCJyZXBvc2l0b3J5IjoicGFwZXItc3BhL21pbnlpIiwicmVwb3NpdG9yeV9vd25lciI6InBhcGVyLXNwYSIsInJ1bl9pZCI6IjE1NDY0NTkzNjQiLCJydW5fbnVtYmVyIjoiMzQiLCJydW5fYXR0ZW1wdCI6IjIiLCJhY3RvciI6IllpTXlzdHkiLCJ3b3JrZmxvdyI6IkNJIiwiaGVhZF9yZWYiOiIiLCJiYXNlX3JlZiI6IiIsImV2ZW50X25hbWUiOiJwdXNoIiwicmVmX3R5cGUiOiJicmFuY2giLCJlbnZpcm9ubWVudCI6IlByb2R1Y3Rpb24iLCJqb2Jfd29ya2Zsb3dfcmVmIjoicGFwZXItc3BhL21pbnlpLy5naXRodWIvd29ya2Zsb3dzL2JsYW5rLnltbEByZWZzL2hlYWRzL21haW4iLCJpc3MiOiJodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tIiwibmJmIjoxNjM4ODI4MDI4LCJleHAiOjE2Mzg4Mjg5MjgsImlhdCI6MTYzODgyODYyOH0.1wyupfxu1HGoTyIqatYg0hIxy2-0bMO-yVlmLSMuu2w' describe('Deployment', () => { + let mockPool + beforeEach(() => { jest.clearAllMocks() process.env.ACTIONS_RUNTIME_URL = 'http://my-url/' @@ -37,11 +42,18 @@ describe('Deployment', () => { jest.spyOn(core, 'setFailed').mockImplementation(param => { return param }) + // Mock error/warning/info/debug jest.spyOn(core, 'error').mockImplementation(jest.fn()) jest.spyOn(core, 'warning').mockImplementation(jest.fn()) jest.spyOn(core, 'info').mockImplementation(jest.fn()) jest.spyOn(core, 'debug').mockImplementation(jest.fn()) + + // Set up Fetch mocking + const mockAgent = new MockAgent() + mockAgent.disableNetConnect() + setGlobalDispatcher(mockAgent) + mockPool = mockAgent.get('https://api.github.com') }) describe('#create', () => { @@ -62,16 +74,32 @@ describe('Deployment', () => { ] }) - const createDeploymentScope = nock('https://api.github.com') - .post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, { - artifact_url: 'https://fake-artifact.com&%24expand=SignedContent', - pages_build_version: process.env.GITHUB_SHA, - oidc_token: fakeJwt - }) - .reply(200, { - status_url: `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`, - page_url: 'https://actions.github.io/is-awesome' + mockPool + .intercept({ + path: `/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, + method: 'POST', + body: bodyString => { + const body = JSON.parse(bodyString) + const keys = Object.keys(body).sort() + return ( + keys.length === 3 && + keys[0] === 'artifact_url' && + keys[1] === 'oidc_token' && + keys[2] === 'pages_build_version' && + body.artifact_url === 'https://fake-artifact.com&%24expand=SignedContent' && + body.pages_build_version === process.env.GITHUB_SHA && + body.oidc_token === fakeJwt + ) + } }) + .reply( + 200, + { + status_url: `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`, + page_url: 'https://actions.github.io/is-awesome' + }, + { headers: { 'content-type': 'application/json' } } + ) core.getIDToken = jest.fn().mockResolvedValue(fakeJwt) @@ -85,7 +113,6 @@ describe('Deployment', () => { ) artifactExchangeScope.done() - createDeploymentScope.done() }) it('can successfully create a preview deployment', async () => { @@ -100,18 +127,35 @@ describe('Deployment', () => { ] }) - const createDeploymentScope = nock('https://api.github.com') - .post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, { - artifact_url: 'https://fake-artifact.com&%24expand=SignedContent', - pages_build_version: process.env.GITHUB_SHA, - oidc_token: fakeJwt, - preview: true - }) - .reply(200, { - status_url: `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`, - page_url: 'https://actions.github.io/is-awesome', - preview_url: 'https://actions.drafts.github.io/is-awesome' + mockPool + .intercept({ + path: `/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, + method: 'POST', + body: bodyString => { + const body = JSON.parse(bodyString) + const keys = Object.keys(body).sort() + return ( + keys.length === 4 && + keys[0] === 'artifact_url' && + keys[1] === 'oidc_token' && + keys[2] === 'pages_build_version' && + keys[3] === 'preview' && + body.artifact_url === 'https://fake-artifact.com&%24expand=SignedContent' && + body.pages_build_version === process.env.GITHUB_SHA && + body.oidc_token === fakeJwt && + body.preview === true + ) + } }) + .reply( + 200, + { + status_url: `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`, + page_url: 'https://actions.github.io/is-awesome', + preview_url: 'https://actions.drafts.github.io/is-awesome' + }, + { headers: { 'content-type': 'application/json' } } + ) core.getIDToken = jest.fn().mockResolvedValue(fakeJwt) @@ -128,7 +172,6 @@ describe('Deployment', () => { ) artifactExchangeScope.done() - createDeploymentScope.done() }) it('reports errors with failed artifact exchange', async () => { @@ -154,12 +197,23 @@ describe('Deployment', () => { .get('/_apis/pipelines/workflows/123/artifacts?api-version=6.0-preview') .reply(200, { value: [{ url: 'https://invalid-artifact.com', name: 'github-pages' }] }) - const createDeploymentScope = nock('https://api.github.com') - .post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, { - artifact_url: 'https://invalid-artifact.com&%24expand=SignedContent', - pages_build_version: process.env.GITHUB_SHA + mockPool + .intercept({ + path: `/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, + method: 'POST', + body: bodyString => { + const body = JSON.parse(bodyString) + const keys = Object.keys(body).sort() + return ( + keys.length === 2 && + keys[0] === 'artifact_url' && + keys[1] === 'pages_build_version' && + body.artifact_url === 'https://invalid-artifact.com&%24expand=SignedContent' && + body.pages_build_version === process.env.GITHUB_SHA + ) + } }) - .reply(500, { message: 'oh no' }) + .reply(500, { message: 'oh no' }, { headers: { 'content-type': 'application/json' } }) // Create the deployment const deployment = new Deployment() @@ -170,7 +224,6 @@ describe('Deployment', () => { ) artifactExchangeScope.done() - createDeploymentScope.done() }) it('reports errors with an unexpected 403 during deployment', async () => { @@ -179,12 +232,23 @@ describe('Deployment', () => { .get('/_apis/pipelines/workflows/123/artifacts?api-version=6.0-preview') .reply(200, { value: [{ url: 'https://invalid-artifact.com', name: 'github-pages' }] }) - const createDeploymentScope = nock('https://api.github.com') - .post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, { - artifact_url: 'https://invalid-artifact.com&%24expand=SignedContent', - pages_build_version: process.env.GITHUB_SHA + mockPool + .intercept({ + path: `/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, + method: 'POST', + body: bodyString => { + const body = JSON.parse(bodyString) + const keys = Object.keys(body).sort() + return ( + keys.length === 2 && + keys[0] === 'artifact_url' && + keys[1] === 'pages_build_version' && + body.artifact_url === 'https://invalid-artifact.com&%24expand=SignedContent' && + body.pages_build_version === process.env.GITHUB_SHA + ) + } }) - .reply(403, { message: 'You are forbidden' }) + .reply(403, { message: 'You are forbidden' }, { headers: { 'content-type': 'application/json' } }) // Create the deployment const deployment = new Deployment() @@ -195,7 +259,6 @@ describe('Deployment', () => { ) artifactExchangeScope.done() - createDeploymentScope.done() }) it('reports errors with an unexpected 404 during deployment', async () => { @@ -204,12 +267,23 @@ describe('Deployment', () => { .get('/_apis/pipelines/workflows/123/artifacts?api-version=6.0-preview') .reply(200, { value: [{ url: 'https://invalid-artifact.com', name: 'github-pages' }] }) - const createDeploymentScope = nock('https://api.github.com') - .post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, { - artifact_url: 'https://invalid-artifact.com&%24expand=SignedContent', - pages_build_version: process.env.GITHUB_SHA + mockPool + .intercept({ + path: `/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, + method: 'POST', + body: bodyString => { + const body = JSON.parse(bodyString) + const keys = Object.keys(body).sort() + return ( + keys.length === 2 && + keys[0] === 'artifact_url' && + keys[1] === 'pages_build_version' && + body.artifact_url === 'https://invalid-artifact.com&%24expand=SignedContent' && + body.pages_build_version === process.env.GITHUB_SHA + ) + } }) - .reply(404, { message: 'Not found' }) + .reply(404, { message: 'Not found' }, { headers: { 'content-type': 'application/json' } }) // Create the deployment const deployment = new Deployment() @@ -220,7 +294,6 @@ describe('Deployment', () => { ) artifactExchangeScope.done() - createDeploymentScope.done() }) it('reports errors with failed deployments', async () => { @@ -229,12 +302,23 @@ describe('Deployment', () => { .get('/_apis/pipelines/workflows/123/artifacts?api-version=6.0-preview') .reply(200, { value: [{ url: 'https://invalid-artifact.com', name: 'github-pages' }] }) - const createDeploymentScope = nock('https://api.github.com') - .post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, { - artifact_url: 'https://invalid-artifact.com&%24expand=SignedContent', - pages_build_version: process.env.GITHUB_SHA + mockPool + .intercept({ + path: `/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, + method: 'POST', + body: bodyString => { + const body = JSON.parse(bodyString) + const keys = Object.keys(body).sort() + return ( + keys.length === 2 && + keys[0] === 'artifact_url' && + keys[1] === 'pages_build_version' && + body.artifact_url === 'https://invalid-artifact.com&%24expand=SignedContent' && + body.pages_build_version === process.env.GITHUB_SHA + ) + } }) - .reply(400, { message: 'Bad request' }) + .reply(400, { message: 'Bad request' }, { headers: { 'content-type': 'application/json' } }) // Create the deployment const deployment = new Deployment() @@ -245,7 +329,6 @@ describe('Deployment', () => { ) artifactExchangeScope.done() - createDeploymentScope.done() }) it('warns if the artifact size is bigger than maximum', async () => { @@ -261,16 +344,32 @@ describe('Deployment', () => { ] }) - const createDeploymentScope = nock('https://api.github.com') - .post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, { - artifact_url: 'https://fake-artifact.com&%24expand=SignedContent', - pages_build_version: process.env.GITHUB_SHA, - oidc_token: fakeJwt - }) - .reply(200, { - status_url: `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`, - page_url: 'https://actions.github.io/is-awesome' + mockPool + .intercept({ + path: `/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, + method: 'POST', + body: bodyString => { + const body = JSON.parse(bodyString) + const keys = Object.keys(body).sort() + return ( + keys.length === 3 && + keys[0] === 'artifact_url' && + keys[1] === 'oidc_token' && + keys[2] === 'pages_build_version' && + body.artifact_url === 'https://fake-artifact.com&%24expand=SignedContent' && + body.oidc_token === fakeJwt && + body.pages_build_version === process.env.GITHUB_SHA + ) + } }) + .reply( + 200, + { + status_url: `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`, + page_url: 'https://actions.github.io/is-awesome' + }, + { headers: { 'content-type': 'application/json' } } + ) const deployment = new Deployment() await deployment.create(fakeJwt) @@ -284,7 +383,6 @@ describe('Deployment', () => { ) artifactExchangeScope.done() - createDeploymentScope.done() }) it('warns when the timeout is greater than the maximum allowed', async () => { @@ -299,19 +397,36 @@ describe('Deployment', () => { ] }) - const createDeploymentScope = nock('https://api.github.com') - .post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, { - artifact_url: 'https://fake-artifact.com&%24expand=SignedContent', - pages_build_version: process.env.GITHUB_SHA, - oidc_token: fakeJwt - }) - .reply(200, { - status_url: `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`, - page_url: 'https://actions.github.io/is-awesome' + mockPool + .intercept({ + path: `/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, + method: 'POST', + body: bodyString => { + const body = JSON.parse(bodyString) + const keys = Object.keys(body).sort() + return ( + keys.length === 3 && + keys[0] === 'artifact_url' && + keys[1] === 'oidc_token' && + keys[2] === 'pages_build_version' && + body.artifact_url === 'https://fake-artifact.com&%24expand=SignedContent' && + body.oidc_token === fakeJwt && + body.pages_build_version === process.env.GITHUB_SHA + ) + } }) + .reply( + 200, + { + status_url: `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`, + page_url: 'https://actions.github.io/is-awesome' + }, + { headers: { 'content-type': 'application/json' } } + ) core.getIDToken = jest.fn().mockResolvedValue(fakeJwt) + // Set timeout to greater than max jest.spyOn(core, 'getInput').mockImplementation(param => { switch (param) { case 'artifact_name': @@ -333,7 +448,6 @@ describe('Deployment', () => { ) artifactExchangeScope.done() - createDeploymentScope.done() }) }) @@ -350,22 +464,39 @@ describe('Deployment', () => { ] }) - const createDeploymentScope = nock('https://api.github.com') - .post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, { - artifact_url: 'https://fake-artifact.com&%24expand=SignedContent', - pages_build_version: process.env.GITHUB_SHA, - oidc_token: fakeJwt - }) - .reply(200, { - status_url: `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`, - page_url: 'https://actions.github.io/is-awesome' + mockPool + .intercept({ + path: `/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, + method: 'POST', + body: bodyString => { + const body = JSON.parse(bodyString) + const keys = Object.keys(body).sort() + return ( + keys.length === 3 && + keys[0] === 'artifact_url' && + keys[1] === 'oidc_token' && + keys[2] === 'pages_build_version' && + body.artifact_url === 'https://fake-artifact.com&%24expand=SignedContent' && + body.oidc_token === fakeJwt && + body.pages_build_version === process.env.GITHUB_SHA + ) + } }) + .reply( + 200, + { + status_url: `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`, + page_url: 'https://actions.github.io/is-awesome' + }, + { headers: { 'content-type': 'application/json' } } + ) - const deploymentStatusScope = nock('https://api.github.com') - .get(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`) - .reply(200, { - status: 'succeed' + mockPool + .intercept({ + path: `/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`, + method: 'GET' }) + .reply(200, { status: 'succeed' }, { headers: { 'content-type': 'application/json' } }) core.getIDToken = jest.fn().mockResolvedValue(fakeJwt) @@ -378,8 +509,6 @@ describe('Deployment', () => { expect(core.info).toHaveBeenLastCalledWith('Reported success!') artifactExchangeScope.done() - createDeploymentScope.done() - deploymentStatusScope.done() }) it('fails check when no deployment is found', async () => { @@ -401,16 +530,32 @@ describe('Deployment', () => { ] }) - const createDeploymentScope = nock('https://api.github.com') - .post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, { - artifact_url: 'https://fake-artifact.com&%24expand=SignedContent', - pages_build_version: process.env.GITHUB_SHA, - oidc_token: fakeJwt - }) - .reply(200, { - status_url: `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`, - page_url: 'https://actions.github.io/is-awesome' + mockPool + .intercept({ + path: `/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, + method: 'POST', + body: bodyString => { + const body = JSON.parse(bodyString) + const keys = Object.keys(body).sort() + return ( + keys.length === 3 && + keys[0] === 'artifact_url' && + keys[1] === 'oidc_token' && + keys[2] === 'pages_build_version' && + body.artifact_url === 'https://fake-artifact.com&%24expand=SignedContent' && + body.oidc_token === fakeJwt && + body.pages_build_version === process.env.GITHUB_SHA + ) + } }) + .reply( + 200, + { + status_url: `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`, + page_url: 'https://actions.github.io/is-awesome' + }, + { headers: { 'content-type': 'application/json' } } + ) core.getIDToken = jest.fn().mockResolvedValue(fakeJwt) @@ -421,9 +566,9 @@ describe('Deployment', () => { expect(core.setFailed).toBeCalledWith('Unable to get deployment status.') artifactExchangeScope.done() - createDeploymentScope.done() }) + // TODO: Fix! Consistently fails. it('enforces max timeout', async () => { process.env.GITHUB_SHA = 'valid-build-version' @@ -436,24 +581,51 @@ describe('Deployment', () => { ] }) - const createDeploymentScope = nock('https://api.github.com') - .post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, { - artifact_url: 'https://fake-artifact.com&%24expand=SignedContent', - pages_build_version: process.env.GITHUB_SHA, - oidc_token: fakeJwt - }) - .reply(200, { - status_url: `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`, - page_url: 'https://actions.github.io/is-awesome' + mockPool + .intercept({ + path: `/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, + method: 'POST', + body: bodyString => { + const body = JSON.parse(bodyString) + const keys = Object.keys(body).sort() + return ( + keys.length === 3 && + keys[0] === 'artifact_url' && + keys[1] === 'oidc_token' && + keys[2] === 'pages_build_version' && + body.artifact_url === 'https://fake-artifact.com&%24expand=SignedContent' && + body.oidc_token === fakeJwt && + body.pages_build_version === process.env.GITHUB_SHA + ) + } }) + .reply( + 200, + { + status_url: `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`, + page_url: 'https://actions.github.io/is-awesome' + }, + { headers: { 'content-type': 'application/json' } } + ) - const cancelDeploymentScope = nock('https://api.github.com') - .post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}/cancel`) - .reply(200, {}) + mockPool + .intercept({ + path: `/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`, + method: 'GET' + }) + .reply(200, { status: 'deployment_in_progress' }, { headers: { 'content-type': 'application/json' } }) + .times(2) + + mockPool + .intercept({ + path: `/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}/cancel`, + method: 'POST' + }) + .reply(200, {}, { headers: { 'content-type': 'application/json' } }) core.getIDToken = jest.fn().mockResolvedValue(fakeJwt) - // Set timeout to great than max + // Set timeout to greater than max jest.spyOn(core, 'getInput').mockImplementation(param => { switch (param) { case 'artifact_name': @@ -462,6 +634,8 @@ describe('Deployment', () => { return process.env.GITHUB_TOKEN case 'error_count': return 10 + // case 'reporting_interval': + // return 50 // The default of 5000 is too long for the test case 'timeout': return MAX_TIMEOUT + 1 default: @@ -475,6 +649,7 @@ describe('Deployment', () => { .spyOn(Date, 'now') .mockImplementationOnce(() => mockStartTime) .mockImplementationOnce(() => now) + .mockImplementationOnce(() => now + MAX_TIMEOUT) // Create the deployment const deployment = new Deployment() @@ -486,8 +661,6 @@ describe('Deployment', () => { expect(core.setFailed).toBeCalledWith('Timeout reached, aborting!') artifactExchangeScope.done() - createDeploymentScope.done() - cancelDeploymentScope.done() }) it('sets timeout to user timeout if user timeout is less than max timeout', async () => { @@ -502,24 +675,43 @@ describe('Deployment', () => { ] }) - const createDeploymentScope = nock('https://api.github.com') - .post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, { - artifact_url: 'https://fake-artifact.com&%24expand=SignedContent', - pages_build_version: process.env.GITHUB_SHA, - oidc_token: fakeJwt - }) - .reply(200, { - status_url: `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`, - page_url: 'https://actions.github.io/is-awesome' + mockPool + .intercept({ + path: `/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, + method: 'POST', + body: bodyString => { + const body = JSON.parse(bodyString) + const keys = Object.keys(body).sort() + return ( + keys.length === 3 && + keys[0] === 'artifact_url' && + keys[1] === 'oidc_token' && + keys[2] === 'pages_build_version' && + body.artifact_url === 'https://fake-artifact.com&%24expand=SignedContent' && + body.oidc_token === fakeJwt && + body.pages_build_version === process.env.GITHUB_SHA + ) + } }) + .reply( + 200, + { + status_url: `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`, + page_url: 'https://actions.github.io/is-awesome' + }, + { headers: { 'content-type': 'application/json' } } + ) - const cancelDeploymentScope = nock('https://api.github.com') - .post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}/cancel`) - .reply(200, {}) + mockPool + .intercept({ + path: `/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}/cancel`, + method: 'POST' + }) + .reply(200, {}, { headers: { 'content-type': 'application/json' } }) core.getIDToken = jest.fn().mockResolvedValue(fakeJwt) - // Set timeout to great than max + // Set timeout to greater than max jest.spyOn(core, 'getInput').mockImplementation(param => { switch (param) { case 'artifact_name': @@ -552,10 +744,9 @@ describe('Deployment', () => { expect(core.setFailed).toBeCalledWith('Timeout reached, aborting!') artifactExchangeScope.done() - createDeploymentScope.done() - cancelDeploymentScope.done() }) + // TODO: Intermittently fails if the other test does it('sets output to success when timeout is set but not reached', async () => { process.env.GITHUB_SHA = 'valid-build-version' @@ -568,26 +759,43 @@ describe('Deployment', () => { ] }) - const createDeploymentScope = nock('https://api.github.com') - .post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, { - artifact_url: 'https://fake-artifact.com&%24expand=SignedContent', - pages_build_version: process.env.GITHUB_SHA, - oidc_token: fakeJwt - }) - .reply(200, { - status_url: `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`, - page_url: 'https://actions.github.io/is-awesome' + mockPool + .intercept({ + path: `/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, + method: 'POST', + body: bodyString => { + const body = JSON.parse(bodyString) + const keys = Object.keys(body).sort() + return ( + keys.length === 3 && + keys[0] === 'artifact_url' && + keys[1] === 'oidc_token' && + keys[2] === 'pages_build_version' && + body.artifact_url === 'https://fake-artifact.com&%24expand=SignedContent' && + body.oidc_token === fakeJwt && + body.pages_build_version === process.env.GITHUB_SHA + ) + } }) + .reply( + 200, + { + status_url: `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`, + page_url: 'https://actions.github.io/is-awesome' + }, + { headers: { 'content-type': 'application/json' } } + ) - const deploymentStatusScope = nock('https://api.github.com') - .get(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`) - .reply(200, { - status: 'succeed' + mockPool + .intercept({ + path: `/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`, + method: 'GET' }) + .reply(200, { status: 'succeed' }, { headers: { 'content-type': 'application/json' } }) core.getIDToken = jest.fn().mockResolvedValue(fakeJwt) - // Set timeout to great than max + // Set timeout to greater than max jest.spyOn(core, 'getInput').mockImplementation(param => { switch (param) { case 'artifact_name': @@ -604,7 +812,7 @@ describe('Deployment', () => { }) const now = Date.now() - const mockStartTime = now + const mockStartTime = now // No time elapsed jest .spyOn(Date, 'now') .mockImplementationOnce(() => mockStartTime) @@ -621,8 +829,6 @@ describe('Deployment', () => { expect(core.info).toHaveBeenLastCalledWith('Reported success!') artifactExchangeScope.done() - createDeploymentScope.done() - deploymentStatusScope.done() }) }) @@ -639,20 +845,39 @@ describe('Deployment', () => { ] }) - const createDeploymentScope = nock('https://api.github.com') - .post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, { - artifact_url: 'https://fake-artifact.com&%24expand=SignedContent', - pages_build_version: process.env.GITHUB_SHA, - oidc_token: fakeJwt - }) - .reply(200, { - status_url: `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`, - page_url: 'https://actions.github.io/is-awesome' + mockPool + .intercept({ + path: `/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, + method: 'POST', + body: bodyString => { + const body = JSON.parse(bodyString) + const keys = Object.keys(body).sort() + return ( + keys.length === 3 && + keys[0] === 'artifact_url' && + keys[1] === 'oidc_token' && + keys[2] === 'pages_build_version' && + body.artifact_url === 'https://fake-artifact.com&%24expand=SignedContent' && + body.oidc_token === fakeJwt && + body.pages_build_version === process.env.GITHUB_SHA + ) + } }) + .reply( + 200, + { + status_url: `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`, + page_url: 'https://actions.github.io/is-awesome' + }, + { headers: { 'content-type': 'application/json' } } + ) - const cancelDeploymentScope = nock('https://api.github.com') - .post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}/cancel`) - .reply(200, {}) + mockPool + .intercept({ + path: `/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}/cancel`, + method: 'POST' + }) + .reply(200, {}, { headers: { 'content-type': 'application/json' } }) core.getIDToken = jest.fn().mockResolvedValue(fakeJwt) @@ -666,8 +891,6 @@ describe('Deployment', () => { expect(core.info).toHaveBeenLastCalledWith(`Canceled deployment with ID ${process.env.GITHUB_SHA}`) artifactExchangeScope.done() - createDeploymentScope.done() - cancelDeploymentScope.done() }) it('can exit if a pages deployment was not created and none need to be cancelled', async () => { @@ -695,21 +918,39 @@ describe('Deployment', () => { ] }) - const createDeploymentScope = nock('https://api.github.com') - .post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, { - artifact_url: 'https://fake-artifact.com&%24expand=SignedContent', - pages_build_version: process.env.GITHUB_SHA, - oidc_token: fakeJwt - }) - .reply(200, { - status_url: `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`, - page_url: 'https://actions.github.io/is-awesome' + mockPool + .intercept({ + path: `/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments`, + method: 'POST', + body: bodyString => { + const body = JSON.parse(bodyString) + const keys = Object.keys(body).sort() + return ( + keys.length === 3 && + keys[0] === 'artifact_url' && + keys[1] === 'oidc_token' && + keys[2] === 'pages_build_version' && + body.artifact_url === 'https://fake-artifact.com&%24expand=SignedContent' && + body.oidc_token === fakeJwt && + body.pages_build_version === process.env.GITHUB_SHA + ) + } }) + .reply( + 200, + { + status_url: `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}`, + page_url: 'https://actions.github.io/is-awesome' + }, + { headers: { 'content-type': 'application/json' } } + ) - // nock will throw an error every time it tries to cancel the deployment - const cancelDeploymentScope = nock('https://api.github.com') - .post(`/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}/cancel`) - .reply(500, {}) + mockPool + .intercept({ + path: `/repos/${process.env.GITHUB_REPOSITORY}/pages/deployments/${process.env.GITHUB_SHA}/cancel`, + method: 'POST' + }) + .reply(500, {}, { headers: { 'content-type': 'application/json' } }) core.getIDToken = jest.fn().mockResolvedValue(fakeJwt) @@ -723,8 +964,6 @@ describe('Deployment', () => { expect(core.error).toHaveBeenCalledWith(`Canceling Pages deployment failed`, expect.anything()) artifactExchangeScope.done() - createDeploymentScope.done() - cancelDeploymentScope.done() }) }) })