|
| 1 | +# react-integration-tester (rit) |
| 2 | + |
| 3 | +CLI to scaffold and run integration checks for multiple React majors (17/18/19) using YOUR project's existing test tooling (Jest / Cypress / TypeScript). It re‑uses a single shared dependency install per React major and creates cheap throw‑away (or reusable) scaffold projects exposing exactly three scripts: `test`, `type-check`, `e2e`. |
| 4 | + |
| 5 | +## Essentials |
| 6 | + |
| 7 | +React majors support: 17, 18, 19 |
| 8 | +Runners support: `test` (Jest), `type-check` (TypeScript), `e2e` (Cypress) |
| 9 | +Shared root: `<repoRoot>/tmp/rit/react-<major>/` (deps installed once) |
| 10 | +Prepared project naming: |
| 11 | + |
| 12 | +``` |
| 13 | +<repoRoot>/tmp/rit/react-<major>/<origin-project-name>-react-<major>-<project-id> |
| 14 | +``` |
| 15 | + |
| 16 | +When you omit `--project-id`, a random suffix is used instead of `<project-id>`, e.g. |
| 17 | + |
| 18 | +``` |
| 19 | +button-react-18-7423891 |
| 20 | +``` |
| 21 | + |
| 22 | +This deterministic pattern (when you pass `--project-id`) lets you reliably re‑use a scaffold across multiple `--run` invocations without re‑preparing. |
| 23 | + |
| 24 | +## How it works |
| 25 | + |
| 26 | +```mermaid |
| 27 | +flowchart LR |
| 28 | + START((Start)) --> A["A: Install dependencies<br/>shared react-<major> root<br/><code>tmp/rit/react-<major></code>"] |
| 29 | + A --> B["B: Scaffold project<br/><code><origin>-react-<major>-<id></code>"] |
| 30 | + B --> C{C: Run selected scripts} |
| 31 | + C -->|test| T["test (Jest)"] |
| 32 | + C -->|type-check| TC["type-check (tsc)"] |
| 33 | + C -->|e2e| E2E["e2e (Cypress)"] |
| 34 | + T --> END((End)) |
| 35 | + TC --> END |
| 36 | + E2E --> END |
| 37 | + classDef phase fill:#eef,stroke:#447,stroke-width:1px; |
| 38 | + class A,B,C phase; |
| 39 | +``` |
| 40 | + |
| 41 | +Legend: |
| 42 | + |
| 43 | +- A runs when you use `--install-deps`, or implicitly during a prepare/run unless you pass `--no-install` with prior deps installed. |
| 44 | +- B runs on `--prepare-only` or any one‑shot run without `--project-id` (temporary) or with `--project-id` (reusable). |
| 45 | +- C executes only the scripts you explicitly list via repeated `--run` flags, sequentially. |
| 46 | + |
| 47 | +## Quick start |
| 48 | + |
| 49 | +```bash |
| 50 | +# Prepare once (install deps -> generate scaffold) |
| 51 | +rit --react 18 --prepare-only --project-id demo |
| 52 | + |
| 53 | +# Run scripts (re-uses scaffold + node_modules -> run) |
| 54 | +rit --react 18 --project-id demo --run test --run type-check |
| 55 | +``` |
| 56 | + |
| 57 | +One‑shot run (install -> prepare -> run -> cleanup): |
| 58 | + |
| 59 | +```bash |
| 60 | +rit --react 19 --run test |
| 61 | +``` |
| 62 | + |
| 63 | +Install deps only (CI cache warm): |
| 64 | + |
| 65 | +```bash |
| 66 | +rit --react 17 --install-deps |
| 67 | +``` |
| 68 | + |
| 69 | +## Usage |
| 70 | + |
| 71 | +```bash |
| 72 | +rit --react <17|18|19> \ |
| 73 | + [--project-id <id>] [--config <file>] [--cwd <path>] \ |
| 74 | + [--prepare-only [--no-install] [--force]] \ |
| 75 | + [--install-deps] \ |
| 76 | + [--run <test|type-check|e2e> ...] \ |
| 77 | + [--cleanup|--no-cleanup] [--verbose] |
| 78 | +``` |
| 79 | +
|
| 80 | +Flag reference (implementation accurate): |
| 81 | +
|
| 82 | +- `--react` (required for every invocation) React major. |
| 83 | +- `--project-id` stable suffix enabling scaffold reuse. Required when using `--prepare-only`. Optional otherwise (random suffix used if omitted). |
| 84 | +- `--config` path to a config module (CommonJS or ESM). Defaults to `./rit.config.js` if present. |
| 85 | +- `--prepare-only` create/update a scaffold (and install unless `--no-install`). Does NOT run scripts. |
| 86 | +- `--no-install` (only valid with `--prepare-only`) skips dependency installation. Requires that dependencies have already been installed earlier via `--install-deps` for that React major; otherwise it fails fast. |
| 87 | +- `--install-deps` install/update shared deps for the React major root and exit (no scaffold created). |
| 88 | +- `--run <script>` select one or more scripts to execute sequentially. Repeat the flag for multiple (e.g. `--run test --run type-check`). You must list all you want; there is no implicit “run all”. |
| 89 | +- `--force` (with `--prepare-only`) delete existing scaffold with the same computed name before recreating it. |
| 90 | +- `--cleanup` / `--no-cleanup` (default: cleanup) remove the temporary project after running. When reusing via `--run` + `--project-id`, cleanup is effectively a no‑op; the scaffold remains unless you prepared and then ran in one shot without reuse. |
| 91 | +- `--verbose` extra logging including resolved metadata. |
| 92 | +- `--cwd` working directory for discovering the origin project (defaults to process cwd). |
| 93 | +
|
| 94 | +Rules & guardrails: |
| 95 | +
|
| 96 | +- `--run` cannot be combined with `--prepare-only` or `--no-install`. |
| 97 | +- `--prepare-only` requires `--project-id` (deterministic reuse is a core feature). |
| 98 | +- You must pass at least one `--run` OR use `--prepare-only` OR `--install-deps`. |
| 99 | +- Reusing (`--run ... --project-id <id>`) requires that dependencies are already installed for that React root (`rit --install-deps --react <major>` or a prior prepare/run that installed them). |
| 100 | +
|
| 101 | +## Configuration (`rit.config.js`) |
| 102 | +
|
| 103 | +If you need to tweak defaults you have 2 options: |
| 104 | +
|
| 105 | +- create `rit.config.js` within your project root |
| 106 | +- create any js module that follows RIT Config API and point `rit` to it via `--config='<path_to_your_config_module>'` |
| 107 | +
|
| 108 | +Override per‑major React version commands and add/override dependencies. Merge is shallow: template defaults + your overrides. |
| 109 | +
|
| 110 | +**Config API:** |
| 111 | +
|
| 112 | +```ts |
| 113 | +export interface ReactOverrides { |
| 114 | + commands?: { |
| 115 | + test?: string; // maps to script "test" |
| 116 | + typeCheck?: string; // maps to script "type-check" |
| 117 | + e2e?: string; // maps to script "e2e" |
| 118 | + }; |
| 119 | + dependencies?: Record<string, string>; // added to shared root |
| 120 | +} |
| 121 | +
|
| 122 | +export interface Config { |
| 123 | + react: { |
| 124 | + 17?: ReactOverrides; |
| 125 | + 18?: ReactOverrides; |
| 126 | + 19?: ReactOverrides; |
| 127 | + }; |
| 128 | +} |
| 129 | +``` |
| 130 | +
|
| 131 | +**Minimal config example:** |
| 132 | +
|
| 133 | +In your project root create `rit.config.js` |
| 134 | +
|
| 135 | +```js |
| 136 | +/** @type {import('@fluentui/react-integration-tester').Config} */ |
| 137 | +module.exports = { |
| 138 | + react: { |
| 139 | + 17: { |
| 140 | + commands: { |
| 141 | + // maps to package.json script "test" |
| 142 | + test: 'jest --passWithNoTests -u --testPathIgnorePatterns test-file-that-wont-work-in-react-17.test.tsx', |
| 143 | + }, |
| 144 | + // installed once under ./tmp/rit/react-17/node_modules |
| 145 | + dependencies: { 'some-package': '^1.2.3' }, |
| 146 | + }, |
| 147 | + }, |
| 148 | +}; |
| 149 | +``` |
| 150 | +
|
| 151 | +Script key mapping (config camelCase → scaffold script name): `test` → `test`, `typeCheck` → `type-check`, `e2e` → `e2e`. |
| 152 | +
|
| 153 | +Only these three script names are runnable (`--run` choices). Additional scripts you add to the template are ignored by the CLI selector. |
| 154 | +
|
| 155 | +## Typical CI flow |
| 156 | +
|
| 157 | +Install dependencies for your React major under test (cache warm; safe to run repeatedly—it only rewrites/reacts when deps change): |
| 158 | +
|
| 159 | +```bash |
| 160 | +rit --react 18 --install-deps |
| 161 | +``` |
| 162 | +
|
| 163 | +From project root: |
| 164 | +
|
| 165 | +```bash |
| 166 | +# prepare project with known suffix so we can target it against --run (depends already installed) |
| 167 | +rit --react 18 --prepare-only --no-install --project-id ci |
| 168 | +
|
| 169 | +# execute following in parallel via your task runner for best performance |
| 170 | +rit --react 18 --project-id ci --run test |
| 171 | +rit --react 18 --project-id ci --run type-check |
| 172 | +``` |
| 173 | +
|
| 174 | +## Multiple runners |
| 175 | +
|
| 176 | +```bash |
| 177 | +rit --react 19 --project-id all --run test --run type-check --run e2e # runs sequentially |
| 178 | +# Partial subset |
| 179 | +rit --react 19 --project-id fast --run type-check |
| 180 | +``` |
| 181 | +
|
| 182 | +## Project naming & reuse |
| 183 | +
|
| 184 | +Given a source package `@scope/button` and `--react 18 --project-id demo` the scaffold will live at: |
| 185 | +
|
| 186 | +```text |
| 187 | +<repoRoot>/tmp/rit/react-18/button-react-18-demo |
| 188 | +``` |
| 189 | +
|
| 190 | +Reusing later: |
| 191 | +
|
| 192 | +```bash |
| 193 | +rit --react 18 --project-id demo --run test |
| 194 | +``` |
| 195 | +
|
| 196 | +If you omit `--project-id` the name ends with a random number and is NOT intended for reuse. |
| 197 | +
|
| 198 | +## Troubleshooting |
| 199 | +
|
| 200 | +- Reset cache (all scaffolds + deps for a major): delete `<repoRoot>/tmp/rit/react-<major>/`. |
| 201 | +- Template or dependency change: run `rit --react <major> --install-deps` (updates root package.json & installs if needed). |
| 202 | +- Missing script: confirm it exists in merged template AND origin project tooling (e.g. Jest/Cypress present). You must invoke with kebab-case (`type-check`). |
| 203 | +- Using `--prepare-only --no-install` without prior `--install-deps` will fail intentionally to prevent unusable scaffolds. |
| 204 | +- Keep a scaffold for iterative local debugging: run with `--no-cleanup` (except when reusing via `--project-id`, cleanup is already a no-op). |
| 205 | +- Force a clean re‑prepare (discard old scaffold): add `--force`. |
| 206 | +
|
| 207 | +## Contributing |
| 208 | +
|
| 209 | +Inside this repo only: |
| 210 | +
|
| 211 | +- Build: `nx run react-integration-tester:build` |
| 212 | +- Tests: `nx test react-integration-tester:test` |
0 commit comments