Update example tests

This commit is contained in:
Nick Alteen 2023-08-24 13:26:10 -04:00
parent 5b3fb38370
commit 05e1cb88d5
5 changed files with 106 additions and 14 deletions

View File

@ -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_<INPUT_NAME>`.
*/
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'
)
})
})

25
__tests__/wait.test.ts Normal file
View File

@ -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)
})
})

View File

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="116" height="20" role="img" aria-label="Coverage: 33.33%"><title>Coverage: 33.33%</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="116" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="63" height="20" fill="#555"/><rect x="63" width="53" height="20" fill="#e05d44"/><rect width="116" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="325" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="530">Coverage</text><text x="325" y="140" transform="scale(.1)" fill="#fff" textLength="530">Coverage</text><text aria-hidden="true" x="885" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">33.33%</text><text x="885" y="140" transform="scale(.1)" fill="#fff" textLength="430">33.33%</text></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="106" height="20" role="img" aria-label="Coverage: 100%"><title>Coverage: 100%</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="106" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="63" height="20" fill="#555"/><rect x="63" width="43" height="20" fill="#4c1"/><rect width="106" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="325" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="530">Coverage</text><text x="325" y="140" transform="scale(.1)" fill="#fff" textLength="530">Coverage</text><text aria-hidden="true" x="835" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="330">100%</text><text x="835" y="140" transform="scale(.1)" fill="#fff" textLength="330">100%</text></g></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

2
dist/index.js generated vendored
View File

@ -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();

View File

@ -5,7 +5,7 @@ import { wait } from './wait'
* The main function for the action.
* @returns {Promise<void>} Resolves when the action is complete.
*/
async function run(): Promise<void> {
export async function run(): Promise<void> {
try {
const ms: string = core.getInput('milliseconds')