Skip to content

Commit 9b081b3

Browse files
committed
Set up Jest and add a few tests
1 parent 52bdc8f commit 9b081b3

File tree

11 files changed

+2317
-60
lines changed

11 files changed

+2317
-60
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/** @type {import('ts-jest').JestConfigWithTsJest} */
2+
// eslint-disable-next-line no-undef
3+
module.exports = {
4+
preset: "ts-jest",
5+
testEnvironment: "node",
6+
testPathIgnorePatterns: ["/node_modules/", "/lib/", "/src/tests/"],
7+
}

packages/create-next-stack/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
"clean": "rimraf lib && pnpm run clean-tests-dir",
5353
"clean-tests-dir": "ts-node src/tests/e2e/clean-tests-dir.ts",
5454
"test": "pnpm build && ts-node src/tests/e2e/test.ts",
55+
"jest": "jest",
5556
"test:manual": "pnpm build && ts-node src/tests/e2e/test-manual.ts --debug",
5657
"test:small": "pnpm build && ts-node src/tests/e2e/test-manual.ts --debug --package-manager=pnpm --styling=css-modules",
5758
"test:large": "pnpm build && ts-node src/tests/e2e/test-manual.ts --debug --package-manager=pnpm --styling=emotion --react-hook-form --formik --prettier --formatting-pre-commit-hook --chakra --framer-motion --github-actions",
@@ -74,6 +75,7 @@
7475
"validate-npm-package-name": "^5.0.0"
7576
},
7677
"devDependencies": {
78+
"@jest/globals": "^29.5.0",
7779
"@types/inquirer": "^9.0.3",
7880
"@types/node": "^18.15.13",
7981
"@types/uuid": "^9.0.1",
@@ -82,7 +84,9 @@
8284
"@typescript-eslint/parser": "^5.59.0",
8385
"eslint": "^8.39.0",
8486
"eslint-config-prettier": "^8.8.0",
87+
"jest": "^29.5.0",
8588
"next": "^13.3.1",
89+
"ts-jest": "^29.1.0",
8690
"ts-node": "^10.9.1",
8791
"uuid": "^9.0.0"
8892
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { logDebug } from "../logging"
2+
3+
/**
4+
* Compares two string values by their order in an array.
5+
* @param a a string value
6+
* @param b a string value
7+
* @param order an array of string values specifying the order
8+
* @returns a negative number if `a` comes before `b` in `order`, a positive number if `b` comes before `a` in `order`, or `0` if `a` and `b` are equal in `order` or if either `a` or `b` are not in `order`
9+
*/
10+
export const compareByOrder = (a: string, b: string, order: string[]) => {
11+
const aIndex = order.indexOf(a)
12+
const bIndex = order.indexOf(b)
13+
if (aIndex === -1 || bIndex === -1) {
14+
logDebug(
15+
`WARNING: One or both of the values being compared are not in the order array. This should be caught by a test.`
16+
)
17+
return 0
18+
}
19+
return aIndex - bIndex
20+
}
Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
import { ValidCNSInputs } from "../../../create-next-stack-types"
2-
import { filterPlugins } from "../../../setup/setup"
2+
import { getSortedFilteredScripts } from "../scripts/sort-order"
33

44
export const generateScriptTableRows = async (
55
inputs: ValidCNSInputs
66
): Promise<string> => {
7-
const pluginScripts = filterPlugins(inputs).flatMap(
8-
(plugin) => plugin.scripts ?? []
9-
)
10-
11-
const scriptRowsString = pluginScripts
7+
const scripts = getSortedFilteredScripts(inputs)
8+
const scriptRowsString = scripts
129
.map((script) => `|\`${script.name}\`|${script.description}|`)
1310
.join("\n")
14-
1511
return scriptRowsString
1612
}

packages/create-next-stack/src/main/plugins/create-next-stack/create-next-stack.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { generateIndexPage } from "./add-content/pages/generate-index"
2222
import { generateLandingPageTemplate } from "./add-content/templates/LandingPage/generate-LandingPageTemplate"
2323
import { generateTechnologies } from "./add-content/templates/LandingPage/generate-technologies"
2424
import { generateReadme } from "./add-readme/generate-readme"
25+
import { getSortedFilteredScripts } from "./scripts/sort-order"
2526

2627
const gitAttributesFilename = ".gitattributes"
2728

@@ -36,11 +37,7 @@ export const createNextStackPlugin = createPlugin({
3637
id: "addScripts",
3738
description: "adding scripts to package.json",
3839
run: async (inputs) => {
39-
const scripts = filterPlugins(inputs).flatMap(
40-
(plugin) => plugin.scripts ?? []
41-
)
42-
43-
// TODO: Add a scripts sort order here. Use TypeScript to force setting all plugin scripts.
40+
const scripts = getSortedFilteredScripts(inputs)
4441

4542
await modifyJsonFile("package.json", (packageJson) => ({
4643
...packageJson,
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { test } from "@jest/globals"
2+
import { plugins } from "../../../setup/setup"
3+
import { scriptsSortOrder } from "./sort-order"
4+
5+
test("`scriptsSortOrder` contains no duplicates", () => {
6+
const seenScripts = new Set<string>()
7+
for (const script of scriptsSortOrder) {
8+
if (seenScripts.has(script)) {
9+
throw new Error(
10+
`Duplicate script with name "${script}" found in sort-order.ts`
11+
)
12+
}
13+
seenScripts.add(script)
14+
}
15+
})
16+
17+
test("`scriptsSortOrder` includes all plugins' scripts", () => {
18+
const requiredScripts = plugins.flatMap((plugin) =>
19+
plugin.scripts //
20+
? Object.values(plugin.scripts).map((script) => script.name)
21+
: []
22+
)
23+
const actualScriptIDs = new Set(scriptsSortOrder)
24+
for (const requiredScript of requiredScripts) {
25+
if (!actualScriptIDs.has(requiredScript)) {
26+
throw new Error(
27+
`Missing script with name "${requiredScript}" in sort-order.ts`
28+
)
29+
}
30+
}
31+
})
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { ValidCNSInputs } from "../../../create-next-stack-types"
2+
import { compareByOrder } from "../../../helpers/sort-by-order"
3+
import { filterPlugins } from "../../../setup/setup"
4+
5+
export const scriptsSortOrder: string[] = [
6+
"prepare",
7+
"test",
8+
"dev",
9+
"build",
10+
"start",
11+
"lint",
12+
"format",
13+
"format:check",
14+
]
15+
16+
export const getSortedFilteredScripts = (inputs: ValidCNSInputs) => {
17+
const pluginScripts = filterPlugins(inputs).flatMap(
18+
(plugin) => plugin.scripts ?? []
19+
)
20+
return pluginScripts.sort((a, b) =>
21+
compareByOrder(a.name, b.name, scriptsSortOrder)
22+
)
23+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { test } from "@jest/globals"
2+
import { plugins } from "./setup"
3+
4+
test("`plugins` contains no duplicates", () => {
5+
const seenPluginIDs = new Set<string>()
6+
for (const plugin of plugins) {
7+
if (seenPluginIDs.has(plugin.id)) {
8+
throw new Error(
9+
`Duplicate plugin with ID "${plugin.id}" found in setup.ts`
10+
)
11+
}
12+
seenPluginIDs.add(plugin.id)
13+
}
14+
})

packages/create-next-stack/src/main/setup/setup.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ import { yarnPlugin } from "../plugins/yarn"
3131
import { steps } from "../steps"
3232
import { printFinalMessages } from "./print-final-messages"
3333

34-
// Ordered by relevance to the user for use in technology lists // TODO: Fix this by having separate ordered lists of plugins where other sortings are needed.
34+
// Ordered by relevance to the user for use in technology lists
35+
// TODO: Fix this by having separate ordered lists of plugins where other sortings are needed.
36+
3537
export const plugins: Plugin[] = [
3638
createNextStackPlugin,
3739
nextPlugin,

packages/create-next-stack/src/main/steps.ts

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,6 @@ import { sassPlugin } from "./plugins/sass/sass"
1313
import { tailwindCSSPlugin } from "./plugins/tailwind-css"
1414
import { yarnPlugin } from "./plugins/yarn"
1515

16-
console.log("createNextApp", typeof nextPlugin?.steps?.createNextApp)
17-
console.log(
18-
"removeOfficialCNAContent",
19-
typeof nextPlugin?.steps?.removeOfficialCNAContent
20-
)
21-
console.log(
22-
"installDependencies:",
23-
typeof createNextStackPlugin?.steps?.installDependencies
24-
)
25-
2616
export const steps: Step[] = [
2717
// Update package manager
2818
pnpmPlugin.steps.updatePnpm,

0 commit comments

Comments
 (0)