diff --git a/.eslintrc.cjs b/.eslintrc.cjs index af26795..c425133 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -5,11 +5,17 @@ require('@rushstack/eslint-patch/modern-module-resolution'); module.exports = { root: true, + ignorePatterns: ['e2e/fixtures/', 'e2e/minimum/', 'e2e/latest/'], + parserOptions: { // https://github.com/typescript-eslint/typescript-eslint/tree/main/packages/parser#parseroptionstsconfigrootdir // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment tsconfigRootDir: __dirname, - project: ['./tsconfig.eslint.json', './packages/*/tsconfig.json'], + project: [ + './tsconfig.eslint.json', + './packages/*/tsconfig.json', + './e2e/tsconfig.json', + ], }, env: { diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a0be4ae..09ba308 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,3 +34,29 @@ jobs: - run: pnpm lint - run: pnpm format:check - run: pnpm build + + e2e: + name: e2e (Node.js ${{ matrix.node-version }}) + runs-on: ubuntu-26.04 + timeout-minutes: 15 + strategy: + fail-fast: false + matrix: + # The oldest supported version and the active LTS version. + node-version: [22, 26] + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + # Reads the pnpm version from the packageManager field in package.json. + - uses: pnpm/action-setup@73e46992e05b19abd31f2f3c20e0e7370d762115 # v6.1.1 + with: + cache: true + + - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 + with: + node-version: ${{ matrix.node-version }} + + - run: pnpm install --frozen-lockfile + - run: pnpm test diff --git a/.prettierignore b/.prettierignore index bd5535a..7a9d280 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1 +1,8 @@ pnpm-lock.yaml + +# Copied fixtures and generated files in the e2e projects. +e2e/.tarballs/ +e2e/minimum/* +e2e/latest/* +!e2e/minimum/package.json +!e2e/latest/package.json diff --git a/README.md b/README.md index cfe82d6..2938a2e 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,15 @@ A collection of packages to help you generate code from GraphQL documents and us - [@dreamonkey/graphql-codegen-vue-query-block](./packages/vue-query-block) - Custom `` block to define GraphQL documents in Vue SFCs - TODO: [@dreamonkey/app-extension-graphql-codegen](./packages/app-extension) - GraphQL Code Generator scaffolding and integration with all the packages in this repo for [Quasar Framework](https://quasar.dev/) as an App Extension +## Testing + +Run `pnpm test`. The command runs the end-to-end tests in `e2e/` with Vitest. +The tests build and pack each package, then install the tarballs into two projects. +The `minimum` project uses the oldest supported versions, and the `latest` project uses the newest. +Each project runs GraphQL Code Generator, type-checks the output, and runs a Vite build. + +To test one project, filter by its name: `pnpm test -t latest`. + ## Donate If you appreciate the work that went into these packages, please consider [donating](https://github.com/sponsors/dreamonkey). diff --git a/e2e/.gitignore b/e2e/.gitignore new file mode 100644 index 0000000..546a6e0 --- /dev/null +++ b/e2e/.gitignore @@ -0,0 +1,6 @@ +.tarballs/ +# Everything in a variant project except package.json comes from fixtures/ or the test run. +/minimum/* +/latest/* +!/minimum/package.json +!/latest/package.json diff --git a/e2e/e2e.test.ts b/e2e/e2e.test.ts new file mode 100644 index 0000000..e0c15c3 --- /dev/null +++ b/e2e/e2e.test.ts @@ -0,0 +1,88 @@ +import { cp, mkdir, readFile, rm, writeFile } from 'node:fs/promises'; +import { join } from 'node:path'; +import { execa } from 'execa'; +import { beforeAll, describe, expect, test } from 'vitest'; + +const fixturesDir = join(import.meta.dirname, 'fixtures'); +const variants = ['minimum', 'latest']; +const moduleResolutionFlags = { + bundler: ['--module', 'preserve', '--moduleResolution', 'bundler'], + node10: ['--module', 'esnext', '--moduleResolution', 'node10'], + nodenext: ['--module', 'nodenext', '--moduleResolution', 'nodenext'], +}; +// Vitest sets NODE_ENV to "test". GraphQL Code Generator prints nothing when NODE_ENV is "test". +const childEnv = Object.fromEntries( + Object.entries(process.env).filter(([name]) => name !== 'NODE_ENV'), +); +const BROKEN_SFC = + '