Skip to content

Commit f277798

Browse files
authored
ci(release): v1.1.0 (#5)
* feat: Add dotenv package * feat: Move template variable parsing into separate function. Modify it to accept JSON and ENV formats. * docs: Update README to clarify template-vars supports ENV style input * fix: issue not checking variable type correctly. * test: Add missing test to check for empty input * ci(build): Combine into distribution * fix: incorrect Action name in package.json * ci(release): Increase version number to v1.1.0
1 parent fd4f2b9 commit f277798

File tree

9 files changed

+795
-1436
lines changed

9 files changed

+795
-1436
lines changed

README.md

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ Typical uses:
1515
Provide the template as a file or direclty as text. If both are provided, the
1616
file will be ignored.
1717

18-
| Input Name | Description | Required | Default |
19-
| --------------- | ---------------------------------------------------------- | -------- | ------- |
20-
| `template-file` | The path to a text file to load as the template. | No | - |
21-
| `template-text` | The template text with variable placeholders. | No | - |
22-
| `template-vars` | A JSON object containing variables to replace in the text. | Yes | - |
18+
| Input Name | Description | Required | Default |
19+
| --------------- | ------------------------------------------------ | -------- | ------- |
20+
| `template-file` | The path to a text file to load as the template. | No | - |
21+
| `template-text` | The template text with variable placeholders. | No | - |
22+
| `template-vars` | An ENV style list or stringified JSON object. | Yes | - |
2323

2424
## Workflow Outputs
2525

@@ -32,7 +32,7 @@ Action output. As such it can easily be referenced in subsequent steps.
3232

3333
## Scenarios
3434

35-
### Direct Text
35+
### Direct Text (JSON variables)
3636

3737
```yaml
3838
steps:
@@ -47,6 +47,22 @@ steps:
4747
run: echo "${{ steps.build-comment.outputs.updated-text }}"
4848
```
4949
50+
### Direct Text (ENV variables)
51+
52+
```yaml
53+
steps:
54+
- name: Build comment using template
55+
id: build-comment
56+
uses: chriswblake/action-text-variables@v1
57+
with:
58+
template-text: 'Hello {{ login }}, nice to meet you!'
59+
template-vars: |
60+
login=${{ github.actor }}
61+
62+
- name: Do something with result
63+
run: echo "${{ steps.build-comment.outputs.updated-text }}"
64+
```
65+
5066
### Use template from same repository
5167
5268
```yaml

__tests__/main.test.js

Lines changed: 184 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ describe('action', () => {
2121
jest.clearAllMocks()
2222
})
2323

24-
// Proper Usage
25-
it('Use template file', async () => {
24+
// Proper Usage - JSON
25+
it('Use template file - JSON', async () => {
2626
// Arrange - Mock responses for the inputs
2727
getInputMock.mockImplementation(inputName => {
2828
switch (inputName) {
@@ -64,7 +64,7 @@ describe('action', () => {
6464
expect(outputValue).not.toMatch(/extra value/)
6565
})
6666

67-
it('Use template text', async () => {
67+
it('Use template text - JSON', async () => {
6868
// Arrange - Mock responses for the inputs
6969
getInputMock.mockImplementation(inputName => {
7070
switch (inputName) {
@@ -95,6 +95,38 @@ describe('action', () => {
9595
expect(outputValue).not.toMatch(/extra value/)
9696
})
9797

98+
// Proper Usage - ENV format
99+
it('Use template text - ENV', async () => {
100+
// Arrange - Mock responses for the inputs
101+
getInputMock.mockImplementation(inputName => {
102+
switch (inputName) {
103+
case 'template-text':
104+
return 'Hello {{ name }}'
105+
case 'template-vars':
106+
return `
107+
name=John1
108+
extra_var=extra value
109+
`
110+
default:
111+
return ''
112+
}
113+
})
114+
115+
// Act - Load the template and replace the variables
116+
await main.run()
117+
expect(runMock).toHaveReturned()
118+
119+
// Assert - Check output name
120+
const call = setOutputMock.mock.calls[0]
121+
const outputName = call[0]
122+
expect(outputName).toBe('updated-text')
123+
124+
// Assert - Check inserted values
125+
const outputValue = call[1]
126+
expect(outputValue).toBe('Hello John1')
127+
expect(outputValue).not.toMatch(/extra value/)
128+
})
129+
98130
// Error Responses - Missing inputs
99131
it('Missing template. Set failed status.', async () => {
100132
// Arrange - Mock responses for the inputs
@@ -163,53 +195,161 @@ describe('action', () => {
163195
expect.stringMatching(/Missing required input/)
164196
)
165197
})
166-
})
167198

168-
// Error Responses - Bad Inputs
169-
it('Provided non-JSON for template-vars. Set failed status.', async () => {
170-
// Arrange - Mock responses for the inputs
171-
getInputMock.mockImplementation(name => {
172-
switch (name) {
173-
case 'template-text':
174-
return 'Hello {{ name }}'
175-
case 'template-vars':
176-
return 1234
177-
default:
178-
return undefined
179-
}
199+
// Error Responses - Bad Inputs
200+
it('Provided number for template-vars. Set failed status.', async () => {
201+
// Arrange - Mock responses for the inputs
202+
getInputMock.mockImplementation(name => {
203+
switch (name) {
204+
case 'template-text':
205+
return 'Hello {{ name }}'
206+
case 'template-vars':
207+
return 1234
208+
default:
209+
return undefined
210+
}
211+
})
212+
213+
// Act - Run action to cause the error
214+
await main.run()
215+
expect(runMock).toHaveReturned()
216+
217+
// Assert - Action was closed with correct error message
218+
expect(setFailedMock).toHaveBeenNthCalledWith(
219+
1,
220+
expect.stringMatching(/Invalid input/)
221+
)
180222
})
181223

182-
// Act - Run action to cause the error
183-
await main.run()
184-
expect(runMock).toHaveReturned()
224+
it('Provided empty string for template-vars. Set failed status.', async () => {
225+
// Arrange - Mock responses for the inputs
226+
getInputMock.mockImplementation(name => {
227+
switch (name) {
228+
case 'template-text':
229+
return 'Hello {{ name }}'
230+
case 'template-vars':
231+
return ''
232+
default:
233+
return undefined
234+
}
235+
})
185236

186-
// Assert - Action was closed with correct error message
187-
expect(setFailedMock).toHaveBeenNthCalledWith(
188-
1,
189-
expect.stringMatching(/Invalid JSON input/)
190-
)
191-
})
237+
// Act - Run action to cause the error
238+
await main.run()
239+
expect(runMock).toHaveReturned()
240+
241+
// Assert - Action was closed with correct error message
242+
expect(setFailedMock).toHaveBeenNthCalledWith(
243+
1,
244+
expect.stringMatching(/Missing required input/)
245+
)
246+
})
247+
248+
it('Badly formed JSON for template-vars. Set failed status.', async () => {
249+
// Arrange - Mock responses for the inputs
250+
getInputMock.mockImplementation(name => {
251+
switch (name) {
252+
case 'template-text':
253+
return 'Hello {{ name }}'
254+
case 'template-vars':
255+
return '{ forgot quotations on values }'
256+
default:
257+
return ''
258+
}
259+
})
260+
261+
// Act - Run action to cause the error
262+
await main.run()
263+
expect(runMock).toHaveReturned()
264+
265+
// Assert - Action was closed with correct error message
266+
expect(setFailedMock).toHaveBeenNthCalledWith(
267+
1,
268+
expect.stringMatching(/Invalid input/)
269+
)
270+
})
192271

193-
it('Badly formed JSON for template-vars. Set failed status.', async () => {
194-
// Arrange - Mock responses for the inputs
195-
getInputMock.mockImplementation(name => {
196-
switch (name) {
197-
case 'template-text':
198-
return 'Hello {{ name }}'
199-
case 'template-vars':
200-
return '{ forgot quotations on values }'
201-
default:
202-
return ''
203-
}
272+
it('Badly formed variable list for template-vars. Set failed status.', async () => {
273+
// Arrange - Mock responses for the inputs
274+
getInputMock.mockImplementation(name => {
275+
switch (name) {
276+
case 'template-text':
277+
return 'Hello {{ name }}'
278+
case 'template-vars':
279+
return `
280+
name!=John1
281+
`
282+
default:
283+
return ''
284+
}
285+
})
286+
287+
// Act - Run action to cause the error
288+
await main.run()
289+
expect(runMock).toHaveReturned()
290+
291+
// Assert - Action was closed with correct error message
292+
expect(setFailedMock).toHaveBeenNthCalledWith(
293+
1,
294+
expect.stringMatching(/Invalid input/)
295+
)
296+
})
297+
298+
// Methods
299+
it('parseTemplateVars - JSON', () => {
300+
// Arrange
301+
const variables = JSON.stringify({
302+
name: 'John1',
303+
person: {
304+
name: 'John2',
305+
unused_value: 'unused'
306+
},
307+
multiline_paragraph: `
308+
Line 1
309+
Line 2
310+
`,
311+
extra_var: 'extra value'
312+
})
313+
// Act
314+
const result = main.parseTemplateVars(variables)
315+
316+
// Assert
317+
expect(result.name).toEqual('John1')
318+
expect(result['person']['name']).toEqual('John2')
319+
expect(result['person']['unused_value']).toEqual('unused')
320+
expect(result.multiline_paragraph).toMatch(/Line 1\s*Line 2/)
204321
})
205322

206-
// Act - Run action to cause the error
207-
await main.run()
208-
expect(runMock).toHaveReturned()
323+
it('parseTemplateVars - ENV', () => {
324+
// Arrange
325+
const variables = `
326+
name=John1
327+
person.name=John2
328+
person.unused_value=unused
329+
multiline_paragraph="
330+
Line 1
331+
Line 2
332+
"
333+
`
334+
// Act
335+
const result = main.parseTemplateVars(variables)
209336

210-
// Assert - Action was closed with correct error message
211-
expect(setFailedMock).toHaveBeenNthCalledWith(
212-
1,
213-
expect.stringMatching(/Invalid JSON input/)
214-
)
337+
// Assert
338+
expect(result.name).toEqual('John1')
339+
expect(result['person.name']).toEqual('John2')
340+
expect(result['person.unused_value']).toEqual('unused')
341+
expect(result.multiline_paragraph).toMatch(/Line 1\s*Line 2/)
342+
})
343+
344+
it('parseTemplateVars - invalid ENV', () => {
345+
// Arrange
346+
const variables = `
347+
name!=John1
348+
`
349+
// Act
350+
const parseAction = () => main.parseTemplateVars(variables)
351+
352+
// Assert
353+
expect(parseAction).toThrow(/Invalid input/)
354+
})
215355
})

0 commit comments

Comments
 (0)