Use stable scalar keys for Angular `@for` loops with rebuilt object
values across breadcrumbs and related list templates to avoid DOM
recreation warnings.
https://community.openproject.org/wp/DREAM-707
Migrates Angular constructor-based dependency injection to the
`inject()` function. The initial pass used the Angular schematic;
manual follow-up handled abstract classes, inheritance-sensitive
constructors, and call sites that still instantiate services
directly.
Schematic command:
cd frontend && npx ng generate @angular/core:inject-migration \
--path ./ \
--migrate-abstract-classes \
--backwards-compatible-constructors=false \
--non-nullable-optional=false
https://community.openproject.org/wp/74950
Apply Angular's Vitest migration schematic to update frontend and plugin
specs from Jasmine globals to Vitest APIs.
ng g @schematics/angular:refactor-jasmine-vitest
Fix migrated edge cases where async assertions or shallow tests changed.
https://community.openproject.org/wp/66563
- `op-autocompleter`: `jasmine.clock()` does not reliably intercept
RxJS `asyncScheduler` timers created inside other timer callbacks
(due to the component's `ngAfterViewInit` wrapping setup in
`setTimeout(..., 25)`). Converts the 'with debounce' test to
`async/await` with real `setTimeout` waits (100ms each), which
lets the component's internal timer chain complete naturally.
The two 'without debounce' tests are unaffected.
- `attribute-help-text`: replaces `await Promise.resolve()` with
`await new Promise(resolve => setTimeout(resolve, 0))`, which
guarantees the full 4-level Promise chain
(`async getId()` → `.then(show)` → `.finally(cleanup)`) has
settled before assertions run.
- `git-actions.service` (github_integration module): removes the
redundant `waitForAsync` `beforeEach` that was overwritten by a
second plain `beforeEach` anyway.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>