angular2 unit test of nested services - service

Im trying to write some Unit Test for a service like:
export class Service1 {
...
public constructor(service2: Service2, service3: Service3) {}
...
}
where Service2 contains, in turn, Service3:
export class Service2 {
...
public constructor(service3: Service3, stringa: string) {}
...
}
i starting test
in a really awful way, like:
it("check XXX", () => {
let service3: Service3= new Service3();
let service2: service2= new service2(service3, "stringa");
let service1: Service1 = new Service1(service2, service3);
expect(X).toEqual(X);
});
but now, i'm using beforeEachProviders and what happen with this:
beforeEachProviders(() => {
return [
provide(Service2, { useclass: MockService2}),
provide(Service3, { useclass: MockService3}),
provide('stringa', { useValue: "stringa"}),
Service1
];
});
it('check XXX ', inject(
[Service2, Service3], (service2: Service2, service3: Service3) => {
expect(true).toEqual(true);
}));
is:
Failed: No provider for String! (Service2-> String).
Could someboby help me ?
Thanks in Advance.

If you want to inject the string value from dependency injection, you need to use the #Inject decorator:
export class Service2 {
...
public constructor(service3: Service3, #Inject('stringa') stringa: string) {}
...
}
As a matter of fact, injection relies on parameter types by default if you don't use the #Inject decorator.

Related

Flutter Chopper: how to create a client with multiple services?

At the moment I have these codes:
import 'package:chopper/chopper.dart';
part 'first_api.chopper.dart';
#ChopperApi(baseUrl: '')
abstract class FirstApi extends ChopperService {
#Get(path: '/api/v1/mobile/first/')
Future<Response> getFirsts();
static FirstApi create() {
final client = ChopperClient(
baseUrl: 'http://10.0.2.2:8081',
services: [
_$FirstApi(),
],
converter: JsonConverter(),
);
return _$FirstApi(client);
}
}
and
import 'package:chopper/chopper.dart';
part 'second_api.chopper.dart';
#ChopperApi(baseUrl: '')
abstract class SecondApi extends ChopperService {
#Get(path: '/api/v1/mobile/second/')
Future<Response> getSeconds();
static SecondApi create() {
final client = ChopperClient(
baseUrl: 'http://10.0.2.2:8081',
services: [
_$SecondApi(),
],
converter: JsonConverter(),
);
return _$SecondApi(client);
}
}
Then I call it like this:
FirstApi.getInstance().getFirsts();
SecondApi.getInstance().getSeconds();
But I see that it accepts more than one services...
services: [
_$SecondApi(),
],
Can I lower the amount of code somehow? (If not, I will have 5 more classes just like these...)
If it is possible, how and how to use it?
Edit:
it works like this:
You create services, an example:
File: test_api.dart
import 'package:chopper/chopper.dart';
part 'test_api.chopper.dart';
#ChopperApi(baseUrl: '/')
abstract class TestApi extends ChopperService {
#Get(path: '/modified/{modified}')
Future<Response> getData(#Path('modified') String modified);
static TestApi create([ChopperClient? client]) => _$TestApi(client);
}
Create the client:
class CustomChopperClient {
static Future<ChopperClient> createChopperClient() {
final client = ChopperClient(
baseUrl: "http://example.com",
services: [
TestApi.create(),
TestApiTwo.create(),
],
interceptors: [],
converter: JsonConverter(),
);
return client;
}
}
Then you can use the servies like this:
ChopperClient chopperClient = CustomChopperClient.createChopperClient();
TestApi testApi = chopperClient.getService<TestApi>();
TestApiTwo testApiTwo = chopperClient.getService<TestApiTwo>();
// now you can call the getData() that you created in the TestApi service
testApi.getData();

Generate constructor call with build macro

How can I generate a main() (access) method for a Haxe class with a constructor call?
For example
static function main() new App()
function new() {
//....
}
and I want to create this with macro, like this:
import haxe.macro.Context;
import haxe.macro.Expr;
class Build {
macro public static function buildFields():Array<Field> {
var fields:Array<Field> = Context.getBuildFields();
var cls = Context.getLocalClass().get();
var pack = cls.pack.concat([cls.name]);
var name = pack.join(".");
fields.push({
name: "main",
access: [Access.APublic, Access.AStatic],
kind: FieldType.FFun({
expr: macro {
Type.createInstance(Type.resolveClass($v{name}), []);
},
args: [],
ret: null
}),
pos: Context.currentPos()
});
return fields;
}
}
#:build(Build.buildFields())
class App {
function new() {
//....
}
}
This generates the main() method fine, but I'm not sure how to generate new App() instead of resorting to Type.createInstance().
To generate a constructor call like new App(), you can reify a haxe.macro.TypePath as documented here.
var typePath:haxe.macro.TypePath = {
pack: cls.pack,
name: cls.name
}
expr: macro new $typePath(),
Btw, instead of manually constructing fields like that, I would suggest using class reification, which lets you use regular Haxe syntax for declaring fields:
fields = fields.concat((macro class {
public static function main() {
new $typePath();
}
}).fields);

angular2-mdl table component with server side data

I experiment with Angular 2 - Material Design Lite especially with the table component but I can not figure out how would I pass data from server on ajax request. Here is the example provided for table initialisation.
How would I pass data from restAPI to table component?
Here I have a kind of working example. I placed the initial data on my Component Init method where I call the DataService which populates the table. I'm not sure if is the right workaround but at this point I have data in table.
import { Component, ViewChild, ViewContainerRef, OnInit, Pipe, PipeTransform } from '#angular/core';
import { MdDialog, MdDialogConfig, MdIcon } from "#angular/material";
import { AuthenticationService, DialogsService, DataService } from '../../../services/';
import { RouterModule, Routes, Router } from '#angular/router';
import {
IMdlTableModelItem,
MdlDefaultTableModel
} from 'angular2-mdl';
export interface ITableItem extends IMdlTableModelItem {
username: string;
email: string;
role: string;
unitPrice: number;
}
#Component({
selector: 'employees',
templateUrl: 'app/layouts/secure/employees/employees.html',
providers: [DialogsService, MdIcon]
})
export class EmployeesComponent implements OnInit {
public message: string;
public employees: any[];
public result: any;
public showSearchBar: false;
public tableData:[ITableItem];
public selected;
public tableModel = new MdlDefaultTableModel([
{key:'username', name:'Username', sortable:true},
{key:'email', name:'Email', sortable:true},
{key:'role', name:'Role', sortable:true},
{key:'status', name:'Status', sortable:true},
{key:'unitPrice', name:'Test', numeric:true}
]);
constructor(
private dialogsService: DialogsService,
public viewContainerRef: ViewContainerRef,
private _dataService : DataService,
private router: Router
) {
}
openDialog() {
this.dialogsService
.confirm('User Form', 'Are you sure you want to do this?', this.viewContainerRef)
.subscribe(res => this.result = res);
}
toggleSearch() {
console.log(this)
}
ngOnInit() {
var self = this;
this._dataService
.GetAll('employees')
.subscribe( data => {
data = Object.keys(data).map((key)=>{ return data[key]})
this.employees = data;
this.tableData = data;
this.tableModel.addAll(this.tableData);
}, error => console.log(error),
() => function ( data ) {
this.tableData = this.employees;
this.tableModel.addAll(this.tableData);
this.selected = this.tableData.filter( data => data.selected);
},
);
}
generateArray(obj){
return Object.keys(obj).map((key)=>{ return obj[key]});
}
selectionChanged($event){
this.selected = $event.value;
}
}
#fefe made it a little more difficult than it had to be, at least with the current version. The magic of the as keyword can do the heavy lifting.
For example my class setup looks like:
import...
export interface IUnreadMessage extends IMdlTableModelItem {
messageId: number;
subject: string;
from: string;
}
#Component ...
export class ...
private unreadMessagesTable = new MdlDefaultTableModel([
{key: 'messageId', name: 'Message ID'},
{key: 'subject', name: 'Subject'},
{key: 'from', name: 'From'}
]);
Then in my ajax call I have:
...ajax call here).subscribe(value => {
const messages = value as Array<IUnreadMessage>;
this.unreadMessagesTable.addAll(messages);
},
error => {
...error handler here...
});
Make sure your interface is EXACTLY (including case) the same as your returned ajax data and it should hook right up!

