Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion .github/workflows/compat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,19 @@ jobs:
strategy:
fail-fast: false
matrix:
# The oldest supported minor of each tested major, then each current major. The tests run
# on Node.js 22 for every version: they load Angular in jsdom, not through its CLI.
include:
- angular: '12.2'
range: '~12.2.0'
# Angular 12 ships View Engine bundles that its CLI compiles for Ivy with ngcc.
ngcc: true
- angular: '15.2'
range: '~15.2.0'
- angular: '17.3'
range: '~17.3.0'
- angular: '19.2'
range: '~19.2.0'
- angular: '20.0'
range: '~20.0.0'
- angular: '21'
Expand All @@ -46,14 +58,33 @@ jobs:
- name: Install Angular ${{ matrix.angular }}
env:
RANGE: ${{ matrix.range }}
# ngcc rewrites the installed files in place, so they are copied rather than linked to
# the pnpm store.
IMPORT_METHOD: ${{ matrix.ngcc && 'copy' || 'auto' }}
run: |
{
echo 'overrides:'
for pkg in animations common compiler core elements forms platform-browser platform-browser-dynamic platform-server router; do
echo " '@angular/$pkg': '$RANGE'"
done
} >> pnpm-workspace.yaml
pnpm install --no-frozen-lockfile
pnpm install --no-frozen-lockfile --config.package-import-method="$IMPORT_METHOD"

- name: Compile Angular ${{ matrix.angular }} for Ivy
if: matrix.ngcc
run: |
version=$(node -p "require('@angular/core/package.json').version")
npm install --prefix "$RUNNER_TEMP/ngcc" --no-audit --no-fund --no-save \
"@angular/compiler-cli@$version" "@angular/compiler@$version" "@angular/core@$version" \
typescript@~4.3.5 rxjs@~7.8.0 zone.js@~0.11.4
# Each package's folder in the pnpm store links its dependencies. A package is compiled
# after the ones it depends on, so core and common go first.
for pkg in core common compiler platform-browser platform-browser-dynamic platform-server forms router elements animations; do
for dir in node_modules/.pnpm/@angular+"$pkg"@"$version"*/node_modules; do
[ -d "$dir" ] || continue
"$RUNNER_TEMP/ngcc/node_modules/.bin/ngcc" --source "$PWD/$dir" --properties main es2015 module --first-only
done
done

