Wave 4: angular-eslint migration, remove protractor e2e, headless unit tests#418
Wave 4: angular-eslint migration, remove protractor e2e, headless unit tests#418tobydrinkall wants to merge 3 commits into
Conversation
…s unit tests Co-Authored-By: Toby Drinkall <toby.drinkall@cognition.ai>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
There was a problem hiding this comment.
🚩 Production build has sourceMap and namedChunks enabled
The production configuration in angular.json:46-47 has "sourceMap": true and "namedChunks": true. These are typically disabled in production builds for performance and bundle size reasons. This is pre-existing (not changed by this PR), but worth noting as it increases the production bundle size and exposes source code.
(Refers to lines 46-47)
Was this helpful? React with 👍 or 👎 to provide feedback.
| "@angular-eslint/no-empty-lifecycle-method": "off", | ||
| "@typescript-eslint/no-empty-function": "off", | ||
| "@typescript-eslint/no-unused-vars": "off", | ||
| "@typescript-eslint/no-explicit-any": "off", | ||
| "@typescript-eslint/no-unsafe-function-type": "off", | ||
| "prefer-const": "off", |
There was a problem hiding this comment.
📝 Info: ESLint config disables several useful lint rules
The new ESLint config disables a broad set of rules: @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-function-type, @typescript-eslint/no-empty-function, and prefer-const (eslint.config.js:37-42). While these are likely disabled to avoid a flood of errors on the existing codebase, they reduce the value of the linter going forward. Consider setting these to "warn" instead of "off" so new violations are surfaced without blocking the build.
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Acknowledged — these are set to off deliberately to keep this wave scoped to tooling migration without mass code edits. Tightening them to warn/error is a good follow-up once the standalone/inject migrations land.
| providedIn: 'root' | ||
| }) | ||
| export class SettingsService { | ||
| export class SettingsService implements OnDestroy { |
There was a problem hiding this comment.
📝 Info: ngOnDestroy on a root-scoped service has minimal practical effect
The PR adds implements OnDestroy to SettingsService (src/app/shared/services/settings.service.ts:8), which is providedIn: 'root'. For root-scoped services, ngOnDestroy is only called when the application's root injector is destroyed (i.e., app shutdown). In a typical single-page app, this means the cleanup code effectively never runs during the app's useful lifetime. The addition is not harmful, but it may create a false sense that the media query listener is being properly managed during the app's lifecycle.
Was this helpful? React with 👍 or 👎 to provide feedback.
Co-Authored-By: Toby Drinkall <toby.drinkall@cognition.ai>
| this.setTheme(theme); | ||
| } | ||
|
|
||
| private boundColorSchemeHandler = this.handleSystemPreferredColorSchemeChange.bind(this); |
There was a problem hiding this comment.
📝 Info: Field initialization order verified safe under useDefineForClassFields: false
The boundColorSchemeHandler field (src/app/shared/services/settings.service.ts:38) is declared textually after the constructor, which raises a question about whether it's initialized before the constructor body calls subscribeToSystemPreferredColorScheme() at line 20. Because tsconfig.json:13 sets useDefineForClassFields: false, TypeScript hoists ALL field initializers to the top of the constructor (before the explicit body). Verified by compiling a test case with the project's own tsc: the emitted JS places this.boundColorSchemeHandler = ... before the constructor body. This would also be safe under useDefineForClassFields: true (TC39 semantics), where all fields are initialized before the constructor body runs. However, the code's readability would benefit from moving the field declaration above the constructor, since this ordering dependency is non-obvious.
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Moved the field declaration above the constructor in bdbb176.
Co-Authored-By: Toby Drinkall <toby.drinkall@cognition.ai>
There was a problem hiding this comment.
📝 Info: Protractor still appears in package-lock.json after e2e removal
The e2e directory, protractor config, and the e2e npm script were all removed, but protractor still appears as a transitive dependency in package-lock.json. This is likely pulled in by @angular-devkit/build-angular which historically depended on it. It's harmless dead weight but could be cleaned up by running npm prune or regenerating the lockfile after confirming no remaining references.
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Checked: the only protractor references in package-lock.json are inside @angular-devkit/build-angular's optional peerDependencies declaration — protractor is not actually installed as a package (no node_modules/protractor entry). Nothing to prune.
Summary
Wave 4 of the Angular 9→20 upgrade (test + lint tooling only), based on
devin/1782947720-angular20-core-upgrade(#417).eslint.config.jsviang add @angular-eslint/schematics, deletedtslint.json, replaced thelintarchitect target with@angular-eslint/builder:lintoversrc/**/*.{ts,html}. Rules requiring codebase-wide migrations are disabled rather than mass-editing code (prefer-standalone,prefer-inject,template/prefer-control-flow, a11y click/focus rules,prefer-const,no-empty-function, etc.). Two small code touches:SettingsService implements OnDestroyand an inline disable for the legacyitemselector.e2e/, thee2earchitect target, and thee2enpm script (protractor is EOL).app.component.spec.ts(creation + settings wiring, usingprovideRouter([])andCUSTOM_ELEMENTS_SCHEMA) andcomment.pipe.spec.ts(discuss / singular / plural).karma.conf.jsunchanged; run headlessly withnpm test -- --watch=false --browsers=ChromeHeadless.Verified locally (Node 22):
npm run lint,npm run build, andnpm test -- --watch=false --browsers=ChromeHeadless(6/6 SUCCESS) all pass. No rxjs or component template/style changes.Link to Devin session: https://app.devin.ai/sessions/781947dcf306489e92d4ada10c3601aa
Requested by: @tobydrinkall
Devin Review