Как я могу протестировать routerLinkActive в автономном компоненте?

Если у меня есть неавтономный компонент следующим образом:

      import { ChangeDetectionStrategy, Component } from '@angular/core';

@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
  selector: 'sb-index',
  template: `
    <a [routerLink]="['routeA']" [routerLinkActive]="'active'">A</a>
    <a [routerLink]="['routeB']" [routerLinkActive]="'active'">B</a>
  `
})
export class IndexComponent {
}

Я могу протестировать следующую спецификацию, как показано в вопросе SO :

      import { Component, NgZone } from '@angular/core';
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { Router, RouterLinkActive } from '@angular/router';
import { IndexComponent } from './index.component';
import { RouterTestingModule } from '@angular/router/testing';

@Component({
  selector: 'sb-stub'
})
class StubComponent {}

describe('IndexComponent', () => {
  let fixture: ComponentFixture<IndexComponent>;
  let component: IndexComponent;

  beforeEach(() => {
    TestBed
      .configureTestingModule({
        declarations: [
          IndexComponent,
          StubComponent
        ],
        imports: [
          RouterTestingModule.withRoutes([
            { path: 'routeA', component: StubComponent },
            { path: 'routeB', component: StubComponent }
          ])
        ]
      })
      .compileComponents();

    fixture = TestBed.createComponent(IndexComponent);
    component = fixture.componentInstance;
  });

  it('should show "A" route as active', fakeAsync(() => {
    fixture.detectChanges();

    TestBed.inject(NgZone).run(() => {
      TestBed.inject(Router).navigate(['routeA']);
      tick();
      fixture.detectChanges();

      fixture.debugElement
              .queryAll(By.directive(RouterLinkActive))
              .map(debugElement => debugElement.nativeElement as HTMLAnchorElement)
              .forEach(nativeElement => {
                if (nativeElement.textContent === 'A') {
                  expect(nativeElement.classList.contains('active')).toBeTrue();
                } else {
                  expect(nativeElement.classList.contains('active')).toBeFalse();
                }
              });
    });
  }));
});

Я не могу понять, как настроить те же тесты, если я изменюIndexComponentбыть отдельным компонентом следующим образом:

      import { ChangeDetectionStrategy, Component } from '@angular/core';
import { RouterLink, RouterLinkActive, RouterModule, RouterOutlet } from '@angular/router';

@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
  selector: 'sb-index',
  standalone: true,
  template: `
    <a [routerLink]="['routeA']" [routerLinkActive]="'active'">A</a>
    <a [routerLink]="['routeB']" [routerLinkActive]="'active'">B</a>
  `,
  imports: [ RouterLink, RouterLinkActive, RouterOutlet ]
})
export class IndexComponent {
}

Я пробовал несколько разных вещей, в основном сосредоточившись на аспектах инъекции и области видимости, поскольку я предполагаю, что это изменилось следующим образом:

      import { Component, EnvironmentInjector, NgZone } from '@angular/core';
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { provideRouter, Router, RouterLinkActive, RouterOutlet } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { RouterLinkDirectiveStub } from '@sb/testing';
import { IndexComponent } from './index.component';

@Component({
  standalone: true,
  selector: 'sb-stub'
})
class StubComponent {}

describe('IndexComponent', () => {
  let fixture: ComponentFixture<IndexComponent>;
  let component: IndexComponent;

  beforeEach(() => {
    TestBed
      .configureTestingModule({
        imports: [
          IndexComponent,
          StubComponent
        ],
        providers: [
          provideRouter([
            { path: 'routeA', component: StubComponent },
            { path: 'routeB', component: StubComponent }
          ])
        ]
      })
      .overrideComponent(
        IndexComponent,
        {
          set: {
            imports: [ RouterOutlet, RouterLinkActive, RouterLinkDirectiveStub ]
          }
        }
      )
      .compileComponents();

    fixture = TestBed.createComponent(IndexComponent);
    component = fixture.componentInstance;
  });

  it('should show "A" route as active', fakeAsync(() => {
    fixture.detectChanges();

    fixture.ngZone?.run(() => {
      fixture.componentRef.injector.get(Router).navigate(['routeA']);
    // TestBed.inject(NgZone).run(() => {
      // TestBed.inject(EnvironmentInjector).get(NgZone).run(() => {
        // TestBed.inject(Router).navigate(['routeA']);
        // TestBed.inject(EnvironmentInjector).get(Router).navigate(['routeA']);
        // TestBed.platform.injector.get(Router).navigate(['routeA']);

      tick();
      fixture.detectChanges();

      fixture.debugElement
              .queryAll(By.directive(RouterLinkActive))
              .map(debugElement => debugElement.nativeElement as HTMLAnchorElement)
              .forEach(nativeElement => {
                if (nativeElement.textContent === 'A') {
                  expect(nativeElement.classList.contains('active')).toBeTrue();
                } else {
                  expect(nativeElement.classList.contains('active')).toBeFalse();
                }
              });
    });
  }));
});

Почти все они дают мне сообщение: IndexComponent должен показывать маршрут «A» как активный. FAILED Ожидается, что false будет истинным.

С помощью отладки я вижу, что тесты находят элементы сRouterLinkActiveдиректива, но маршрутизация, которая выполняется в начале тестового метода, похоже, не влияет на routerLinkActive, поэтому ни один из элементов не получает класс «активный».

Есть ли способ протестировать routerLinkActiveэлементы внутри автономного компонента?

0 ответов

Другие вопросы по тегам