Haxe macros, calling static method from generated var setter

I'm adding getter and setters to a variable using haxe macros, now I'm stuck trying to call a static function from within the newly generated setter:
public static function build():Array<Field> {
//.........
// create setter
var setterBody = macro {
$variableRef = v;
// mypackage.MyClass.myFunc(this) <-------- DOES NOT WORK!!
return $variableRef;
};
newFields.push({
pos: Context.currentPos(),
name: "set_" + field.name,
meta: [],
kind: FieldType.FFun({
ret: readType,
params: [],
expr: setterBody,
args: [{
value: null,
type: readType,
opt: false,
name: "v"
}]
}),
doc: "",
access: []
});
In the code above I can't find a way to call MyClass.myFun(this), I don't know how to generate that code for the setter, this refers to the instance of the object where the setter is called.
Thank you very much.
Without a more complete example it's hard to know what went wrong. What I can do is show you code that works:
TiagoLrMacroTest.hx:
#:build( TiagoLrMacro.build() )
class TiagoLrMacroTest {
public static function main() {
var test = new TiagoLrMacroTest();
test.name = "hello";
}
function new() {}
public var name(default,set):String;
}
class MyStaticClass {
public static function staticMethod( a:TiagoLrMacroTest ) {
trace( a.name );
}
}
TiagoLrMacro.hx
import haxe.macro.Expr;
import haxe.macro.Context;
class TiagoLrMacro {
public static function build():Array<Field> {
var fields = Context.getBuildFields();
var setterBody = macro {
name = v;
TiagoLrMacroTest.MyStaticClass.staticMethod( this );
return name;
};
fields.push({
pos: Context.currentPos(),
name: "set_name",
meta: [],
kind: FieldType.FFun({
ret: macro :String,
params: [],
expr: setterBody,
args: [{
value: null,
type: macro :String,
opt: false,
name: "v"
}]
}),
doc: "",
access: []
});
return fields;
}
}
Result (Haxe 3.1.3):
TiagoLrMacroTest.hx:15: hello
The one common gotcha I run into with calling static methods in macros is that imports are not respected, so you have to use full type paths like mypackage.MyClass.myFunc(this), but you are already doing this, so the error must be somewhere else in your code. Happy macro-ing :)

