1
votes

I am configuring test spec for my component which has routes, also I have defined my spec with dependencies as follows. And the ActivatedRoute has these properties, But I don't see its object/instance being created while debugging my test spec. Also I have referred different methods of mocking ActivatedRoute but nothing is helping me. Please correct me if I am doing anything wrong

class UserInfotypeDetailComponent implements OnInit, OnDestroy {
    constructor(
        private userInfotypeDetailService: UserInfotypeDetailService,
        private appLookupService: AppLookupService,
        private router: Router,
        private activatedRoute: ActivatedRoute
    ) {}

 performAction(event: { action: string; objectKey: string | null }) {
    let extras: any = { relativeTo: this.activatedRoute };
    if (event.objectKey) {
          extras.queryParams = { objectKey: event.objectKey };
    }

    switch (event.action) {
      case "new":
      case "edit":
      case "copy":
      case "view":
        this.router.navigate([event.action], extras);
        break;
      case "delete":
        this.deleteRecord(event.objectKey as string);
    }
  }

}

Here is my Routes:

{
        path: "infotype/:id",
        component: UserInfotypeDetailComponent,
        outlet: "slidein",
        children: [
          {
            path: "new",
            component: UserRecordFormComponent,
            data: { actionId: "A", buttonDesc: "Save" }
          },
          {
            path: "edit",
            component: UserRecordFormComponent,
            data: { actionId: "E", buttonDesc: "Update" }
          },
          {
            path: "copy",
            component: UserRecordFormComponent,
            data: { actionId: "C", buttonDesc: "Save" }
          },
          {
            path: "view",
            component: UserRecordFormComponent,
            data: { actionId: "V", actionDesc: "View" }
          }
        ]
      }

And my test spec is as follows:

beforeEach(async(() => {
        TestBed.configureTestingModule({
            imports: [
              RouterTestingModule.withRoutes([]),
                BrowserAnimationsModule,
                RouterModule
            ],
            declarations: [
                UserInfotypeDetailComponent
            ],
            providers: [
                { provide: ActivatedRoute, useValue: {
                                          outlet: "slidein",
                                          params: of({ 
                                              id: "0009"
                                          })
                                      }
                },
                { provide: AppLookupService, useClass: AppLookupServiceStub },
                { provide: UserInfotypeDetailService, useClass: UserInfotypeDetailServiceStub },
                { provide: Router, useClass: AppRouterStub }
            ],
            schemas: [NO_ERRORS_SCHEMA]
        }).compileComponents();
    }));

    class AppRouterStub {
        navigate() {}
    }

And test case:

it('make expect calls to router navigate', fakeAsync(() => {
      let router = TestBed.get(Router);
      let spy = spyOn(router, 'navigate');

      component.performAction(event);

      let extras: any = { relativeTo: ActivatedRoute };
      if (event.objectKey) {
        extras.queryParams = { objectKey: event.objectKey };
      }
      fixture.detectChanges();

      expect(spy).toHaveBeenCalledWith([event.action], extras);
    }))

The error that it throws is:

"spy navigate to have been called with [ [ 'edit' ], Object({ relativeTo: Function, queryParams: Object({ objectKey: '36353539363A393C3535353E352525252525253E3E3E3E363738363735363E35363536353535' }) }) ] but actual calls were [ [ 'edit' ], Object({ relativeTo: Object({ snapshot: Object({ }), parent: Object({ params: Subject({ _isScalar: false, observers: [ ], closed: false, isStopped: false, hasError: false, thrownError: null }) }), params: Subject({ _isScalar: false, observers: [ ], closed: false, isStopped: false, hasError: false, thrownError: null }), queryParams: Subject({ _isScalar: false, observers: [ ], closed: false, isStopped: false, hasError: false, thrownError: null }), testParams: Object({ id: '0009' }) }), queryParams: Object({ objectKey: '36353539363A393C3535353E352525252525253E3E3E3E363738363735363E35363536353535' }) }) ]."

1

1 Answers

1
votes

It's failing because with

let extras: any = { relativeTo: ActivatedRoute };

you are actually using angular's ActivatedRoute but what you should be using is the useValue which you have defined in providers.

Make activatedRoute public in constructor of the component, so that we can access it

public activatedRoute: ActivatedRoute,
public router : Router

Try:

it('make expect calls to router navigate', fakeAsync(() => {
      spyOn(component.router, 'navigate');

      component.performAction(event);
      // I hope you have defined "event" somewhere in code, because I can't see
      // it anywhere here !

      let extras: any = { relativeTo: component.activatedRoute};
      if (event.objectKey) {
        extras.queryParams = { objectKey: event.objectKey };
      }

      expect(component.router.navigate).toHaveBeenCalledWith([event.action], extras);
    }))