|
1 | 1 | /** |
2 | 2 | * Unit tests for the action's main functionality, src/main.ts |
3 | | - * |
4 | | - * To mock dependencies in ESM, you can create fixtures that export mock |
5 | | - * functions and objects. For example, the core module is mocked in this test, |
6 | | - * so that the actual '@actions/core' module is not imported. |
7 | 3 | */ |
8 | 4 | import { jest } from '@jest/globals' |
9 | 5 | import * as core from '../__fixtures__/core.js' |
10 | | -import { wait } from '../__fixtures__/wait.js' |
11 | 6 |
|
12 | 7 | // Mocks should be declared before the module being tested is imported. |
13 | 8 | jest.unstable_mockModule('@actions/core', () => core) |
14 | | -jest.unstable_mockModule('../src/wait.js', () => ({ wait })) |
| 9 | +jest.unstable_mockModule('node:fs', () => ({ |
| 10 | + writeFileSync: jest.fn<(...args: unknown[]) => void>() |
| 11 | +})) |
| 12 | + |
| 13 | +// Mock gensvg to avoid heavy physics simulation in tests |
| 14 | +const mockGensvg = jest |
| 15 | + .fn<(...args: unknown[]) => Promise<string>>() |
| 16 | + .mockResolvedValue('<svg>test</svg>' as never) |
| 17 | +jest.unstable_mockModule('../src/gensvg.js', () => ({ |
| 18 | + gensvg: mockGensvg |
| 19 | +})) |
15 | 20 |
|
16 | | -// The module being tested should be imported dynamically. This ensures that the |
17 | | -// mocks are used in place of any actual dependencies. |
18 | 21 | const { run } = await import('../src/main.js') |
19 | 22 |
|
20 | 23 | describe('main.ts', () => { |
21 | 24 | beforeEach(() => { |
22 | | - // Set the action's inputs as return values from core.getInput(). |
23 | | - core.getInput.mockImplementation(() => '500') |
24 | | - |
25 | | - // Mock the wait function so that it does not actually wait. |
26 | | - wait.mockImplementation(() => Promise.resolve('done!')) |
| 25 | + core.getInput.mockImplementation((name: string) => { |
| 26 | + if (name === 'username') return 'testuser' |
| 27 | + return '' |
| 28 | + }) |
27 | 29 | }) |
28 | 30 |
|
29 | 31 | afterEach(() => { |
30 | 32 | jest.resetAllMocks() |
31 | 33 | }) |
32 | 34 |
|
33 | | - it('Sets the time output', async () => { |
| 35 | + it('generates SVG and sets output', async () => { |
34 | 36 | await run() |
35 | 37 |
|
36 | | - // Verify the time output was set. |
37 | | - expect(core.setOutput).toHaveBeenNthCalledWith( |
38 | | - 1, |
39 | | - 'time', |
40 | | - // Simple regex to match a time string in the format HH:MM:SS. |
41 | | - expect.stringMatching(/^\d{2}:\d{2}:\d{2}/) |
42 | | - ) |
| 38 | + expect(core.setOutput).toHaveBeenCalledWith('svg-path', 'gravity.svg') |
43 | 39 | }) |
44 | 40 |
|
45 | | - it('Sets a failed status', async () => { |
46 | | - // Clear the getInput mock and return an invalid value. |
47 | | - core.getInput.mockClear().mockReturnValueOnce('this is not a number') |
| 41 | + it('uses custom output path', async () => { |
| 42 | + core.getInput.mockImplementation((name: string) => { |
| 43 | + if (name === 'username') return 'testuser' |
| 44 | + if (name === 'output-path') return 'custom.svg' |
| 45 | + return '' |
| 46 | + }) |
| 47 | + |
| 48 | + await run() |
| 49 | + |
| 50 | + expect(core.setOutput).toHaveBeenCalledWith('svg-path', 'custom.svg') |
| 51 | + }) |
| 52 | + |
| 53 | + it('uses text input when provided', async () => { |
| 54 | + core.getInput.mockImplementation((name: string) => { |
| 55 | + if (name === 'username') return 'testuser' |
| 56 | + if (name === 'text') return 'Custom Text' |
| 57 | + return '' |
| 58 | + }) |
| 59 | + |
| 60 | + await run() |
48 | 61 |
|
49 | | - // Clear the wait mock and return a rejected promise. |
50 | | - wait |
51 | | - .mockClear() |
52 | | - .mockRejectedValueOnce(new Error('milliseconds is not a number')) |
| 62 | + expect(mockGensvg).toHaveBeenCalledWith( |
| 63 | + expect.objectContaining({ |
| 64 | + username: 'testuser', |
| 65 | + text: 'Custom Text' |
| 66 | + }) |
| 67 | + ) |
| 68 | + }) |
| 69 | + |
| 70 | + it('falls back to username when text is empty', async () => { |
| 71 | + core.getInput.mockImplementation((name: string) => { |
| 72 | + if (name === 'username') return 'testuser' |
| 73 | + return '' |
| 74 | + }) |
53 | 75 |
|
54 | 76 | await run() |
55 | 77 |
|
56 | | - // Verify that the action was marked as failed. |
57 | | - expect(core.setFailed).toHaveBeenNthCalledWith( |
58 | | - 1, |
59 | | - 'milliseconds is not a number' |
| 78 | + expect(mockGensvg).toHaveBeenCalledWith( |
| 79 | + expect.objectContaining({ |
| 80 | + username: 'testuser', |
| 81 | + text: 'testuser' |
| 82 | + }) |
60 | 83 | ) |
61 | 84 | }) |
| 85 | + |
| 86 | + it('sets failed status on error', async () => { |
| 87 | + mockGensvg.mockRejectedValueOnce(new Error('Simulation failed')) |
| 88 | + |
| 89 | + await run() |
| 90 | + |
| 91 | + expect(core.setFailed).toHaveBeenCalledWith('Simulation failed') |
| 92 | + }) |
62 | 93 | }) |
0 commit comments