angular component test for events - dart

I have a custom component and try to test for the emitted events
My component looks like this:
#Component(
selector: "my-component",
templateUrl: 'component/my-component.html',
useShadowDom: false,
publishAs: "ctrl"
)
class MyComponent implements ScopeAware {
Scope scope;
String value = "foo"
void onButtonClick(){
scope.emit('on-select', value);
}
}
The component emits a 'on-select' event when a button is clicked. Works like expected but since i'm a huge fan of testing i want to test for that event.
Is this possible in angular 0.14.0?
I write my tests like the tests in angulardart-sample-app
The whole component testing has really a lot of boilerplate and is everything else then fun to write. Are there simpler ways for component testing in 0.14.0 or the future?

Related

use service as decorator

Is there a way to do a static decorator on routes that check certain logics before loading?
example
have a auth decorator
#Injector()
class Auth{
Auth(){
if (isLoggedIn){
proceed();
}else{
showLoginRoute();
}
}
}
and use like
#Auth()
#Component(
selector: 'auth-view',
styleUrls: const ['login_component.css'],
template:
'<router-outlet name="dashboard" [routes]="routes.authView_routes"></router-outlet>',
directives: const [materialDirectives, routerDirectives, coreDirectives],
providers: const [r.Routes, materialProviders, Auth],
)
class Dashboard{
....
}
I know what i want to do but just not sure how to get it done. Currently i am importing services across several components and doing lots of repetition and i want to avoid that as much as possible.
Dart doesn't support anything like decorators in TS.
What might work for you is code generation like it's done in build_value, json_serializable, ...
https://github.com/dart-lang/build

How to fetch data before navigating in AngularDart?

I want to fetch all data from remote service at once before routing to Profile.
I find typescript version angular have Resolve to help to fetch data before navigating. But I cannot find any example in Dart version ( angular2: ^3.0.0).
#RouteConfig(const [
const Route(path: '/', name: 'Home', component: HomeComponent, useAsDefault: true]),
const Route(path: '/profile', name: 'Profile', component: ProfileComponent),])
class AppComponent implements OnInit{
}
Anyone know how to handle it by using Dart?
The current router in Angular.dart doesn't have Resolve.
Depending on what exactly you try to accomplish, there might be different workarounds.
Usually just wrapping the content of the components template with
<template [ngIf]="data != null"> ... </template>
should do, and then assign to data when it's available and the component will be shown.
Another more generic way might be to create a custom MyRouterOutlet that might extend RouterOutlet and customize it so that it delays adding the component until an event was received.
Add to the RouterOutlet
#HostBinding()
dataArrived() {
// call the code that actually adds the component
}
then use it like
<router-outlet fetchDataDirective></router-outlet>
and a directive like
#Directive(selector: '[fetchDataDirective]')
class FetchDataDirective implements OnInit {
final DataService dataService;
FetchDataDirective(this.dataService);
#Output()
get dataArrived => _dataArrived.stream;
final _dataArrived = new StreamController();
ngOnInit() async {
await dataService.fetchData();
}
}
that emits the event the RouterOutlet waits for.
It was also mentioned that a new router for Angular.dart is work in progress (might still take a while though).

Angular2 Inject components into other components

I'm messing around with Angular2 and I'm wanting the ability to inject one component into another based on the bootstrapped bindings.
class HelloComponent {
name: string;
}
#Component({
selector: 'hello'
}
#View({
template: `<h3>Hello {{ name }}</h3>`
})
class HelloBobComponent extends HelloComponent {
constructor() {
this.name = 'Bob';
}
}
#Component({
selector: 'app'
}
#View({
directives: [HelloComponent]
template: `<h1>Welcome to my Angular2 app</h1>
<hello></hello>`
}
class AppComponent {
}
bootstrap(AppComponent, [
bind(HelloComponent).toClass(HelloBobComponent)
]);
Here I'm using HelloComponent as a token that I want Angular2's Injector to resolve HelloBobComponent. I'm doing this so that I can swap components in and out based on the current app configuration. The above example obviously doesn't work. Is this possible using one of the frameworks decorators? I haven't found an answer yet digging though blogs or the source.
edit: To clarify, how do I get the directives property on the View decorator to treat HelloComponent as a di token instead of a type.
This is currently not supported as of alpha37. The compiler resolves directives passed in the View decorator by either type or binding but does not look up from the parent injector.
For example:
#View({
url: '...',
directives: [
Directive1,
bind(Directive2).toClass(Directive2Impl),
]
})
The intention for the "directives" property here was only to prevent selector naming collision. Later bind support was added to aid in testing.
The only solution I can think of without editing the compiler function would be to maintain an external Injector and resolve types on component declaration.

Wait for dom ready without useShadowDom

I want to wait until my component is fully loaded. The current approach would be to implement the ShadowRootAware interface. However this does not work, if the component disables the use of shadow dom:
#Component(
selector: 'travel-step',
templateUrl: 'packages/TravelPlanner/travelstep/travel_step_component.html',
useShadowDom: false,
publishAs: 'cmp')
class TravelStepComponent extends AttachAware{
I need to disable the usage of ShadowDom, because I want to use styles from my parent object (e.g. Bootstrap). Is there another way to wait for the dom to be ready?
I want to reference a file upload input. At the moment (angular v.012) there seems to be no other way to upload a file.
You can implement ShadowRootAware interface. For example:
class NgFreeTree implements ShadowRootAware {
void onShadowRoot(ShadowRoot shadowRoot) { ... }
}
It should work regardless of useShadowDom attribute.
It does not give you the error message if you use the following signature:
void onShadowRoot(Node n) {
HtmlElement element = n;
...
}

Do something after attribute value got assigned

I would like to do some mapping after the members have been set by angular dart:
#Component(
selector: 'travel-step',
templateUrl: 'packages/TravelPlanner/travelstep/travel_step_component.html',
useShadowDom: false,
publishAs: 'cmp')
class TravelStepComponent {
// Deprecated but impossible to replace, since the new syntax is not ready
#NgTwoWay('step')
TravelStep step;
TravelStepComponent() {
// step is null at the moment
}
}
I'm using angular v. 0.12. When the constructor is called, step is still null.
I could do it with a watch expression but I only want to do it once, so this workaround is not how I want to do it.
You can implement AttachAware and put your code into the attach() method.
Similar behavior can be achieved by implementing ShadowRootAware and onShadowRoot().
You need to give Angular some time to evaluate the bindings and assign the values. Use one of these methods according to your requirements.
Sometimes it might help to (additionally) wrap your code into a
new Future(() {
your code here
});
to delay the execution of your code.
Another approach is to implement a setter and execute your logic there
#NgTwoWay('step')
TravelStep _step;
TravelStep get step => _step;
set step(TravelStep s) {
// your code here
_step = s;
// or here
}

Resources