diff --git a/packages/@ember/routing/router-service.ts b/packages/@ember/routing/router-service.ts index f99166ae6b7..936e7539d1c 100644 --- a/packages/@ember/routing/router-service.ts +++ b/packages/@ember/routing/router-service.ts @@ -311,6 +311,7 @@ class RouterService extends Service.extend(Evented) { */ isActive(...args: RouteArgs) { let { routeName, models, queryParams } = extractRouteArgs(args); + this._router.setupRouter(); let routerMicrolib = this._router._routerMicrolib; // When using isActive() in a getter, we want to entagle with the auto-tracking system diff --git a/packages/ember/tests/routing/router_service_test/isActive_test.js b/packages/ember/tests/routing/router_service_test/isActive_test.js index 4a4f45ad4d7..f06f5db7bdd 100644 --- a/packages/ember/tests/routing/router_service_test/isActive_test.js +++ b/packages/ember/tests/routing/router_service_test/isActive_test.js @@ -1,4 +1,5 @@ import Controller from '@ember/controller'; +import { Component } from '@ember/-internals/glimmer'; import { RouterTestCase, moduleFor } from 'internal-test-helpers'; import Service, { service } from '@ember/service'; @@ -168,5 +169,42 @@ moduleFor( assert.deepEqual(qp.queryParams, { sort: 'ascending' }); }); } + + ['@test RouterService#isActive works reliably during component rendering before router initialization'](assert) { + assert.expect(1); + + // This simulates the scenario where isActive is called during component rendering + // before the router has been fully set up, which used to throw an error + + let componentInstance; + + this.addTemplate('parent.index', '{{foo-component}}'); + + this.addComponent('foo-component', { + ComponentClass: class extends Component { + @service('router') + routerService; + + init() { + super.init(); + componentInstance = this; + } + + get isRouteActive() { + // This used to throw "Cannot read properties of undefined (reading 'isActiveIntent')" + // before setupRouter() was added to the isActive method + return this.routerService.isActive('parent.child'); + } + }, + template: `{{this.isRouteActive}}`, + }); + + return this.visit('/').then(() => { + // The test passes if no error is thrown during rendering + // and isActive returns a boolean value + assert.strictEqual(typeof componentInstance.isRouteActive, 'boolean', + 'isActive should return a boolean value without throwing an error'); + }); + } } );