Skip to content

Commit 0d888b7

Browse files
authored
fix: Replace implicit workflows source with explicit local source (#23)
1 parent 9686bde commit 0d888b7

8 files changed

Lines changed: 68 additions & 56 deletions

File tree

.github/workflows/test.yml

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,20 @@ jobs:
1717
- name: Test developer is greeted
1818
uses: ./
1919
with:
20-
assertion: workflows://is-equal
20+
assertion: local://.github/workflows/assertions/is-equal
2121
actual: "${{ env.greeting }}"
2222
expected: "Hello, World!"
2323
- name: Test developer is dismissed
2424
uses: ./
2525
continue-on-error: true
2626
with:
27-
assertion: workflows://is-equal
27+
assertion: local://.github/workflows/assertions/is-equal
2828
actual: "${{ env.dismissal }}"
2929
expected: "Goodbye, World!"
3030
- name: Test each line is the greeting
3131
uses: ./
3232
with:
33-
assertion: workflows://is-equal
33+
assertion: local://.github/workflows/assertions/is-equal
3434
actual: |
3535
${{ env.greeting }}
3636
${{ env.greeting }}
@@ -44,14 +44,14 @@ jobs:
4444
- name: Test an even number is even
4545
uses: ./
4646
with:
47-
assertion: workflows://is-even
47+
assertion: local://.github/workflows/assertions/is-even
4848
actual: 2
4949
type: number
5050
- name: Test an odd number is not even
5151
continue-on-error: true
5252
uses: ./
5353
with:
54-
assertion: workflows://is-even
54+
assertion: local://.github/workflows/assertions/is-even
5555
actual: 3
5656
type: number
5757
npm-assertions:
@@ -114,7 +114,7 @@ jobs:
114114
id: equal-strings
115115
uses: ./
116116
with:
117-
assertion: workflows://is-equal
117+
assertion: local://.github/workflows/assertions/is-equal
118118
actual: "Hello, World!"
119119
expected: "Hello, World!"
120120
- name: Test `message` output is set from Result `message`
@@ -130,11 +130,12 @@ jobs:
130130
assertion: npm://@assertions/is-equal
131131
actual: "${{ steps.equal-strings.outputs.pass }}"
132132
expected: "true"
133-
test-dist-v1:
133+
test-dist:
134134
runs-on: ubuntu-latest
135135
steps:
136-
- uses: pr-mpt/actions-assert@v1
136+
- uses: actions/checkout@v2
137+
- uses: pr-mpt/actions-assert@v2
137138
with:
138-
assertion: workflows://is-equal
139+
assertion: local://.github/workflows/assertions/is-equal
139140
actual: "Hello, World!"
140141
expected: "Hello, World!"

README.md

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
# Assert
22

33
A GitHub Action for asserting **actual** is **expected** in GitHub Workflows.
4-
Designed for GitHub Action integration tests and build pipelines.
4+
Designed for GitHub Action integration tests and robust build pipelines.
55

66
* Cast action input values from strings to `type` for type safety
7-
* Add custom Javascript assertions to your project to meet unique testing requirements
7+
* Distribute reusable assertions via [npm][npm]
8+
* Write local Javascript assertions to meet project-specific testing needs
89
* Run tests against multiple values using `each`
910

1011
```yaml
@@ -13,10 +14,10 @@ jobs:
1314
runs-on: ubuntu-latest
1415
steps:
1516
- name: Test actor is @shrink
16-
uses: pr-mpt/actions-assert@v1
17+
uses: pr-mpt/actions-assert@v2
1718
with:
1819
assertion: npm://@assertions/is-equal
19-
actual: ${{ github.actor }}
20+
actual: "${{ github.actor }}"
2021
expected: shrink
2122
```
2223
@@ -26,11 +27,12 @@ jobs:
2627
2728
| Name | Description | Default | Examples |
2829
| :--- | :---------- | :------ | :------- |
29-
| **`assertion`** | **Reference to a supported [assertion](#assertions)** | | **`npm://@assertions/is-equal`** |
30-
| **`actual`** | **Dynamic value to perform test on** | | **`${{steps.m.outputs.greeting}}`** |
31-
| `expected` | Value that `actual` should match | | `Hello, World!` |
30+
| **`assertion`** | **Reference to a supported [assertion](#assertions)** in `source://name` format | | **`npm://@assertions/is-equal`**<br/>**`local://is-even`** |
31+
| `expected` | Value the assertion is looking for | | `Hello, World!` |
32+
| `actual` | Value the assertion will test against the expected value | | `${{steps.fields.outputs.greeting}}` |
3233
| `type` | A supported [data type](#data-types) that `actual` and `expected` will be cast to before performing assertion | `string` | `string` `json` `number` |
3334
| `each` | Parse multi-line `actual` into many values and test each | `false` | `true` `false` |
35+
| `local-path` | Path to directory containing `local` assertion | `${{github.workspace}}` | `.github/workflows/assertions` |
3436

3537
### Assertions
3638

@@ -47,13 +49,13 @@ module.exports = function (expected, actual) {
4749
}
4850
```
4951

50-
Assertions are resolved using `type` and `name` accepted in `type://name`
52+
Assertions are resolved using `source` and `name` accepted in `source://name`
5153
format.
5254

53-
| Type | Resolved To | Example |
55+
| Source | Resolved To | Example |
5456
| :--- | :---------- | :------ |
55-
| `workflows` | A Javascript file in `.github/workflows/assertions` that exports an assertion as default | `workflows://is-equal` |
5657
| `npm` | An [npm][npm] package with an assertion as the [main exported module][package.json/main] | `npm://@assertions/is-equal` |
58+
| `local` | A Javascript file (on the runner's filesystem) that exports an assertion as default | `local://is-equal` |
5759

5860
#### `npm`
5961

@@ -102,7 +104,7 @@ jobs:
102104
major: true
103105
minor: false
104106
- name: Assert alias is prefixed
105-
uses: pr-mpt/actions-assert@v1
107+
uses: pr-mpt/actions-assert@v2
106108
with:
107109
assertion: npm://@assertions/starts-with
108110
each: true
@@ -120,3 +122,4 @@ jobs:
120122
[@assertions/is-strictly-equal]: https://npmjs.com/package/@assertions/is-strictly-equal
121123
[@assertions/starts-with]: https://npmjs.com/package/@assertions/starts-with
122124
[npm/@assertions]: https://www.npmjs.com/org/assertions
125+
[workflows/workspace]: https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#github-context

__tests__/assertions.test.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
import {resolveAssertion} from '../src/assertions'
22

3+
const isEven = require(`../.github/workflows/assertions/is-even.js`)
4+
35
describe('assertions resolver', () => {
4-
describe('workflows resolution', () => {
5-
it('resolves to workflows assertions directory', () => {
6+
describe('local resolution', () => {
7+
it('resolves to specified assertions directory', () => {
68
expect.assertions(1)
79

8-
const isEven = require('../.github/workflows/assertions/is-even')
9-
10-
resolveAssertion('workflows://is-even').then(assertion =>
10+
resolveAssertion(
11+
'local://is-even',
12+
'../.github/workflows/assertions'
13+
).then(assertion =>
1114
expect(assertion.toString()).toStrictEqual(isEven.toString())
1215
)
1316
})
@@ -27,16 +30,16 @@ describe('assertions resolver', () => {
2730
})
2831
})
2932

30-
it('throws error when no type is provided', () => {
33+
it('throws error when no source is provided', () => {
3134
expect.assertions(1)
32-
return resolveAssertion('without-type').catch(e =>
35+
return resolveAssertion('without-source').catch(e =>
3336
expect(e instanceof URIError).toBe(true)
3437
)
3538
})
3639

37-
it('throws error when type does not have resolver', () => {
40+
it('throws error when source does not have resolver', () => {
3841
expect.assertions(1)
39-
return resolveAssertion('invalid-type://example').catch(e =>
42+
return resolveAssertion('invalid-source://example').catch(e =>
4043
expect(e instanceof RangeError).toBe(true)
4144
)
4245
})

action.yml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,24 @@ inputs:
88
assertion:
99
description: "Name of the assertion to run against value"
1010
required: true
11+
expected:
12+
description: "Value the assertion is looking for"
13+
required: false
1114
actual:
1215
description: "Dynamic value to test against"
13-
required: true
14-
expected:
15-
description: "Value that `actual` should match"
1616
required: false
1717
type:
1818
description: "Javascript data type that actual and expected will be cast to"
1919
default: "string"
2020
required: true
2121
each:
2222
description: "Parse multi-line `actual` into many values and assert against each"
23-
required: false
2423
default: "false"
24+
required: false
25+
local-path:
26+
description: "Path to assertions on the runner's filesystem"
27+
default: "${{ github.workspace }}"
28+
required: true
2529
outputs:
2630
message:
2731
description: "Human readable result of the assertion"

dist/index.js

Lines changed: 8 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/assertions.ts

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
import {Assertion} from './execute'
22
import {PluginManager} from 'live-plugin-manager'
33

4-
async function loadAssertionFromFile(filename: string): Promise<Assertion> {
5-
return eval(`require('${filename}')`)
6-
}
7-
84
async function loadAssertionFromNpmPackage(name: string): Promise<Assertion> {
95
const manager = new PluginManager()
106

@@ -15,22 +11,25 @@ async function loadAssertionFromNpmPackage(name: string): Promise<Assertion> {
1511

1612
const resolvers = {
1713
npm: loadAssertionFromNpmPackage,
18-
workflows: async (name: string): Promise<Assertion> =>
19-
loadAssertionFromFile(`./../.github/workflows/assertions/${name}.js`)
14+
local: async (name: string, path: string): Promise<Assertion> =>
15+
eval(`require('${path}/${name}.js')`)
2016
}
2117

22-
export async function resolveAssertion(resource: string): Promise<Assertion> {
18+
export async function resolveAssertion(
19+
resource: string,
20+
localPath = ''
21+
): Promise<Assertion> {
2322
if (!resource.includes('://')) {
2423
throw new URIError(`Assertion reference is not valid, must include type.`)
2524
}
2625

27-
const [type, name] = resource.split('://')
26+
const [source, name] = resource.split('://')
2827

29-
if (!resolvers.hasOwnProperty(type)) {
30-
throw new RangeError(`Assertion type ${type} is not supported.`)
28+
if (!resolvers.hasOwnProperty(source)) {
29+
throw new RangeError(`Assertion source ${source} is not supported.`)
3130
}
3231

3332
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
3433
// @ts-ignore
35-
return resolvers[type](name)
34+
return resolvers[source](name, localPath)
3635
}

src/main.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ async function run(): Promise<void> {
1616
const assertion: string = core.getInput('assertion')
1717
const type: string = core.getInput('type')
1818
const each: boolean = core.getBooleanInput('each')
19+
const localPath: string = core.getInput('local-path')
1920

2021
if (type in types === false) {
2122
throw new Error(
@@ -26,7 +27,10 @@ async function run(): Promise<void> {
2627
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
2728
// @ts-ignore
2829
const typeOfInput: InputType = types[type]
29-
const assertionFunction: Assertion = await resolveAssertion(assertion)
30+
const assertionFunction: Assertion = await resolveAssertion(
31+
assertion,
32+
localPath
33+
)
3034

3135
const actualValues: String[] = each === true ? actual.split('\n') : [actual]
3236

0 commit comments

Comments
 (0)