diff --git a/__tests__/index.test.ts b/__tests__/index.test.ts index 30bda16..8d7a010 100644 --- a/__tests__/index.test.ts +++ b/__tests__/index.test.ts @@ -1,15 +1,80 @@ -import { wait } from '../src/wait' -import { expect, test } from '@jest/globals' +/** + * Unit tests for the action's entrypoint, src/index.ts + * + * These should be run as if the action was called from a workflow. + * Specifically, the inputs listed in `action.yml` should be set as environment + * variables following the pattern `INPUT_`. + */ -test('throws invalid number', async () => { - const input = parseInt('foo', 10) - await expect(wait(input)).rejects.toThrow('milliseconds not a number') -}) +import * as core from '@actions/core' +import * as index from '../src/index' -test('wait 500 ms', async () => { - const start = new Date() - await wait(500) - const end = new Date() - const delta = Math.abs(end.getTime() - start.getTime()) - expect(delta).toBeGreaterThan(450) +// Mock the GitHub Actions core library +const debugMock = jest.spyOn(core, 'debug') +const getInputMock = jest.spyOn(core, 'getInput') +const setFailedMock = jest.spyOn(core, 'setFailed') +const setOutputMock = jest.spyOn(core, 'setOutput') + +// Mock the action's entrypoint +const runMock = jest.spyOn(index, 'run') + +// Other utilities +const timeRegex = /^\d{2}:\d{2}:\d{2}/ + +describe('action', () => { + beforeEach(() => { + jest.clearAllMocks() + }) + + it('sets the time output', async () => { + // Set the action's inputs as return values from core.getInput() + getInputMock.mockImplementation((name: string): string => { + switch (name) { + case 'milliseconds': + return '500' + default: + return '' + } + }) + + await index.run() + expect(runMock).toHaveReturned() + + // Verify that all of the core library functions were called correctly + expect(debugMock).toHaveBeenNthCalledWith(1, 'Waiting 500 milliseconds ...') + expect(debugMock).toHaveBeenNthCalledWith( + 2, + expect.stringMatching(timeRegex) + ) + expect(debugMock).toHaveBeenNthCalledWith( + 3, + expect.stringMatching(timeRegex) + ) + expect(setOutputMock).toHaveBeenNthCalledWith( + 1, + 'time', + expect.stringMatching(timeRegex) + ) + }) + + it('sets a failed status', async () => { + // Set the action's inputs as return values from core.getInput() + getInputMock.mockImplementation((name: string): string => { + switch (name) { + case 'milliseconds': + return 'this is not a number' + default: + return '' + } + }) + + await index.run() + expect(runMock).toHaveReturned() + + // Verify that all of the core library functions were called correctly + expect(setFailedMock).toHaveBeenNthCalledWith( + 1, + 'milliseconds not a number' + ) + }) }) diff --git a/__tests__/wait.test.ts b/__tests__/wait.test.ts new file mode 100644 index 0000000..1336aaa --- /dev/null +++ b/__tests__/wait.test.ts @@ -0,0 +1,25 @@ +/** + * Unit tests for src/wait.ts + */ + +import { wait } from '../src/wait' +import { expect } from '@jest/globals' + +describe('wait.ts', () => { + it('throws an invalid number', async () => { + const input = parseInt('foo', 10) + expect(isNaN(input)).toBe(true) + + await expect(wait(input)).rejects.toThrow('milliseconds not a number') + }) + + it('waits with a valid number', async () => { + const start = new Date() + await wait(500) + const end = new Date() + + const delta = Math.abs(end.getTime() - start.getTime()) + + expect(delta).toBeGreaterThan(450) + }) +}) diff --git a/badges/coverage.svg b/badges/coverage.svg index 8c73e34..5bb55be 100644 --- a/badges/coverage.svg +++ b/badges/coverage.svg @@ -1 +1 @@ -Coverage: 33.33%Coverage33.33% \ No newline at end of file +Coverage: 100%Coverage100% \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index 9fad885..b6fbd26 100644 --- a/dist/index.js +++ b/dist/index.js @@ -2751,6 +2751,7 @@ var __importStar = (this && this.__importStar) || function (mod) { return result; }; Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.run = void 0; const core = __importStar(__nccwpck_require__(186)); const wait_1 = __nccwpck_require__(259); /** @@ -2775,6 +2776,7 @@ async function run() { core.setFailed(error.message); } } +exports.run = run; // eslint-disable-next-line @typescript-eslint/no-floating-promises run(); diff --git a/src/index.ts b/src/index.ts index 8af1760..b6f3f31 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,7 +5,7 @@ import { wait } from './wait' * The main function for the action. * @returns {Promise} Resolves when the action is complete. */ -async function run(): Promise { +export async function run(): Promise { try { const ms: string = core.getInput('milliseconds')