diff --git a/src/initialize/index.test.ts b/src/initialize/index.test.ts index 675aaa6e7..703dcdd83 100644 --- a/src/initialize/index.test.ts +++ b/src/initialize/index.test.ts @@ -1,15 +1,23 @@ import { describe, expect, it, vi } from "vitest"; import { StatusCodes } from "../shared/codes.js"; +import { RunOrRestoreOptions } from "../shared/runOrRestore.js"; import { initialize } from "./index.js"; const mockOutro = vi.fn(); -vi.mock("@clack/prompts", () => ({ +vi.mock("../shared/cli/outro.js", () => ({ get outro() { return mockOutro; }, - spinner: vi.fn(), +})); + +const mockEnsureGitRepository = vi.fn(); + +vi.mock("../shared/ensureGitRepository.js", () => ({ + get ensureGitRepository() { + return mockEnsureGitRepository; + }, })); const mockReadOptions = vi.fn(); @@ -20,11 +28,18 @@ vi.mock("../shared/options/readOptions.js", () => ({ }, })); -const mockInitializeAndEnterRepository = vi.fn(); +vi.mock("../shared/runOrRestore.js", () => ({ + async runOrRestore({ run }: RunOrRestoreOptions) { + await run(); + return StatusCodes.Success; + }, +})); + +const mockInitializeWithOptions = vi.fn(); -vi.mock("./initializeAndEnterRepository.js", () => ({ - get initializeAndEnterRepository() { - return mockInitializeAndEnterRepository; +vi.mock("./initializeWithOptions.js", () => ({ + get initializeWithOptions() { + return mockInitializeWithOptions; }, })); @@ -45,5 +60,49 @@ describe("initialize", () => { code: StatusCodes.Cancelled, options: optionsBase, }); + expect(mockEnsureGitRepository).not.toHaveBeenCalled(); + }); + + it("runs initializeWithOptions when readOptions returns inputs", async () => { + mockReadOptions.mockResolvedValue({ + cancelled: false, + options: optionsBase, + }); + + const result = await initialize([]); + + expect(result).toEqual({ + code: StatusCodes.Success, + options: optionsBase, + }); + expect(mockEnsureGitRepository).toHaveBeenCalled(); + expect(mockOutro.mock.calls).toMatchInlineSnapshot(` + [ + [ + [ + { + "label": "You may consider committing these changes:", + "lines": [ + "git add -A", + "git commit -m "feat: initialized repo ✨", + "git push", + ], + "variant": "code", + }, + { + "label": "Be sure to:", + "lines": [ + "- enable the GitHub apps: + - Codecov (https://github.com/apps/codecov) + - Renovate (https://github.com/apps/renovate)", + "- populate the secrets: + - ACCESS_TOKEN (a GitHub PAT with repo and workflow permissions) + - NPM_TOKEN (an npm access token with automation permissions)", + ], + }, + ], + ], + ] + `); }); }); diff --git a/src/initialize/initializeWithOptions.test.ts b/src/initialize/initializeWithOptions.test.ts new file mode 100644 index 000000000..5cdd120d5 --- /dev/null +++ b/src/initialize/initializeWithOptions.test.ts @@ -0,0 +1,187 @@ +import { describe, expect, it, vi } from "vitest"; + +import { GitHub } from "../shared/options/getGitHub.js"; +import { Options } from "../shared/types.js"; +import { initializeWithOptions } from "./initializeWithOptions.js"; + +vi.mock("../shared/cli/spinners.js", () => ({ + async withSpinner(_label: string, task: () => Promise) { + await task(); + }, + withSpinners: vi.fn(), +})); + +const mockAddOwnerAsAllContributor = vi.fn(); + +vi.mock("../steps/addOwnerAsAllContributor.js", () => ({ + get addOwnerAsAllContributor() { + return mockAddOwnerAsAllContributor; + }, +})); + +const mockClearChangelog = vi.fn(); + +vi.mock("../steps/clearChangelog.js", () => ({ + get clearChangelog() { + return mockClearChangelog; + }, +})); + +const mockInitializeGitHubRepository = vi.fn(); + +vi.mock("../steps/initializeGitHubRepository/index.js", () => ({ + get initializeGitHubRepository() { + return mockInitializeGitHubRepository; + }, +})); + +const mockRemoveSetupScripts = vi.fn(); + +vi.mock("../steps/removeSetupScripts.js", () => ({ + get removeSetupScripts() { + return mockRemoveSetupScripts; + }, +})); + +const mockResetGitTags = vi.fn(); + +vi.mock("../steps/resetGitTags.js", () => ({ + get resetGitTags() { + return mockResetGitTags; + }, +})); + +const mockRunCleanup = vi.fn(); + +vi.mock("../steps/runCleanup.js", () => ({ + get runCleanup() { + return mockRunCleanup; + }, +})); + +const mockUninstallPackages = vi.fn(); + +vi.mock("../steps/uninstallPackages.js", () => ({ + get uninstallPackages() { + return mockUninstallPackages; + }, +})); + +const optionsBase = {} as Options; + +describe("initializeWithOptions", () => { + it("runs addOwnerAsAllContributor when excludeAllContributors is false", async () => { + const options = { + ...optionsBase, + excludeAllContributors: false, + }; + + await initializeWithOptions({ + github: undefined, + options, + }); + + expect(mockAddOwnerAsAllContributor).toHaveBeenCalledWith(options); + }); + + it("does not run addOwnerAsAllContributor when excludeAllContributors is true", async () => { + const options = { + ...optionsBase, + excludeAllContributors: true, + }; + + await initializeWithOptions({ + github: undefined, + options, + }); + + expect(mockAddOwnerAsAllContributor).not.toHaveBeenCalled(); + }); + + it("runs initializeGitHubRepository when github is truthy", async () => { + const github = { + octokit: {}, + } as GitHub; + + await initializeWithOptions({ + github, + options: optionsBase, + }); + + expect(mockInitializeGitHubRepository).toHaveBeenCalledWith( + github.octokit, + optionsBase, + ); + }); + + it("does not run initializeGitHubRepository when github is falsy", async () => { + const options = { + ...optionsBase, + excludeAllContributors: true, + }; + + await initializeWithOptions({ + github: undefined, + options, + }); + + expect(mockInitializeGitHubRepository).not.toHaveBeenCalled(); + }); + + it("runs removeSetupScripts when skipRemoval is false", async () => { + const options = { + ...optionsBase, + skipRemoval: false, + }; + + await initializeWithOptions({ + github: undefined, + options, + }); + + expect(mockRemoveSetupScripts).toHaveBeenCalled(); + }); + + it("does not run removeSetupScripts when skipRemoval is true", async () => { + const options = { + ...optionsBase, + skipRemoval: true, + }; + + await initializeWithOptions({ + github: undefined, + options, + }); + + expect(mockRemoveSetupScripts).not.toHaveBeenCalled(); + }); + + it("runs uninstallPackages when skipUninstall is false", async () => { + const options = { + ...optionsBase, + offline: true, + skipUninstall: false, + }; + + await initializeWithOptions({ + github: undefined, + options, + }); + + expect(mockUninstallPackages).toHaveBeenCalledWith(options.offline); + }); + + it("does not run uninstallPackages when skipUninstall is true", async () => { + const options = { + ...optionsBase, + skipUninstall: true, + }; + + await initializeWithOptions({ + github: undefined, + options, + }); + + expect(mockUninstallPackages).not.toHaveBeenCalled(); + }); +}); diff --git a/src/shared/runOrRestore.ts b/src/shared/runOrRestore.ts index 3fba6ff3e..4d48f3157 100644 --- a/src/shared/runOrRestore.ts +++ b/src/shared/runOrRestore.ts @@ -3,6 +3,7 @@ import chalk from "chalk"; import { $ } from "execa"; import { logLine } from "./cli/lines.js"; +import { StatusCodes } from "./codes.js"; export interface RunOrRestoreOptions { run: () => Promise; @@ -12,7 +13,7 @@ export interface RunOrRestoreOptions { export async function runOrRestore({ run, skipRestore }: RunOrRestoreOptions) { try { await run(); - return 0; + return StatusCodes.Success; } catch (error) { logLine(); console.log(error);