Skip to content

Commit b3c7970

Browse files
fix: corrected readOptions using provided values (#1084)
## PR Checklist - [x] Addresses an existing open issue: fixes #1083 - [x] That issue was marked as [`status: accepting prs`](https://github.com/JoshuaKGoldberg/create-typescript-app/issues?q=is%3Aopen+is%3Aissue+label%3A%22status%3A+accepting+prs%22) - [x] Steps in [CONTRIBUTING.md](https://github.com/JoshuaKGoldberg/create-typescript-app/blob/main/.github/CONTRIBUTING.md) were taken ## Overview Prepends `options.owner` in front of the default value getter. Same with other options values. The unit test doesn't quite catch this specific addition but I'm annoyed at how convoluted `readOptions` has gotten...
1 parent c3f93db commit b3c7970

4 files changed

+259
-71
lines changed

src/shared/options/getPrefillOrPromptedOption.test.ts

+20-20
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,23 @@ describe("getPrefillOrPromptedValue", () => {
1616
it("returns the placeholder when auto is true and it exists", async () => {
1717
const value = "Test Value";
1818

19-
const actual = await getPrefillOrPromptedOption(
20-
"field",
21-
true,
22-
"Input message.",
23-
vi.fn().mockResolvedValue(value),
24-
);
19+
const actual = await getPrefillOrPromptedOption({
20+
auto: true,
21+
getDefaultValue: vi.fn().mockResolvedValue(value),
22+
message: "Input message.",
23+
name: "field",
24+
});
2525

2626
expect(actual).toEqual({ error: undefined, value });
2727
});
2828

2929
it("returns an error when auto is true and no placeholder exists", async () => {
30-
const actual = await getPrefillOrPromptedOption(
31-
"field",
32-
true,
33-
"Input message.",
34-
vi.fn().mockResolvedValue(undefined),
35-
);
30+
const actual = await getPrefillOrPromptedOption({
31+
auto: true,
32+
getDefaultValue: vi.fn().mockResolvedValue(undefined),
33+
message: "Input message.",
34+
name: "field",
35+
});
3636

3737
expect(actual).toEqual({
3838
error: "Could not infer a default value for field.",
@@ -43,7 +43,7 @@ describe("getPrefillOrPromptedValue", () => {
4343
it("provides no placeholder when one is not provided and auto is false", async () => {
4444
const message = "Test message";
4545

46-
await getPrefillOrPromptedOption("Input message.", false, message);
46+
await getPrefillOrPromptedOption({ auto: false, message, name: "field" });
4747

4848
expect(mockText).toHaveBeenCalledWith({
4949
message,
@@ -56,12 +56,12 @@ describe("getPrefillOrPromptedValue", () => {
5656
const message = "Test message";
5757
const placeholder = "Test placeholder";
5858

59-
const actual = await getPrefillOrPromptedOption(
60-
"field",
61-
false,
59+
const actual = await getPrefillOrPromptedOption({
60+
auto: false,
61+
getDefaultValue: vi.fn().mockResolvedValue(placeholder),
6262
message,
63-
vi.fn().mockResolvedValue(placeholder),
64-
);
63+
name: "field",
64+
});
6565

6666
expect(actual).toEqual({
6767
error: undefined,
@@ -73,7 +73,7 @@ describe("getPrefillOrPromptedValue", () => {
7373
it("validates entered text when it's not blank and auto is false", async () => {
7474
const message = "Test message";
7575

76-
await getPrefillOrPromptedOption("Input message.", false, message);
76+
await getPrefillOrPromptedOption({ auto: false, message, name: "field" });
7777

7878
const { validate } = (mockText.mock.calls[0] as [Required<TextOptions>])[0];
7979

@@ -83,7 +83,7 @@ describe("getPrefillOrPromptedValue", () => {
8383
it("invalidates entered text when it's blank and auto is false", async () => {
8484
const message = "";
8585

86-
await getPrefillOrPromptedOption("Input message.", false, message);
86+
await getPrefillOrPromptedOption({ auto: false, message, name: "field" });
8787

8888
const { validate } = (mockText.mock.calls[0] as [Required<TextOptions>])[0];
8989

src/shared/options/getPrefillOrPromptedOption.ts

+13-6
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,19 @@ import * as prompts from "@clack/prompts";
22

33
import { filterPromptCancel } from "../prompts.js";
44

5-
export async function getPrefillOrPromptedOption(
6-
name: string,
7-
auto: boolean,
8-
message: string,
9-
getDefaultValue?: () => Promise<string | undefined>,
10-
) {
5+
export interface GetPrefillOrPromptedOptionOptions {
6+
auto: boolean;
7+
getDefaultValue?: () => Promise<string | undefined>;
8+
message: string;
9+
name: string;
10+
}
11+
12+
export async function getPrefillOrPromptedOption({
13+
auto,
14+
getDefaultValue,
15+
message,
16+
name,
17+
}: GetPrefillOrPromptedOptionOptions) {
1118
const defaultValue = await getDefaultValue?.();
1219

1320
if (auto || defaultValue) {

src/shared/options/readOptions.test.ts

+180-4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { describe, expect, it, vi } from "vitest";
22
import z from "zod";
33

44
import { Options } from "../types.js";
5+
import { GetPrefillOrPromptedOptionOptions } from "./getPrefillOrPromptedOption.js";
56
import { optionsSchemaShape } from "./optionsSchema.js";
67
import { readOptions } from "./readOptions.js";
78

@@ -60,6 +61,14 @@ vi.mock("../cli/spinners.ts", () => ({
6061
},
6162
}));
6263

64+
const mockReadPackageData = vi.fn();
65+
66+
vi.mock("../packages.js", () => ({
67+
get readPackageData() {
68+
return mockReadPackageData;
69+
},
70+
}));
71+
6372
const mockAugmentOptionsWithExcludes = vi.fn();
6473

6574
vi.mock("./augmentOptionsWithExcludes.js", () => ({
@@ -113,10 +122,11 @@ vi.mock("./createOptionDefaults/index.js", () => ({
113122
},
114123
}));
115124

116-
const mockReadPackageData = vi.fn();
117-
vi.mock("../packages.js", () => ({
118-
get readPackageData() {
119-
return mockReadPackageData;
125+
const mockLogInferredOptions = vi.fn();
126+
127+
vi.mock("./logInferredOptions.js", () => ({
128+
get logInferredOptions() {
129+
return mockLogInferredOptions;
120130
},
121131
}));
122132

@@ -595,4 +605,170 @@ describe("readOptions", () => {
595605
},
596606
});
597607
});
608+
609+
it("uses values when provided on the CLI", async () => {
610+
mockReadPackageData.mockImplementationOnce(() => ({}));
611+
mockGetPrefillOrPromptedOption.mockImplementation(
612+
async ({ getDefaultValue }: GetPrefillOrPromptedOptionOptions) => ({
613+
value: (await getDefaultValue?.()) ?? "mock",
614+
}),
615+
);
616+
617+
const description = "Test description.";
618+
const owner = "TestOwner";
619+
const repository = "test-repository";
620+
const title = "Test Title";
621+
622+
expect(
623+
await readOptions(
624+
[
625+
"--offline",
626+
"--description",
627+
description,
628+
"--owner",
629+
owner,
630+
"--repository",
631+
repository,
632+
"--title",
633+
title,
634+
],
635+
"migrate",
636+
),
637+
).toStrictEqual({
638+
cancelled: false,
639+
github: mockOptions.github,
640+
options: {
641+
...emptyOptions,
642+
...mockOptions,
643+
access: "public",
644+
base: "minimum",
645+
description,
646+
directory: repository,
647+
email: {
648+
github: "mock",
649+
npm: "mock",
650+
},
651+
guide: undefined,
652+
logo: undefined,
653+
mode: "migrate",
654+
offline: true,
655+
owner,
656+
skipAllContributorsApi: true,
657+
skipGitHubApi: true,
658+
title,
659+
},
660+
});
661+
662+
expect(mockLogInferredOptions).not.toHaveBeenCalled();
663+
});
664+
665+
it("uses and logs values when provided on the CLI with auto", async () => {
666+
mockReadPackageData.mockImplementationOnce(() => ({}));
667+
mockGetPrefillOrPromptedOption.mockImplementation(
668+
async ({ getDefaultValue }: GetPrefillOrPromptedOptionOptions) => ({
669+
value: (await getDefaultValue?.()) ?? "mock",
670+
}),
671+
);
672+
673+
const description = "Test description.";
674+
const owner = "TestOwner";
675+
const repository = "test-repository";
676+
const title = "Test Title";
677+
678+
expect(
679+
await readOptions(
680+
[
681+
"--auto",
682+
"--offline",
683+
"--description",
684+
description,
685+
"--owner",
686+
owner,
687+
"--repository",
688+
repository,
689+
"--title",
690+
title,
691+
],
692+
"migrate",
693+
),
694+
).toStrictEqual({
695+
cancelled: false,
696+
github: mockOptions.github,
697+
options: {
698+
...emptyOptions,
699+
...mockOptions,
700+
access: "public",
701+
auto: true,
702+
base: "minimum",
703+
description,
704+
directory: repository,
705+
email: {
706+
github: "mock",
707+
npm: "mock",
708+
},
709+
guide: undefined,
710+
logo: undefined,
711+
mode: "migrate",
712+
offline: true,
713+
owner,
714+
skipAllContributorsApi: true,
715+
skipGitHubApi: true,
716+
title,
717+
},
718+
});
719+
720+
expect(mockLogInferredOptions.mock.calls).toMatchInlineSnapshot(`
721+
[
722+
[
723+
{
724+
"access": "public",
725+
"author": undefined,
726+
"auto": true,
727+
"base": "minimum",
728+
"bin": undefined,
729+
"description": "Test description.",
730+
"directory": "test-repository",
731+
"email": {
732+
"github": "mock",
733+
"npm": "mock",
734+
},
735+
"excludeAllContributors": undefined,
736+
"excludeCompliance": undefined,
737+
"excludeLintDeprecation": undefined,
738+
"excludeLintESLint": undefined,
739+
"excludeLintJSDoc": undefined,
740+
"excludeLintJson": undefined,
741+
"excludeLintKnip": undefined,
742+
"excludeLintMd": undefined,
743+
"excludeLintPackageJson": undefined,
744+
"excludeLintPackages": undefined,
745+
"excludeLintPerfectionist": undefined,
746+
"excludeLintRegex": undefined,
747+
"excludeLintSpelling": undefined,
748+
"excludeLintStrict": undefined,
749+
"excludeLintYml": undefined,
750+
"excludeReleases": undefined,
751+
"excludeRenovate": undefined,
752+
"excludeTests": undefined,
753+
"funding": undefined,
754+
"github": "mock.git",
755+
"guide": undefined,
756+
"logo": undefined,
757+
"mode": "migrate",
758+
"offline": true,
759+
"owner": "TestOwner",
760+
"preserveGeneratedFrom": false,
761+
"repository": "mock.repository",
762+
"skipAllContributorsApi": true,
763+
"skipGitHubApi": true,
764+
"skipInstall": undefined,
765+
"skipRemoval": undefined,
766+
"skipRestore": undefined,
767+
"skipUninstall": undefined,
768+
"title": "Test Title",
769+
},
770+
],
771+
]
772+
`);
773+
});
598774
});

0 commit comments

Comments
 (0)