Skip to content

Commit b56f0e2

Browse files
test: add unit tests to hydrate/values (#573)
<!-- 👋 Hi, thanks for sending a PR to template-typescript-node-package! 💖. Please fill out all fields below and make sure each item is true and [x] checked. Otherwise we may not be able to review your PR. --> ## PR Checklist - [x] Addresses an existing open issue: fixes #447 - [x] That issue was marked as [`status: accepting prs`](https://github.com/JoshuaKGoldberg/template-typescript-node-package/issues?q=is%3Aopen+is%3Aissue+label%3A%22status%3A+accepting+prs%22) - [x] Steps in [CONTRIBUTING.md](https://github.com/JoshuaKGoldberg/template-typescript-node-package/blob/main/.github/CONTRIBUTING.md) were taken ## Overview An ongoing PR for adding unit tests to hydrate components. currently added: - `src/hydrate/values/readAuthorIfExists` - `src/hydrate/values/readOwnerFromGitRemote` - `src/hydrate/values/readFundingIfExists` --------- Co-authored-by: Josh Goldberg <[email protected]>
1 parent b0c8b46 commit b56f0e2

File tree

6 files changed

+122
-15
lines changed

6 files changed

+122
-15
lines changed

src/hydrate/values/getHydrationDefaults.ts

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
import { $ } from "execa";
2-
31
import type { PartialPackageData } from "./types.js";
42

5-
import { getNpmAuthor } from "../../shared/getNpmAuthor.js";
63
import { readFileSafe } from "../readFileSafe.js";
4+
import { readAuthorIfExists } from "./readAuthorIfExists.js";
75
import { readEmailIfExists } from "./readEmailIfExists.js";
86
import { readFundingIfExists } from "./readFundingIfExists.js";
7+
import { readOwnerFromGitRemote } from "./readOwnerFromGitRemote.js";
98

109
export async function getHydrationDefaults() {
1110
const existingReadme = await readFileSafe("./README.md", "");
@@ -14,20 +13,10 @@ export async function getHydrationDefaults() {
1413
) as PartialPackageData;
1514

1615
return {
17-
author: async () => {
18-
const fromPackage =
19-
typeof existingPackage.author === "string"
20-
? existingPackage.author.split("<")[0].trim()
21-
: existingPackage.author?.name;
22-
23-
return fromPackage ?? (await getNpmAuthor());
24-
},
16+
author: () => readAuthorIfExists(existingPackage),
2517
email: () => readEmailIfExists(existingPackage),
2618
funding: readFundingIfExists,
27-
owner: async () =>
28-
(await $`git remote -v`).stdout.match(
29-
/origin\s+https:\/\/\S+\.\w+\/([^/]+)/
30-
)?.[1],
19+
owner: readOwnerFromGitRemote,
3120
releases: true,
3221
title: existingReadme.match(/^(?:# |<h1\s+align="center">)(\S+)/)?.[1],
3322
unitTests: true,
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { describe, expect, it, vi } from "vitest";
2+
3+
import { readAuthorIfExists } from "./readAuthorIfExists.js";
4+
5+
const mockGetNpmAuthor = vi.fn();
6+
7+
vi.mock("../../shared/getNpmAuthor.js", () => ({
8+
get getNpmAuthor() {
9+
return mockGetNpmAuthor;
10+
},
11+
}));
12+
13+
const npmAuthorMockResult = "Someone from NPM <[email protected]>";
14+
15+
describe("readAuthorIfExists", () => {
16+
it('reads author as a string from the existing package "author" field when it exists', async () => {
17+
mockGetNpmAuthor.mockResolvedValue(npmAuthorMockResult);
18+
const author = await readAuthorIfExists({
19+
author: "John Doe <[email protected]>",
20+
});
21+
expect(author).not.toBe(npmAuthorMockResult);
22+
expect(author).not.toContain(" <[email protected]>");
23+
expect(author).toBe("John Doe");
24+
});
25+
26+
it('reads author as an object from the existing package "author" field when it exists', async () => {
27+
mockGetNpmAuthor.mockResolvedValue(npmAuthorMockResult);
28+
const author = await readAuthorIfExists({
29+
author: { email: "[email protected]", name: "John Doe" },
30+
});
31+
expect(author).not.toBe(npmAuthorMockResult);
32+
expect(author).toBe("John Doe");
33+
});
34+
35+
it("reads author from getNpmAuthor when author is missing from package", async () => {
36+
mockGetNpmAuthor.mockResolvedValue(npmAuthorMockResult);
37+
const author = await readAuthorIfExists({});
38+
expect(author).toBe(npmAuthorMockResult);
39+
});
40+
});
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import type { PartialPackageData } from "./types";
2+
3+
import { getNpmAuthor } from "../../shared/getNpmAuthor.js";
4+
5+
export async function readAuthorIfExists(
6+
existingPackage: PartialPackageData
7+
): Promise<string | undefined> {
8+
const fromPackage =
9+
typeof existingPackage.author === "string"
10+
? existingPackage.author.split("<")[0].trim()
11+
: existingPackage.author?.name;
12+
13+
return fromPackage ?? (await getNpmAuthor());
14+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { describe, expect, it, vi } from "vitest";
2+
3+
import { readFundingIfExists } from "./readFundingIfExists.js";
4+
5+
const mockReadFile = vi.fn();
6+
7+
vi.mock("node:fs/promises", () => ({
8+
get default() {
9+
return {
10+
get readFile() {
11+
return mockReadFile;
12+
},
13+
};
14+
},
15+
}));
16+
17+
describe("readFundingIfExists", () => {
18+
it("reads funding from .github/FUNDING.yml when it exists", async () => {
19+
mockReadFile.mockResolvedValue("github: Contributor");
20+
const result = await readFundingIfExists();
21+
expect(result).toBe("Contributor");
22+
});
23+
24+
it("returns undefined when funding does not exists", async () => {
25+
mockReadFile.mockRejectedValue("Oops");
26+
const result = await readFundingIfExists();
27+
expect(result).toBe(undefined);
28+
});
29+
});
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { describe, expect, it, vi } from "vitest";
2+
3+
import { readOwnerFromGitRemote } from "./readOwnerFromGitRemote.js";
4+
5+
const mock$ = vi.fn();
6+
7+
vi.mock("execa", () => ({
8+
get $() {
9+
return mock$;
10+
},
11+
}));
12+
13+
describe("readOwnerFromGitRemote", () => {
14+
it("reads owner from the git remote when it exists", async () => {
15+
mock$.mockResolvedValue({
16+
stdout:
17+
"origin https://github.com/Contributor/template-typescript-node-package.git (fetch)",
18+
});
19+
const result = await readOwnerFromGitRemote();
20+
21+
expect(result).toBe("Contributor");
22+
});
23+
24+
it("reads undefined when no remote available", async () => {
25+
mock$.mockResolvedValue({ stdout: "" });
26+
const result = await readOwnerFromGitRemote();
27+
expect(result).toBe(undefined);
28+
});
29+
});
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { $ } from "execa";
2+
3+
export async function readOwnerFromGitRemote(): Promise<string | undefined> {
4+
const { stdout } = await $`git remote -v`;
5+
return stdout.match(/origin\s+https:\/\/\S+\.\w+\/([^/]+)/)?.[1];
6+
}

0 commit comments

Comments
 (0)