From 7390c1799ce7dc18c9b1e9bbc3381b8efca21955 Mon Sep 17 00:00:00 2001 From: Mohammad Bagher Abiyat Date: Sat, 30 Dec 2023 12:43:43 +0330 Subject: [PATCH] chore: verify changes on allowedFiles according to the template (#1048) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit script/migrate-test-e2e.js ## PR Checklist - [x] Addresses an existing open issue: fixes #546 - [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 We track the changes using createRootFiles and we watch the changes files based on the function result. --------- Co-authored-by: Josh Goldberg โœจ --- cspell.json | 3 +- knip.jsonc | 1 + package.json | 2 +- script/__snapshots__/migrate-test-e2e.js.snap | 838 ++++++++++++++++++ script/migrate-test-e2e.js | 117 +-- script/vitest.config.ts | 3 + 6 files changed, 911 insertions(+), 53 deletions(-) create mode 100644 script/__snapshots__/migrate-test-e2e.js.snap create mode 100644 script/vitest.config.ts diff --git a/cspell.json b/cspell.json index 386ca4223..8210d612e 100644 --- a/cspell.json +++ b/cspell.json @@ -6,7 +6,8 @@ "CHANGELOG.md", "lib", "node_modules", - "pnpm-lock.yaml" + "pnpm-lock.yaml", + "./script/__snapshots__" ], "words": [ "allcontributors", diff --git a/knip.jsonc b/knip.jsonc index 83c853705..3b1a0801e 100644 --- a/knip.jsonc +++ b/knip.jsonc @@ -8,6 +8,7 @@ "script/*e2e.js" ], "ignoreBinaries": ["gh"], + "ignoreDependencies": ["script"], "ignoreExportsUsedInFile": { "interface": true, "type": true diff --git a/package.json b/package.json index f7b1cbf2a..edccdcd28 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "test": "vitest", "test:create": "node script/create-test-e2e.js", "test:initialize": "node script/initialize-test-e2e.js", - "test:migrate": "node script/migrate-test-e2e.js", + "test:migrate": "vitest run -r script/", "tsc": "tsc" }, "lint-staged": { diff --git a/script/__snapshots__/migrate-test-e2e.js.snap b/script/__snapshots__/migrate-test-e2e.js.snap new file mode 100644 index 000000000..48dda1835 --- /dev/null +++ b/script/__snapshots__/migrate-test-e2e.js.snap @@ -0,0 +1,838 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`verify .all-contributorsrc 1`] = ` +"--- a/.all-contributorsrc ++++ b/.all-contributorsrc +@@ -1,5 +1,5 @@ + { +- "badgeTemplate": "\\"All ๐Ÿค\\" src=\\"https://img.shields.io/badge/all_contributors-<%= contributors.length %>_๐Ÿค-21bb42.svg\\" />", ++ "badgeTemplate": "\\t\\"All ๐Ÿ‘ช\\" src=\\"https://img.shields.io/badge/all_contributors-<%= contributors.length %>_๐Ÿ‘ช-21bb42.svg\\" />", + "commit": false, + "commitConvention": "angular", + "contributors": [ +@@ -24,363 +24,274 @@ + "name": "Jeff Wen", + "avatar_url": "https://avatars.githubusercontent.com/u/3297859?v=4", + "profile": "https://sinchang.me", +- "contributions": [ +- "code" +- ] ++ "contributions": ["code"] + }, + { + "login": "Pinjasaur", + "name": "Paul Esch-Laurent", + "avatar_url": "https://avatars.githubusercontent.com/u/6335792?v=4", + "profile": "https://paulisaweso.me/", +- "contributions": [ +- "code" +- ] ++ "contributions": ["code"] + }, + { + "login": "NazCodeland", + "name": "NazCodeland", + "avatar_url": "https://avatars.githubusercontent.com/u/113494366?v=4", + "profile": "https://github.com/NazCodeland", +- "contributions": [ +- "code" +- ] ++ "contributions": ["code"] + }, + { + "login": "johnnyreilly", + "name": "John Reilly", + "avatar_url": "https://avatars.githubusercontent.com/u/1010525?v=4", + "profile": "https://blog.johnnyreilly.com/", +- "contributions": [ +- "code", +- "ideas" +- ] ++ "contributions": ["code", "ideas"] + }, + { + "login": "webpro", + "name": "Lars Kappert", + "avatar_url": "https://avatars.githubusercontent.com/u/456426?v=4", + "profile": "https://webpro.nl", +- "contributions": [ +- "code" +- ] ++ "contributions": ["code"] + }, + { + "login": "RebeccaStevens", + "name": "Rebecca Stevens", + "avatar_url": "https://avatars.githubusercontent.com/u/7224206?v=4", + "profile": "https://github.com/RebeccaStevens", +- "contributions": [ +- "code", +- "infra" +- ] ++ "contributions": ["code", "infra"] + }, + { + "login": "ronthetech", + "name": "Ron Jean-Francois", + "avatar_url": "https://avatars.githubusercontent.com/u/105710107?v=4", + "profile": "http://ronjeanfrancois.com", +- "contributions": [ +- "code", +- "infra" +- ] ++ "contributions": ["code", "infra"] + }, + { + "login": "nowyDEV", + "name": "Dominik Nowik", + "avatar_url": "https://avatars.githubusercontent.com/u/12304307?v=4", + "profile": "https://github.com/nowyDEV", +- "contributions": [ +- "tool", +- "code" +- ] ++ "contributions": ["tool", "code"] + }, + { + "login": "TAKANOME-DEV", + "name": "takanomedev", + "avatar_url": "https://avatars.githubusercontent.com/u/79809121?v=4", + "profile": "https://github.com/TAKANOME-DEV", +- "contributions": [ +- "code" +- ] ++ "contributions": ["code"] + }, + { + "login": "emday4prez", + "name": "Emerson", + "avatar_url": "https://avatars.githubusercontent.com/u/35363144?v=4", + "profile": "https://github.com/emday4prez", +- "contributions": [ +- "code" +- ] ++ "contributions": ["code"] + }, + { + "login": "jsjoeio", + "name": "Joe Previte", + "avatar_url": "https://avatars.githubusercontent.com/u/3806031?v=4", + "profile": "https://typescriptcourse.com/tutorials", +- "contributions": [ +- "bug", +- "code" +- ] ++ "contributions": ["bug", "code"] + }, + { + "login": "navin-moorthy", + "name": "Navin Moorthy", + "avatar_url": "https://avatars.githubusercontent.com/u/39694575?v=4", + "profile": "https://navinmoorthy.me/", +- "contributions": [ +- "bug", +- "code" +- ] ++ "contributions": ["bug", "code"] + }, + { + "login": "garuna-m6", + "name": "Anurag", + "avatar_url": "https://avatars.githubusercontent.com/u/23234342?v=4", + "profile": "https://github.com/garuna-m6", +- "contributions": [ +- "code" +- ] ++ "contributions": ["code"] + }, + { + "login": "danielroe", + "name": "Daniel Roe", + "avatar_url": "https://avatars.githubusercontent.com/u/28706372?v=4", + "profile": "https://roe.dev/", +- "contributions": [ +- "code" +- ] ++ "contributions": ["code"] + }, + { + "login": "the-lazy-learner", + "name": "Sudhansu", + "avatar_url": "https://avatars.githubusercontent.com/u/13695177?v=4", + "profile": "https://github.com/the-lazy-learner", +- "contributions": [ +- "code" +- ] ++ "contributions": ["code"] + }, + { + "login": "RNR1", + "name": "Ron Braha", + "avatar_url": "https://avatars.githubusercontent.com/u/45559220?v=4", + "profile": "https://linktr.ee/ronbraha", +- "contributions": [ +- "code", +- "design", +- "test" +- ] ++ "contributions": ["code", "design", "test"] + }, + { + "login": "tungbq", + "name": "Tung Bui (Leo)", + "avatar_url": "https://avatars.githubusercontent.com/u/85242618?v=4", + "profile": "https://github.com/tungbq", +- "contributions": [ +- "code" +- ] ++ "contributions": ["code"] + }, + { + "login": "orta", + "name": "Orta Therox", + "avatar_url": "https://avatars.githubusercontent.com/u/49038?v=4", + "profile": "https://orta.io", +- "contributions": [ +- "code" +- ] ++ "contributions": ["code"] + }, + { + "login": "promise-dash", + "name": "Promise Dash", + "avatar_url": "https://avatars.githubusercontent.com/u/86062880?v=4", + "profile": "https://github.com/promise-dash", +- "contributions": [ +- "code" +- ] ++ "contributions": ["code"] + }, + { + "login": "jolg42", + "name": "Joรซl Galeran", + "avatar_url": "https://avatars.githubusercontent.com/u/1328733?v=4", + "profile": "https://twitter.com/Jolg42", +- "contributions": [ +- "code" +- ] ++ "contributions": ["code"] + }, + { + "login": "kristo-baricevic", + "name": "Kristo Baricevic", + "avatar_url": "https://avatars.githubusercontent.com/u/108290619?v=4", + "profile": "https://kristo-baricevic.github.io/", +- "contributions": [ +- "code" +- ] ++ "contributions": ["code"] + }, + { + "login": "ryota-murakami", + "name": "Ryota Murakami", + "avatar_url": "https://avatars.githubusercontent.com/u/5501268?v=4", + "profile": "https://ryota-murakami.github.io/", +- "contributions": [ +- "code", +- "bug" +- ] ++ "contributions": ["code", "bug"] + }, + { + "login": "ruthwikreddy09", + "name": "Ruthwik", + "avatar_url": "https://avatars.githubusercontent.com/u/126862059?v=4", + "profile": "https://github.com/RuthwikReddy09", +- "contributions": [ +- "code" +- ] ++ "contributions": ["code"] + }, + { + "login": "jdwilkin4", + "name": "Jessica Wilkins ", + "avatar_url": "https://avatars.githubusercontent.com/u/67210629?v=4", + "profile": "https://jessicawilkins.dev/", +- "contributions": [ +- "code" +- ] ++ "contributions": ["code"] + }, + { + "login": "vasanth9", + "name": "Vasanth Kumar Cheepurupalli", + "avatar_url": "https://avatars.githubusercontent.com/u/42891954?v=4", + "profile": "https://github.com/vasanth9", +- "contributions": [ +- "code" +- ] ++ "contributions": ["code"] + }, + { + "login": "conrmahr", + "name": "Conor Meagher", + "avatar_url": "https://avatars.githubusercontent.com/u/363781?v=4", + "profile": "https://conormeagher.com/", +- "contributions": [ +- "code" +- ] ++ "contributions": ["code"] + }, + { + "login": "DanexQ", + "name": "Daniel", + "avatar_url": "https://avatars.githubusercontent.com/u/72567464?v=4", + "profile": "https://github.com/DanexQ", +- "contributions": [ +- "infra" +- ] ++ "contributions": ["infra"] + }, + { + "login": "jaas666", + "name": "Juan A.", + "avatar_url": "https://avatars.githubusercontent.com/u/30204147?v=4", + "profile": "https://github.com/jaas666", +- "contributions": [ +- "code", +- "doc" +- ] ++ "contributions": ["code", "doc"] + }, + { + "login": "katt", + "name": "Alex / KATT", + "avatar_url": "https://avatars.githubusercontent.com/u/459267?v=4", + "profile": "https://katt.dev", +- "contributions": [ +- "bug" +- ] ++ "contributions": ["bug"] + }, + { + "login": "dertimonius", + "name": "Timon Jurschitsch", + "avatar_url": "https://avatars.githubusercontent.com/u/103483059?v=4", + "profile": "https://www.linkedin.com/in/timonjurschitsch/", +- "contributions": [ +- "code" +- ] ++ "contributions": ["code"] + }, + { + "login": "biplobsd", + "name": "Biplob Sutradhar", + "avatar_url": "https://avatars.githubusercontent.com/u/43641536?v=4", + "profile": "http://biplobsd.me", +- "contributions": [ +- "code" +- ] ++ "contributions": ["code"] + }, + { + "login": "mrswastik-robot", + "name": "Swastik Patel", + "avatar_url": "https://avatars.githubusercontent.com/u/107865087?v=4", + "profile": "https://github.com/mrswastik-robot", +- "contributions": [ +- "doc" +- ] ++ "contributions": ["doc"] + }, + { + "login": "gv14982", + "name": "Graham Vasquez", + "avatar_url": "https://avatars.githubusercontent.com/u/7041175?v=4", + "profile": "https://gvasquez.dev", +- "contributions": [ +- "code" +- ] ++ "contributions": ["code"] + }, + { + "login": "dominicduffin1", + "name": "Dominic Duffin", + "avatar_url": "https://avatars.githubusercontent.com/u/26224873?v=4", + "profile": "https://dominicduffin.uk", +- "contributions": [ +- "code" +- ] ++ "contributions": ["code"] + }, + { + "login": "5hraddha", + "name": "Shraddha", + "avatar_url": "https://avatars.githubusercontent.com/u/27571141?v=4", + "profile": "https://www.shraddha.tech", +- "contributions": [ +- "code" +- ] ++ "contributions": ["code"] + }, + { + "login": "xl4624", + "name": "Xiaomin Liu", + "avatar_url": "https://avatars.githubusercontent.com/u/116298054?v=4", + "profile": "https://github.com/xl4624", +- "contributions": [ +- "code" +- ] ++ "contributions": ["code"] + }, + { + "login": "jamiemagee", + "name": "Jamie Magee", + "avatar_url": "https://avatars.githubusercontent.com/u/1358764?v=4", + "profile": "https://jamiemagee.co.uk", +- "contributions": [ +- "ideas" +- ] ++ "contributions": ["ideas"] + }, + { + "login": "praveenshinde3", + "name": "Praveen Shinde", + "avatar_url": "https://avatars.githubusercontent.com/u/107350270?v=4", + "profile": "https://praveenshinde.vercel.app/", +- "contributions": [ +- "code" +- ] ++ "contributions": ["code"] + } + ], + "contributorsPerLine": 7, + "contributorsSortAlphabetically": true, +- "files": [ +- "README.md" +- ], ++ "files": ["README.md"], + "imageSize": 100, + "projectName": "create-typescript-app", + "projectOwner": "JoshuaKGoldberg", + "repoHost": "https://github.com", +- "repoType": "github", +- "commitType": "docs" ++ "repoType": "github" + }" +`; + +exports[`verify .eslintignore 1`] = ` +"--- a/.eslintignore ++++ b/.eslintignore +@@ -1,5 +1,5 @@ + !.* +-coverage* ++coverage + lib + node_modules + pnpm-lock.yaml" +`; + +exports[`verify .eslintrc.cjs 1`] = ` +"--- a/.eslintrc.cjs ++++ b/.eslintrc.cjs +@@ -1,13 +1,3 @@ +-/* +-๐Ÿ‘‹ Hi! This ESLint configuration contains a lot more stuff than many repos'! +-You can read from it to see all sorts of linting goodness, but don't worry - +-it's not something you need to exhaustively understand immediately. ๐Ÿ’™ +- +-If you're interested in learning more, see the 'getting started' docs on: +-- ESLint: https://eslint.org +-- typescript-eslint: https://typescript-eslint.io +-*/ +- + /** @type {import("@types/eslint").Linter.Config} */ + module.exports = { + env: { +@@ -76,18 +66,6 @@ module.exports = { + rules: { + // These off-by-default rules work well for this repo and we like them on. + "deprecation/deprecation": "error", +- +- // These more-strict-by-default rules don't work well for this repo and we like them less strict. +- "@typescript-eslint/no-unnecessary-condition": [ +- "error", +- { +- allowConstantLoopConditions: true, +- }, +- ], +- "@typescript-eslint/prefer-nullish-coalescing": [ +- "error", +- { ignorePrimitives: true }, +- ], + }, + }, + {" +`; + +exports[`verify .github/DEVELOPMENT.md 1`] = ` +"--- a/.github/DEVELOPMENT.md ++++ b/.github/DEVELOPMENT.md +@@ -99,116 +99,3 @@ Add \`--watch\` to keep the type checker running in a watch mode that updates the + \`\`\`shell + pnpm tsc --watch + \`\`\` +- +-## Setup Scripts +- +-As described in the \`README.md\` file and \`docs/\`, this template repository comes with three scripts that can set up an existing or new repository. +- +-Each follows roughly the same general flow: +- +-1. \`bin/index.ts\` uses \`bin/mode.ts\` to determine which of the three setup scripts to run +-2. \`readOptions\` parses in options from local files, Git commands, npm APIs, and/or files on disk +-3. \`runOrRestore\` wraps the setup script's main logic in a friendly prompt wrapper +-4. The setup script wraps each portion of its main logic with \`withSpinner\` +- - Each step of setup logic is generally imported from within \`src/steps\` +-5. A call to \`outro\` summarizes the results for the user +- +-> **Warning** +-> Each setup script overrides many files in the directory they're run in. +-> Make sure to save any changes you want to preserve before running them. +- +-### The Creation Script +- +-This template's "creation" script is located in \`src/create/\`. +-You can run it locally with \`node bin/index.js --mode create\`. +-Note that files need to be built with \`pnpm run build\` beforehand. +- +-#### Testing the Creation Script +- +-You can run the end-to-end test for creation locally on the command-line. +-Note that the files need to be built with \`pnpm run build\` beforehand. +- +-\`\`\`shell +-pnpm run test:create +-\`\`\` +- +-That end-to-end test executes \`script/create-test-e2e.js\`, which: +- +-1. Runs the creation script to create a new \`test-repository\` child directory and repository, capturing code coverage +-2. Asserts that commands such as \`build\` and \`lint\` each pass +- +-The \`pnpm run test:create\` script is run in CI to ensure that templating changes are in sync with the template's actual files. +-See \`.github/workflows/test-create.yml\`. +- +-### The Initialization Script +- +-This template's "initialization" script is located in \`src/initialize/\`. +-You can run it locally with \`pnpm run initialize\`. +-It uses [\`tsx\`](https://github.com/esbuild-kit/tsx) so you don't need to build files before running. +- +-\`\`\`shell +-pnpm run initialize +-\`\`\` +- +-#### Testing the Initialization Script +- +-You can run the end-to-end test for initializing locally on the command-line. +-Note that files need to be built with \`pnpm run build\` beforehand. +- +-\`\`\`shell +-pnpm run test:initialize +-\`\`\` +- +-That end-to-end test executes \`script/initialize-test-e2e.js\`, which: +- +-1. Runs the initialization script using \`--skip-github-api\` and other skip flags +-2. Checks that the local repository's files were changed correctly (e.g. removed initialization-only files) +-3. Runs \`pnpm run lint:knip\` to make sure no excess dependencies or files were left over +-4. Resets everything +-5. Runs initialization a second time, capturing test coverage +- +-The \`pnpm run test:initialize\` script is run in CI to ensure that templating changes are in sync with the template's actual files. +-See \`.github/workflows/test-initialize.yml\`. +- +-### The Migration Script +- +-This template's "migration" script is located in \`src/migrate/\`. +-Note that files need to be built with \`pnpm run build\` beforehand. +- +-To test out the script locally, run it from a different repository's directory: +- +-\`\`\`shell +-cd ../other-repo +-node ../create-typescript-app/bin/migrate.js +-\`\`\` +- +-The migration script will work on any directory. +-You can try it out in a blank directory with scripts like: +- +-\`\`\`shell +-cd .. +-mkdir temp +-cd temp +-node ../create-typescript-app/bin/migrate.js +-\`\`\` +- +-#### Testing the Migration Script +- +-You can run the end-to-end test for migrating locally on the command-line: +- +-\`\`\`shell +-pnpm run test:migrate +-\`\`\` +- +-That end-to-end test executes \`script/migrate-test-e2e.js\`, which: +- +-1. Runs the migration script using \`--skip-github-api\` and other skip flags, capturing code coverage +-2. Checks that only a small list of allowed files were changed +-3. Checks that the local repository's files were changed correctly (e.g. removed initialization-only files) +- +-The \`pnpm run test:migrate\` script is run in CI to ensure that templating changes are in sync with the template's actual files. +-See \`.github/workflows/test-migrate.yml\`. +- +-> Tip: if the migration test is failing in CI and you don't see any errors, try [downloading the full logs](https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/using-workflow-run-logs#downloading-logs). +-> There'll likely be a list of changed files under a message like _\`Oh no! Running the migrate script modified some files:\`_. +-> You can also try running the test script locally." +`; + +exports[`verify .github/workflows/lint-knip.yml 1`] = ` +"--- a/.github/workflows/lint-knip.yml ++++ b/.github/workflows/lint-knip.yml +@@ -4,7 +4,6 @@ jobs: + steps: + - uses: actions/checkout@v4 + - uses: ./.github/actions/prepare +- - run: pnpm build || true + - run: pnpm lint:knip + + name: Lint Knip" +`; + +exports[`verify .github/workflows/test.yml 1`] = ` +"--- a/.github/workflows/test.yml ++++ b/.github/workflows/test.yml +@@ -7,14 +7,6 @@ jobs: + - run: pnpm run test --coverage + - name: Codecov + uses: codecov/codecov-action@v3 +- with: +- flags: unit +- - if: always() +- name: Archive code coverage results +- uses: actions/upload-artifact@v4 +- with: +- name: code-coverage-report +- path: coverage + + name: Test + " +`; + +exports[`verify .gitignore 1`] = ` +"--- a/.gitignore ++++ b/.gitignore +@@ -1,3 +1,3 @@ +-coverage*/ ++coverage/ + lib/ + node_modules/" +`; + +exports[`verify .prettierignore 1`] = ` +"--- a/.prettierignore ++++ b/.prettierignore +@@ -1,4 +1,4 @@ + .all-contributorsrc +-coverage*/ ++coverage/ + lib/ + pnpm-lock.yaml" +`; + +exports[`verify README.md 1`] = ` +"--- a/README.md ++++ b/README.md +@@ -5,57 +5,20 @@ +

+ + +-All Contributors: 39 ๐Ÿค ++ All Contributors: 39 ๐Ÿ‘ช + + + Codecov Test Coverage +- Code of Conduct: Enforced ๐Ÿค +- License: MIT ๐Ÿ“ +- Sponsor: On GitHub ๐Ÿ’ธ +- Style: Prettier ๐Ÿงน +- TypeScript: Strict ๐Ÿ’ช ++ Contributor Covenant ++ License: MIT ++ Sponsor: On GitHub ++ Style: Prettier ++ TypeScript: Strict + npm package version ++ All Contributors: 39 ๐Ÿค ++ Sponsor: On GitHub ๐Ÿ’ธ +

+ +-Project logo: the TypeScript blue square with rounded corners, but a plus sign instead of 'TS' +- +-\`create-typescript-app\` is a one-stop-shop solution to set up a new or existing repository with the latest and greatest TypeScript tooling. +-It includes options not just for building and testing but also GitHub repository templates, contributor recognition, automated release management, and more. +- +-## Getting Started +- +-First make sure you have the following installed: +- +-- [GitHub CLI](https://cli.github.com) _(you'll need to be logged in)_ +-- [Node.js](https://nodejs.org) +-- [pnpm](https://pnpm.io) +- +-Then in an existing repository or in your directory where you'd like to make a new repository: +- +-\`\`\`shell +-npx create-typescript-app +-\`\`\` +- +-That setup script will walk you through using the template. +-You can read more about the supported setup modes in their docs pages: +- +-- [**Creating from the terminal**](./docs/Creation.md): creating a new repository locally on the command-line _(recommended)_ +-- [**Initializing from the template**](./docs/Initialization.md): creating a new repository with the [_Use this template_](https://github.com/JoshuaKGoldberg/create-typescript-app/generate) button on GitHub +-- [**Migrating an existing repository**](./docs/Migration.md): adding this template's tooling on top of an existing repository +- +-## Documentation +- +-You can read more about \`create-typescript-app\` and the tooling it supports: +- +-1. [**Tooling**](./docs/Tooling.md): a breakdown of all the pieces this template can set up. +-2. [**Options**](./docs/Options.md): granular options to customize how the template is run. +-3. [**FAQs**](./docs/FAQs.md): frequently asked questions +- +-> [!NOTE] +-> This template is early stage, opinionated, and not endorsed by the TypeScript team. +-> It can be configured to set up a _lot_ of tooling out of the box. +-> If you don't want to use any particular tool, you can always remove it manually. +- + ## Development + + See [\`.github/CONTRIBUTING.md\`](./.github/CONTRIBUTING.md), then [\`.github/DEVELOPMENT.md\`](./.github/DEVELOPMENT.md). +@@ -128,3 +91,7 @@ Thanks! ๐Ÿ’– + + + ++ ++ ++ ++> ๐Ÿ’™ This package was templated with [\`create-typescript-app\`](https://github.com/JoshuaKGoldberg/create-typescript-app)." +`; + +exports[`verify bin/index.js 1`] = `""`; + +exports[`verify cspell.json 1`] = ` +"--- a/cspell.json ++++ b/cspell.json +@@ -1,40 +1,27 @@ + { + "dictionaries": ["typescript"], + "ignorePaths": [ +- "./coverage*", + ".github", + "CHANGELOG.md", ++ "coverage", + "lib", + "node_modules", +- "pnpm-lock.yaml", +- "./script/__snapshots__" ++ "pnpm-lock.yaml" + ], + "words": [ +- "allcontributors", +- "apexskier", +- "arethetypeswrong", + "Codecov", + "codespace", + "commitlint", + "contributorsrc", + "conventionalcommits", +- "execa", +- "infile", +- "joshuakgoldberg", + "knip", + "lcov", + "markdownlintignore", +- "mtfoley", +- "npmignore", +- "npmjs", + "npmpackagejsonlintrc", + "outro", + "packagejson", + "quickstart", +- "tada", + "tsup", +- "Unstaged", +- "vitest", + "wontfix" + ] + }" +`; + +exports[`verify knip.jsonc 1`] = ` +"--- a/knip.jsonc ++++ b/knip.jsonc +@@ -1,17 +1,6 @@ + { + "$schema": "https://unpkg.com/knip@latest/schema.json", +- "entry": [ +- "src/index.ts!", +- "src/guide/index.ts", +- "src/initialize/index.ts", +- "src/migrate/index.ts", +- "script/*e2e.js" +- ], +- "ignoreBinaries": ["gh"], +- "ignoreDependencies": ["script"], +- "ignoreExportsUsedInFile": { +- "interface": true, +- "type": true +- }, +- "project": ["src/**/*.ts!", "script/**/*.js"] ++ "entry": ["src/index.ts!"], ++ "ignoreExportsUsedInFile": { "interface": true, "type": true }, ++ "project": ["src/**/*.ts!"] + }" +`; + +exports[`verify package.json 1`] = ` +"--- a/package.json ++++ b/package.json +@@ -15,7 +15,6 @@ + "main": "./lib/index.js", + "bin": "./bin/index.js", + "files": [ +- "bin/", + "lib/", + "package.json", + "LICENSE.md", +@@ -24,7 +23,6 @@ + "scripts": { + "build": "tsup", + "format": "prettier \\"**/*\\" --ignore-unknown", +- "initialize": "tsx ./src/bin/index.js --mode initialize", + "lint": "eslint . .*js --max-warnings 0", + "lint:knip": "knip", + "lint:md": "markdownlint \\"**/*.md\\" \\".github/**/*.md\\" --rules sentences-per-line", +@@ -34,9 +32,6 @@ + "prepare": "husky install", + "should-semantic-release": "should-semantic-release --verbose", + "test": "vitest", +- "test:create": "node script/create-test-e2e.js", +- "test:initialize": "node script/initialize-test-e2e.js", +- "test:migrate": "vitest run -r script/", + "tsc": "tsc" + }, + "lint-staged": { +@@ -107,7 +102,7 @@ + "vitest": "^1.0.2", + "yaml-eslint-parser": "^1.2.2" + }, +- "packageManager": "pnpm@8.13.1", ++ "packageManager": "pnpm@8.7.0", + "engines": { + "node": ">=18" + }," +`; diff --git a/script/migrate-test-e2e.js b/script/migrate-test-e2e.js index 4c870d9e9..79483d7d5 100644 --- a/script/migrate-test-e2e.js +++ b/script/migrate-test-e2e.js @@ -1,37 +1,15 @@ import chalk from "chalk"; import { $, execaCommand } from "execa"; +import { assert, expect, test } from "vitest"; import packageData from "../package.json" assert { type: "json" }; -const { description, name: repository } = packageData; -const emailGithub = "github@joshuakgoldberg.com"; -const emailNpm = "npm@joshuakgoldberg.com"; -const owner = "JoshuaKGoldberg"; -const title = "Create TypeScript App"; - -await $({ - stdio: "inherit", -})`c8 -o ./coverage -r html -r lcov --src src node ./bin/index.js --base everything --mode migrate --bin ./bin/index.js --description ${description} --email-github ${emailGithub} --email-npm ${emailNpm} --guide https://www.joshuakgoldberg.com/blog/contributing-to-a-create-typescript-app-repository --guide-title "Contributing to a create-typescript-app Repository" --owner ${owner} --title ${title} --repository ${repository} --skip-all-contributors-api --skip-github-api --skip-install`; - -const { stdout: gitStatus } = await $`git status`; -console.log(`Stdout from running \`git status\`:\n${gitStatus}`); - -const indexOfUnstagedFilesMessage = gitStatus.indexOf( - "Changes not staged for commit:", -); -if (indexOfUnstagedFilesMessage === -1) { - throw new Error( - `Looks like migrate didn't cause any file changes? That's ...probably incorrect? ๐Ÿ˜ฌ`, - ); -} - const filesExpectedToBeChanged = new Set([ ".all-contributorsrc", "bin/index.js", "README.md", "knip.jsonc", "package.json", - "pnpm-lock.yaml", ".eslintignore", ".eslintrc.cjs", ".github/DEVELOPMENT.md", @@ -42,35 +20,72 @@ const filesExpectedToBeChanged = new Set([ "cspell.json", ]); -const unstagedModifiedFiles = gitStatus - .slice(indexOfUnstagedFilesMessage) - .match(/modified: {3}(\S+)\n/g) - .map((match) => match.split(/\s+/g)[1]) - .filter((filePath) => !filesExpectedToBeChanged.has(filePath)); +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 owner = "JoshuaKGoldberg"; +const title = "Create TypeScript App"; + +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} --owner ${owner} --title ${title} --repository ${repository} --skip-all-contributors-api --skip-github-api --skip-install`; -console.log("Unexpected modified files are:", unstagedModifiedFiles); +test.each([...filesExpectedToBeChanged])("verify %s", async (file) => { + const { stdout } = await execaCommand(`git diff HEAD -- ${file}`); + expect(stdout.split("\n").slice(2).join("\n")).toMatchSnapshot(); +}); -if (unstagedModifiedFiles.length) { - const gitDiffCommand = `git diff HEAD -- ${unstagedModifiedFiles.join(" ")}`; - console.log( - `Stdout from running \`${gitDiffCommand}\`:\n${ - (await execaCommand(gitDiffCommand)).stdout - }`, +// eslint-disable-next-line vitest/expect-expect +test("check for unstagedModifiedFiles", async () => { + const { stdout: gitStatus } = await $`git status`; + console.log(`Stdout from running \`git status\`:\n${gitStatus}`); + + const indexOfUnstagedFilesMessage = gitStatus.indexOf( + "Changes not staged for commit:", ); - console.error( - [ - "", - "Oh no! Running the migrate script modified some files:", - ...unstagedModifiedFiles.map((filePath) => ` - ${filePath}`), - "", - "That likely indicates changes made to the repository without", - "corresponding updates to templates in src/.", - "", - "Please search for those file(s)' name(s) under src/migrate for", - "the corresponding template and update those as well.", - ] - .map((line) => chalk.red(line)) - .join("\n"), + assert( + indexOfUnstagedFilesMessage !== -1, + `Looks like migrate didn't cause any file changes? That's ...probably incorrect? ๐Ÿ˜ฌ`, ); - process.exitCode = 1; -} + + const unstagedModifiedFiles = gitStatus + .slice(indexOfUnstagedFilesMessage) + .match(/modified: {3}(\S+)\n/g) + .map((match) => match.split(/\s+/g)[1]) + .filter((filePath) => !filesExpectedToBeChanged.has(filePath)); + + console.log("Unexpected modified files are:", unstagedModifiedFiles); + + if (unstagedModifiedFiles.length) { + const gitDiffCommand = `git diff HEAD -- ${unstagedModifiedFiles.join( + " ", + )}`; + console.log( + `Stdout from running \`${gitDiffCommand}\`:\n${ + (await execaCommand(gitDiffCommand)).stdout + }`, + ); + throw new Error( + [ + "", + "Oh no! Running the migrate script modified some files:", + ...unstagedModifiedFiles.map((filePath) => ` - ${filePath}`), + "", + "That likely indicates changes made to the repository without", + "corresponding updates to templates in src/.", + "", + "Please search for those file(s)' name(s) under src/migrate for", + "the corresponding template and update those as well.", + ] + .map((line) => chalk.red(line)) + .join("\n"), + ); + } +}); diff --git a/script/vitest.config.ts b/script/vitest.config.ts new file mode 100644 index 000000000..2e458efaf --- /dev/null +++ b/script/vitest.config.ts @@ -0,0 +1,3 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ test: { include: ["./migrate-test-e2e.js"] } });