ngUpgraders / ng-forward

The default solution for those that want to write Angular 2.x style code in Angular 1.x
410 stars 36 forks source link

Cannot mock dependencies #167

Open prbaron opened 8 years ago

prbaron commented 8 years ago

Hi,

I would like to test this component :

import {Component, Inject} from "ng-forward";
import {TeleportService} from "../../services/teleport/teleport.service";

@Component({
  selector: "city",
  templateUrl: "app/routes/city/city.html"
})
@Inject("$stateParams", TeleportService)
export class CityRouteComponent {
  details: any[];

  constructor(private $stateParams: ng.ui.IStateParamsService, private teleportService: TeleportService) {}

  ngOnInit() {
    this.teleportService.fetchUrbanAreaDetails(this.$stateParams["slug"])
      .then((result) => this.details = result);
  }
}

here is my spec file :

/// <reference path="../../../../../typings/index.d.ts" />

import {providers} from "ng-forward/cjs/testing/providers";
import {TestComponentBuilder} from "ng-forward/cjs/testing/test-component-builder";
import {Component} from "ng-forward/index";
import {CityRouteComponent} from "../city";
import {TeleportService} from "../../../services/teleport/teleport.service";
declare var sinon: any;

describe("RouteComponent : CityRouteComponent", function () {
  let tcb;
  let fixture;
  let testComponent;
  let testComponentElement;
  let component;
  let componentElement;
  let mockTeleportService;

  beforeEach(angular.mock.module("templates"));
  beforeEach(() => {
    providers(provide => {
      mockTeleportService = {
        fetchUrbanAreaDetails: sinon.stub()
      };

      return [
        provide(TeleportService, {useValue: mockTeleportService}),
      ];
    })
  });

  beforeEach(() => {

    @Component({
      selector: "test-component",
      template: `<city"></city>`,
      directives: [CityRouteComponent]
    })
    class TestComponent {
    }

    tcb = new TestComponentBuilder();
    fixture = tcb.create(TestComponent);
    testComponent = fixture.componentInstance;
    testComponentElement = fixture.nativeElement;
    let childFixture = fixture.debugElement.componentViewChildren[0];
    component = childFixture.componentInstance;
    componentElement = childFixture.nativeElement;
  });

  it("initializes the component", () => {
    console.log(component);
  });
});

When I try to run this spec file, I have the following error and cannot run the tests.

  SyntaxError: Use of reserved word 'let' in strict mode
  at /Users/pierrebaron/Sites/ngForward-poc/src/index.spec.js:3214

When I remove the providers I do not have the errors but component is then null.

I am using Jasmine instead of Chai.

prbaron commented 8 years ago

Any idea why it does not work ?

prbaron commented 8 years ago

Ok so I found out that we need to add the module "ui.router" as dependency

import {Component, Inject} from "ng-forward";
import {TeleportService} from "../../services/teleport/teleport.service";

@Component({
  selector: "city",
  templateUrl: "app/routes/city/city.html",
  providers: ["ui.router", TeleportService]
})
@Inject("$stateParams", TeleportService)
export class CityRouteComponent {
  details: any[];

  constructor(private $stateParams: ng.ui.IStateParamsService, private teleportService: TeleportService) {}

  ngOnInit() {
    this.teleportService.fetchUrbanAreaDetails(this.$stateParams["slug"])
      .then((result) => this.details = result);
  }
}
prbaron commented 8 years ago

I found another problem now, using inject and providers in the same test suite does not work. How can I solve this ?

/// <reference path="../../../../../typings/index.d.ts" />

import {TestComponentBuilder, providers} from "ng-forward/cjs/testing";
import {Component} from "ng-forward";
import {CityRouteComponent} from "../city";
import {TeleportService} from "../../../services/teleport/teleport.service";
import IAugmentedJQuery = angular.IAugmentedJQuery;
declare var sinon: any;

describe("Component : CityRowComponent", function () {
  let $q;
  let $stateParams;
  let tcb;
  let fixture;
  let testComponent;
  let testComponentElement: IAugmentedJQuery;
  let component: CityRouteComponent;
  let componentElement: IAugmentedJQuery;

  beforeEach(angular.mock.module("templates"));
  beforeEach(inject((_$q_) => {
    $q = _$q_;
  }));
  beforeEach(() => {
    providers((provide) => {
      let mockTeleportService = {
        fetchUrbanAreaDetails: $q.when({key: "London"})
      };

      let mockStateParams = {
        slug: "london"
      };

      return [
        provide(TeleportService, {useValue: mockTeleportService}),
        provide("$stateParams", {useValue: mockStateParams})
      ];
    });
  });
  beforeEach(() => {

    @Component({
      selector: "test-component",
      template: `<city></city>`,
      directives: [CityRouteComponent]
    })
    class TestComponent {
    }

    tcb = new TestComponentBuilder();
    fixture = tcb.create(TestComponent);
    testComponent = fixture.componentInstance;
    testComponentElement = fixture.nativeElement;
    let childFixture = fixture.debugElement.componentViewChildren[0];
    component = childFixture.componentInstance;
    componentElement = childFixture.nativeElement;
  });

  it("renders the component", () => {
    console.log(testComponent);  // returns undefined
    console.log(testComponentElement); // returns undefined
    console.log(component); // returns undefined
    console.log(componentElement); // returns undefined

    expect(component.details).toEqual({key: "London"});
  });
});