|
| 1 | +# End-to-end testing |
| 2 | + |
| 3 | +## Publishing (only used for E2E tests with local registry) |
| 4 | + |
| 5 | +> [!NOTE] Projects are marked as publishabel by adding a target named `publishabel`. |
| 6 | +> Those libraries will have dynamic targets to publish and install the package. |
| 7 | +
|
| 8 | +Every publishable project in the monorepo has the following targets: |
| 9 | + |
| 10 | +- [`publish`](./tools/src/publish/README.md#publish) - publish the package to the local registry |
| 11 | +- [`npm-check`](./tools/src/npm/README.md#npm-check) - check if the package is installed in registry |
| 12 | +- [`npm-install`](./tools/src/npm/README.md#npm-install) - install package in workspace. |
| 13 | +- [`npm-uninstall`](./tools/src/npm/README.md#npm-uninstall) - uninstall package form workspace |
| 14 | + |
| 15 | +The following steps are necessary to publish a package: |
| 16 | + |
| 17 | +1. `nx run <project-name>:npm-check` - check if the package is not already published |
| 18 | +2. `nx run <project-name>:publish --nextVersion=<version>` - publish package (login required) |
| 19 | +3. `nx run <project-name>:npm-check` - check if the package is published |
| 20 | + |
| 21 | +## E2E testing |
| 22 | + |
| 23 | +> [!NOTE] Projects that need verdaccio are identified over the `e2e` target. |
| 24 | +> Those libraries will have dynamic targets to start verdaccio and test the package. |
| 25 | +
|
| 26 | +All E2E tests use verdaccio to test the build artefact in a real registry. |
| 27 | + |
| 28 | +Every E2E project in the monorepo has the following targets: |
| 29 | + |
| 30 | +- [`start-verdaccio`](./tools/src/verdaccio/README.md#start-verdaccio) - start a local registry |
| 31 | + |
| 32 | +#### Running E2E tests for a given project: |
| 33 | + |
| 34 | +Every project in the monorepo that has E2E tests follows the project naming pattern: `<project-name>-e2e`. |
| 35 | + |
| 36 | +Examples: |
| 37 | + |
| 38 | +- `npx nx e2e cli-e2e` - run E2E tests for the cli project |
| 39 | +- `npx nx e2e cli-e2e --skipNxCache` - pass Nx CLI arguments |
| 40 | +- `npx nx run-many -t e2e` - run all E2E tests |
| 41 | + |
| 42 | +### E2E testing process |
| 43 | + |
| 44 | +The `e2e` testing process is complex and involves multiple steps and targets. |
| 45 | + |
| 46 | +#### Overview: |
| 47 | + |
| 48 | +- `nx run e2e <project-name>` |
| 49 | + - `global-setup.e2e.ts#setup` (vitest setup script configured in `vite.config.e2e.ts`) |
| 50 | + - setup - `nx start-verdaccio` |
| 51 | + - setup - `nx run-many -t publish` |
| 52 | + - setup - `nx run-many -t npm-install` |
| 53 | + - **run tests** |
| 54 | + - `global-setup.e2e.ts#teardown` (vitest teardown script configured in `vite.config.e2e.ts`) |
| 55 | + - teardown - `nx run-many -t npm-uninstall` |
| 56 | + - teardown - `process.kill(<verdaccio-port>)` |
| 57 | + |
| 58 | +```mermaid |
| 59 | +graph TD |
| 60 | + A["nx run e2e <project-name>"] --> B[global-setup.e2e.ts] |
| 61 | + B --> C[nx start-verdaccio] |
| 62 | + C --> D[nx run-many -t publish] |
| 63 | + D --> E[nx run-many -t npm-install] |
| 64 | + E --> F[vitest test] |
| 65 | + F --> G[nx run-many -t npm-uninstall] |
| 66 | + G --> H["process.kill(<verdaccio-port>)"] |
| 67 | +``` |
| 68 | + |
| 69 | +#### Involved files: |
| 70 | + |
| 71 | +```sh |
| 72 | +Root/ |
| 73 | +├── e2e/ |
| 74 | +│ └── <project-name>-e2e/ |
| 75 | +│ ├── tests/ |
| 76 | +│ │ └── <file-name>.e2e.ts |
| 77 | +│ ├── vite.config.e2e.ts # uses `global-setup.e2e.ts` for as `globalSetup` script |
| 78 | +│ └── project.json |
| 79 | +├── packages/ |
| 80 | +│ └── <project-name>/ |
| 81 | +│ └── project.json # marked as "publishable" |
| 82 | +├── .verdaccio/ |
| 83 | +│ └── config.yaml |
| 84 | +├── tools/ # all plugins registered in nx.json |
| 85 | +│ └── src/ |
| 86 | +│ ├── npm/ |
| 87 | +│ │ └── npm.plugin.ts |
| 88 | +│ ├── publish/ |
| 89 | +│ │ └── publish.plugin.ts |
| 90 | +│ └── verdaccio/ |
| 91 | +│ └── verdaccio.plugin.ts |
| 92 | +├── global-setup.e2e.ts |
| 93 | +└── nx.json # registers npm, publish and verdaccio plugin |
| 94 | +``` |
| 95 | + |
| 96 | +#### `nx e2e <project-name>` process: |
| 97 | + |
| 98 | +1. Nx derives all dynamic targets from the plugins registered in `nx.json`. |
| 99 | + The following plugins are registered to publish packages to a local registry: |
| 100 | + |
| 101 | +```jsonc |
| 102 | +// nx.json |
| 103 | +{ |
| 104 | + // ... |
| 105 | + "plugins": ["tools/src/npm/npm.plugin.ts", "tools/src/publish/publish.plugin.ts", "tools/src/verdaccio/verdaccio.plugin.ts"] |
| 106 | +} |
| 107 | +``` |
| 108 | + |
| 109 | +2. The `e2e` target registered in `<project-name>/project.json` is executed: |
| 110 | + |
| 111 | +```jsonc |
| 112 | +{ |
| 113 | + "targets": { |
| 114 | + // ... |
| 115 | + "e2e": { |
| 116 | + "executor": "@nx/vite:test", |
| 117 | + "options": { |
| 118 | + "configFile": "e2e/<project-name>-e2e/vite.config.e2e.ts" |
| 119 | + } |
| 120 | + } |
| 121 | + } |
| 122 | +} |
| 123 | +``` |
| 124 | + |
| 125 | +2. 1. The `vite.config.e2e.ts` file is used to configure the Vite test runner. |
| 126 | + Inside the file, the `globalSetup` option is set to `global-setup.e2e.ts`: |
| 127 | + |
| 128 | +```typescript |
| 129 | +export default defineConfig({ |
| 130 | + // ... |
| 131 | + globalSetup: ['../../global-setup.e2e.ts'], |
| 132 | +}); |
| 133 | +``` |
| 134 | + |
| 135 | +2. 2. The `global-setup.e2e.ts` file is used to configure the global `setup` scripts for the test runner: |
| 136 | + The `setup` function is executed before the tests are run. |
| 137 | + It starts a local registry, publishes the package, and installs it in the project. |
| 138 | + |
| 139 | +> [!NOTE] |
| 140 | +> ATM the E2E tests install the packages in the workspace root which blocks the parallel execution of E2E tests. |
| 141 | +
|
| 142 | +```typescript |
| 143 | +// global-setup.e2e.ts |
| 144 | + |
| 145 | +// to avoid port conflicts ever E2E targets has a unique port |
| 146 | +const uniquePort = 6000 + Math.round(Math.random() * 1000); |
| 147 | +const e2eDir = join('tmp', 'e2e'); |
| 148 | + |
| 149 | +export async function setup() { |
| 150 | + // start local verdaccio registry |
| 151 | + const { registry } = await startLocalRegistry({ |
| 152 | + localRegistryTarget: '@code-pushup/cli-source:start-verdaccio', |
| 153 | + // to avoid file system conflicts ever E2E targets has a unique storage folder |
| 154 | + storage: join(join(e2eDir, `registry-${uniquePort}`), 'storage'), |
| 155 | + port: uniquePort, |
| 156 | + }); |
| 157 | + |
| 158 | + // package publish & install |
| 159 | + const version = findLatestVersion(); |
| 160 | + nxRunManyPublish({ registry, nextVersion: version }); |
| 161 | + nxRunManyNpmInstall({ registry, pkgVersion: version }); |
| 162 | +} |
| 163 | +``` |
| 164 | + |
| 165 | +3. The tests are executed and import the packages over their package name not over the build output. |
| 166 | + |
| 167 | +```typescript |
| 168 | +// correct |
| 169 | +import * as packageName from "<package-name>" |
| 170 | +// wrong |
| 171 | +import * as packageName from "./dist/packages/<project-name>/src/index.js" |
| 172 | +``` |
| 173 | + |
| 174 | +4. The `global-setup.e2e.ts` file is used to configure the global `teardown` scripts for the test runner: |
| 175 | + The `teardown` function is executed after the tests are run. |
| 176 | + It uninstalls the package and stops the local registry. |
| 177 | + |
| 178 | +```typescript |
| 179 | +// global-setup.e2e.ts |
| 180 | + |
| 181 | +export async function teardown() { |
| 182 | + // package uninstall |
| 183 | + nxRunManyNpmUninstall(); |
| 184 | + // stop local verdaccio registry |
| 185 | + stopLocalRegistry({ port: uniquePort }); |
| 186 | +} |
| 187 | +``` |
| 188 | + |
| 189 | +#### Changes/generated files during e2e tests: |
| 190 | + |
| 191 | +```sh |
| 192 | +Root/ |
| 193 | +├── dist/ |
| 194 | +│ └── packages/ |
| 195 | +│ └── <project-name>/... |
| 196 | +├── e2e/ |
| 197 | +│ └── <project-name>-e2e/ |
| 198 | +│ └── __snapshots__/... |
| 199 | +├── tmp/ |
| 200 | +│ └── e2e/ |
| 201 | +│ └── registry-<port>/ |
| 202 | +│ ├── storage/... |
| 203 | +│ ├── node_modules/... |
| 204 | +│ └── <test-name>/... |
| 205 | +│ └── src/... |
| 206 | +├── package-lock.json # npm install/uninstall installs into workspace root |
| 207 | +└── package.json # npm install/uninstall installs into workspace root |
| 208 | +``` |
| 209 | + |
| 210 | +After running the E2E tests all changes are reverted, and the workspace is in the same state as before the tests. |
| 211 | + |
| 212 | +### E2E testing troubleshooting |
| 213 | + |
| 214 | +- start local registry manually with `nx start-verdaccio` - logs port |
| 215 | +- check if a package is published with `nx npm-check <project-name> --registry=http://localhost:<port>` |
| 216 | +- install a package in workspace `nx npm-install <project-name> --registry=http://localhost:<port>` |
| 217 | +- uninstall a package from workspace `nx npm-uninstall <project-name>` |
0 commit comments