Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

backport angular 2 unit testing capabilities #93

Open
Hotell opened this issue Jun 2, 2016 · 15 comments
Open

backport angular 2 unit testing capabilities #93

Hotell opened this issue Jun 2, 2016 · 15 comments

Comments

@Hotell
Copy link
Member

Hotell commented Jun 2, 2016

  • app logic migration is number 1 priority, what about testing?

currently we provide renderFactory which leverages angular 1 testing patterns.

We need to do better and support https://angular.io/docs/ts/latest/api/#!?apiFilter=core%2Ftesting

@Hotell Hotell added this to the 2.0 milestone Jun 11, 2016
@Hotell Hotell modified the milestones: 2.1, 2.0 Jun 26, 2016
@aciccarello
Copy link
Collaborator

Do you have a list of the specific testing APIs you'd like to implement? The inject and beforeEachProviders functions looks like good ones to start with.

Also, your docs link is broken 😢. Here's all of the testing APIs: https://angular.io/docs/ts/latest/api/#!?apiFilter=testing

@Hotell
Copy link
Member Author

Hotell commented Jun 27, 2016

yes, those two are the primary ones I guess. In the meantime you can do something similar with little utility method https://hotell.gitbooks.io/ng-metadata/content/docs/api/testing/function.html see that queryByDirective at the end.

What link is broken? Anyway if you found something broken, file an issue or even better submit a PR. It doesn't hurt ;)

@aciccarello
Copy link
Collaborator

Good to know 😃 . And the docs link is the one in this issue to the Angular Docs.

@Hotell
Copy link
Member Author

Hotell commented Jun 29, 2016

oh thanks for pointing that out, updated!

@Hotell
Copy link
Member Author

Hotell commented Jun 30, 2016

So it looks like I've made a very good decision to move this to 2.1 because ng2 RC.4 was just released with another set of breaking changes https://github.com/angular/angular/blob/master/CHANGELOG.md#200-rc4-2016-06-30

@aciccarello
Copy link
Collaborator

aciccarello commented Jun 30, 2016

Good call. Overall, I'm glad to see the API not being so tightly bound to jasmine.

@aciccarello
Copy link
Collaborator

aciccarello commented Aug 23, 2016

Was thinking about this today. Since RC5 brought more breaking changes to testing, here's what I see as the top testing features to implement.

@angular/core/testing

Some of the methods of TestBed refer to the RC5 modules but the implementation could be routed to angular.mock.module and be updated when #126 is implemented. There are a lot of methods/properties but we'd only need the main ones.

interface TestBed {
  configureTestingModule: (moduleDef: { providers?: any[]; declarations?: any[]; imports?: any[]; }) => void;
  createComponent: (component: T) => ComponentFixture;
  get: (token: T) => T;
}

Here's the ng-metadata interface I imagine for ComponentFixture. I may be missing some ways that the ChangeDetectionStrategy feature could be used to add additional functionality (see commented out methods from ng2).

interface ComponentFixture {
  componentInstance : T;
  nativeElement : HTMLElement; // root DOM element from elementRef
  elementRef : angular.IAugmentedJQuery;
  // debugElement : DebugElement
  // componentRef : ComponentRef<T>;
  $scope: angular.IScope; // instead of ngZone
  detectChanges: () => void; // i.e. $scope.$apply()
  destroy: () => void; // i.e. $scope.$destroy()
  // changeDetectorRef : ChangeDetectorRef;
  // checkNoChanges() : void;
  // autoDetectChanges(autoDetect?: boolean);
  // isStable() : boolean;
  // whenStable() : Promise<any>;
}

@aciccarello
Copy link
Collaborator

I've implemented a POC for this. I setup a separate project b/c it uses angular-mocks as a dependency. I'm not sure how it could be integrated. Are there plans to move to multiple scoped packages like ng2? I don't think it's really necessary but it would allow having different dependencies for the testing module.

https://github.com/aciccarello/ng-metadata-testing

@Hotell Hotell added the 3.x label Sep 19, 2016
@Hotell
Copy link
Member Author

Hotell commented Sep 19, 2016

Hey @aciccarello. I took look at your code. Looks good so far.

I'm not very keen to create separate scoped packages like ng2 does(or more simplified, don't have time for that :D), just namespaced modules should be sufficient. Anyway it doesn't make much sense for ng1 IMHO.

We can leverage your work when first [email protected] is released which should be today or tomorrow ( which will include NgModule support and so it will be aligned with ng2 stable )

@aciccarello
Copy link
Collaborator

Thanks for taking the time to take a look at it. That all makes sense. I'll work on integrating NgModule support. This is my first major OS contribution so I apologize if I make more work for you. Feel free to correct me if necessary.

@JamesHenry
Copy link
Member

JamesHenry commented Sep 19, 2016

Yeah, thanks @aciccarello! I would say it is definitely fair to assume that all Angular 1 projects have angular-mocks as a peerDependency already. If they don't, they have bigger problems than ng-metadata utilities not working 😄

@michaelkrog
Copy link

michaelkrog commented Oct 6, 2016

This may be a dumb question, but it is still not clear to me how I can create a test that injects one of my own typescript classes?

Take the example from https://hotell.gitbooks.io/ng-metadata/content/docs/recipes/service.html in which the UserComponent uses the @Injectable UserService.

// user.service.ts
import { Inject, Injectable } from 'ng-metadata/core';

@Injectable()
export class UserService{

  hobbies: string[] = [];

  constructor( @Inject('$http') private $http: ng.IHttpService ){}

  addHobby(name: string){
     this.hobbies.push(name);
  }

  getInfo(){
    return this.$http.get('/foo/bar/info')
      .then((response)=>response.data);
  }

}
// user.component.ts
import { Component } from 'ng-metadata/core';

import { UserService } from './user.service';

@Component({
  selector:'my-user',
  providers: [ UserService ],
  template: `...`
})
export class UserComponent{}

Is it possible to test this scenario?
It is not clear to me from https://hotell.gitbooks.io/ng-metadata/content/docs/api/testing. It shows the possibility of injecting a plain old angular service, but how should UserServicebe injected?

@aciccarello
Copy link
Collaborator

aciccarello commented Oct 6, 2016

@michaelkrog, currently the easiest way to do this is to use the getInjectableName() function to get the dependency injection string and the angular $injector service to get the instance of your service.

In the future you will be able to use angular 2-like apis such as

import { inject } from 'ng-metadata/testing';
import { UserService } from './user.service';

inject([UserService], (userService: UserService) => {
  // Use instance of UserService in test
});

@michaelkrog
Copy link

Ahh ok.. Got it now. I can inject a mocked service like this:

let authenticationServiceString = getInjectableName(AuthenticationService);

  beforeEach( angular.mock.module( TestModule, ($provide) => {
      $provide.value(authenticationServiceString, new MockAuthenticationService());
  }));

That will make my mock available as AuthenticationService in the component I am testing.

@aciccarello
Copy link
Collaborator

Yep, angular.mock.module also accepts an object mapping mocks. Same effect but different option for syntax.

let authenticationServiceString = getInjectableName(AuthenticationService);

  beforeEach( angular.mock.module( TestModule, {
      [authenticationServiceString]: new MockAuthenticationService()
  }));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants