mirror of
https://github.com/Kir-Antipov/mc-publish.git
synced 2024-11-25 18:01:07 -05:00
Added tests for action-output
This commit is contained in:
parent
de278c43b0
commit
4dc999955c
1 changed files with 297 additions and 0 deletions
297
tests/unit/utils/actions/action-output.spec.ts
Normal file
297
tests/unit/utils/actions/action-output.spec.ts
Normal file
|
@ -0,0 +1,297 @@
|
||||||
|
import mockFs from "mock-fs";
|
||||||
|
import { readFile } from "node:fs/promises";
|
||||||
|
import { ActionMetadata } from "@/utils/actions/action-metadata";
|
||||||
|
import { ActionParameterPathParser } from "@/utils/actions/action-parameter-path-parser";
|
||||||
|
import { ActionOutputControllerOptions, createActionOutputController, createActionOutputControllerUsingMetadata, getActionOutput, getActionOutputs, getAllActionOutputs, setActionOutput, setActionOutputs } from "@/utils/actions/action-output";
|
||||||
|
|
||||||
|
const ENV = Object.freeze({
|
||||||
|
GITHUB_OUTPUT: "output.txt",
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
mockFs({
|
||||||
|
"output.txt": "",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
mockFs.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("setActionOutput", () => {
|
||||||
|
test("writes the value of an output to a file", async () => {
|
||||||
|
setActionOutput("output1", "value1", ENV);
|
||||||
|
|
||||||
|
const outputFile = await readFile(ENV.GITHUB_OUTPUT, "utf8");
|
||||||
|
expect(outputFile).toMatch(/^output1<<(.+)\r?\nvalue1\r?\n\1$/m);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("writes values of multiple outputs to a file", async () => {
|
||||||
|
setActionOutput("output1", "value1", ENV);
|
||||||
|
setActionOutput("output2", "value2", ENV);
|
||||||
|
|
||||||
|
const outputFile = await readFile(ENV.GITHUB_OUTPUT, "utf8");
|
||||||
|
expect(outputFile).toMatch(/^output1<<(.+)\r?\nvalue1\r?\n\1$/m);
|
||||||
|
expect(outputFile).toMatch(/^output2<<(.+)\r?\nvalue2\r?\n\1$/m);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("writes an empty string if the specified value is null or undefined", async () => {
|
||||||
|
setActionOutput("output1", null, ENV);
|
||||||
|
setActionOutput("output2", undefined, ENV);
|
||||||
|
|
||||||
|
const outputFile = await readFile(ENV.GITHUB_OUTPUT, "utf8");
|
||||||
|
expect(outputFile).toMatch(/^output1<<(.+)\r?\n\r?\n\1$/m);
|
||||||
|
expect(outputFile).toMatch(/^output2<<(.+)\r?\n\r?\n\1$/m);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("stringifies non-string values before writing them to the file", async () => {
|
||||||
|
const value1 = { foo: "bar" };
|
||||||
|
const value2 = { baz: 1 };
|
||||||
|
|
||||||
|
setActionOutput("output1", value1, ENV);
|
||||||
|
setActionOutput("output2", value2, ENV);
|
||||||
|
|
||||||
|
const outputFile = await readFile(ENV.GITHUB_OUTPUT, "utf8");
|
||||||
|
const outputs = [...outputFile.matchAll(/^(?<name>.+)<<(.+)\r?\n(?<value>.+)\r?\n\2$/gm)]
|
||||||
|
.map(x => [x.groups.name, JSON.parse(x.groups.value)])
|
||||||
|
.reduce((a, [name, value]) => (a[name] = value) && a, {});
|
||||||
|
|
||||||
|
expect(outputs["output1"]).toEqual(value1);
|
||||||
|
expect(outputs["output2"]).toEqual(value2);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("throws an error if the output file does not exist", () => {
|
||||||
|
expect(() => setActionOutput("output1", "value1", {})).toThrowError();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("setActionOutputs", () => {
|
||||||
|
test("sets multiple action outputs at once", async () => {
|
||||||
|
const outputs = [
|
||||||
|
["output1", "value1"] as const,
|
||||||
|
["output2", "value2"] as const,
|
||||||
|
];
|
||||||
|
|
||||||
|
setActionOutputs(outputs, ENV);
|
||||||
|
|
||||||
|
const outputFile = await readFile(ENV.GITHUB_OUTPUT, "utf8");
|
||||||
|
expect(outputFile).toMatch(/^output1<<(.+)\r?\nvalue1\r?\n\1$/m);
|
||||||
|
expect(outputFile).toMatch(/^output2<<(.+)\r?\nvalue2\r?\n\1$/m);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("sets multiple action outputs with non-string values", async () => {
|
||||||
|
const value1 = { foo: "bar" };
|
||||||
|
const value2 = { baz: 1 };
|
||||||
|
const outputs = [
|
||||||
|
["output1", value1] as const,
|
||||||
|
["output2", value2] as const,
|
||||||
|
];
|
||||||
|
|
||||||
|
setActionOutputs(outputs, ENV);
|
||||||
|
|
||||||
|
const outputFile = await readFile(ENV.GITHUB_OUTPUT, "utf8");
|
||||||
|
const deserializedOutputs = [...outputFile.matchAll(/^(?<name>.+)<<(.+)\r?\n(?<value>.+)\r?\n\2$/gm)]
|
||||||
|
.map(x => [x.groups.name, JSON.parse(x.groups.value)])
|
||||||
|
.reduce((a, [name, value]) => (a[name] = value) && a, {});
|
||||||
|
|
||||||
|
expect(deserializedOutputs["output1"]).toEqual(value1);
|
||||||
|
expect(deserializedOutputs["output2"]).toEqual(value2);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("throws an error if the output file does not exist", () => {
|
||||||
|
const outputs = [
|
||||||
|
["output1", "value1"] as const,
|
||||||
|
["output2", "value2"] as const,
|
||||||
|
];
|
||||||
|
|
||||||
|
expect(() => setActionOutputs(outputs, {})).toThrowError();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("getActionOutput", () => {
|
||||||
|
test("returns the value of an output if it was set", () => {
|
||||||
|
const env = { ...ENV };
|
||||||
|
const name = "output1";
|
||||||
|
const value = "value1";
|
||||||
|
|
||||||
|
setActionOutput(name, value, env);
|
||||||
|
const output = getActionOutput(name, env);
|
||||||
|
|
||||||
|
expect(output).toEqual(value);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("returns the object value of an output if it was set", () => {
|
||||||
|
const env = { ...ENV };
|
||||||
|
const name = "output1";
|
||||||
|
const value = { foo: "bar" };
|
||||||
|
|
||||||
|
setActionOutput(name, value, env);
|
||||||
|
const output = getActionOutput(name, env);
|
||||||
|
|
||||||
|
expect(output).toEqual(value);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("returns undefined if the output was not set", () => {
|
||||||
|
const output = getActionOutput("output1", { ...ENV });
|
||||||
|
|
||||||
|
expect(output).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("getActionOutputs", () => {
|
||||||
|
test("returns the values of multiple outputs if they were set", () => {
|
||||||
|
const env = { ...ENV };
|
||||||
|
const names = ["output1", "output2"];
|
||||||
|
const values = ["value1", "value2"];
|
||||||
|
|
||||||
|
setActionOutputs(names.map((x, i) => [x, values[i]]), env);
|
||||||
|
const outputs = getActionOutputs(names, env);
|
||||||
|
|
||||||
|
expect(outputs).toEqual(values);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("returns the object values of multiple outputs if they were set", () => {
|
||||||
|
const env = { ...ENV };
|
||||||
|
const names = ["output1", "output2"];
|
||||||
|
const values = [{ foo: "bar" }, { baz: 1 }];
|
||||||
|
|
||||||
|
setActionOutputs(names.map((x, i) => [x, values[i]]), env);
|
||||||
|
const outputs = getActionOutputs(names, env);
|
||||||
|
|
||||||
|
expect(outputs).toEqual(values);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("returns undefined for the outputs that were not set", () => {
|
||||||
|
const names = ["output1", "output2"];
|
||||||
|
|
||||||
|
const outputs = getActionOutputs(names, { ...ENV });
|
||||||
|
|
||||||
|
expect(outputs).toEqual([undefined, undefined]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("getAllActionOutputs", () => {
|
||||||
|
test("returns a map containing all outputs set by the action", () => {
|
||||||
|
const env = { ...ENV };
|
||||||
|
const outputs = [
|
||||||
|
["output1", "value1"] as const,
|
||||||
|
["output2", { foo: "bar" }] as const,
|
||||||
|
];
|
||||||
|
|
||||||
|
setActionOutputs(outputs, env);
|
||||||
|
const result = getAllActionOutputs(env);
|
||||||
|
|
||||||
|
expect(result).toEqual(new Map<string, unknown>(outputs));
|
||||||
|
});
|
||||||
|
|
||||||
|
test("returns an empty map if no outputs were set", () => {
|
||||||
|
const result = getAllActionOutputs({ ...ENV });
|
||||||
|
|
||||||
|
expect(result).toEqual(new Map());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("createActionOutputController", () => {
|
||||||
|
test("creates a new output controller based on the provided descriptors and options", async () => {
|
||||||
|
const descriptors = [
|
||||||
|
{ name: "output1", path: ["output1"], type: undefined, description: "" },
|
||||||
|
{ name: "output2", path: ["foo", "output2"], type: undefined, description: "" },
|
||||||
|
{ name: "output3", path: ["foo", "bar", "output3"], type: undefined, description: "" },
|
||||||
|
{ name: "output4", path: ["foo", "bar", "output4"], type: undefined, description: "" },
|
||||||
|
{ name: "output5", path: ["foo", "bar", "output5"], redirect: "output4", type: undefined, description: "" },
|
||||||
|
];
|
||||||
|
const options = {
|
||||||
|
getOutput: name => getActionOutput(name, ENV),
|
||||||
|
setOutput: (name, value) => setActionOutput(name, value, ENV),
|
||||||
|
} as ActionOutputControllerOptions;
|
||||||
|
|
||||||
|
const controller = createActionOutputController(descriptors, options);
|
||||||
|
controller["output1"] = "value1";
|
||||||
|
controller["foo"]["output2"] = true;
|
||||||
|
controller["foo"] = {
|
||||||
|
bar: {
|
||||||
|
output3: { foo: "bar" },
|
||||||
|
output5: { baz: 42 },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const outputFile = await readFile(ENV.GITHUB_OUTPUT, "utf8");
|
||||||
|
const deserializedOutputs = [...outputFile.matchAll(/^(?<name>.+)<<(.+)\r?\n(?<value>.+)\r?\n\2$/gm)]
|
||||||
|
.map(x => [x.groups.name, x.groups.value])
|
||||||
|
.reduce((a, [name, value]) => (a[name] = value) && a, {});
|
||||||
|
|
||||||
|
expect(deserializedOutputs["output1"]).toEqual("value1");
|
||||||
|
expect(deserializedOutputs["output2"]).toEqual("true");
|
||||||
|
expect(deserializedOutputs["output3"]).toEqual(JSON.stringify({ foo: "bar" }));
|
||||||
|
expect(deserializedOutputs["output4"]).toEqual(JSON.stringify({ baz: 42 }));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("createActionOutputControllerUsingMetadata", () => {
|
||||||
|
const METADATA = Object.freeze({
|
||||||
|
name: "test-metadata",
|
||||||
|
description: "Test description",
|
||||||
|
runs: { main: "index.js", using: "node16" },
|
||||||
|
|
||||||
|
outputs: {
|
||||||
|
output1: {
|
||||||
|
description: "",
|
||||||
|
},
|
||||||
|
|
||||||
|
output2: {
|
||||||
|
description: "",
|
||||||
|
},
|
||||||
|
|
||||||
|
output3: {
|
||||||
|
description: "",
|
||||||
|
},
|
||||||
|
|
||||||
|
output4: {
|
||||||
|
description: "",
|
||||||
|
},
|
||||||
|
|
||||||
|
output5: {
|
||||||
|
description: "",
|
||||||
|
redirect: "output4",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as ActionMetadata);
|
||||||
|
|
||||||
|
test("creates a new output controller based on the provided metadata and options", async () => {
|
||||||
|
const pathParser: ActionParameterPathParser = name => {
|
||||||
|
switch (name[name.length - 1]) {
|
||||||
|
case "1":
|
||||||
|
return [name];
|
||||||
|
|
||||||
|
case "2":
|
||||||
|
return ["foo", name];
|
||||||
|
|
||||||
|
default:
|
||||||
|
return ["foo", "bar", name];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const options = {
|
||||||
|
pathParser,
|
||||||
|
getOutput: name => getActionOutput(name, ENV),
|
||||||
|
setOutput: (name, value) => setActionOutput(name, value, ENV),
|
||||||
|
} as ActionOutputControllerOptions;
|
||||||
|
|
||||||
|
const controller = createActionOutputControllerUsingMetadata(METADATA, options);
|
||||||
|
controller["output1"] = "value1";
|
||||||
|
controller["foo"]["output2"] = true;
|
||||||
|
controller["foo"]["bar"] = {
|
||||||
|
output3: { foo: "bar" },
|
||||||
|
output5: { baz: 42 },
|
||||||
|
};
|
||||||
|
|
||||||
|
const outputFile = await readFile(ENV.GITHUB_OUTPUT, "utf8");
|
||||||
|
const deserializedOutputs = [...outputFile.matchAll(/^(?<name>.+)<<(.+)\r?\n(?<value>.+)\r?\n\2$/gm)]
|
||||||
|
.map(x => [x.groups.name, x.groups.value])
|
||||||
|
.reduce((a, [name, value]) => (a[name] = value) && a, {});
|
||||||
|
|
||||||
|
expect(deserializedOutputs["output1"]).toEqual("value1");
|
||||||
|
expect(deserializedOutputs["output2"]).toEqual("true");
|
||||||
|
expect(deserializedOutputs["output3"]).toEqual(JSON.stringify({ foo: "bar" }));
|
||||||
|
expect(deserializedOutputs["output4"]).toEqual(JSON.stringify({ baz: 42 }));
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in a new issue