Skip to content

Commit 929eebe

Browse files
authored
Add omit input, deprecate others (#15)
* add omit input, deprecate others * naming * docs + additional dist checking * quickstart
1 parent 89f9398 commit 929eebe

File tree

13 files changed

+398
-143
lines changed

13 files changed

+398
-143
lines changed

.github/workflows/test.yml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
name: test
22

33
on:
4-
push:
5-
branches: [ main ]
64
pull_request:
75
branches: [ main ]
86

@@ -17,3 +15,14 @@ jobs:
1715
node-version: 20
1816
- run: npm ci
1917
- run: npm test
18+
- run: npm run build
19+
- name: check dist
20+
run: |
21+
changed_files_count=$(git status --porcelain | wc -l)
22+
if [ $changed_files_count -ne 0 ]; then
23+
echo 'mismatched files from ncc generation! did you forget to run `npm run build`?' | tee -a $GITHUB_STEP_SUMMARY
24+
echo '```diff' >> $GITHUB_STEP_SUMMARY
25+
git diff >> $GITHUB_STEP_SUMMARY
26+
echo '```' >> $GITHUB_STEP_SUMMARY
27+
exit 1
28+
fi

README.md

Lines changed: 79 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,56 @@
11
# go-test-action
22

3-
GitHub Action for running `go test ...` and getting rich summary and annotations as output.
3+
- [go-test-action](#go-test-action)
4+
- [Quick start](#quick-start)
5+
- [Inputs](#inputs)
6+
- [Screenshots](#screenshots)
7+
- [Examples](#examples)
8+
- [Basic](#basic)
9+
- [Using existing test file](#using-existing-test-file)
10+
- [Omitting elements](#omitting-elements)
11+
12+
GitHub Action for running `go test ./...` and getting rich summary and annotations as output.
413

514
Powered by [Job Summaries](https://github.blog/2022-05-09-supercharging-github-actions-with-job-summaries/), this Action will generate a convenient interactive viewer for tests based on Go's [test2json](https://pkg.go.dev/cmd/test2json) output. If there are any errors during `go test`, the Action will report back the same exit code, which will fail the job.
615

16+
## Quick start
17+
18+
```yaml
19+
- name: Test
20+
uses: robherley/go-test-action@v0
21+
```
22+
723
## Inputs
824
9-
| Input | Default | Description |
10-
| - | - | - |
11-
| moduleDirectory | `.` | relative path to the directory containing the `go.mod` of the module you wish to test |
12-
| testArguments | `./...` | arguments to pass to `go test`, `-json` will be prepended automatically |
13-
| fromJSONFile | null | parse an exisiting [test2json](https://pkg.go.dev/cmd/test2json) file, instead of executing go test |
14-
| omitUntestedPackages | `false` | omit any go packages that don't have any tests from the summary output |
15-
| omitSuccessfulPackages | `false` | omit any go packages that didn't contain failed tests |
16-
| omitPie | `false` | omit the pie chart from the summary output
25+
```yaml
26+
- uses: robherley/go-test-action@v0
27+
with:
28+
# Relative path to the directory containing the go.mod of the module you wish to test.
29+
# Optional. Default is '.'
30+
moduleDirectory:
31+
32+
# Arguments to pass to go test, -json will be prepended automatically.
33+
# Optional. Default is './...'
34+
testArguments:
35+
36+
# Parse an exisiting [test2json](https://pkg.go.dev/cmd/test2json) file, instead of executing go test.
37+
# Will always exit(0) on successful test file parse.
38+
# Optional. No default
39+
fromJSONFile:
40+
41+
# Whitespace separated list of renderable items to omit.
42+
# Valid options to omit are:
43+
# untested: packages that have no tests
44+
# successful: packages that are successful
45+
# pie: mermaid.js pie chart
46+
# pkg-tests: per-package test list
47+
# pkg-output: per-package test output
48+
# stderr: standard error output of `go test` subprocess
49+
# Optional. No default
50+
omit:
51+
```
1752
18-
## Demo
53+
## Screenshots
1954
2055
Tests are organized per package, with a brief summary of individual test results:
2156
@@ -25,7 +60,9 @@ Expand for per-test (with subtest) results and to view raw test output:
2560
2661
![summary expanded](docs/img/expanded.png)
2762
28-
## Example workflow
63+
## Examples
64+
65+
### Basic
2966
3067
```yaml
3168
name: Go
@@ -48,6 +85,36 @@ jobs:
4885
run: go build -v ./...
4986

5087
- name: Test
51-
uses: robherley/[email protected]
88+
uses: robherley/go-test-action@v0
89+
```
90+
91+
### Using existing test file
92+
93+
```yaml
94+
- name: Test
95+
uses: robherley/go-test-action@v0
96+
with:
97+
fromJSONFile: /path/to/test2json.json
98+
```
99+
100+
### Omitting elements
101+
102+
See [Inputs](#inputs) above for valid options
103+
104+
```yaml
105+
- name: Test
106+
uses: robherley/go-test-action@v0
107+
with:
108+
omit: |
109+
pie
110+
stderr
52111
```
53112
113+
or
114+
115+
```yaml
116+
- name: Test
117+
uses: robherley/go-test-action@v0
118+
with:
119+
omit: 'pie'
120+
```

__tests__/helpers.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,7 @@ export const removeSummaryFile = async () => {
3535
export const setupActionsInputs = () => {
3636
process.env['INPUT_MODULEDIRECTORY'] = testModuleDirectory
3737
process.env['INPUT_TESTARGUMENTS'] = testArguments
38-
process.env['INPUT_OMITUNTESTEDPACKAGES'] = 'false'
39-
process.env['INPUT_OMITPIE'] = 'false'
38+
process.env['INPUT_OMIT'] = ''
4039
}
4140

4241
export const createFakeGoModule = async () => {

__tests__/inputs.test.ts

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import * as core from '@actions/core'
2+
import { OmitOption, getInputs } from '../src/inputs'
3+
4+
jest.mock('@actions/core')
5+
6+
const mockGetInput = core.getInput as jest.MockedFunction<typeof core.getInput>
7+
const mockGetBooleanInput = core.getBooleanInput as jest.MockedFunction<
8+
typeof core.getBooleanInput
9+
>
10+
11+
const mockInput = (name: string, value: string) => {
12+
mockGetInput.mockImplementation((n: string) => (n === name ? value : ''))
13+
}
14+
15+
describe('renderer', () => {
16+
beforeEach(() => {
17+
jest.resetAllMocks()
18+
})
19+
20+
it('uses default values', () => {
21+
mockGetInput.mockReturnValue('')
22+
const inputs = getInputs()
23+
24+
expect(inputs).toEqual({
25+
moduleDirectory: '.',
26+
testArguments: ['./...'],
27+
fromJSONFile: null,
28+
omit: new Set(),
29+
})
30+
})
31+
32+
it('parses moduleDirectory', () => {
33+
mockInput('moduleDirectory', 'foo')
34+
const inputs = getInputs()
35+
36+
expect(inputs.moduleDirectory).toEqual('foo')
37+
})
38+
39+
it('parses testArguments', () => {
40+
mockInput('testArguments', 'foo bar')
41+
const inputs = getInputs()
42+
43+
expect(inputs.testArguments).toEqual(['foo', 'bar'])
44+
})
45+
46+
it('parses fromJSONFile', () => {
47+
mockInput('fromJSONFile', 'foo.json')
48+
const inputs = getInputs()
49+
50+
expect(inputs.fromJSONFile).toEqual('foo.json')
51+
})
52+
53+
it('parses omit', () => {
54+
mockInput(
55+
'omit',
56+
[...Object.values(OmitOption), 'foo', 'bar', 'baz'].join('\n')
57+
)
58+
const inputs = getInputs()
59+
60+
expect(inputs.omit).toEqual(new Set(Object.values(OmitOption)))
61+
})
62+
63+
it('supports deprecated inputs', () => {
64+
mockGetInput.mockImplementation((name: string) => {
65+
switch (name) {
66+
case 'omitUntestedPackages':
67+
case 'omitSuccessfulPackages':
68+
case 'omitPie':
69+
return 'true'
70+
default:
71+
return ''
72+
}
73+
})
74+
75+
mockGetBooleanInput.mockReturnValue(true)
76+
77+
const inputs = getInputs()
78+
expect(inputs.omit).toEqual(
79+
new Set([OmitOption.Untested, OmitOption.Successful, OmitOption.Pie])
80+
)
81+
expect(core.warning).toHaveBeenCalled()
82+
})
83+
})

__tests__/renderer.test.ts

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
import { parseTestEvents } from '../src/events'
1313
import Renderer from '../src/renderer'
1414
import { SummaryTableCell } from '@actions/core/lib/summary'
15+
import { OmitOption } from '../src/inputs'
1516

1617
const loadSummaryHTML = async (): Promise<cheerio.CheerioAPI> => {
1718
const file = await fs.readFile(testSummaryFilePath, { encoding: 'utf8' })
@@ -26,9 +27,7 @@ const getRenderer = async (): Promise<Renderer> => {
2627
'github.com/robherley/go-test-example',
2728
testEvents,
2829
'', // stderr
29-
false, // omitUntestedPackages
30-
false, // omitSuccessfulPackages
31-
false // omitPie
30+
new Set()
3231
)
3332
}
3433

@@ -105,9 +104,7 @@ describe('renderer', () => {
105104
'github.com/robherley/empty-module',
106105
[],
107106
'',
108-
false,
109-
false,
110-
false
107+
new Set()
111108
)
112109
await renderer.writeSummary()
113110

@@ -169,9 +166,9 @@ describe('renderer', () => {
169166
expect($.text()).toContain(pieData)
170167
})
171168

172-
it('does not render pie when omitPie is true', async () => {
169+
it('does not render pie when pie in omit', async () => {
173170
const renderer = await getRenderer()
174-
renderer.omitPie = true
171+
renderer.omit.add(OmitOption.Pie)
175172
await renderer.writeSummary()
176173
const $ = await loadSummaryHTML()
177174

@@ -201,22 +198,22 @@ describe('renderer', () => {
201198
})
202199
})
203200

204-
it('renders correct number of table rows when omitUntestedPackages is true', async () => {
201+
it('renders correct number of table rows when untested is in omit', async () => {
205202
const renderer = await getRenderer()
206-
renderer.omitUntestedPackages = true
203+
renderer.omit.add(OmitOption.Untested)
207204
await renderer.writeSummary()
208205
const $ = await loadSummaryHTML()
209206

210207
expect($('tr')).toHaveLength(7)
211208
})
212209

213-
it('renders correct number of table rows when omitUntestedPackages is true', async () => {
210+
it('renders correct number of table rows when successful is in omit', async () => {
214211
const renderer = await getRenderer()
215-
renderer.omitUntestedPackages = true
212+
renderer.omit.add(OmitOption.Successful)
216213
await renderer.writeSummary()
217214
const $ = await loadSummaryHTML()
218215

219-
expect($('tr')).toHaveLength(7)
216+
expect($('tr')).toHaveLength(5)
220217
})
221218

222219
it('does not render stderr when empty', async () => {
@@ -237,4 +234,41 @@ describe('renderer', () => {
237234
expect($('summary:contains(Standard Error Output)')).toHaveLength(1)
238235
expect($('details:contains(hello world)')).toHaveLength(1)
239236
})
237+
238+
it('does not render stderr when in omit', async () => {
239+
const renderer = await getRenderer()
240+
renderer.omit.add(OmitOption.Stderr)
241+
renderer.stderr = 'i should not be rendered'
242+
await renderer.writeSummary()
243+
const $ = await loadSummaryHTML()
244+
245+
expect($('summary:contains(Standard Error Output)')).toHaveLength(0)
246+
})
247+
248+
it('renders package test and output list', async () => {
249+
const renderer = await getRenderer()
250+
await renderer.writeSummary()
251+
const $ = await loadSummaryHTML()
252+
253+
expect($('summary:contains(🧪 Tests)')).toHaveLength(4)
254+
expect($('summary:contains(🖨️ Output)')).toHaveLength(4)
255+
})
256+
257+
it('does not render package test list when in omit', async () => {
258+
const renderer = await getRenderer()
259+
renderer.omit.add(OmitOption.PackageTests)
260+
await renderer.writeSummary()
261+
const $ = await loadSummaryHTML()
262+
263+
expect($('summary:contains(🧪 Tests)')).toHaveLength(0)
264+
})
265+
266+
it('does not render package output list when in omit', async () => {
267+
const renderer = await getRenderer()
268+
renderer.omit.add(OmitOption.PackageOutput)
269+
await renderer.writeSummary()
270+
const $ = await loadSummaryHTML()
271+
272+
expect($('summary:contains(🖨️ Output)')).toHaveLength(0)
273+
})
240274
})

__tests__/runner.test.ts

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,32 +23,6 @@ describe('runner', () => {
2323
setupActionsInputs()
2424
})
2525

26-
it("sets defaults if inputs aren't set", async () => {
27-
delete process.env['INPUT_MODULEDIRECTORY']
28-
delete process.env['INPUT_TESTARGUMENTS']
29-
delete process.env['INPUT_OMITUNTESTEDPACKAGES']
30-
delete process.env['INPUT_OMITPIE']
31-
32-
const runner = new Runner()
33-
expect(runner.moduleDirectory).toBe('.')
34-
expect(runner.testArguments).toEqual(['./...'])
35-
expect(runner.omitUntestedPackages).toEqual(false)
36-
expect(runner.omitPie).toEqual(false)
37-
})
38-
39-
it('uses inputs if they are set', async () => {
40-
process.env['INPUT_MODULEDIRECTORY'] = '/some/random/directory'
41-
process.env['INPUT_TESTARGUMENTS'] = '-foo -bar\t-baz'
42-
process.env['INPUT_OMITUNTESTEDPACKAGES'] = 'true'
43-
process.env['INPUT_OMITPIE'] = 'true'
44-
45-
const runner = new Runner()
46-
expect(runner.moduleDirectory).toBe('/some/random/directory')
47-
expect(runner.testArguments).toEqual(['-foo', '-bar', '-baz'])
48-
expect(runner.omitUntestedPackages).toEqual(true)
49-
expect(runner.omitPie).toEqual(true)
50-
})
51-
5226
it('resolves module name from go.mod', async () => {
5327
const runner = new Runner()
5428
const modName = await runner.findModuleName()

0 commit comments

Comments
 (0)