How to exclude property of a collection in JSON rendering in Grails 2.3

I am trying to setup a rest webservice (JSON) this is what I am getting:
{"name":"test","routines":[{"class":"Routine","id":1},{"class":"Routine","id":2}]}
This is what I want to get:
{"name":"test","routines":[{"name": "routine-1"},{"name": "routine-2"}]}
I have these domains:
class Program {
String name;
static hasMany = [routines: Routine]
}
class Routine {
String name
}
I have this controller:
class ProgramController extends RestfulController {
static responseFormats = ['json']
def show(Program program) {
respond program
}
}
I added this in the resources.groovy
programRenderer(JsonRenderer, Program) {
excludes = ['class', 'id']
}
routineRenderer(JsonRenderer, Routine) {
excludes = ['class', 'id']
}
How do I include the name property of Routine in the json response using the show method/action of ProgramController?
The ObjectMarshaller approach is the technically correct way. However, the code is cumbersome to write and it's a maintenance headache syncing the fields of the domain with the marshaller.
In the spirit of being Groovy and keeping things really simple, we've been quite happy just adding a little out() method to each REST domain.
Program.groovy
class Program {
String name
static hasMany = [routines: Routine]
def out() {
return [
name: name,
count: routines?.size(),
routines: routines?.collect { [name: it.name] }
]
}
}
ProgramController.groovy
import grails.converters.JSON
class ProgramController {
def show() {
def resource = Program.read(params.id)
render resource.out() as JSON
}
}
JSON Response
{
name: "test",
count: 2,
routines: [{ name: "routine-1" }, { name: "routine-2" }]
}
The out() method approach makes it easy to customize the response JSON, such as adding count for the number of routines.