Hacktoberfest 2026: die Issues, die Maintainer für den Oktober markiert haben – offen und einsteigerfreundlich. Hacktoberfest-Issues durchsuchen

`@angular/build:unit-test` virtual `init-testbed.js` guards `initTestEnvironment()` behind a once-per-worker symbol → stale DomAdapter under vitest ≥4.0.5 + `isolate: false`

Offen
#33,047 0 Kommentare 1 Reaktion 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

Bewertung

Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Anfängerfreundlichkeit
55/100
Issue-Typ
Bug
Klarheit
Klar beschrieben
Aktivitätsstatus
Ruhig
Tech-Stack
angular, typescript

Rechercherichtung

Beginnen Sie mit packages/angular/build/src/builders/unit-test/runners/vitest/build-options.ts und plugins.ts und führen Sie dann die gemeldete jsdom-Suite wiederholt mit ng test --force, isolate: false und vitest 4.x aus. Überprüfen Sie, dass der stale-DomAdapter-Fehler nicht mehr über Spec-Dateien hinweg auftritt, während das Unit-Test-Setup-Verhalten des Builders erhalten bleibt; das Issue schlägt das reset-and-reinitialize-Muster aus analogjs/analog#2244 vor und weist auf die Dokumentation als nachgelagerte Folgeaufgabe hin.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Beschreibung

angular/build:unit-test area: @angular/build gemini-triaged

This is a follow-up to the now-closed/auto-locked #32754 with the missing details. That issue was dismissed as potentially analog-specific because the reporter had @analogjs/vitest-angular in their deps. This report uses @angular/build:unit-test only and pins the bug to specific lines in @angular/build's own source.

Which @angular/* package(s) are the source of the bug?

@angular/build

Is this a regression?

Yes — surfaces with vitest ≥4.0.5 (see vitest-dev/vitest#8944).

Description

@angular/build:unit-test's vitest runner combines two defaults that interact badly under vitest ≥4.0.5:

  • plugins.ts:254 hardcodes isolate: false for the vitest pool (intentional, "align with the Karma/Jasmine experience"). Worker module graphs are therefore reused across spec files.
  • build-options.ts:73-89 — the injected virtual init-testbed.js wraps getTestBed().initTestEnvironment(...) in an if (!globalThis[ANGULAR_TESTBED_SETUP]) guard. The comment on line 79 explicitly says "the guard condition above ensures that the setup is only performed once". That's the anti-pattern.

The first spec file in a worker initializes a platformBrowserTesting whose DomAdapter captures the jsdom document as a closure reference. Subsequent spec files in the same worker skip the init block entirely, so the DomAdapter keeps being reused. When jsdom's document swaps between spec files — and vitest ≥4.0.5 no longer re-executes setup files between spec files under isolate: false (vitest-dev/vitest#8944) — _getDOM().getDefaultDocument().createElement(tagName) returns something that is not a real HTMLElement, and DOMTestComponentRenderer.insertRootElement crashes:

```
TypeError: rootElement.setAttribute is not a function
at DOMTestComponentRenderer.insertRootElement (@angular/platform-browser/testing)
at _TestBedImpl.createComponent
```

Different spec files fail each run; each failing spec passes in isolation. Classic test-isolation bug.

The analog project had the analogous pattern in setupTestBed() and fixed it in analogjs/analog#2244 by calling resetTestEnvironment() + initTestEnvironment() on every setup invocation instead of guarding with a once-only singleton.

Reproduction

I can put up a public minimal repro if helpful, but the bug is visible from the builder source alone — the conditions are:

  • Angular 22 (or 21 with vitest ≥4.0.5) monorepo using @angular/build:unit-test with jsdom.
  • runnerConfig unset, so the builder's default isolate: false applies.
  • Suite of ~50+ spec files to make the race frequent.
  • Run ng test --force (or equivalent) several times. A different 1–10 specs crash each run with the setAttribute trace.

Confirmed environment:

```
Angular CLI: 22.0.0-next.6
@angular/build: 22.0.0-next.6
@angular/core: 22.0.0-next.9
vitest: 4.1.4 (via ^4.0.17)
Environment: jsdom
Runtime: Node 22 / Bun 1.x
OS: Windows 11 (also reported on Ubuntu CI via analogjs/analog#2222)
```

Exception

```
TypeError: rootElement.setAttribute is not a function
❯ DOMTestComponentRenderer.insertRootElement node_modules/@angular/platform-browser/fesm2022/testing.mjs:24
❯ _TestBedImpl.createComponent packages/core/testing/src/test_bed.ts:420
```

(The #32754 variant Cannot set base providers because it has already been called is the same root cause but a different downstream symptom — it fires when the user's own test-setup.ts re-calls initTestEnvironment. Projects that don't re-call it land on setAttribute is not a function instead.)

Proposed fix

Primary — mirror analogjs/analog#2244. Replace the if (!globalThis[ANGULAR_TESTBED_SETUP]) guard in build-options.ts:73-89 with a reset-and-reinit pattern:

```ts
getTestBed().resetTestEnvironment();
getTestBed().initTestEnvironment([BrowserTestingModule, TestModule], platformBrowserTesting(), {
errorOnUnknownElements: true,
errorOnUnknownProperties: true,
// ...
});
```

Even under isolate: false, if the setup file re-runs (or a user hook calls it), each spec file gets a fresh platform targeting the current jsdom.

Secondary (defensive) — either flip the default to isolate: true with a documented opt-out for projects that want the Karma-style speed, or make DOMTestComponentRenderer.insertRootElement throw a clearer error when rootElement.setAttribute is not callable (e.g. "TestBed's DOM adapter is referencing a document that has been torn down — check your vitest `isolate` setting"). Today the TypeError has no breadcrumb to the root cause.

Docs — the unit-test builder docs should warn that isolate: false + vitest ≥4.0.5 + jsdom silently bleeds DOM state across spec files.

Local workaround

Override to isolate: true via a project-level vitest-base.config.ts (possible because runnerConfig: true merges user config on top of the builder defaults). 10 consecutive ng test --force runs then pass deterministically. Wall-time cost is ~10–30%. This is a workaround, not a fix — the builder's guard is what should change.

References
Vorherrschende Sprache
TypeScript
Sterne
27k
Forks
11.8k
Ø Merge
17 Std. 25 Min.
Gemergte PRs (30 T.)
183

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Mehr aus angular/angular-cli

Alle Issues in angular/angular-cli

Ähnliche Issues

Weitere Issues zu TypeScript

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.