diff --git a/src/lib/pipelines/pipelines.test.ts b/src/lib/pipelines/pipelines.test.ts index 9e63d141f..c9fe562a8 100644 --- a/src/lib/pipelines/pipelines.test.ts +++ b/src/lib/pipelines/pipelines.test.ts @@ -1,18 +1,21 @@ -jest.mock("./pipelines"); - import { disableVerboseLogging, enableVerboseLogging } from "../../logger"; import { - IAzureRepoPipelineConfig, + createPipelineForDefinition, + definitionForAzureRepoPipeline, + definitionForGithubRepoPipeline, + getBuildApiClient, GithubRepoPipelineConfig, + IAzureRepoPipelineConfig, + queueBuild, RepositoryTypes } from "./pipelines"; - import { BuildDefinition, BuildRepository, YamlProcess } from "azure-devops-node-api/interfaces/BuildInterfaces"; +import * as azdoClient from "../azdoClient"; beforeAll(() => { enableVerboseLogging(); @@ -22,9 +25,15 @@ afterAll(() => { disableVerboseLogging(); }); -describe("It builds an azure repo pipeline definition", () => { - const { definitionForAzureRepoPipeline } = jest.requireActual("./pipelines"); +describe("test getBuildApiClient function", () => { + it("positive test", async () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + jest.spyOn(azdoClient, "getBuildApi").mockResolvedValueOnce({} as any); + await expect(getBuildApiClient("org", "token")).toBeDefined(); + }); +}); +describe("It builds an azure repo pipeline definition", () => { test("pipeline definition is well-formed", () => { const sampleAzureConfig = { branchFilters: ["master"], @@ -70,8 +79,6 @@ describe("It builds an azure repo pipeline definition", () => { }); describe("It builds a github repo pipeline definition", () => { - const { definitionForGithubRepoPipeline } = jest.requireActual("./pipelines"); - test("pipeline definition is well-formed", () => { const sampleGithubConfig = { branchFilters: ["master"], @@ -122,3 +129,67 @@ describe("It builds a github repo pipeline definition", () => { } }); }); + +describe("test createPipelineForDefinition function", () => { + it("positive test", async () => { + const result = await createPipelineForDefinition( + { + createDefinition: () => { + return {}; + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as any, + "project", + // eslint-disable-next-line @typescript-eslint/no-explicit-any + {} as any + ); + expect(result).toBeDefined(); + }); + it("negative test", async () => { + await expect( + createPipelineForDefinition( + { + createDefinition: () => { + throw Error("fake"); + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as any, + "project", + // eslint-disable-next-line @typescript-eslint/no-explicit-any + {} as any + ) + ).rejects.toThrow(); + }); +}); + +describe("test queueBuild function", () => { + it("positive test", async () => { + const result = await queueBuild( + { + queueBuild: () => { + return {}; + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as any, + "project", + // eslint-disable-next-line @typescript-eslint/no-explicit-any + {} as any + ); + expect(result).toBeDefined(); + }); + it("negative test", async () => { + await expect( + queueBuild( + { + queueBuild: () => { + throw Error("fake"); + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as any, + "project", + // eslint-disable-next-line @typescript-eslint/no-explicit-any + {} as any + ) + ).rejects.toThrow(); + }); +}); diff --git a/src/lib/pipelines/variableGroup.test.ts b/src/lib/pipelines/variableGroup.test.ts index 5a794e636..8d1ed9ae7 100644 --- a/src/lib/pipelines/variableGroup.test.ts +++ b/src/lib/pipelines/variableGroup.test.ts @@ -7,11 +7,7 @@ import uuid from "uuid/v4"; import * as azdoClient from "../azdoClient"; import { readYaml } from "../../config"; import * as config from "../../config"; -import { - disableVerboseLogging, - enableVerboseLogging, - logger -} from "../../logger"; +import { disableVerboseLogging, enableVerboseLogging } from "../../logger"; import { VariableGroupData, VariableGroupDataVariable } from "../../types"; import { addVariableGroup, @@ -21,6 +17,8 @@ import { deleteVariableGroup, doAddVariableGroup } from "./variableGroup"; +import * as variableGroup from "./variableGroup"; +import * as serviceEndpoint from "./serviceEndpoint"; // Mocks jest.mock("azure-devops-node-api"); @@ -38,21 +36,21 @@ afterAll(() => { describe("addVariableGroup", () => { test("should fail when variable group config is not set", async () => { - (readYaml as jest.Mock).mockReturnValue({}); + (readYaml as jest.Mock).mockReturnValueOnce({}); const data = readYaml(""); await expect(addVariableGroup(data)).rejects.toThrow(); }); test("should fail when variable group config variables are not set", async () => { - (readYaml as jest.Mock).mockReturnValue({ + (readYaml as jest.Mock).mockReturnValueOnce({ variables: undefined }); const data = readYaml(""); await expect(addVariableGroup(data)).rejects.toThrow(); }); - test("should pass when variable group data is set", async () => { - (readYaml as jest.Mock).mockReturnValue({ + it("should pass when variable group data is set", async () => { + (readYaml as jest.Mock).mockReturnValueOnce({ description: "mydesc", name: "myvg", type: "Vsts", @@ -65,35 +63,21 @@ describe("addVariableGroup", () => { } ] }); - const data = readYaml(""); - let group: VariableGroup | undefined; - try { - logger.info("calling add variable group with mock config"); - group = await addVariableGroup(data); - } catch (err) { - logger.error(err); - } - expect(group).toBeUndefined(); + jest.spyOn(variableGroup, "doAddVariableGroup").mockResolvedValueOnce({}); + const group = await addVariableGroup(data); + expect(group).toBeDefined(); }); }); describe("addVariableGroupWithKeyVaultMap", () => { test("should fail when variable group data is not set", async () => { - (readYaml as jest.Mock).mockReturnValue({}); + (readYaml as jest.Mock).mockReturnValueOnce({}); const data = readYaml(""); - let invalidGroupError: Error | undefined; - try { - logger.info("calling add variable group with Key Vault map"); - await addVariableGroupWithKeyVaultMap(data); - } catch (err) { - invalidGroupError = err; - } - expect(invalidGroupError).toBeDefined(); + await expect(addVariableGroupWithKeyVaultMap(data)).rejects.toThrow(); }); - test("should fail when key vault data is not set for variable group", async () => { - (readYaml as jest.Mock).mockReturnValue({ + (readYaml as jest.Mock).mockReturnValueOnce({ description: "mydesc", name: "myvg", type: "AzureKeyVault", @@ -105,20 +89,11 @@ describe("addVariableGroupWithKeyVaultMap", () => { } ] }); - const data = readYaml(""); - let group: VariableGroup | undefined; - try { - logger.info("calling addVariableGroupWithKeyVaultMap with mock config"); - group = await addVariableGroupWithKeyVaultMap(data); - } catch (err) { - logger.error(err); - } - expect(group).toBeUndefined(); + await expect(addVariableGroupWithKeyVaultMap(data)).rejects.toThrow(); }); - test("should fail when key vault name is not set for variable group", async () => { - (readYaml as jest.Mock).mockReturnValue({ + (readYaml as jest.Mock).mockReturnValueOnce({ description: "mydesc", key_vault_provider: { service_endpoint: { @@ -142,17 +117,10 @@ describe("addVariableGroupWithKeyVaultMap", () => { }); const data = readYaml(""); - let group: VariableGroup | undefined; - try { - group = await addVariableGroupWithKeyVaultMap(data); - } catch (err) { - logger.error(err); - } - expect(group).toBeUndefined(); + await expect(addVariableGroupWithKeyVaultMap(data)).rejects.toThrow(); }); - test("should fail when service endpoint data is not set for variable group", async () => { - (readYaml as jest.Mock).mockReturnValue({ + (readYaml as jest.Mock).mockReturnValueOnce({ description: "myvg desc", key_vault_provider: { name: "mykv", @@ -167,19 +135,11 @@ describe("addVariableGroupWithKeyVaultMap", () => { } ] }); - const data = readYaml(""); - let group: VariableGroup | undefined; - try { - group = await addVariableGroupWithKeyVaultMap(data); - } catch (err) { - logger.error(err); - } - expect(group).toBeUndefined(); + await expect(addVariableGroupWithKeyVaultMap(data)).rejects.toThrow(); }); - test("should pass when variable group data is valid", async () => { - (readYaml as jest.Mock).mockReturnValue({ + (readYaml as jest.Mock).mockReturnValueOnce({ description: "myvg desc", key_vault_provider: { name: "mykv", @@ -203,20 +163,49 @@ describe("addVariableGroupWithKeyVaultMap", () => { }); const data = readYaml(""); - let group: VariableGroup | undefined; - try { - logger.info("calling add variable group with mock config"); - group = await addVariableGroupWithKeyVaultMap(data); - } catch (err) { - logger.error(err); - } - expect(group).toBeUndefined(); + jest + .spyOn(serviceEndpoint, "createServiceEndpointIfNotExists") + .mockResolvedValueOnce({ + id: "test" + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as any); + jest.spyOn(variableGroup, "doAddVariableGroup").mockResolvedValueOnce({}); + const group = await addVariableGroupWithKeyVaultMap(data); + expect(group).toBeDefined(); }); }); +const mockForDoAddVariableGroupTest = (): void => { + jest.spyOn(config, "Config").mockReturnValueOnce({ + azure_devops: { + project: "project" + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as any); + jest.spyOn(azdoClient, "getTaskAgentApi").mockResolvedValueOnce({ + addVariableGroup: () => { + return { + id: "test" + }; + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as any); + jest + .spyOn(variableGroup, "authorizeAccessToAllPipelines") + .mockResolvedValueOnce(true); +}; + describe("doAddVariableGroup", () => { + test("negative test: project is not provided", async () => { + jest.spyOn(config, "Config").mockReturnValueOnce({ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as any); + // project is not in config.yaml + await expect(doAddVariableGroup({}, true)).rejects.toThrow(); + }); test("should pass when variable group with vsts data is set", async () => { - (readYaml as jest.Mock).mockReturnValue({ + mockForDoAddVariableGroupTest(); + (readYaml as jest.Mock).mockReturnValueOnce({ description: uuid(), name: uuid(), type: "Vsts", @@ -233,7 +222,7 @@ describe("doAddVariableGroup", () => { }); const data = readYaml(""); - const variablesMap = await buildVariablesMap(data.variables); + const variablesMap = buildVariablesMap(data.variables); // create variable group parameterts const params: VariableGroupParameters = { @@ -243,18 +232,12 @@ describe("doAddVariableGroup", () => { variables: variablesMap }; - let variableGroup: VariableGroup | undefined; - - try { - variableGroup = await doAddVariableGroup(params, true); - } catch (_) { - // ignored - } - expect(variableGroup).toBeUndefined(); + const group = await doAddVariableGroup(params, true); + expect(group).toBeDefined(); }); - test("should pass when variable group with key vault data is set", async () => { - (readYaml as jest.Mock).mockReturnValue({ + mockForDoAddVariableGroupTest(); + (readYaml as jest.Mock).mockReturnValueOnce({ description: uuid(), key_vault_data: { name: "mykv", @@ -282,24 +265,17 @@ describe("doAddVariableGroup", () => { }); const data = readYaml(""); - const variablesMap = await buildVariablesMap(data.variables); // create variable group parameterts const params: VariableGroupParameters = { description: data.description, name: data.name, type: data.type, - variables: variablesMap + variables: buildVariablesMap(data.variables) }; - let variableGroup: VariableGroup | undefined; - - try { - variableGroup = await doAddVariableGroup(params, true); - } catch (_) { - // ignore - } - expect(variableGroup).toBeUndefined(); + const group = await doAddVariableGroup(params, true); + expect(group).toBeDefined(); }); }); @@ -336,6 +312,14 @@ describe("authorizeAccessToAllPipelines", () => { test("should fail when passing null variable group", async () => { await expect(authorizeAccessToAllPipelines({})).rejects.toThrow(); }); + test("should fail when project is missing", async () => { + await expect( + authorizeAccessToAllPipelines({ + id: 1, + name: "group" + }) + ).rejects.toThrow(); + }); }); describe("buildVariablesMap", () => { @@ -351,9 +335,8 @@ describe("buildVariablesMap", () => { } }; - const map = await buildVariablesMap(variables); + const map = buildVariablesMap(variables); expect(map).toEqual(variables); - logger.info(`map: ${JSON.stringify(map)}`); }); test("should create variable map with one variable", async () => { @@ -364,13 +347,13 @@ describe("buildVariablesMap", () => { } }; - const map = await buildVariablesMap(variables); + const map = buildVariablesMap(variables); expect(map).toEqual(variables); }); test("should create empty variable map with no variables", async () => { const variables: VariableGroupDataVariable = {}; - const map = await buildVariablesMap(variables); + const map = buildVariablesMap(variables); expect(Object.keys(map).length).toBe(0); }); @@ -384,7 +367,7 @@ describe("buildVariablesMap", () => { } }; - const secretsMap = await buildVariablesMap(variables); + const secretsMap = buildVariablesMap(variables); expect(secretsMap).toEqual(variables); }); @@ -395,13 +378,12 @@ describe("buildVariablesMap", () => { } }; - const secretsMap = await buildVariablesMap(variables); + const secretsMap = buildVariablesMap(variables); expect(secretsMap).toEqual(variables); }); test("should create empty variable map with no secrets", async () => { - const variables: VariableGroupDataVariable = {}; - const secretsMap = await buildVariablesMap(variables); + const secretsMap = buildVariablesMap({}); expect(Object.keys(secretsMap).length).toBe(0); }); }); @@ -409,7 +391,7 @@ describe("buildVariablesMap", () => { describe("test deleteVariableGroup function", () => { it("positive test: group found", async () => { const delFn = jest.fn(); - jest.spyOn(azdoClient, "getTaskAgentApi").mockResolvedValue({ + jest.spyOn(azdoClient, "getTaskAgentApi").mockResolvedValueOnce({ deleteVariableGroup: delFn, getVariableGroups: () => [ { @@ -424,7 +406,7 @@ describe("test deleteVariableGroup function", () => { }); it("positive test: no matching groups found", async () => { const delFn = jest.fn(); - jest.spyOn(azdoClient, "getTaskAgentApi").mockResolvedValue({ + jest.spyOn(azdoClient, "getTaskAgentApi").mockResolvedValueOnce({ deleteVariableGroup: delFn, getVariableGroups: () => [] // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/src/lib/pipelines/variableGroup.ts b/src/lib/pipelines/variableGroup.ts index 1cb3d3b44..be37d406f 100644 --- a/src/lib/pipelines/variableGroup.ts +++ b/src/lib/pipelines/variableGroup.ts @@ -17,9 +17,9 @@ import { createServiceEndpointIfNotExists } from "./serviceEndpoint"; * @param variableGroup The Variable group object * @returns `IVariablesMap[]` with Varibale Group variables */ -export const buildVariablesMap = async ( +export const buildVariablesMap = ( variables: VariableGroupDataVariable -): Promise => { +): VariableGroupDataVariable => { const variablesMap: VariableGroupDataVariable = {}; logger.debug(`variables: ${JSON.stringify(variables)}`); @@ -159,7 +159,7 @@ export const addVariableGroup = async ( } // map variables from configuration - const variablesMap = await buildVariablesMap(variableGroupData.variables); + const variablesMap = buildVariablesMap(variableGroupData.variables); // create variable group parameters const params: VariableGroupParameters = { @@ -221,7 +221,7 @@ export const addVariableGroupWithKeyVaultMap = async ( }; // map variables as secrets from input - const secretsMap = await buildVariablesMap(variableGroupData.variables); + const secretsMap = buildVariablesMap(variableGroupData.variables); // creating variable group parameters const params: VariableGroupParameters = {