【问题标题】:Testing routerLink directive in Angular 2在 Angular 2 中测试 routerLink 指令
【发布时间】:2016-05-05 17:32:56
【问题描述】:

我正在尝试测试路由的工作。我将导航栏移动到一个单独的组件 - MdNavbar。那里基本上只有 html 和 css,RouteConfig 在其他组件中,MdNavbar 在那里注入。我想在单击链接时测试该路线的变化。在测试中,我正在寻找 Profile 链接并单击它。我预计路线会改变。这是我的测试代码 -

import {it, inject,async, describe, beforeEachProviders, tick,  fakeAsync} from '@angular/core/testing';

import {TestComponentBuilder} from '@angular/compiler/testing';
import {Component, provide} from '@angular/core';

import {RouteRegistry, Router, ROUTER_PRIMARY_COMPONENT,  ROUTER_DIRECTIVES,RouteConfig} from '@angular/router-deprecated';    
import {Location, LocationStrategy, PathLocationStrategy} from '@angular/common';

import {RootRouter} from '@angular/router-deprecated/src/router';
import {SpyLocation} from '@angular/common/testing';

import {IndexComponent} from '../../home/dashboard/index/index.component';
import {ProfileComponent} from '../../home/dashboard/profile/profile.component';

// Load the implementations that should be tested
import {MdNavbar} from './md-navbar.component';    

describe('md-navbar component', () => {
  // provide our implementations or mocks to the dependency injector
  beforeEachProviders(() => [
    RouteRegistry,
    provide(Location, { useClass: SpyLocation }),
    { provide: LocationStrategy, useClass: PathLocationStrategy },
    provide(Router, { useClass: RootRouter }),
    provide(ROUTER_PRIMARY_COMPONENT, { useValue: TestComponent }),
  ]);

  // Create a test component to test directives
  @Component({
    template: '',
    directives: [ MdNavbar, ROUTER_DIRECTIVES ]
  })
  @RouteConfig([
    { path: '/', name: 'Index', component: IndexComponent, useAsDefault: true },
    { path: '/profile', name: 'Profile', component: ProfileComponent },
  ])
  class TestComponent {}

   it('should be able navigate to profile',
      async(inject([TestComponentBuilder, Router, Location],
        (tcb: TestComponentBuilder, router: Router, location: Location) => {
      return tcb.overrideTemplate(TestComponent, '<md-navbar></md-navbar>')
        .createAsync(TestComponent).then((fixture: any) => {
          fixture.detectChanges();

          let links = fixture.nativeElement.querySelectorAll('a');
          links[8].click()
          expect(location.path()).toBe('/profile');


        //   router.navigateByUrl('/profile').then(() => {
        //     expect(location.path()).toBe('/profile');
        //   })
      })
  })));

测试运行结果如下 -

Expected '' to be '/profile'.

还有第二个——

谁能给我一个提示,我到底做错了什么?

这里是部分导航栏组件模板 -

<nav class="navigation mdl-navigation mdl-color--grey-830">
<a [routerLink]="['./Index']" class="mdl-navigation__link" href=""><i class="material-icons" role="presentation">home</i>Home</a>
<a [routerLink]="['./Profile']" class="mdl-navigation__link" href=""><i class="material-icons" role="presentation">settings</i>My Profile</a>
</nav>

添加: 感谢 Günter Zöchbauer 的回答,我设法为我找到了一个可行的解决方案。

   it('should be able navigate to profile',
      async(inject([TestComponentBuilder, Router, Location],
        (tcb: TestComponentBuilder, router: Router, location: Location) => {
      return tcb.overrideTemplate(TestComponent, '<md-navbar></md-navbar>')
        .createAsync(TestComponent).then((fixture: any) => {
          fixture.detectChanges();

          let links = fixture.nativeElement.querySelectorAll('a');
          links[8].click();
          fixture.detectChanges();

          setTimeout(() {
            expect(location.path()).toBe('/profile');
          });
      })
  })));

【问题讨论】:

    标签: html typescript angular angular2-routing angular2-testing


    【解决方案1】:

    点击事件是异步处理的。您需要延迟检查更改的路径。

       it('should be able navigate to profile',
          inject([TestComponentBuilder, AsyncTestCompleter, Router, Location],
            (tcb: TestComponentBuilder, async:AsyncTestCompleter, router: Router, location: Location) => {
          return tcb.overrideTemplate(TestComponent, '<md-navbar></md-navbar>')
            .createAsync(TestComponent).then((fixture: any) => {
              fixture.detectChanges();
    
              let links = fixture.nativeElement.querySelectorAll('a');
              links[8].click()
              setTimeout(() {
                expect(location.path()).toBe('/profile');
                async.done();
              });
    
    
            //   router.navigateByUrl('/profile').then(() => {
            //     expect(location.path()).toBe('/profile');
            //   })
          })
      })));
    

    或

       it('should be able navigate to profile',
          async(inject([TestComponentBuilder, Router, Location],
            (tcb: TestComponentBuilder, router: Router, location: Location) => {
          return tcb.overrideTemplate(TestComponent, '<md-navbar></md-navbar>')
            .createAsync(TestComponent).then((fixture: any) => {
              fixture.detectChanges();
    
              let links = fixture.nativeElement.querySelectorAll('a');
              links[8].click()
              return new Promise((resolve, reject) => {
                expect(location.path()).toBe('/profile');
                resolve();
              });
    
    
            //   router.navigateByUrl('/profile').then(() => {
            //     expect(location.path()).toBe('/profile');
            //   })
          })
      })));
    

    我自己没有使用 TypeScript,因此语法可能不正确。

    【讨论】:

    • 非常感谢您的帮助。尽管这两种解决方案都对我不起作用(很确定,因为我缺乏理解),但是当我稍微调整一下你的第一个解决方案时,它就成功了。
    • 很高兴听到你可以让它工作。正如我所指的那样,我自己并没有使用 TS,它最近改变了很多异步测试如何指示它们已完成。我刚刚浏览了 Angular GitHub 存储库中的一些测试,以检查它们是如何做到的。基本思想是 click 事件处理程序异步执行 - 但无论如何你已经得到了。
    猜你喜欢
    • 2017-01-27
    • 1970-01-01
    • 2019-12-24
    • 1970-01-01
    • 2017-12-30
    • 1970-01-01
    • 1970-01-01
    • 2013-10-18
    • 1970-01-01
    相关资源
    最近更新 更多