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

how to write tests ? #164

Open prbaron opened 8 years ago

prbaron commented 8 years ago

Hello, the testing documentation is not clear about how to write tests with ngForward. Here is a service I would like to test :

import {Injectable, Inject} from "ng-forward";
import {City} from "../../models/city.model";
import * as _ from "lodash";

@Injectable()
@Inject("$timeout")
export class CityService {
  constructor(private $timeout: ng.ITimeoutService) {}

  getCities(): ng.IPromise<City[]> {
    return this.$timeout(() => {
      let array = JSON.parse(localStorage.getItem("cities")) || [];
      return _.map(array, (city: any) => new City(city.name, city.geonameId));
    }, 0);
  }

  saveCities(cities: City[]) {
    localStorage.setItem("cities", JSON.stringify(cities));
  }
}

for the spec file, I was thinking about something like that skeleton:

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

import {CityService} from "../city.service";

describe("CityService", () => {
  let cityService: CityService;

  beforeEach(() => {
   // how do I load the dependencies here ?
   cityService = new CityService()
  });

  it("gets the cities from the localStorage", () => {
    cityService.getCities().then((cities) => expect(cities).toEqual([]));
    //timeout.flush(1001);
  });
});

Is it possible to get more documentation about testing services, pipes, components please ? maybe full example ?

regards

timkindberg commented 8 years ago

You could still use TestComponentBuilder because it has the most features for testing. Basically you'd be bootstrapping a 'testbed' component, just in order to grab your service and make assertions against it.

A general example seen here: https://github.com/ngUpgraders/ng-forward/blob/master/lib/testing/test-component-builder.spec.ts#L230-L330

Here's how you grab a service from the testbed: https://github.com/ngUpgraders/ng-forward/blob/master/lib/testing/test-component-builder.spec.ts#L328

prbaron commented 8 years ago

I finally made it without TCB.

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

import {CityService} from "../city.service";
import {City} from "../../../models/city.model";

describe("CityService", () => {
  let $timeout;
  let cityService;

  beforeEach(function () {
    let store = {};

    spyOn(localStorage, "getItem").and.callFake(function (key: any) {
      return store[key];
    });
    spyOn(localStorage, "setItem").and.callFake(function (key: any, value: any) {
      return store[key] = value + "";
    });
    spyOn(localStorage, "clear").and.callFake(function () {
      store = {};
    });
  });

  beforeEach(inject((_$timeout_) => {
    $timeout = _$timeout_;
    cityService = new CityService($timeout);
  }));

  it("get the cities saved in the localStorage", () => {
    localStorage.setItem("cities", JSON.stringify([
      {
        "name": "Paris, Île-de-France, France",
        "geonameId": 2988507,
        "shortName": "paris"
      },
      {
        "name": "London, England, United Kingdom",
        "geonameId": 2643743,
        "shortName": "london"
      }
    ]));

    cityService.getCities().then((cities) => {
      var city = cities[0];
      expect(city).toEqual(jasmine.any(City));
      expect(city.name).toEqual("Paris, Île-de-France, France");
      expect(city.geonameId).toEqual(Number("2988507"));
      expect(city.shortName).toEqual("paris");
    });
    $timeout.flush();
  });

  it("get an empty array if no cities in localStorage", () => {
    localStorage.setItem("cities", JSON.stringify([]));

    cityService.getCities().then((cities) => {
      expect(cities.length).toEqual(0);
    });
    $timeout.flush();
  });

  it("save the array of cities", () => {
    cityService.saveCities([
      new City("Paris, Île-de-France, France", 2988507),
      new City("London, England, United Kingdom", 2643743)
    ]);

    let array = JSON.parse(localStorage.getItem("cities")) || [];
    expect(array.length).toEqual(2);

    let cityObj = array[0];
    expect(cityObj.name).toEqual("Paris, Île-de-France, France");
    expect(cityObj.geonameId).toEqual(2988507);
    expect(cityObj.shortName).toEqual("paris");
  });
});

Do you think it is a better solution ?