import { describe, test, expect, beforeAll, afterAll } from "@jest/globals"; import { setupInput, unsetInput } from "./utils/input-utils"; import { getInputAsObject, mapStringInput, mapObjectInput, mapNumberInput, mapBooleanInput, mapEnumInput } from "../src/utils/input-utils"; const defaultInput = { "boolean": true, "object": { foo: "bar" }, "number": 1, "array": ["foo", "bar"], "undefined": "${undefined}", "files-primary": "primaryPath", "files-secondary": "secondaryPath", "files-secondary-inner": "innerSecondaryPath", "files": "path", "modrinth-id": 42, "modrinth-token": "1234", "modrinth-files-primary": "primaryPath", "modrinth-files-secondary": "secondaryPath", "This is a Very--Long_Name!": "foo" }; describe("getInputAsObject", () => { beforeAll(() => setupInput(defaultInput)); afterAll(() => unsetInput()); test("input object contains only strings", () => { const input = getInputAsObject(); expect(input).toHaveProperty("boolean", "true"); expect(input).toHaveProperty("object", {}.toString()); expect(input).not.toHaveProperty("object.foo"); expect(input).toHaveProperty("number", "1"); expect(input).toHaveProperty("array", ["foo", "bar"].toString()); }); test("property names are converted to paths inside of the input object (a-b -> a.b and aB)", () => { const input = getInputAsObject(); expect(input).toHaveProperty("modrinth.id", "42"); expect(input).toHaveProperty("modrinthId", "42"); expect(input).toHaveProperty("modrinth.token", "1234"); expect(input).toHaveProperty("modrinthToken", "1234"); expect(input).toHaveProperty("modrinth.files.primary", "primaryPath"); expect(input).toHaveProperty("modrinth.filesPrimary", "primaryPath"); expect(input).toHaveProperty("modrinthFilesPrimary", "primaryPath"); expect(input).toHaveProperty("modrinth.files.secondary", "secondaryPath"); expect(input).toHaveProperty("modrinth.filesSecondary", "secondaryPath"); expect(input).toHaveProperty("modrinthFilesSecondary", "secondaryPath"); }); test("string values do not have additional properties", () => { const input = getInputAsObject(); expect(input).toHaveProperty("files", "path"); expect(input).toHaveProperty("filesPrimary", "primaryPath"); expect(input).toHaveProperty("filesSecondary", "secondaryPath"); expect(input).toHaveProperty("filesSecondaryInner", "innerSecondaryPath"); expect(input).not.toHaveProperty("files.primary"); expect(input).not.toHaveProperty("files.secondary"); }); test("input object does not have empty property names", () => { const input = getInputAsObject(); expect(input).toHaveProperty("this.is.a.very.long.name", "foo"); expect(input).toHaveProperty("thisIsAVeryLongName", "foo"); }); test("special case for GitHub Actions: ${undefined} transforms into undefined", () => { const input = getInputAsObject(); expect(input.undefined).toBeUndefined(); }); }); describe("mapStringInput", () => { beforeAll(() => setupInput(defaultInput)); afterAll(() => unsetInput()); test("returns default value if input is not a string", () => { const input = getInputAsObject(); expect(input["undefined"]).toBeUndefined(); expect(mapStringInput(input["undefined"], "42")).toBe("42"); }); test("maps strings to string", () => { const input = getInputAsObject(); expect(mapStringInput(input["boolean"], "")).toBe("true"); expect(mapStringInput(input["number"], "")).toBe("1"); expect(mapStringInput(input["object"])).toBe({}.toString()); }); }); describe("mapObjectInput", () => { beforeAll(() => setupInput(defaultInput)); afterAll(() => unsetInput()); test("returns default value if input is not an object", () => { const input = getInputAsObject(); expect(input["boolean"]).not.toBeUndefined(); expect(mapObjectInput(input["boolean"], null)).toBeNull(); expect(input["number"]).not.toBeUndefined(); expect(mapObjectInput(input["number"], null)).toBeNull() expect(input["array"]).not.toBeUndefined(); expect(mapObjectInput(input["array"])).toBeNull() expect(input["undefined"]).toBeUndefined(); expect(mapObjectInput(input["undefined"], { answer: 42 })).toStrictEqual({ answer: 42 }); }); test("maps object values to object", () => { const input = getInputAsObject(); expect(mapObjectInput(input["modrinth"], null)).toStrictEqual({ id: "42", token: "1234", filesPrimary: "primaryPath", filesSecondary: "secondaryPath", files: { primary: "primaryPath", secondary: "secondaryPath" } }); }); }); describe("mapNumberInput", () => { beforeAll(() => setupInput({ ...defaultInput, numberOne: 1, numberOneString: "1", numberOneStringWithWhitespace: " 1 ", })); afterAll(() => unsetInput()); test("returns default value if input is not number or number-like", () => { const input = getInputAsObject(); expect(input["boolean"]).not.toBeUndefined(); expect(mapNumberInput(input["boolean"], 0)).toBe(0); expect(input["object"]).not.toBeUndefined(); expect(mapNumberInput(input["object"], 0)).toBe(0); expect(input["array"]).not.toBeUndefined(); expect(mapNumberInput(input["array"], 0)).toBe(0); expect(input["undefined"]).toBeUndefined(); expect(mapNumberInput(input["undefined"], 1)).toBe(1); }); test("maps number and number-like values to number", () => { const input = getInputAsObject(); expect(mapNumberInput(input["numberone"], 0)).toBe(1); expect(mapNumberInput(input["numberonestring"], 0)).toBe(1); expect(mapNumberInput(input["numberonestringwithwhitespace"])).toBe(1); }); }); describe("mapBooleanInput", () => { beforeAll(() => setupInput({ ...defaultInput, booleanTrue: true, booleanTrueStringLowerCase: "true", booleanTrueStringUpperCase: "TRUE", booleanTrueStringUpperCaseWithWhitespace: " TRUE ", booleanFalse: false, booleanFalseStringLowerCase: "false", booleanFalseStringUpperCase: "FALSE", booleanFalseStringUpperCaseWithWhitespace: " FALSE ", })); afterAll(() => unsetInput()); test("returns default value if input is not boolean or boolean-like", () => { const input = getInputAsObject(); expect(input["object"]).not.toBeUndefined(); expect(mapBooleanInput(input["object"], false)).toBe(false); expect(input["number"]).not.toBeUndefined(); expect(mapBooleanInput(input["number"], false)).toBe(false); expect(input["array"]).not.toBeUndefined(); expect(mapBooleanInput(input["array"], false)).toBe(false); expect(input["undefined"]).toBeUndefined(); expect(mapBooleanInput(input["undefined"], true)).toBe(true); }); test("maps boolean and boolean-like values to boolean", () => { const input = getInputAsObject(); expect(mapBooleanInput(input["booleantrue"], false)).toBe(true); expect(mapBooleanInput(input["booleantruestringlowercase"], false)).toBe(true); expect(mapBooleanInput(input["booleantruestringuppercase"], false)).toBe(true); expect(mapBooleanInput(input["booleantruestringuppercasewithwhitespace"])).toBe(true); expect(mapBooleanInput(input["booleanfalse"], true)).toBe(false); expect(mapBooleanInput(input["booleanfalsestringlowercase"], true)).toBe(false); expect(mapBooleanInput(input["booleanfalsestringuppercase"], true)).toBe(false); expect(mapBooleanInput(input["booleanfalsestringuppercasewithwhitespace"], true)).toBe(false); }); }); describe("mapEnumInput", () => { enum TestEnum { None = 0, A = 1, B = 2, C = 4, A_B = 1 | 2, A_C = 1 | 4, B_C = 2 | 4, A_B_C = 1 | 2 | 4, } beforeAll(() => setupInput({ ...defaultInput, enumAB: TestEnum.A_B, enumABStringUpperCase: "A_B", enumABStringLowerCase: "a_b", enumABStringLowerCaseWithWhitespace: " a_b ", enumABStringLowerCaseWithWhitespaceAndDifferentSeparator: " a-b ", enumABStringLowerCaseWithWhitespaceBitwise: " a | b ", enumABCStringLowerCaseWithWhitespaceBitwise: " c | b | b | a ", })); afterAll(() => unsetInput()); test("returns default value if input cannot be casted to the given enum", () => { const input = getInputAsObject(); expect(input["object"]).not.toBeUndefined(); expect(mapEnumInput(input["object"], TestEnum)).toBeNull(); expect(input["boolean"]).not.toBeUndefined(); expect(mapEnumInput(input["boolean"], TestEnum)).toBeNull(); expect(input["array"]).not.toBeUndefined(); expect(mapEnumInput(input["array"], TestEnum)).toBeNull(); expect(input["undefined"]).toBeUndefined(); expect(mapEnumInput(input["undefined"], TestEnum, TestEnum.A_B_C)).toBe(TestEnum.A_B_C); }); test("maps values to the given enum", () => { const input = getInputAsObject(); expect(mapEnumInput(input["enumab"], TestEnum)).toBe(TestEnum.A_B); expect(mapEnumInput(input["enumabstringuppercase"], TestEnum)).toBe(TestEnum.A_B); expect(mapEnumInput(input["enumabstringlowercase"], TestEnum)).toBe(TestEnum.A_B); expect(mapEnumInput(input["enumabstringlowercasewithwhitespace"], TestEnum)).toBe(TestEnum.A_B); expect(mapEnumInput(input["enumabstringlowercasewithwhitespaceanddifferentseparator"], TestEnum)).toBe(TestEnum.A_B); expect(mapEnumInput(input["enumabstringlowercasewithwhitespacebitwise"], TestEnum)).toBe(TestEnum.A_B); expect(mapEnumInput(input["enumabcstringlowercasewithwhitespacebitwise"], TestEnum, TestEnum.A_B)).toBe(TestEnum.A_B_C); }); });