diff --git a/.vscode/launch.json b/.vscode/launch.json index dedf01609..1d2f28d89 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,6 +10,14 @@ "skipFiles": ["/**", "**/node_modules/**"], "smartStep": true, "type": "node" + }, + { + "name": "Debug Program", + "preLaunchTask": "build", + "program": "./bin/index.js", + "request": "launch", + "skipFiles": ["/**"], + "type": "node" } ], "version": "0.2.0" diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 000000000..ea91cf7ec --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,11 @@ +{ + "tasks": [ + { + "detail": "Build the project", + "label": "build", + "script": "build", + "type": "npm" + } + ], + "version": "2.0.0" +} diff --git a/src/steps/writing/creation/dotVSCode.test.ts b/src/steps/writing/creation/dotVSCode.test.ts new file mode 100644 index 000000000..0d71be5e9 --- /dev/null +++ b/src/steps/writing/creation/dotVSCode.test.ts @@ -0,0 +1,301 @@ +import { describe, expect, it } from "vitest"; + +import { Options } from "../../../shared/types.js"; +import { createDotVSCode } from "./dotVSCode.js"; + +/* spellchecker: disable */ +function fakeOptions( + getExcludeValue: (exclusionName: string) => boolean, + bin?: string | undefined, +) { + return { + access: "public", + author: "TestAuthor", + base: "everything", + ...(bin ? { bin } : {}), + description: "Test description.", + directory: ".", + email: { + github: "github@email.com", + npm: "npm@email.com", + }, + ...Object.fromEntries( + [ + "excludeCompliance", + "excludeAllContributors", + "excludeLintDeprecation", + "excludeLintESLint", + "excludeLintJSDoc", + "excludeLintJson", + "excludeLintKnip", + "excludeLintMd", + "excludeLintPackageJson", + "excludeLintPackages", + "excludeLintPerfectionist", + "excludeLintRegex", + "excludeLintSpelling", + "excludeLintStrict", + "excludeLintStylistic", + "excludeLintYml", + "excludeReleases", + "excludeRenovate", + "excludeTests", + ].map((key) => [key, getExcludeValue(key)]), + ), + mode: "create", + owner: "TestOwner", + repository: "test-repository", + skipGitHubApi: true, + skipInstall: true, + skipRemoval: true, + title: "Test Title", + } satisfies Options; +} + +describe("createDotVSCode", () => { + it("creates a minimal config when all exclusions are enabled", async () => { + expect(await createDotVSCode(fakeOptions(() => true))) + .toMatchInlineSnapshot(` + { + "extensions.json": "{ + "recommendations": [ + "DavidAnson.vscode-markdownlint", + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode" + ] + } + ", + "settings.json": "{ + "editor.codeActionsOnSave": { "source.fixAll.eslint": "explicit" }, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.rulers": [80], + "eslint.probe": [ + "javascript", + "javascriptreact", + "json", + "jsonc", + "markdown", + "typescript", + "typescriptreact", + "yaml" + ], + "eslint.rules.customizations": [{ "rule": "*", "severity": "warn" }], + "typescript.tsdk": "node_modules/typescript/lib" + } + ", + "tasks.json": "{ + "tasks": [ + { + "detail": "Build the project", + "label": "build", + "script": "build", + "type": "npm" + } + ], + "version": "2.0.0" + } + ", + } + `); + }); + + it("creates a full config when all exclusions are disabled and bin is provided", async () => { + expect(await createDotVSCode(fakeOptions(() => false, "bin/index.js"))) + .toMatchInlineSnapshot(` + { + "extensions.json": "{ + "recommendations": [ + "DavidAnson.vscode-markdownlint", + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "streetsidesoftware.code-spell-checker" + ] + } + ", + "launch.json": "{ + "configurations": [ + { + "args": ["run", "\${relativeFile}"], + "autoAttachChildProcesses": true, + "console": "integratedTerminal", + "name": "Debug Current Test File", + "program": "\${workspaceRoot}/node_modules/vitest/vitest.mjs", + "request": "launch", + "skipFiles": ["/**", "**/node_modules/**"], + "smartStep": true, + "type": "node" + }, + { + "name": "Debug Program", + "preLaunchTask": "build", + "program": "bin/index.js", + "request": "launch", + "skipFiles": ["/**"], + "type": "node" + } + ], + "version": "0.2.0" + } + ", + "settings.json": "{ + "editor.codeActionsOnSave": { "source.fixAll.eslint": "explicit" }, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.rulers": [80], + "eslint.probe": [ + "javascript", + "javascriptreact", + "json", + "jsonc", + "markdown", + "typescript", + "typescriptreact", + "yaml" + ], + "eslint.rules.customizations": [{ "rule": "*", "severity": "warn" }], + "typescript.tsdk": "node_modules/typescript/lib" + } + ", + "tasks.json": "{ + "tasks": [ + { + "detail": "Build the project", + "label": "build", + "script": "build", + "type": "npm" + } + ], + "version": "2.0.0" + } + ", + } + `); + }); + + it("creates a full config when all exclusions are disabled and bin is not provided", async () => { + expect(await createDotVSCode(fakeOptions(() => false))) + .toMatchInlineSnapshot(` + { + "extensions.json": "{ + "recommendations": [ + "DavidAnson.vscode-markdownlint", + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "streetsidesoftware.code-spell-checker" + ] + } + ", + "launch.json": "{ + "configurations": [ + { + "args": ["run", "\${relativeFile}"], + "autoAttachChildProcesses": true, + "console": "integratedTerminal", + "name": "Debug Current Test File", + "program": "\${workspaceRoot}/node_modules/vitest/vitest.mjs", + "request": "launch", + "skipFiles": ["/**", "**/node_modules/**"], + "smartStep": true, + "type": "node" + } + ], + "version": "0.2.0" + } + ", + "settings.json": "{ + "editor.codeActionsOnSave": { "source.fixAll.eslint": "explicit" }, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.rulers": [80], + "eslint.probe": [ + "javascript", + "javascriptreact", + "json", + "jsonc", + "markdown", + "typescript", + "typescriptreact", + "yaml" + ], + "eslint.rules.customizations": [{ "rule": "*", "severity": "warn" }], + "typescript.tsdk": "node_modules/typescript/lib" + } + ", + "tasks.json": "{ + "tasks": [ + { + "detail": "Build the project", + "label": "build", + "script": "build", + "type": "npm" + } + ], + "version": "2.0.0" + } + ", + } + `); + }); + + it("creates a minimal config including launch.json when all exclusions are enabled and bin is provided", async () => { + expect(await createDotVSCode(fakeOptions(() => true, "bin/index.js"))) + .toMatchInlineSnapshot(` + { + "extensions.json": "{ + "recommendations": [ + "DavidAnson.vscode-markdownlint", + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode" + ] + } + ", + "launch.json": "{ + "configurations": [ + { + "name": "Debug Program", + "preLaunchTask": "build", + "program": "bin/index.js", + "request": "launch", + "skipFiles": ["/**"], + "type": "node" + } + ], + "version": "0.2.0" + } + ", + "settings.json": "{ + "editor.codeActionsOnSave": { "source.fixAll.eslint": "explicit" }, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.rulers": [80], + "eslint.probe": [ + "javascript", + "javascriptreact", + "json", + "jsonc", + "markdown", + "typescript", + "typescriptreact", + "yaml" + ], + "eslint.rules.customizations": [{ "rule": "*", "severity": "warn" }], + "typescript.tsdk": "node_modules/typescript/lib" + } + ", + "tasks.json": "{ + "tasks": [ + { + "detail": "Build the project", + "label": "build", + "script": "build", + "type": "npm" + } + ], + "version": "2.0.0" + } + ", + } + `); + }); +}); diff --git a/src/steps/writing/creation/dotVSCode.ts b/src/steps/writing/creation/dotVSCode.ts index 6f0c46fd5..22e977457 100644 --- a/src/steps/writing/creation/dotVSCode.ts +++ b/src/steps/writing/creation/dotVSCode.ts @@ -12,24 +12,43 @@ export async function createDotVSCode(options: Options) { !options.excludeLintSpelling && "streetsidesoftware.code-spell-checker", ].filter(Boolean), }), - ...(!options.excludeTests && { - "launch.json": await formatJson({ - configurations: [ - { - args: ["run", "${relativeFile}"], - autoAttachChildProcesses: true, - console: "integratedTerminal", - name: "Debug Current Test File", - program: "${workspaceRoot}/node_modules/vitest/vitest.mjs", - request: "launch", - skipFiles: ["/**", "**/node_modules/**"], - smartStep: true, - type: "node", - }, - ], - version: "0.2.0", - }), - }), + ...(options.excludeTests && !options.bin + ? {} + : { + "launch.json": await formatJson({ + configurations: [ + ...(options.excludeTests + ? [] + : [ + { + args: ["run", "${relativeFile}"], + autoAttachChildProcesses: true, + console: "integratedTerminal", + name: "Debug Current Test File", + program: + "${workspaceRoot}/node_modules/vitest/vitest.mjs", + request: "launch", + skipFiles: ["/**", "**/node_modules/**"], + smartStep: true, + type: "node", + }, + ]), + ...(options.bin + ? [ + { + name: "Debug Program", + preLaunchTask: "build", + program: options.bin, + request: "launch", + skipFiles: ["/**"], + type: "node", + }, + ] + : []), + ], + version: "0.2.0", + }), + }), "settings.json": await formatJson({ "editor.codeActionsOnSave": { "source.fixAll.eslint": "explicit", @@ -50,5 +69,16 @@ export async function createDotVSCode(options: Options) { "eslint.rules.customizations": [{ rule: "*", severity: "warn" }], "typescript.tsdk": "node_modules/typescript/lib", }), + "tasks.json": await formatJson({ + tasks: [ + { + detail: "Build the project", + label: "build", + script: "build", + type: "npm", + }, + ], + version: "2.0.0", + }), }; }