-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add unit tests * Add GitHub Actions CI workflow * Add Prettier
- Loading branch information
Showing
5 changed files
with
8,417 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
name: Node.js CI | ||
|
||
on: [push] | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
|
||
strategy: | ||
matrix: | ||
node-version: [14.x, 16.x, 18.x] | ||
|
||
env: | ||
CI: true | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- name: Use Node.js ${{ matrix.node-version }} | ||
uses: actions/setup-node@v1 | ||
with: | ||
node-version: ${{ matrix.node-version }} | ||
- run: npm ci | ||
- run: npm test | ||
- run: npm run lint |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,252 @@ | ||
const { Toolkit } = require('actions-toolkit') | ||
const { Toolkit } = require("actions-toolkit"); | ||
const mockedEnv = require("mocked-env"); | ||
|
||
describe('Required Labels', () => { | ||
let action, tools | ||
describe("Required Labels", () => { | ||
let action, tools; | ||
|
||
// Mock Toolkit.run to define `action` so we can call it | ||
Toolkit.run = jest.fn((actionFn) => { action = actionFn }) | ||
Toolkit.run = jest.fn((actionFn) => { | ||
action = actionFn; | ||
}); | ||
|
||
// Load up our entrypoint file | ||
require('.') | ||
require("."); | ||
|
||
let restore; | ||
let restoreTest; | ||
beforeEach(() => { | ||
// Create a new Toolkit instance | ||
tools = new Toolkit() | ||
// Mock methods on it! | ||
tools.exit.success = jest.fn() | ||
}) | ||
|
||
it('exits successfully', () => { | ||
action(tools) | ||
expect(tools.exit.success).toHaveBeenCalled() | ||
expect(tools.exit.success).toHaveBeenCalledWith('We did it!') | ||
}) | ||
}) | ||
restore = mockedEnv({ | ||
GITHUB_WORKFLOW: "demo-workflow", | ||
GITHUB_ACTION: "required-labels", | ||
GITHUB_ACTOR: "mheap", | ||
GITHUB_REPOSITORY: "mheap/missing-repo", | ||
GITHUB_WORKSPACE: "/github/workspace", | ||
GITHUB_SHA: "e21490305ed7ac0897b7c7c54c88bb47f7a6d6c4", | ||
GITHUB_EVENT_NAME: "", | ||
GITHUB_EVENT_PATH: "", | ||
}); | ||
|
||
tools = new Toolkit(); | ||
tools.context.loadPerTestEnv = function () { | ||
this.payload = process.env.GITHUB_EVENT_PATH | ||
? require(process.env.GITHUB_EVENT_PATH) | ||
: {}; | ||
this.event = process.env.GITHUB_EVENT_NAME; | ||
}; | ||
tools.exit.success = jest.fn(); | ||
tools.exit.failure = jest.fn(); | ||
}); | ||
|
||
afterEach(() => { | ||
restore(); | ||
restoreTest(); | ||
jest.resetModules(); | ||
}); | ||
|
||
describe("success", () => { | ||
it("exact count", () => { | ||
// Create a new Toolkit instance | ||
restoreTest = mockPr(tools, ["enhancement"], { | ||
INPUT_LABELS: "enhancement,bug", | ||
INPUT_MODE: "exactly", | ||
INPUT_COUNT: "1", | ||
}); | ||
|
||
action(tools); | ||
expect(tools.exit.success).toBeCalledTimes(1); | ||
expect(tools.exit.success).toBeCalledWith("Complete"); | ||
}); | ||
|
||
it("at least X", () => { | ||
// Create a new Toolkit instance | ||
restoreTest = mockPr(tools, ["enhancement", "triage"], { | ||
INPUT_LABELS: "enhancement,bug,triage", | ||
INPUT_MODE: "minimum", | ||
INPUT_COUNT: "2", | ||
}); | ||
|
||
action(tools); | ||
expect(tools.exit.success).toBeCalledTimes(1); | ||
expect(tools.exit.success).toBeCalledWith("Complete"); | ||
}); | ||
|
||
it("at most X", () => { | ||
// Create a new Toolkit instance | ||
restoreTest = mockPr(tools, ["enhancement", "triage"], { | ||
INPUT_LABELS: "enhancement,bug,triage", | ||
INPUT_MODE: "maximum", | ||
INPUT_COUNT: "2", | ||
}); | ||
|
||
action(tools); | ||
expect(tools.exit.success).toBeCalledTimes(1); | ||
expect(tools.exit.success).toBeCalledWith("Complete"); | ||
}); | ||
}); | ||
|
||
describe("failure", () => { | ||
it("exact count", () => { | ||
// Create a new Toolkit instance | ||
restoreTest = mockPr(tools, ["enhancement", "bug"], { | ||
INPUT_LABELS: "enhancement,bug", | ||
INPUT_MODE: "exactly", | ||
INPUT_COUNT: "1", | ||
}); | ||
|
||
action(tools); | ||
expect(tools.exit.failure).toBeCalledTimes(1); | ||
expect(tools.exit.failure).toBeCalledWith( | ||
"Label error. Requires exactly 1 of: enhancement, bug. Found: enhancement, bug" | ||
); | ||
}); | ||
|
||
it("at least X", () => { | ||
// Create a new Toolkit instance | ||
restoreTest = mockPr(tools, ["enhancement"], { | ||
INPUT_LABELS: "enhancement,bug,triage", | ||
INPUT_MODE: "minimum", | ||
INPUT_COUNT: "2", | ||
}); | ||
|
||
action(tools); | ||
expect(tools.exit.failure).toBeCalledTimes(1); | ||
expect(tools.exit.failure).toBeCalledWith( | ||
"Label error. Requires at least 2 of: enhancement, bug, triage. Found: enhancement" | ||
); | ||
}); | ||
|
||
it("at most X", () => { | ||
// Create a new Toolkit instance | ||
restoreTest = mockPr(tools, ["enhancement", "triage", "bug"], { | ||
INPUT_LABELS: "enhancement,bug,triage", | ||
INPUT_MODE: "maximum", | ||
INPUT_COUNT: "2", | ||
}); | ||
|
||
action(tools); | ||
expect(tools.exit.failure).toBeCalledTimes(1); | ||
expect(tools.exit.failure).toBeCalledWith( | ||
"Label error. Requires at most 2 of: enhancement, bug, triage. Found: enhancement, triage, bug" | ||
); | ||
}); | ||
}); | ||
|
||
describe("validation", () => { | ||
it("missing INPUT_COUNT", () => { | ||
restoreTest = mockPr(tools, [], { | ||
INPUT_LABELS: "enhancement,bug", | ||
INPUT_MODE: "exactly", | ||
}); | ||
action(tools); | ||
expect(tools.exit.failure).toBeCalledTimes(1); | ||
expect(tools.exit.failure).toBeCalledWith( | ||
"[count] input is not provided" | ||
); | ||
}); | ||
|
||
it("missing INPUT_LABELS", () => { | ||
restoreTest = mockPr(tools, [], { | ||
INPUT_MODE: "exactly", | ||
INPUT_COUNT: "1", | ||
}); | ||
|
||
action(tools); | ||
expect(tools.exit.failure).toBeCalledTimes(1); | ||
expect(tools.exit.failure).toBeCalledWith( | ||
"[labels] input is empty or not provided" | ||
); | ||
}); | ||
|
||
it("unknown mode", () => { | ||
restoreTest = mockPr(tools, [], { | ||
INPUT_MODE: "bananas", | ||
INPUT_LABELS: "enhancement,bug", | ||
INPUT_COUNT: "1", | ||
}); | ||
|
||
action(tools); | ||
expect(tools.exit.failure).toBeCalledTimes(1); | ||
expect(tools.exit.failure).toBeCalledWith( | ||
"Unknown mode input [bananas]. Must be one of: exactly, minimum, maximum" | ||
); | ||
}); | ||
}); | ||
|
||
describe("data integrity", () => { | ||
it("supports spaces in INPUT_LABELS", () => { | ||
restoreTest = mockPr(tools, ["enhancement"], { | ||
INPUT_LABELS: "enhancement , bug", | ||
INPUT_MODE: "exactly", | ||
INPUT_COUNT: "1", | ||
}); | ||
|
||
action(tools); | ||
expect(tools.exit.success).toBeCalledTimes(1); | ||
expect(tools.exit.success).toBeCalledWith("Complete"); | ||
}); | ||
|
||
it("fetches labels from the API when provided with a GITHUB_TOKEN", async () => { | ||
tools.github.issues.listLabelsOnIssue = jest | ||
.fn() | ||
.mockReturnValue(Promise.resolve({ data: [{ name: "enhancement" }] })); | ||
|
||
restoreTest = mockPr(tools, ["should_not_be_used"], { | ||
GITHUB_TOKEN: "this_is_a_test_token", | ||
INPUT_LABELS: "enhancement , bug", | ||
INPUT_MODE: "exactly", | ||
INPUT_COUNT: "1", | ||
}); | ||
|
||
await action(tools); | ||
|
||
expect(tools.github.issues.listLabelsOnIssue).toBeCalledTimes(1); | ||
expect(tools.github.issues.listLabelsOnIssue).toBeCalledWith({ | ||
issue_number: 28, | ||
owner: "mheap", | ||
repo: "missing-repo", | ||
}); | ||
|
||
expect(tools.exit.success).toBeCalledTimes(1); | ||
expect(tools.exit.success).toBeCalledWith("Complete"); | ||
}); | ||
}); | ||
}); | ||
|
||
function mockPr(tools, labels, env) { | ||
return mockEvent( | ||
tools, | ||
"pull_request", | ||
{ | ||
action: "opened", | ||
pull_request: { | ||
number: 28, | ||
labels: labels.map((name) => { | ||
return { name }; | ||
}), | ||
}, | ||
}, | ||
env | ||
); | ||
} | ||
|
||
function mockEvent(tools, eventName, mockPayload, additionalParams = {}) { | ||
jest.mock( | ||
"/github/workspace/event.json", | ||
() => { | ||
return mockPayload; | ||
}, | ||
{ | ||
virtual: true, | ||
} | ||
); | ||
|
||
const params = { | ||
GITHUB_EVENT_NAME: eventName, | ||
GITHUB_EVENT_PATH: "/github/workspace/event.json", | ||
...additionalParams, | ||
}; | ||
|
||
const r = mockedEnv(params); | ||
tools.context.loadPerTestEnv(); | ||
return r; | ||
} |
Oops, something went wrong.