- name: List the versions under test
run: |
Expand Down
12 changes: 9 additions & 3 deletions apps/docs/src/content/contributing/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,20 +184,26 @@ A separate `axe` job in the same workflow installs Chromium and runs `pnpm test:

### Angular compatibility

`.github/workflows/compat.yml` runs the page-side tests on the oldest and newest Angular versions the peer range allows, and on the `next` prerelease. It runs on pushes to `main`, every Monday at 06:00 UTC, and on demand from the **Actions** tab. It doesn't run on pull requests.
`.github/workflows/compat.yml` runs the page-side tests on the oldest Angular version the peer range allows, the last minor of 15, 17 and 19, each current major, and the `next` prerelease. It runs on pushes to `main`, every Monday at 06:00 UTC, and on demand from the **Actions** tab. It doesn't run on pull requests.

| Job | Angular range | Node.js |
| ------------ | ------------- | ------- |
| Angular 12.2 | `~12.2.0` | 22 |
| Angular 15.2 | `~15.2.0` | 22 |
| Angular 17.3 | `~17.3.0` | 22 |
| Angular 19.2 | `~19.2.0` | 22 |
| Angular 20.0 | `~20.0.0` | 22 |
| Angular 21 | `^21.0.0` | 22 |
| Angular 22 | `^22.0.0` | 22 |
| Angular next | `next` | 22 |

The `next` job installs the `next` dist-tag, so a renamed `ɵ` API shows up before the next major ships. It runs with `continue-on-error`: a failure marks the job red but not the workflow.

Each job appends `overrides` for the `@angular/*` runtime packages to `pnpm-workspace.yaml`, reinstalls, and runs `vitest` with `packages/devtools/vitest.compat.config.ts`. That config picks the tests that render a real Angular app or read Angular's private debug APIs, including the `*-real` tests that boot a real app where the main tests use fakes, and leaves out the panel tests and most server tests. It adds the Signal Forms tests on Angular 22 and later, and loads `zone.js` before Angular 21, where `TestBed` still expects it. A test that needs a feature from a later release checks the version with `angularAtLeast()` from `src/__tests__/angular-version.ts` and skips on older ones.
Each job appends `overrides` for the `@angular/*` runtime packages to `pnpm-workspace.yaml`, reinstalls, and runs `vitest` with `packages/devtools/vitest.compat.config.ts`. That config picks the tests that render a real Angular app or read Angular's private debug APIs, including the `*-real` tests that boot a real app where the main tests use fakes, and leaves out the panel tests and most server tests. It adds the Signal Forms tests on Angular 22 and later, and loads `zone.js` before Angular 21, where `TestBed` still expects it. Before Angular 17 it also points `@angular/core/primitives/signals` at the stub the Vite plugin uses. The Angular 12 job then compiles the View Engine packages for Ivy with ngcc from `@angular/compiler-cli` 12, after a copying install, since ngcc rewrites the installed files.

To reproduce a job, add the same `overrides` block to `pnpm-workspace.yaml`, run `pnpm install --no-frozen-lockfile`, then `pnpm exec vitest run --root packages/devtools --config vitest.compat.config.ts`. Don't commit the changed lockfile.
`src/__tests__/angular-version.ts` has the helpers that make a test run on every version: `initAngularTestBed()`, `bootstrapRoot()` (an NgModule before 14.1), `zonelessProviders()`, `STANDALONE`, `writableSignal()` and `testModuleFor()`. `router-testing.ts` gives `provideRouter` or `RouterModule.forRoot`. A test of a feature that a version's debug API lacks checks the unavailable result there with `angularAtLeast()`. It is skipped only when the Angular API the test builds on doesn't exist yet, such as `@defer` before 17.0.

To reproduce a job, add the same `overrides` block to `pnpm-workspace.yaml`, run `pnpm install --no-frozen-lockfile`, then `pnpm exec vitest run --root packages/devtools --config vitest.compat.config.ts`. For Angular 12, run the ngcc step from the workflow before the tests. Do this in a copy of the repository, and don't commit the changed lockfile.

### Pull request checks

Expand Down
44 changes: 35 additions & 9 deletions apps/docs/src/content/getting-started/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ The devtools ship as one npm package, `@pangular-inspector/devtools`. It contain
<ngmd-card icon="terminal" title="Node.js 22 or later">
The package declares <code>node &gt;=22</code> in its <code>engines</code> field. CI tests Node.js 22 and 24.
</ngmd-card>
<ngmd-card icon="code" title="Angular 20 or later">
<code>&#64;angular/core</code> and <code>&#64;angular/common</code> 20 and newer are supported, with no upper bound. See <a href="#supported-angular-versions">Supported Angular versions</a> for older versions.
<ngmd-card icon="code" title="Angular 12.2 or later">
<code>&#64;angular/core</code> and <code>&#64;angular/common</code> 12.2 and newer are supported, with no upper bound. Older versions show less data. See <a href="#supported-angular-versions">Supported Angular versions</a>.
</ngmd-card>
<ngmd-card icon="box" title="Package manager">
pnpm, npm, yarn or bun. Any of the four.
Expand All @@ -31,7 +31,7 @@ The devtools ship as one npm package, `@pangular-inspector/devtools`. It contain

## Supported Angular versions

The peer range covers Angular 20 and later, and CI tests it (see [Tested versions](#tested-versions)). The overlay checks each debug API on the page and sends what it finds with the page's Angular version, so each tab shows the data that version provides. Only the profiler also looks at the version: the overlay uses `ɵsetProfiler` from Angular 20.0, because before that it holds a single profiler.
The peer range covers Angular 12.2 and later, and CI tests it (see [Tested versions](#tested-versions)). The overlay checks each debug API on the page and sends what it finds with the page's Angular version, so each tab shows the data that version provides. Only the profiler also looks at the version: the overlay uses `ɵsetProfiler` from Angular 20.0, because before that it holds a single profiler.

When a tab needs a debug API the page doesn't have, it says which Angular version the feature needs and which one the page runs, for example "The live signal graph needs Angular 20.1 or later; this page runs Angular 15.2." The agent tools answer **Unsupported on this Angular version** with the same sentence, and `list-pages` shows each page's Angular version next to its platform.

Expand All @@ -41,6 +41,8 @@ When a tab needs a debug API the page doesn't have, it says which Angular versio
| Injected services, providers and environment injectors | 16.2 |
| Full injector tree with lookup paths | 17.0 |
| Signal values in the component detail (`ng.isSignal`) | 17.1 |
| Form events from `AbstractControl.events` | 18.0 |
| The `@pangular-inspector/devtools/http` entry | 19.0 |
| **Defer blocks** list | 19.1 |
| Change detection recording and Angular profiling | 20.0 |
| Live signal graph | 20.1 |
Expand All @@ -50,27 +52,51 @@ All of them need a development build, since production builds leave out `window.

### Angular 12 to 19

Angular 12 to 19 are outside the peer range and CI doesn't test them, so your package manager warns about the peer dependency. On those versions the overlay degrades as the table above shows:
On Angular 12 to 19 the overlay degrades as the table above shows:

- The **Injectors** tab shows the element injectors with their components and directives. From 16.2 it adds providers, dependencies and environment injectors.
- Before 16.2, the overlay finds the `Router` through a router link, the component an outlet renders or the root component, whichever holds it. A page where none of them injects the `Router` shows no router data.
- Before 16.2, the overlay finds the `Router` through a router link, the component an outlet renders or the root component, whichever holds it. A page where none of them injects the `Router` shows no router data. The router setup is then read in `events-only` mode, so the setup kind shows `unknown` and features found through providers (preloading, the scroller, `withDebugTracing()`) show `off`.
- Before 16.2, the **NgRx** tab can't find the `@ngrx/store` `Store` or signal stores that components provide.
- Before 16.2, the errors collector can't wrap the app's `ErrorHandler`. It counts the errors Angular's default handler logs instead, so errors a custom handler swallows don't show.
- Before 18.0, the **Forms** tab builds its event timeline by comparing snapshots, since controls have no `events` stream.

The overlay loads `@angular/core/primitives/signals` for exact signal history. That entry exists from Angular 17, so a build that resolves it ahead of time can fail on Angular 12 to 16.
### Setup on Angular 12 to 19

| Setup | Angular 12 to 16 | Angular 17 to 19 |
| ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| Overlay import in `main.ts` | Works with the webpack-based `@angular-devkit/build-angular:browser` builder. Signal history uses samples, since `@angular/core/primitives/signals` exists from 17.0. | Works with `browser` and `application`. Under webpack, signal history uses samples. |
| Vite plugin (Analog) | Works. The plugin points `@angular/core/primitives/signals` at a stub before 17.0. | Works. |
| `initPangularHub()` in an Express server | Works when the server runs on Node.js 22 or later. If the server must stay on an older Node.js, run the standalone CLI on Node.js 22 or later beside it instead. | Works. |
| Standalone CLI next to `ng serve` | Works. Run `npx pangular dev` with Node.js 22 or later, and the app's own CLI with the Node.js version it supports. | Works. |
| Chrome extension | Works on top of any of the setups above. | Works. |
| `@pangular-inspector/devtools/http` | Not available. It imports `REQUEST` and `provideEnvironmentInitializer`, so the build fails. Leave it out; the HTTP timeline and fault rules need it. | Not available before 19.0, for the same reason. |

With the webpack-based `browser` builder, use the standalone CLI next to `ng serve`, as in [Client-only Angular CLI app](#client-only-angular-cli-app), or the Express hub for an SSR app.

TypeScript before 4.7 (Angular 12 and 13) can't read the package's `.d.mts` types, so `import('@pangular-inspector/devtools/overlay')` fails the type check. Declare the module in a typings file:

```ts
// src/typings.d.ts
declare module '@pangular-inspector/devtools/overlay';
```

### Tested versions

The peer range is `@angular/* >=20` with no upper bound. CI tests these versions:
The peer range is `@angular/core` and `@angular/common` `>=12.2` with no upper bound. CI tests these versions:

| Angular | Node.js | What runs | When |
| ----------------------- | ------- | ------------------------------------------------------------------------- | ------------------------------------- |
| 20.0 (lowest supported) | 22 | The page-side tests against a real Angular app | Every push to `main`, and weekly |
| 12.2 (lowest supported) | 22 | The page-side tests against a real Angular app, after ngcc | Every push to `main`, and weekly |
| 15.2 | 22 | The page-side tests against a real Angular app | Every push to `main`, and weekly |
| 17.3 | 22 | The page-side tests against a real Angular app | Every push to `main`, and weekly |
| 19.2 | 22 | The page-side tests against a real Angular app | Every push to `main`, and weekly |
| 20.0 | 22 | The page-side tests against a real Angular app | Every push to `main`, and weekly |
| 21 (latest 21.x) | 22 | The page-side tests against a real Angular app | Every push to `main`, and weekly |
| 22 (latest 22.x) | 22 | The page-side tests, including Signal Forms | Every push to `main`, and weekly |
| 22 (repository version) | 24 | Every package and panel test, the type checks and axe | Every pull request and push to `main` |
| Newest the ranges allow | 24 | A fresh Angular CLI app and a fresh Analog app with the package installed | Weekly |

Some features need a later Angular release than 20.0. The inspector pages list them, for example [abort and probe](../inspectors/router.md#abort-and-probe-need-angular-20-2) (20.2) and the live [signal graph](../inspectors/signals.md#debug-apis) (20.1). The Signal Forms tests run on Angular 22 and later, where Signal Forms are stable.
The page-side tests run in Node.js 22 for every Angular version, since they load Angular in jsdom rather than through its CLI. Tests of a feature a version lacks check the unavailable state on that version instead. Angular 13, 14, 16 and 18 are in the peer range but not tested. Some features need a later Angular release than 20.0. The inspector pages list them, for example [abort and probe](../inspectors/router.md#abort-and-probe-need-angular-20-2) (20.2) and the live [signal graph](../inspectors/signals.md#debug-apis) (20.1). The Signal Forms tests run on Angular 22 and later, where Signal Forms are stable.

## Install the package

Expand Down
4 changes: 2 additions & 2 deletions apps/docs/src/content/getting-started/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ The devtools are a <a href="https://devfra.me" target="_blank" rel="noopener nor
## Requirements

<ngmd-card-grid columns="3">
<ngmd-card icon="code" title="Angular 20 or later">
The package declares Angular 20 and later as its peer range.
<ngmd-card icon="code" title="Angular 12.2 or later">
The package declares Angular 12.2 and later as its peer range. Older versions show less data.
</ngmd-card>
<ngmd-card icon="terminal" title="Node.js 22 or later">
The package runs on Node.js 22 and newer.
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/src/content/inspectors/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ When several tabs report, **Page** picks one, or **All pages** to see them toget

<ngmd-card-grid columns="3">
<ngmd-card icon="shield" title="ErrorHandler">
The overlay wraps the <code>handleError</code> method of the app's <code>ErrorHandler</code>, your own or Angular's. Your handler still runs, with the same arguments, after the overlay records the error.
The overlay wraps the <code>handleError</code> method of the app's <code>ErrorHandler</code>, your own or Angular's. Your handler still runs, with the same arguments, after the overlay records the error. Before Angular 16.2 the overlay can't find the handler, so it records what Angular's default handler logs.
</ngmd-card>
<ngmd-card icon="zap" title="Window">
Listeners for <code>error</code> and <code>unhandledrejection</code> on <code>window</code>. They only listen, so the browser and Angular handle the event as before.
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/src/content/inspectors/forms.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ The actions bar works on the selected form:

### When the page reports

The overlay reads the forms after change detection and pushes them when they change. It also pushes shortly after each `input`, `change`, `focusout`, `submit` or `reset` event. Reactive and template-driven forms also report each change through `control.events`.
The overlay reads the forms after change detection and pushes them when they change. It also pushes shortly after each `input`, `change`, `focusout`, `submit` or `reset` event. Reactive and template-driven forms also report each change through `control.events`, which Angular has from 18.0. On older versions the timeline comes from comparing the forms between reads.

### Validators run only when needed

Expand Down
Loading
Loading