Files
slack-github-action/test/index.spec.js

117 lines
3.5 KiB
JavaScript

import { mock } from "node:test";
import webapi from "@slack/web-api";
import axios, { AxiosError } from "axios";
/**
* Hello experimenter! These tests are here to confirm that the happy paths keep
* working and error cases are thrown.
*
* Tests are grouped with related related code using a file *.spec.js extension.
* These test related functionalities of units but a full suite of integration
* tests confirm correctness of the actual workflows in .github/workflows/*.yml.
*
* Actual tests begin in send.spec.js which has integration tests. Other modules
* test the edges of this action.
*/
/**
* The Mock class sets expected behaviors and test listeners for dependencies.
*/
export class Mock {
/**
* @typedef Errors - A collection of mocked errors to use in tests.
* @prop {Object.<string, AxiosError>} axios - The mocked axios errors.
*/
/**
* The mocked errors.
* @type {Errors}
*/
errors = {
axios: {
network_failed: new AxiosError("network_failed"),
},
};
/**
* Lookup tables for input values.
*/
inputs = {};
booleanInputs = {};
/**
* Setup mocked dependencies and configure default input arguments for all
* tests.
*
* @see {@link ../action.yml}
*/
constructor() {
this.axios = {
post: mock.fn((..._args) => {
if (this.axios.post._promise !== undefined) {
return this.axios.post._promise;
}
throw new Error(
"Test error: axios.post was called but no promise was configured. " +
"Set mocks.axios.post._promise = Promise.resolve(...) or Promise.reject(...)",
);
}),
};
axios.post = this.axios.post;
this.calls = mock.fn((..._args) => {
if (this.calls._resolvesWith !== undefined) {
return Promise.resolve(this.calls._resolvesWith);
}
if (this.calls._rejectsWith !== undefined) {
return Promise.reject(this.calls._rejectsWith);
}
throw new Error(
"Test error: apiCall was called but no promise was configured. " +
"Set mocks.calls._resolvesWith = {...} or mocks.calls._rejectsWith = {...}",
);
});
webapi.WebClient.prototype.apiCall = this.calls;
this.core = {
debug: mock.fn(),
error: mock.fn(),
getInput: mock.fn((key) => this.inputs[key] ?? ""),
getBooleanInput: mock.fn((key) => this.booleanInputs[key] ?? false),
info: mock.fn(),
isDebug: mock.fn(() => this._isDebug ?? false),
setFailed: mock.fn(),
setOutput: mock.fn(),
setSecret: mock.fn(),
warning: mock.fn(),
};
}
/**
* Testing interface that removes internal state from existing mocks.
*/
reset() {
this._isDebug = false;
this.axios.post.mock.resetCalls();
this.axios.post._promise = undefined;
this.booleanInputs = {};
this.calls.mock.resetCalls();
this.calls._resolvesWith = undefined;
this.calls._rejectsWith = undefined;
this.core.debug.mock.resetCalls();
this.core.error.mock.resetCalls();
this.core.getBooleanInput.mock.resetCalls();
this.core.getInput.mock.resetCalls();
this.core.info.mock.resetCalls();
this.core.isDebug.mock.resetCalls();
this.core.setFailed.mock.resetCalls();
this.core.setOutput.mock.resetCalls();
this.core.setSecret.mock.resetCalls();
this.core.warning.mock.resetCalls();
this.inputs = {};
this.webapi = {};
process.env.SLACK_TOKEN = "";
process.env.SLACK_WEBHOOK_URL = "";
}
}
export const mocks = new Mock();