Open Hotell opened 8 years ago
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 :cry:. Here's all of the testing APIs: https://angular.io/docs/ts/latest/api/#!?apiFilter=testing
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 ;)
Good to know :smiley: . And the docs link is the one in this issue to the Angular Docs.
oh thanks for pointing that out, updated!
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
Good call. Overall, I'm glad to see the API not being so tightly bound to jasmine.
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.
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>;
}
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.
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 ng-metadata@3.beta-0 is released which should be today or tomorrow ( which will include NgModule support and so it will be aligned with ng2 stable )
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.
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 😄
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 UserService
be injected?
@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
});
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.
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()
}));
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