1/25/17

Creating My First Type Definition

Typescript Main Point

One of reasons the typescript was invented is to get javascript errors to be detected in compilation step.
For example:
If you defined function myFunc and it suppose to be called without any params, and your code use its call in multipple places:


function myFunc() {
  alert('my name is Shlomo');
}
//call
myFunc()

And after some time you decided to change function code to use the parameter:

function myFunc(nm) {
  alert('my name is ' + nm);
}
//call
myFunc('Shlomo')

In case you using javascript and you forgot to change call in some place to its new shape - you will got 'nm is undefined' error when code will try to run following call.

//call
myFunc()

in typescript After you changed myFunc definition to use parameter:

myFunc(nm:string) {
  alert('my name is ' + nm);
}
//call
myFunc()//this will not compile

If there are some calls which not using parameter left- Typescript compiler will fail.

What are type definitions?

So if you use typescript and want to use some javascript library or plugin in your code - this plugin and its methods need to be defined in a way that typescript will "recognize" it.

Experiment With Selectize

For example purposes lets take our old angular-seed project which uses typescript. To demonstrate what happen when you try to use some javascript plugin inside typescript project lets install selectize.js jquery plugin

bower install selectize --save-dev

And place the call to the plugin inside View2Ctrl controller:
As you can see - trying to use the plugin as it is made vscode angry
You can see also compilation error:

Create Starter Definition File

As we can see in other definitions - the selective definition must be hosted inside node_modules/@types directory. lets add selectize directory and add index.d.ts file inside it. I will not write here about create real definition - since guys much wiser than me already created it here,
My purpose now is only to create something that make the typescript compiler calm.


/// <reference types="jquery"/>

declare namespace Selectize {
 
}
interface JQuery {
    selectize(options?: any): JQuery;
}


As you can see - i only added selectize method to Jquery interface
That is enough for get the source compiled -

Thanks For reading

1/18/17

Unit Tests In Angular2 - part 3 (Component That Uses Service)

In previous post we've learned how to test the angular2 component.
That was very nice and we have a lot of fun, but everybody knows that in real life many components may use services to bring data from server.
Lets demonstrate it on our user component:
Lets make it to display friends list of this user:



@Component({
  selector: 'my-app',
  template: `<span>name: <strong>Victor Savkin</strong></span>
   <hr/>
   <strong>Friends:</strong>
   <ul>
     <li *ngFor="let friend of friends">
       {{friend}}
     </li>
   </ul>`
})
export class App {
   
    public friends:string[]=[]
    constructor(private usersService:UsersService) {
    }
    ngOnInit(): void {
       this.usersService.getUsers().subscribe(
         users => {
           this.friends=users;
         },
         error=>console.log(error) 
       );
    }
}


And the code of UsersSerivice:

import {Injectable} from '@angular/core';
import {Http} from '@angular/http';
import 'rxjs/add/operator/map';

@Injectable()
export class UsersService {
  constructor(private http:Http) { }
  
  getUsers(){
    return this.http.get('api/users.json')
      .map(response => response.json());
  }
}


So How To Test This Thing?

Lets say we want to test that request populates the "friends" section with friends names.
Since it is bad practice to make real http request for testing purposes - we need to create a mock of UsersService:


import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
  
  class MockUsersService {
    public get() {return  Observable.of(['John', 'Steve']);}
  }

Once we have the mock of UsersService -lets inject it into the module instead of usersService:

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [UserComponent], 
      providers:[// <--HERE IS THE MAGIC!!!
       { provide: UsersService, useClass: MockUsersService}
      ],
      imports: [ HttpModule,BrowserModule ]
    })
    .compileComponents();
  }));

Great, inst it?
Now we can test the component and see if friends are displayed as planned:

  beforeEach(() => {
    fixture = TestBed.createComponent(UserComponent);
    comp = fixture.componentInstance;
    comp.user = new UserModel('Vasia','Kozlov')
    de = fixture.debugElement.query(By.css('span'));
    element = fixture.nativeElement;// to access DOM element
  });

  it('should have list of friends displayed inside UL',  async(() => {
    fixture.detectChanges();
    fixture.whenStable().then(() => { 
      expect(element.querySelector('li:first-child').innerText).toBe('John');
      expect(element.querySelector('li:last-child').innerText).toBe('Steve');
    })
  }));

