Skip to content

Commit b16e5bf

Browse files
authored
Merge pull request #4 from caseycs/allow-emty-map
allow empty map #3
2 parents 61d627a + 37a1015 commit b16e5bf

File tree

7 files changed

+441
-144
lines changed

7 files changed

+441
-144
lines changed

.github/workflows/ci.yml

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,26 @@ jobs:
5353
id: checkout
5454
uses: actions/checkout@v4
5555

56-
- name: Test Local Action
57-
id: test-action
56+
- name: Test Local Action 1
57+
id: test-action-1
5858
uses: ./
5959
with:
6060
key: staging-5
6161
map: |
6262
staging-\d+: staging
6363
64-
- name: Print Output
65-
id: output
66-
run: echo "${{ steps.test-action.outputs.value }}"
64+
- name: Test Local Action 1 - print output
65+
run: set -e; [ "${{ steps.test-action-1.outputs.value }}" == "staging" ]
66+
67+
- name: Test Local Action 2
68+
id: test-action-2
69+
uses: ./
70+
with:
71+
key: staging-5
72+
allow_empty_map: true
73+
mode: fallback-to-original
74+
map: ''
75+
76+
- name: Test Local Action 2 - print output
77+
run:
78+
set -e; [ "${{ steps.test-action-2.outputs.value }}" == "staging-5" ]

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,21 @@ Also showcasing different output options
9393
echo ${{ steps.mapper.outputs.value }}
9494
# playground
9595
```
96+
97+
## Edge case - map can be empty
98+
99+
Mode `strict` is not supported in this case
100+
101+
```yaml
102+
- uses: caseycs/single-variable-mapper@master
103+
id: mapper
104+
with:
105+
key: staging-5
106+
map: ''
107+
mode: fallback-to-original
108+
allow_empty_map: true
109+
- name: Print mapped value
110+
run: |
111+
echo ${{ steps.mapper.outputs.value }}
112+
# staging-5
113+
```

__tests__/main.test.ts

Lines changed: 138 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,107 @@ describe('correct input values, edge cases', () => {
190190
})
191191
})
192192

193+
describe('allowed empty map', () => {
194+
beforeEach(() => {
195+
jest.clearAllMocks()
196+
197+
errorMock = jest.spyOn(core, 'error').mockImplementation()
198+
getInputMock = jest.spyOn(core, 'getInput').mockImplementation()
199+
setFailedMock = jest.spyOn(core, 'setFailed').mockImplementation()
200+
setOutputMock = jest.spyOn(core, 'setOutput').mockImplementation()
201+
exportVariableMock = jest.spyOn(core, 'exportVariable').mockImplementation()
202+
})
203+
204+
it('map not empty, fallback-to-default', () => {
205+
const input: { [name: string]: string } = {
206+
key: 'k1',
207+
map: 'k1:v2',
208+
separator: ':',
209+
export_to: 'output',
210+
mode: 'fallback-to-default',
211+
allow_empty_map: '1'
212+
}
213+
getInputMock.mockImplementation(name => input[name])
214+
215+
main.run()
216+
expect(runMock).toHaveReturned()
217+
218+
expect(errorMock).not.toHaveBeenCalled()
219+
expect(exportVariableMock).not.toHaveBeenCalled()
220+
expect(setFailedMock).not.toHaveBeenCalled()
221+
222+
expect(setOutputMock).toHaveBeenNthCalledWith(1, 'value', 'v2')
223+
})
224+
225+
it('map not empty, strict', () => {
226+
const input: { [name: string]: string } = {
227+
key: 'k1',
228+
map: 'k1:v2',
229+
separator: ':',
230+
export_to: 'output',
231+
mode: 'strict',
232+
allow_empty_map: '1'
233+
}
234+
getInputMock.mockImplementation(name => input[name])
235+
236+
main.run()
237+
expect(runMock).toHaveReturned()
238+
239+
expect(errorMock).not.toHaveBeenCalled()
240+
expect(exportVariableMock).not.toHaveBeenCalled()
241+
expect(setOutputMock).not.toHaveBeenCalled()
242+
243+
expect(setFailedMock).toHaveBeenNthCalledWith(
244+
1,
245+
'Strict mode is not possible when empty map is allowed'
246+
)
247+
})
248+
249+
it('map empty, fallback-to-default', () => {
250+
const input: { [name: string]: string } = {
251+
key: 'k1',
252+
map: '',
253+
separator: ':',
254+
export_to: 'output',
255+
mode: 'fallback-to-default',
256+
default: 'v2',
257+
allow_empty_map: '1'
258+
}
259+
getInputMock.mockImplementation(name => input[name])
260+
261+
main.run()
262+
expect(runMock).toHaveReturned()
263+
264+
expect(errorMock).not.toHaveBeenCalled()
265+
expect(exportVariableMock).not.toHaveBeenCalled()
266+
expect(setFailedMock).not.toHaveBeenCalled()
267+
268+
expect(setOutputMock).toHaveBeenNthCalledWith(1, 'value', 'v2')
269+
})
270+
271+
it('map empty, fallback-to-original', () => {
272+
const input: { [name: string]: string } = {
273+
key: 'k1',
274+
map: '',
275+
separator: ':',
276+
export_to: 'output',
277+
mode: 'fallback-to-original',
278+
default: 'v2',
279+
allow_empty_map: '1'
280+
}
281+
getInputMock.mockImplementation(name => input[name])
282+
283+
main.run()
284+
expect(runMock).toHaveReturned()
285+
286+
expect(errorMock).not.toHaveBeenCalled()
287+
expect(exportVariableMock).not.toHaveBeenCalled()
288+
expect(setFailedMock).not.toHaveBeenCalled()
289+
290+
expect(setOutputMock).toHaveBeenNthCalledWith(1, 'value', 'k1')
291+
})
292+
})
293+
193294
describe('input validation', () => {
194295
beforeEach(() => {
195296
jest.clearAllMocks()
@@ -204,7 +305,10 @@ describe('input validation', () => {
204305
it('empty key', () => {
205306
const input: { [name: string]: string } = {
206307
key: '',
207-
map: 'k1:v1'
308+
map: 'k1:v1',
309+
separator: ':',
310+
mode: 'strict',
311+
export_to: 'output'
208312
}
209313
getInputMock.mockImplementation(name => input[name])
210314

@@ -221,7 +325,9 @@ describe('input validation', () => {
221325
it('empty map', () => {
222326
const input: { [name: string]: string } = {
223327
key: 'k1',
224-
map: ''
328+
map: '',
329+
mode: 'strict',
330+
export_to: 'output'
225331
}
226332
getInputMock.mockImplementation(name => input[name])
227333

@@ -239,7 +345,9 @@ describe('input validation', () => {
239345
const input: { [name: string]: string } = {
240346
key: 'k1',
241347
map: 'k1:v1',
242-
separator: ''
348+
mode: 'strict',
349+
separator: '',
350+
export_to: 'output'
243351
}
244352
getInputMock.mockImplementation(name => input[name])
245353

@@ -253,10 +361,34 @@ describe('input validation', () => {
253361
expect(setFailedMock).toHaveBeenNthCalledWith(1, 'Separator is empty')
254362
})
255363

364+
it('incorrect mode', () => {
365+
const input: { [name: string]: string } = {
366+
key: 'k1',
367+
map: 'k1:v1',
368+
mode: 'invalid',
369+
separator: ':',
370+
export_to: 'env'
371+
}
372+
getInputMock.mockImplementation(name => input[name])
373+
374+
main.run()
375+
expect(runMock).toHaveReturned()
376+
377+
expect(errorMock).not.toHaveBeenCalled()
378+
expect(exportVariableMock).not.toHaveBeenCalled()
379+
expect(setOutputMock).not.toHaveBeenCalled()
380+
381+
expect(setFailedMock).toHaveBeenNthCalledWith(
382+
1,
383+
expect.stringMatching('Invalid mode')
384+
)
385+
})
386+
256387
it('incorrect export_to - empty', () => {
257388
const input: { [name: string]: string } = {
258389
key: 'k1',
259390
map: 'k1:v1',
391+
mode: 'strict',
260392
separator: ':',
261393
export_to: ''
262394
}
@@ -271,14 +403,15 @@ describe('input validation', () => {
271403

272404
expect(setFailedMock).toHaveBeenNthCalledWith(
273405
1,
274-
expect.stringMatching('Invalid mode')
406+
expect.stringMatching('Invalid export_to')
275407
)
276408
})
277409

278410
it('incorrect export_to - invalid', () => {
279411
const input: { [name: string]: string } = {
280412
key: 'k1',
281413
map: 'k1:v1',
414+
mode: 'strict',
282415
separator: ':',
283416
export_to: 'env,invalid'
284417
}
@@ -293,7 +426,7 @@ describe('input validation', () => {
293426

294427
expect(setFailedMock).toHaveBeenNthCalledWith(
295428
1,
296-
expect.stringMatching('Invalid mode')
429+
expect.stringMatching('Invalid export_to')
297430
)
298431
})
299432

action.yml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ inputs:
1818
required: true
1919
export_to:
2020
description:
21-
'Comma-separated list of targets to export variables to. log, env and
22-
output are valid values.'
23-
default: 'output,log'
21+
'Comma-separated list of targets to export variables to. Possible optoins:
22+
env, output'
23+
default: 'output'
2424
export_to_env_name:
2525
description: 'Environment variable name when export_to contains env'
2626
default: ''
@@ -37,6 +37,11 @@ inputs:
3737
'Default value, used when mode is fallback-to-default and not match was
3838
found'
3939
default: ''
40+
allow_empty_map:
41+
description:
42+
'Do not throw error when empty map was provided, requires mode to be other
43+
than strict'
44+
default: ''
4045

4146
# Define your outputs here.
4247
outputs:

0 commit comments

Comments
 (0)