Skip to content

Commit

Permalink
fix: correct remaining --auto mismatches (#1612)
Browse files Browse the repository at this point in the history
## PR Checklist

- [x] Addresses an existing open issue: fixes #934; fixes #1157; fixes
#1613
- [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

Fills in a lot of logic around defaults that was previously not hooked
up. `--auto` now completely works as expected in this repository.

💖
  • Loading branch information
JoshuaKGoldberg authored Aug 11, 2024
1 parent ebc96fa commit 551737a
Show file tree
Hide file tree
Showing 12 changed files with 288 additions and 102 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
},
"license": "MIT",
"author": {
"name": "Josh Goldberg",
"name": "Josh Goldberg",
"email": "npm@joshuakgoldberg.com"
},
"type": "module",
Expand Down
19 changes: 1 addition & 18 deletions script/migrate-test-e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import * as fs from "node:fs/promises";
import { rimraf } from "rimraf";
import { assert, describe, expect, test } from "vitest";

import packageData from "../package.json" assert { type: "json" };

const filesExpectedToBeChanged = [
"README.md",
"knip.json",
Expand All @@ -21,21 +19,6 @@ const filesThatMightBeChanged = new Set([
"script/__snapshots__/migrate-test-e2e.ts.snap",
]);

const {
author: { email: emailNpm, name: authorName },
description,
name: repository,
} = packageData;
const emailGithub = "github@joshuakgoldberg.com";
const bin = "./bin/index.js";
const guide =
"https://www.joshuakgoldberg.com/blog/contributing-to-a-create-typescript-app-repository";
const guideTitle = "Contributing to a create-typescript-app Repository";
const logo = "./docs/create-typescript-app.png";
const logoAlt = `Project logo: the TypeScript blue square with rounded corners, but a plus sign instead of 'TS'`;
const owner = "JoshuaKGoldberg";
const title = "Create TypeScript App";

await rimraf("coverage*");

const originalReadme = (await fs.readFile("README.md")).toString();
Expand All @@ -46,7 +29,7 @@ const originalSnapshots = (

await $({
stdio: "inherit",
})`c8 -o ./coverage -r html -r lcov --src src node ${bin} --base everything --author ${authorName} --mode migrate --bin ${bin} --description ${description} --email-github ${emailGithub} --email-npm ${emailNpm} --guide ${guide} --guide-title ${guideTitle} --logo ${logo} --logo-alt ${logoAlt} --owner ${owner} --title ${title} --repository ${repository} --skip-all-contributors-api --skip-github-api --skip-install`;
})`c8 -o ./coverage -r html -r lcov --src src node ./bin/index.js --auto --mode migrate --skip-all-contributors-api --skip-github-api --skip-install`;

// All Contributors seems to not be using Prettier to format files...
await fs.writeFile(
Expand Down
79 changes: 63 additions & 16 deletions src/shared/options/createOptionDefaults/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { describe, expect, it, vi } from "vitest";
import { beforeEach, describe, expect, it, vi } from "vitest";

import { createOptionDefaults } from "./index.js";

Expand Down Expand Up @@ -34,6 +34,14 @@ vi.mock("../../packages.js", () => ({
},
}));

const mockReadGitHubEmail = vi.fn();

vi.mock("./readGitHubEmail.js", () => ({
get readGitHubEmail() {
return mockReadGitHubEmail;
},
}));

describe("createOptionDefaults", () => {
describe("bin", () => {
it("returns undefined when package data does not have a bin", async () => {
Expand All @@ -56,24 +64,29 @@ describe("createOptionDefaults", () => {
});

describe("email", () => {
beforeEach(() => {
mockNpmUser.mockImplementation((username: string) => ({
email: `npm-${username}@test.com`,
}));
});

it("returns the npm whoami email from npm when only an npm exists", async () => {
mock$.mockImplementation(([command]: string[]) =>
command === "npm whoami" ? { stdout: "npm-username" } : undefined,
command === "npm whoami" ? { stdout: "username" } : undefined,
);
mockNpmUser.mockImplementation((username: string) => ({
email: `test@${username}.com`,
}));
mockReadGitHubEmail.mockResolvedValueOnce(undefined);

const actual = await createOptionDefaults().email();

expect(actual).toEqual({
github: "test@npm-username.com",
npm: "test@npm-username.com",
github: "npm-username@test.com",
npm: "npm-username@test.com",
});
});

it("returns the npm whoami email from npm when only a package author email exists", async () => {
mock$.mockResolvedValue({ stdout: "" });
mockReadGitHubEmail.mockResolvedValueOnce(undefined);
mockReadPackageData.mockResolvedValue({
author: {
email: "test@package.com",
Expand All @@ -88,41 +101,75 @@ describe("createOptionDefaults", () => {
});
});

it("returns the github email when only a github email exists", async () => {
mock$.mockResolvedValue({ stdout: "" });
mockReadPackageData.mockResolvedValueOnce({});
mockReadGitHubEmail.mockResolvedValueOnce("github@test.com");

const actual = await createOptionDefaults().email();

expect(actual).toEqual({
github: "github@test.com",
npm: "github@test.com",
});
});

it("returns the git user email when only a git user email exists", async () => {
mock$.mockImplementation(([command]: string[]) =>
command === "git config --get user.email"
? { stdout: "test@git.com" }
? { stdout: "git@test.com" }
: undefined,
);
mockReadGitHubEmail.mockResolvedValueOnce(undefined);
mockReadPackageData.mockResolvedValue({});

const actual = await createOptionDefaults().email();

expect(actual).toEqual({
github: "git@test.com",
npm: "git@test.com",
});
});

it("returns both the git user email and the npm user email when only those two exist", async () => {
mock$.mockImplementation(([command]: string[]) => ({
stdout:
command === "git config --get user.email"
? "git@test.com"
: "username",
}));
mockReadGitHubEmail.mockResolvedValueOnce(undefined);
mockReadPackageData.mockResolvedValue({});

const actual = await createOptionDefaults().email();

expect(actual).toEqual({
github: "test@git.com",
npm: "test@git.com",
github: "git@test.com",
npm: "npm-username@test.com",
});
});

it("returns both the git user email and the npm user email when both exist", async () => {
it("returns all three emails when they all exist", async () => {
mock$.mockImplementation(([command]: string[]) => ({
stdout:
command === "git config --get user.email"
? "test@git.com"
: "npm-username",
? "git@test.com"
: "username",
}));
mockReadGitHubEmail.mockResolvedValueOnce("github@test.com");
mockReadPackageData.mockResolvedValue({});

const actual = await createOptionDefaults().email();

expect(actual).toEqual({
github: "test@git.com",
npm: "test@npm-username.com",
github: "github@test.com",
npm: "npm-username@test.com",
});
});

it("returns undefined when neither git nor npm emails exist", async () => {
it("returns undefined when none of the emails exist", async () => {
mock$.mockResolvedValue({ stdout: "" });
mockReadGitHubEmail.mockResolvedValueOnce(undefined);
mockReadPackageData.mockResolvedValue({});

const actual = await createOptionDefaults().email();
Expand Down
19 changes: 13 additions & 6 deletions src/shared/options/createOptionDefaults/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { PromptedOptions } from "../../types.js";
import { parsePackageAuthor } from "./parsePackageAuthor.js";
import { readDefaultsFromDevelopment } from "./readDefaultsFromDevelopment.js";
import { readDefaultsFromReadme } from "./readDefaultsFromReadme.js";
import { readGitHubEmail } from "./readGitHubEmail.js";

export function createOptionDefaults(promptedOptions?: PromptedOptions) {
const gitDefaults = tryCatchLazyValueAsync(async () =>
Expand All @@ -29,19 +30,25 @@ export function createOptionDefaults(promptedOptions?: PromptedOptions) {
);

return {
author: async () => (await packageAuthor()).author ?? npmDefaults.name,
author: async () =>
(await packageAuthor()).author ?? (await npmDefaults())?.name,
bin: async () => (await packageData()).bin,
description: async () => (await packageData()).description,
email: async () => {
const gitEmail = await tryCatchAsync(
async () => (await $`git config --get user.email`).stdout,
);
const githubEmail =
(await readGitHubEmail()) ??
(await tryCatchAsync(
async () => (await $`git config --get user.email`).stdout,
));
const npmEmail =
(await npmDefaults())?.email ?? (await packageAuthor()).email;

/* eslint-disable @typescript-eslint/no-non-null-assertion */
return gitEmail || npmEmail
? { github: (gitEmail || npmEmail)!, npm: (npmEmail || gitEmail)! }
return githubEmail || npmEmail
? {
github: (githubEmail || npmEmail)!,
npm: (npmEmail || githubEmail)!,
}
: undefined;
/* eslint-enable @typescript-eslint/no-non-null-assertion */
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ describe("readDefaultsFromDevelopment", () => {
expect(guide).toBeUndefined();
});

it("reads guide when it exists", async () => {
it("reads the href and title when the tag exists", async () => {
mockReadFileSafe.mockResolvedValue(`# Development
> If you'd like a more guided walkthrough, see [Contributing to a create-typescript-app Repository](https://www.joshuakgoldberg.com/blog/contributing-to-a-create-typescript-app-repository).
Expand All @@ -29,33 +29,10 @@ describe("readDefaultsFromDevelopment", () => {

const guide = await readDefaultsFromDevelopment().guide();

expect(guide).toBe(
"https://www.joshuakgoldberg.com/blog/contributing-to-a-create-typescript-app-repository",
);
});
});

describe("guideTitle", () => {
it("defaults to undefined when .github/DEVELOPMENT.md cannot be found", async () => {
mockReadFileSafe.mockResolvedValue("");

const guideTitle = await readDefaultsFromDevelopment().guideTitle();

expect(guideTitle).toBeUndefined();
});

it("reads guideTitle when it exists", async () => {
mockReadFileSafe.mockResolvedValue(`# Development
> If you'd like a more guided walkthrough, see [Contributing to a create-typescript-app Repository](https://www.joshuakgoldberg.com/blog/contributing-to-a-create-typescript-app-repository).
> It'll walk you through the common activities you'll need to contribute.
`);

const guideTitle = await readDefaultsFromDevelopment().guideTitle();

expect(guideTitle).toBe(
"Contributing to a create-typescript-app Repository",
);
expect(guide).toEqual({
href: "https://www.joshuakgoldberg.com/blog/contributing-to-a-create-typescript-app-repository",
title: "Contributing to a create-typescript-app Repository",
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,20 @@ import lazyValue from "lazy-value";
import { readFileSafe } from "../../readFileSafe.js";

export function readDefaultsFromDevelopment() {
const development = lazyValue(
async () => await readFileSafe(".github/DEVELOPMENT.md", ""),
);
return {
guide: lazyValue(async () => {
const tag = /> .*guided walkthrough, see \[((?!\[).+)\]\((.+)\)/i.exec(
await readFileSafe(".github/DEVELOPMENT.md", ""),
);

const guideTag = lazyValue(async () =>
/> .*guided walkthrough, see \[((?!\[).+)\]\((.+)\)/i.exec(
await development(),
),
);
if (!tag) {
return undefined;
}

return {
guide: async () => (await guideTag())?.[2],
guideTitle: async () => (await guideTag())?.[1],
return {
href: tag[2],
title: tag[1],
};
}),
};
}
Loading

0 comments on commit 551737a

Please sign in to comment.