you can see the full code on this plunker

1/10/17

Unit Tests In Angular2 - part 2 (The Component)

Testing The Component

In previous post we've learned how to test the model (Simple javascript object) and the Service in angular2. Now I think' we ready for next step:

How To Test The Component

Lets say we have a User Component which should display the full name of some user:
(user-component.ts):


import { Component,  Input} from '@angular/core';
import {UserModel} from './user-model'
@Component({
    selector: 'user-component',
    template:   `{{ user.fullname() }}`
})
export class UserComponent {
    @Input() user:UserModel;
}

This component contains @input annotation - which means the parameter from outside (named user) should be set

The Test

As in case of Service we should start with setup the module with testBed util:
(user-component.spec.ts):



import {UserComponent} from './user-component'
import {UserModel} from './user-model'
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By }           from '@angular/platform-browser';
import { DebugElement } from '@angular/core';

describe('UserComponent tests', function () {
  let de: DebugElement;
  let comp: UserComponent;
  let fixture: ComponentFixture;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [  UserComponent ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(UserComponent);
    comp = fixture.componentInstance;
    comp.user = new UserModel('Vasia','Kozlov')// <--here we passing the outer parameter
    de = fixture.debugElement.query(By.css('span'));
  });

  it('should create component', () => expect(comp).toBeDefined() );

  it('should have fullname of user displayed inside "span" tag', () => {
    fixture.detectChanges();
    const h1 = de.nativeElement;
    expect(h1.innerText).toMatch(/Vasia Kozlov/i,
      ' should state user Full Name');
  });
});

As you can see - the outer parameter passed using fixture.componentInstance helper
You can view the running code on the plunker

1/5/17

Unit Tests In Angular2 - part 1 (Get Started)

Get Started

Here is link to amazing tutorial for someone who wanted to learn from real angular developers...
Angular 2 has it's way for writing unit tests, it is pretty resembles the angular1. The same jasmine, only in typescript

Example of Testing Person Model

Lets start with models since they are usual javascript objects:
(person-model.ts):


export class PersonModel {

    constructor(
        public firstname: string = '',
        public lastname: string = ''
    ) {};

}

So here how the tests should look:
(person-model.spec.ts):

import {PersonModel} from './person-model';

describe('PersonModel', () => {

  it('should return the correct properties', () => {

      var person = new PersonModel();
      person.firstname = 'Shlomo';
      person.lastname = 'The King';

      expect(person.firstname).toBe('Shlomo');
      expect(person.lastname).toBe('The King');

  });

});

Nothing complicate here...

Testing Angular2 Service

Next step I want to show how to test some service.
Services are usually built for send http requests and bring data:


import {Injectable} from '@angular/core';
import {Http} from '@angular/http';
import 'rxjs/add/operator/map';

@Injectable()
export class UsersService {
  constructor(private http:Http) { }
  
  get(){
    return this.http.get('api/users.json')
      .map(response => response.json());
  }
}

The Users service has only one method - get
So, this is how the tests should look:
users.service.spec.ts

import {inject, TestBed, async} from '@angular/core/testing';
import {HttpModule} from '@angular/http';

import {UsersService} from './users.service'
describe('Service: UsersService', () => {
  let service;
  
  //setup
  beforeEach(() => TestBed.configureTestingModule({
    imports: [ HttpModule ],
    providers: [ UsersService ]
  }));
  
  beforeEach(inject([UsersService], s => {
    service = s;
  }));
  
  //specs
  it('should return available users (async)', async(() => {
    service.get().subscribe(x => { 
      expect(x).toContain('sasha');
      expect(x).toContain('vasia');
      expect(x).toContain('pasha');
      expect(x.length).toEqual(3);
    });
  }));
  

}) 

Note that I'm using TestBed utility to initiate ngModel and the service with injected Http.
here is working plunker

Getting started with docker

It is very simple to get started usig docker. All you need to do-is download the docker desktop for your system Once you get docker syste...