├── .npmignore
├── .gitignore
├── src
├── models
│ ├── employee.ts
│ └── employee.spec.ts
├── main.ts
├── pages
│ ├── app.component.html
│ ├── employee-list.component.html
│ ├── employee-detail.component.html
│ ├── employee-form.component.html
│ └── employee-edit-form.component.html
├── tsconfig.json
├── assets
│ └── stylesheets
│ │ └── style.css
├── services
│ ├── employee-list-service.component.ts
│ ├── employee-detail-service.component.ts
│ ├── employee-delete-service.component.ts
│ ├── employee-edit-form-service.component.ts
│ ├── employee-form-service.component.ts
│ ├── employee-form-service.component.spec.ts
│ ├── employee-delete-service.component.spec.ts
│ ├── employee-list-service.component.spec.ts
│ └── employee-detail-service.component.spec.ts
├── components
│ ├── employee-form.component.ts
│ ├── list.component.ts
│ ├── employee-edit-form.component.ts
│ ├── employee-detail.component.ts
│ ├── employee-form.component.spec.ts
│ ├── employee-edit-form.component.spec.ts
│ ├── employee-detail.component.spec.ts
│ └── list.component.spec.ts
└── app.component.ts
├── typings.json
├── LICENSE
├── index.html
├── package.json
├── README.md
├── karma-test-shim.js
└── karma.conf.js
/.npmignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .idea
3 | coverage
4 | src
5 | typings
6 | typings.json
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .idea
3 | coverage
4 | dist
5 | typings
6 | npm-debug.log
7 | db.json
8 | listing.md
9 |
--------------------------------------------------------------------------------
/src/models/employee.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | export class Employee {
4 | constructor (
5 | public id: number,
6 | public name: string
7 | ) {}
8 | }
9 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import { bootstrap } from 'angular2/platform/browser';
2 | import { AppComponent } from './app.component';
3 | import { ROUTER_PROVIDERS } from 'angular2/router';
4 | import 'rxjs/Rx';
5 |
6 | bootstrap(AppComponent, [ROUTER_PROVIDERS]);
--------------------------------------------------------------------------------
/src/pages/app.component.html:
--------------------------------------------------------------------------------
1 |
EMPLOYEE CRUD APP
2 |
3 | Employee List
4 |
5 |
6 | Add Employee
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/pages/employee-list.component.html:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/typings.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular2-testing",
3 | "dependencies": {},
4 | "devDependencies": {},
5 | "ambientDependencies": {
6 | "es6-shim": "github:DefinitelyTyped/DefinitelyTyped/es6-shim/es6-shim.d.ts#4de74cb527395c13ba20b438c3a7a419ad931f1c",
7 | "jasmine": "github:DefinitelyTyped/DefinitelyTyped/jasmine/jasmine.d.ts#dd638012d63e069f2c99d06ef4dcc9616a943ee4"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES5",
4 | "module": "commonjs",
5 | "moduleResolution": "node",
6 | "emitDecoratorMetadata": true,
7 | "experimentalDecorators": true,
8 | "sourceMap": true,
9 | "removeComments": true,
10 | "declaration": true,
11 | "outDir": "../dist"
12 | },
13 | "exclude": [
14 | "node_modules"
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/src/pages/employee-detail.component.html:
--------------------------------------------------------------------------------
1 | EMPLOYEE DETAIL
2 |
3 |
4 | Name: {{currentEmployee.name}}
5 |
6 |
7 | EDIT
8 |
9 |
13 |
14 |
--------------------------------------------------------------------------------
/src/assets/stylesheets/style.css:
--------------------------------------------------------------------------------
1 | /* Master Styles */
2 | h1 {
3 | color: #369;
4 | font-family: Arial, Helvetica, sans-serif;
5 | font-size: 250%;
6 | }
7 |
8 | h2, h3 {
9 | color: #444;
10 | font-family: Arial, Helvetica, sans-serif;
11 | font-weight: lighter;
12 | }
13 |
14 | body {
15 | margin: 2em;
16 | }
17 |
18 | body, input[text], button {
19 | color: #888;
20 | font-family: Cambria, Georgia;
21 | }
22 |
23 | .headings {
24 | display: inline-block;
25 | margin-right: 10px;
26 | }
--------------------------------------------------------------------------------
/src/models/employee.spec.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import {it, describe, expect} from "angular2/testing";
4 |
5 | import { Employee } from './employee';
6 |
7 | describe('Tests for Employee Model', () => {
8 | let employee;
9 |
10 | beforeEach(function() {
11 | employee = new Employee(1, 'Abhinav Mishra');
12 | });
13 |
14 | it('should have name as assigned',() => {
15 | expect(employee.name).toEqual('Abhinav Mishra');
16 | });
17 |
18 | it('should have id as assigned',() => {
19 | expect(employee.id).toEqual(1);
20 | });
21 | });
--------------------------------------------------------------------------------
/src/pages/employee-form.component.html:
--------------------------------------------------------------------------------
1 |
2 |
Employee Form
3 |
15 |
16 |
--------------------------------------------------------------------------------
/src/pages/employee-edit-form.component.html:
--------------------------------------------------------------------------------
1 |
2 |
Employee Edit Form
3 |
14 |
15 |
--------------------------------------------------------------------------------
/src/services/employee-list-service.component.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import { Injectable } from 'angular2/core';
4 | import {Http, Response } from 'angular2/http';
5 | import { Observable } from 'rxjs/Observable';
6 |
7 | import { Employee } from '../models/employee';
8 |
9 | @Injectable()
10 | export class EmployeeListServiceComponent {
11 | constructor(private http: Http) { }
12 |
13 | private _employeesUrl: string = 'http://localhost:3000/employees';
14 |
15 | getEmployees () {
16 | return this.http.get(this._employeesUrl)
17 | .map(res => res.json())
18 | .catch(this._handleError);
19 | }
20 |
21 | private _handleError (error: Response) {
22 | console.error(error);
23 | return Observable.throw(error.json().error || 'Server error');
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/components/employee-form.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from 'angular2/core';
2 |
3 | import { Employee } from '../models/employee';
4 | import { EmployeeFormServiceComponent } from '../services/employee-form-service.component';
5 |
6 | @Component({
7 | selector: 'employee-form',
8 | templateUrl: 'src/pages/employee-form.component.html',
9 | providers: [EmployeeFormServiceComponent]
10 | })
11 |
12 | export class EmployeeFormComponent {
13 | constructor(
14 | private _employeeService: EmployeeFormServiceComponent
15 | ){}
16 |
17 | public model: Employee = {name: '', id: 1 };
18 | public errorMessage: string;
19 |
20 | newEmployee() {
21 | this._employeeService.addEmployee(this.model.name)
22 | .subscribe(
23 | employee => this.model = employee,
24 | error => this.errorMessage = error
25 | );
26 | window.history.back();
27 | }
28 |
29 | onKey(event: any) {
30 | this.model.name = event.target.value;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/services/employee-detail-service.component.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import { Injectable } from 'angular2/core';
4 | import {Http, Response } from 'angular2/http';
5 | import { Observable } from 'rxjs/Observable';
6 |
7 | import { Employee } from '../models/employee';
8 |
9 | @Injectable()
10 | export class EmployeeDetailServiceComponent {
11 | constructor(private http: Http) { }
12 |
13 | private _employeesUrl: string = 'http://localhost:3000/employees/';
14 |
15 | getEmployee (id: number): Observable {
16 | this._employeesUrl += id;
17 |
18 | return this.http.get(this._employeesUrl)
19 | .map(res => this._log(res))
20 | .catch(this._handleError);
21 | }
22 |
23 | private _handleError (error: Response) {
24 | console.error(error);
25 | return Observable.throw(error.json().error || 'Server error');
26 | }
27 |
28 | private _log(res): Employee {
29 | return res.json();
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/services/employee-delete-service.component.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import { Injectable } from 'angular2/core';
4 | import {Http, Response } from 'angular2/http';
5 | import { Observable } from 'rxjs/Observable';
6 |
7 | import { Employee } from '../models/employee';
8 |
9 | @Injectable()
10 | export class EmployeeDeleteServiceComponent {
11 | public currentEmployee: Employee;
12 | public errorMessage: string;
13 |
14 | constructor(
15 | private http: Http
16 | ) {}
17 |
18 | private _employeesUrl: string = 'http://localhost:3000/employees/';
19 |
20 | deleteEmployee (id: number): Observable {
21 | this._employeesUrl += id;
22 |
23 | return this.http.delete(this._employeesUrl)
24 | .map(res => res.json())
25 | .catch(this._handleError);
26 | }
27 |
28 | private _handleError (error: Response) {
29 | console.error(error);
30 | return Observable.throw(error.json().error || 'Server error');
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/components/list.component.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import { Component, OnInit } from 'angular2/core';
3 | import { ROUTER_DIRECTIVES } from 'angular2/router';
4 |
5 | import { Employee } from '../models/employee';
6 | import { EmployeeListServiceComponent } from '../services/employee-list-service.component';
7 |
8 | @Component({
9 | selector: 'employee-list',
10 | templateUrl: 'src/pages/employee-list.component.html',
11 | directives: [ROUTER_DIRECTIVES],
12 | providers: [EmployeeListServiceComponent]
13 | })
14 |
15 | export class EmployeeListComponent implements OnInit {
16 | public employees: Employee[];
17 | public errorMessage: string;
18 |
19 | constructor(
20 | private _listingService: EmployeeListServiceComponent
21 | ){}
22 |
23 | ngOnInit() {
24 | this._listingService.getEmployees().subscribe(
25 | employees => this.employees = employees,
26 | error => this.errorMessage = error
27 | );
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/services/employee-edit-form-service.component.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from 'angular2/core';
2 | import {Http, Response, Headers, RequestOptions } from 'angular2/http';
3 | import { Observable } from 'rxjs/Observable';
4 |
5 | import { Employee } from '../models/employee';
6 |
7 | @Injectable()
8 | export class EmployeeEditFormServiceComponent {
9 | constructor(private http: Http) { }
10 |
11 | private _employeesUrl: string = 'http://localhost:3000/employees/';
12 |
13 | editEmployee (employee: Employee) : Observable {
14 | this._employeesUrl += employee.id;
15 |
16 | let body = JSON.stringify({ name: employee.name });
17 | let headers = new Headers({ 'Content-Type': 'application/json' });
18 | let options = new RequestOptions({ headers: headers });
19 |
20 | return this.http.patch(this._employeesUrl, body, options)
21 | .map(res => res.json())
22 | .catch(this._handleError)
23 | }
24 |
25 | private _handleError (error: Response) {
26 | console.error(error);
27 | return Observable.throw(error.json().error || 'Server error');
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Abhinav Mishra
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Angular 2 Testing
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/src/services/employee-form-service.component.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import { Injectable } from 'angular2/core';
4 | import {Http, Response, Headers, RequestOptions } from 'angular2/http';
5 | import { Observable } from 'rxjs/Observable';
6 |
7 | import { Employee } from '../models/employee';
8 |
9 | @Injectable()
10 | export class EmployeeFormServiceComponent {
11 | constructor(private http: Http) { }
12 |
13 | private _employeesUrl: string = 'http://localhost:3000/employees';
14 |
15 | addEmployee (name: string) : Observable {
16 |
17 | let body = JSON.stringify({ name: name });
18 | let headers = new Headers({ 'Content-Type': 'application/json' });
19 | let options = new RequestOptions({ headers: headers });
20 |
21 | return this.http.post(this._employeesUrl, body, options)
22 | .map(res => res.json())
23 | .catch(this._handleError)
24 | }
25 |
26 | private _handleError (error: Response) {
27 | // in a real world app, we may send the error to some remote logging infrastructure
28 | // instead of just logging it to the console
29 | console.error(error);
30 | return Observable.throw(error.json().error || 'Server error');
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/app.component.ts:
--------------------------------------------------------------------------------
1 | import {Component} from 'angular2/core';
2 | import {
3 | RouteConfig,
4 | ROUTER_DIRECTIVES
5 | } from 'angular2/router';
6 | import {HTTP_PROVIDERS} from 'angular2/http';
7 |
8 | import {EmployeeListComponent} from './components/list.component';
9 | import {EmployeeFormComponent} from './components/employee-form.component';
10 | import {EmployeeDetailComponent} from './components/employee-detail.component';
11 | import {EmployeeEditFormComponent} from './components/employee-edit-form.component';
12 |
13 | @Component({
14 | selector: 'my-app',
15 | templateUrl: 'src/pages/app.component.html',
16 | styleUrls: ['src/assets/stylesheets/style.css'],
17 | directives: [
18 | ROUTER_DIRECTIVES
19 | ],
20 | providers: [HTTP_PROVIDERS]
21 | })
22 |
23 | @RouteConfig([
24 | {
25 | path: '/employee',
26 | name: 'EmployeeList',
27 | component: EmployeeListComponent
28 | },
29 | {
30 | path: '/employee/new',
31 | name: 'NewEmployee',
32 | component: EmployeeFormComponent
33 | },
34 | {
35 | path: '/employee/:id',
36 | name: 'EmployeeDetail',
37 | component: EmployeeDetailComponent
38 | },
39 | {
40 | path: '/employee/:id/edit',
41 | name: 'EditEmployee',
42 | component: EmployeeEditFormComponent
43 | }
44 | ])
45 |
46 | export class AppComponent {}
47 |
--------------------------------------------------------------------------------
/src/components/employee-edit-form.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from 'angular2/core';
2 | import { RouteParams, Router } from 'angular2/router';
3 |
4 | import { Employee } from '../models/employee';
5 | import { EmployeeDetailServiceComponent } from '../services/employee-detail-service.component';
6 | import { EmployeeEditFormServiceComponent } from '../services/employee-edit-form-service.component';
7 |
8 | @Component({
9 | selector: 'employee-edit-form',
10 | templateUrl: 'src/pages/employee-edit-form.component.html',
11 | providers: [
12 | EmployeeDetailServiceComponent,
13 | EmployeeEditFormServiceComponent
14 | ]
15 | })
16 |
17 | export class EmployeeEditFormComponent implements OnInit {
18 | public currentEmployee: Employee;
19 | public errorMessage: string;
20 |
21 | constructor(
22 | private _router: Router,
23 | private _routeParams: RouteParams,
24 | private _detailService: EmployeeDetailServiceComponent,
25 | private _editService: EmployeeEditFormServiceComponent
26 | ){}
27 |
28 | ngOnInit() {
29 | let id = parseInt(this._routeParams.get('id'));
30 | this._detailService.getEmployee(id).subscribe(
31 | employee => this.currentEmployee = employee
32 | );
33 | }
34 |
35 | editEmployee() {
36 | this._editService.editEmployee(this.currentEmployee)
37 | .subscribe(
38 | employee => this.currentEmployee = employee,
39 | error => this.errorMessage = error,
40 | () => this._router.navigate(['EmployeeDetail', {id: this.currentEmployee.id}])
41 | );
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular2",
3 | "version": "1.0.0",
4 | "description": "Angular 2 testing with Karma, Jasmine and Istanbul",
5 | "main": "index.js",
6 | "scripts": {
7 | "postinstall": "npm run typings",
8 | "typings": "typings install",
9 | "lite": "lite-server",
10 | "start": "concurrently \"tsc -w -p src/ \" \"npm run lite .\"",
11 | "build": "rm -rf dist && tsc -p src",
12 | "pretest": "npm run build",
13 | "test": "karma start karma.conf.js",
14 | "posttest": "node_modules/.bin/remap-istanbul -i coverage/coverage-final.json -o coverage -t html"
15 | },
16 | "author": "Abhinav Mishra ",
17 | "license": "MIT",
18 | "dependencies": {
19 | "angular2": "2.0.0-beta.13",
20 | "bootstrap": "^3.3.6",
21 | "es6-promise": "3.0.2",
22 | "es6-shim": "0.35.0",
23 | "reflect-metadata": "0.1.2",
24 | "rxjs": "5.0.0-beta.2",
25 | "zone.js": "0.6.6"
26 | },
27 | "devDependencies": {
28 | "concurrently": "^2.0.0",
29 | "lite-server": "^2.2.0",
30 | "jasmine-core": "2.4.1",
31 | "karma": "0.13.19",
32 | "karma-chrome-launcher": "0.2.2",
33 | "karma-coverage": "0.5.3",
34 | "karma-jasmine": "0.3.6",
35 | "remap-istanbul": "0.5.1",
36 | "systemjs": "0.19.17",
37 | "typescript": "1.7.5",
38 | "typings": "0.6.8"
39 | },
40 | "repository": {
41 | "type": "git",
42 | "url": "git+https://github.com/abhinavmsra/angular2.git"
43 | },
44 | "keywords": [
45 | "angular2",
46 | "karma",
47 | "jasmine",
48 | "istanbul",
49 | "unit-testing",
50 | "typescript"
51 | ],
52 | "bugs": {
53 | "url": "https://github.com/abhinavmsra/angular2/issues"
54 | },
55 | "homepage": "https://github.com/abhinavmsra/angular2#readme"
56 | }
57 |
--------------------------------------------------------------------------------
/src/components/employee-detail.component.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import { Component, OnInit } from 'angular2/core';
4 | import { RouteParams, Router, ROUTER_DIRECTIVES } from 'angular2/router';
5 |
6 | import { EmployeeEditFormComponent } from './employee-edit-form.component';
7 | import { EmployeeDetailServiceComponent } from '../services/employee-detail-service.component';
8 | import { EmployeeDeleteServiceComponent } from '../services/employee-delete-service.component';
9 |
10 | @Component({
11 | selector: 'employee-detail',
12 | templateUrl: 'src/pages/employee-detail.component.html',
13 | providers: [
14 | EmployeeDetailServiceComponent,
15 | EmployeeDeleteServiceComponent
16 | ],
17 | directives: [ ROUTER_DIRECTIVES, EmployeeEditFormComponent ]
18 | })
19 |
20 | export class EmployeeDetailComponent implements OnInit {
21 | public currentEmployee;
22 | public errorMessage: string;
23 |
24 | constructor(
25 | private _router: Router,
26 | private _routeParams: RouteParams,
27 | private _detailService: EmployeeDetailServiceComponent,
28 | private _deleteService: EmployeeDeleteServiceComponent
29 | ){}
30 |
31 | ngOnInit() {
32 | let id = parseInt(this._routeParams.get('id'));
33 | this._detailService.getEmployee(id).subscribe(
34 | employee => this.currentEmployee = employee,
35 | error => this.errorMessage = error
36 | );
37 | }
38 |
39 | deleteHandler(id: number) {
40 | this._deleteService.deleteEmployee(id).subscribe(
41 | employee => this.currentEmployee = employee,
42 | errorMessage => this.errorMessage = errorMessage,
43 | () => this._router.navigate(['EmployeeList'])
44 | )
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/services/employee-form-service.component.spec.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import {
4 | it,
5 | describe,
6 | expect,
7 | beforeEachProviders,
8 | inject
9 | } from "angular2/testing";
10 | import {
11 | Response,
12 | XHRBackend,
13 | ResponseOptions,
14 | HTTP_PROVIDERS
15 | } from "angular2/http";
16 | import {MockConnection, MockBackend} from "angular2/src/http/backends/mock_backend";
17 | import {provide} from "angular2/core";
18 | import 'rxjs/Rx';
19 |
20 | import { EmployeeFormServiceComponent } from './employee-form-service.component';
21 |
22 | describe('Employee Detail Service Tests', () => {
23 | beforeEachProviders(() => {
24 | return [
25 | HTTP_PROVIDERS,
26 | provide(XHRBackend, {useClass: MockBackend}),
27 | EmployeeFormServiceComponent
28 | ]
29 | });
30 |
31 | it('should create an employee',
32 | inject([XHRBackend, EmployeeFormServiceComponent], (backend, service) => {
33 | backend.connections.subscribe(
34 | (connection:MockConnection) => {
35 | var options = new ResponseOptions({
36 | body: {
37 | "name": "Abhinav Mishra",
38 | "id": 1
39 | }
40 | });
41 |
42 | var response = new Response(options);
43 |
44 | connection.mockRespond(response);
45 | }
46 | );
47 |
48 | service.addEmployee('Abhinav Mishra').subscribe(
49 | (employee) => {
50 | expect(employee.name).toBe('Abhinav Mishra');
51 | }
52 | );
53 | })
54 | );
55 | });
56 |
57 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Intro
2 |
3 | This repository is a basic CRUD Angular2 application, with an intention to learn Angular2 along with unit testing in it.
4 |
5 | ## Software Prerequisites
6 |
7 | In order to run this project, the following software is required
8 |
9 | ### Git
10 |
11 | See [Setting Up Git](https://help.github.com/articles/set-up-git/) from the GitHub guides.
12 |
13 | ### Node.js and npm
14 |
15 | Node.js and Node's package manager, npm, are used for installing dependencies,
16 | running the build steps, and running tests.
17 |
18 |
19 | ## Getting Started
20 |
21 | Begin by cloning the repository.
22 |
23 | Use npm to get dependencies:
24 |
25 | `npm install`
26 |
27 | Take a look at the `src` folder. All application and test code are placed here. Typings configuration are also placed in this folder in `tsconfig.json`.
28 |
29 | ### Build
30 |
31 | The build step invokes the TypeScript compiler to create ES5 javascript
32 | files and source maps from the `.ts` files. Run with:
33 |
34 | `npm run build`
35 |
36 | You can examine the configuration for the TypeScript compiler in `tsconfig.json`.
37 | The generated files are output in the `dist` folder which provides as a destination to fetch pure `Javascript` files and also provides good separation of `Typescript` and `Javascript` files.
38 |
39 | ### Serve
40 |
41 | The app uses `json-server` to simulate client-server communication. Follow the [GIT Repo](https://github.com/typicode/json-server) to configure it to run on port 3000.
42 |
43 | To see the app, run
44 |
45 | `npm run start`
46 |
47 | and navigate to `localhost:3001`.
48 |
49 | ### Test
50 |
51 | I used Karma with the `Jasmine` test framework to run unit tests. Try them with
52 |
53 | `npm run test`
54 |
55 | I have also used `karma-coverage` to generate the coverage report. The corresponding reports can be found under `coverage` directory.
56 |
--------------------------------------------------------------------------------
/src/services/employee-delete-service.component.spec.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import {it, describe, expect, beforeEachProviders, inject} from "angular2/testing";
4 | import {Response, XHRBackend, ResponseOptions, HTTP_PROVIDERS} from "angular2/http";
5 | import 'rxjs/Rx';
6 |
7 | import { EmployeeDeleteServiceComponent } from './employee-delete-service.component';
8 | import {MockConnection, MockBackend} from "angular2/src/http/backends/mock_backend";
9 | import {provide} from "angular2/core";
10 |
11 | describe('Employee Delete Service Tests', () => {
12 | beforeEachProviders(() => {
13 | return [
14 | HTTP_PROVIDERS,
15 | provide(XHRBackend, {useClass: MockBackend}),
16 | EmployeeDeleteServiceComponent
17 | ]
18 | });
19 |
20 | it('should delete an employee',
21 | inject([XHRBackend, EmployeeDeleteServiceComponent], (backend, service) => {
22 | backend.connections.subscribe(
23 | (connection:MockConnection) => {
24 | var options = new ResponseOptions({
25 | body: {
26 | "name": "Abhinav Mishra",
27 | "id": 1
28 | }
29 | });
30 |
31 | var response = new Response(options);
32 |
33 | connection.mockRespond(response);
34 | }
35 | );
36 |
37 | service.deleteEmployee(1).subscribe(
38 | (employee) => {
39 | expect(employee.name).toBe('Abhinav Mishra');
40 | }
41 | );
42 |
43 | service.deleteEmployee(1).subscribe(
44 | (employee) => {
45 | expect(employee.id).toBe(1);
46 | }
47 | );
48 | })
49 | );
50 | });
51 |
52 |
--------------------------------------------------------------------------------
/src/services/employee-list-service.component.spec.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import {it, describe, expect, beforeEachProviders, inject} from "angular2/testing";
4 | import {Response, XHRBackend, ResponseOptions, HTTP_PROVIDERS} from "angular2/http";
5 | import 'rxjs/Rx';
6 |
7 | import { EmployeeListServiceComponent } from './employee-list-service.component';
8 | import {MockConnection, MockBackend} from "angular2/src/http/backends/mock_backend";
9 | import {provide} from "angular2/core";
10 |
11 | describe('Employee List Service Tests', () => {
12 | beforeEachProviders(() => {
13 | return [
14 | HTTP_PROVIDERS,
15 | provide(XHRBackend, {useClass: MockBackend}),
16 | EmployeeListServiceComponent
17 | ]
18 | });
19 |
20 | it('should return a list of employees',
21 | inject([XHRBackend, EmployeeListServiceComponent], (backend, service) => {
22 | backend.connections.subscribe(
23 | (connection:MockConnection) => {
24 | var options = new ResponseOptions({
25 | body: [
26 | {
27 | "name": "Abhinav Mishra",
28 | "id": 1
29 | }
30 | ]
31 | });
32 |
33 | var response = new Response(options);
34 |
35 | connection.mockRespond(response);
36 | }
37 | );
38 |
39 | service.getEmployees().subscribe(
40 | (employees) => {
41 | expect(employees[0].name).toBe('Abhinav Mishra');
42 | }
43 | );
44 |
45 | service.getEmployees().subscribe(
46 | (employees) => {
47 | expect(employees[0].id).toBe(1);
48 | }
49 | );
50 | })
51 | );
52 | });
53 |
54 |
--------------------------------------------------------------------------------
/src/services/employee-detail-service.component.spec.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import {
4 | it,
5 | describe,
6 | expect,
7 | beforeEachProviders,
8 | inject
9 | } from "angular2/testing";
10 | import {
11 | Response,
12 | XHRBackend,
13 | ResponseOptions,
14 | HTTP_PROVIDERS
15 | } from "angular2/http";
16 | import {MockConnection, MockBackend} from "angular2/src/http/backends/mock_backend";
17 | import {provide} from "angular2/core";
18 | import 'rxjs/Rx';
19 |
20 | import { EmployeeDetailServiceComponent } from './employee-detail-service.component';
21 |
22 | describe('Employee Detail Service Tests', () => {
23 | beforeEachProviders(() => {
24 | return [
25 | HTTP_PROVIDERS,
26 | provide(XHRBackend, {useClass: MockBackend}),
27 | EmployeeDetailServiceComponent
28 | ]
29 | });
30 |
31 | it('should return details of employee',
32 | inject([XHRBackend, EmployeeDetailServiceComponent], (backend, service) => {
33 | backend.connections.subscribe(
34 | (connection:MockConnection) => {
35 | var options = new ResponseOptions({
36 | body: {
37 | "name": "Abhinav Mishra",
38 | "id": 1
39 | }
40 | });
41 |
42 | var response = new Response(options);
43 |
44 | connection.mockRespond(response);
45 | }
46 | );
47 |
48 | service.getEmployee(1).subscribe(
49 | (employee) => {
50 | expect(employee.name).toBe('Abhinav Mishra');
51 | }
52 | );
53 |
54 | service.getEmployee(1).subscribe(
55 | (employee) => {
56 | expect(employee.id).toBe(1);
57 | }
58 | );
59 | })
60 | );
61 | });
62 |
63 |
--------------------------------------------------------------------------------
/karma-test-shim.js:
--------------------------------------------------------------------------------
1 | // Tun on full stack traces in errors to help debugging
2 | Error.stackTraceLimit = Infinity;
3 |
4 | jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000;
5 |
6 | // // Cancel Karma's synchronous start,
7 | // // we will call `__karma__.start()` later, once all the specs are loaded.
8 | __karma__.loaded = function() {};
9 |
10 | System.config({
11 | packages: {
12 | 'base/dist': {
13 | defaultExtension: false,
14 | format: 'cjs',
15 | map: Object.keys(window.__karma__.files).filter(onlyAppFiles).reduce(createPathRecords, {})
16 | }
17 | }
18 | });
19 |
20 | System.import('angular2/src/platform/browser/browser_adapter')
21 | .then(function(browser_adapter) { browser_adapter.BrowserDomAdapter.makeCurrent(); })
22 | .then(function() { return Promise.all(resolveTestFiles()); })
23 | .then(function() { __karma__.start(); }, function(error) { __karma__.error(error.stack || error); });
24 |
25 | function createPathRecords(pathsMapping, appPath) {
26 | // creates local module name mapping to global path with karma's fingerprint in path, e.g.:
27 | // './vg-player/vg-player':
28 | // '/base/dist/vg-player/vg-player.js?f4523daf879cfb7310ef6242682ccf10b2041b3e'
29 | var moduleName = './' + resolveKeyPathForMapping('base/dist/', appPath);
30 | moduleName = moduleName.replace(/\.js$/, '');
31 | pathsMapping[moduleName] = appPath + '?' + window.__karma__.files[appPath];
32 | return pathsMapping;
33 | }
34 |
35 | function onlyAppFiles(filePath) {
36 | return /\/base\/dist\/(?!.*\.spec\.js$).*\.js$/.test(filePath);
37 | }
38 |
39 | function onlySpecFiles(path) {
40 | return /\.spec\.js$/.test(path);
41 | }
42 |
43 | function resolveTestFiles() {
44 | return Object.keys(window.__karma__.files) // All files served by Karma.
45 | .filter(onlySpecFiles)
46 | .map(function(moduleName) {
47 | // loads all spec files via their global module names (e.g.
48 | // 'base/dist/vg-player/vg-player.spec')
49 | return System.import(moduleName);
50 | });
51 | }
52 |
53 | function resolveKeyPathForMapping(basePathWhereToStart, appPath) {
54 | var location = appPath.indexOf(basePathWhereToStart);
55 | if (location > -1) {
56 | return appPath.substring(basePathWhereToStart.length + 1);
57 | } else {
58 | return appPath;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | module.exports = function(config) {
2 | config.set({
3 |
4 | basePath: '.',
5 |
6 | frameworks: ['jasmine'],
7 |
8 | files: [
9 | // paths loaded by Karma
10 | {pattern: 'node_modules/angular2/bundles/angular2-polyfills.js', included: true, watched: true},
11 | {pattern: 'node_modules/systemjs/dist/system.src.js', included: true, watched: true},
12 | {pattern: 'node_modules/rxjs/bundles/Rx.js', included: true, watched: true},
13 | {pattern: 'node_modules/angular2/bundles/angular2.dev.js', included: true, watched: true},
14 | {pattern: 'node_modules/angular2/bundles/testing.dev.js', included: true, watched: true},
15 | {pattern: 'node_modules/angular2/bundles/http.dev.js', included: true, watched: true},
16 | {pattern: 'node_modules/angular2/bundles/router.dev.js', included: true, watched: true},
17 | {pattern: 'karma-test-shim.js', included: true, watched: true},
18 |
19 | // paths loaded via module imports
20 | {pattern: 'dist/**/*.js', included: false, watched: true},
21 | {pattern: 'src/pages/**/*.html', included: false, watched: true},
22 |
23 | // paths to support debugging with source maps in dev tools
24 | {pattern: 'src/**/*.ts', included: false, watched: false},
25 | {pattern: 'dist/**/*.js.map', included: false, watched: false}
26 | ],
27 |
28 | // proxied base paths
29 | proxies: {
30 | // required for component assests fetched by Angular's compiler
31 | '/src/': '/base/src/'
32 | },
33 |
34 | port: 9876,
35 |
36 | logLevel: config.LOG_INFO,
37 |
38 | colors: true,
39 |
40 | autoWatch: true,
41 |
42 | browsers: ['Chrome'],
43 |
44 | // Karma plugins loaded
45 | plugins: [
46 | 'karma-jasmine',
47 | 'karma-coverage',
48 | 'karma-chrome-launcher'
49 | ],
50 |
51 | // Coverage reporter generates the coverage
52 | reporters: ['progress', 'dots', 'coverage'],
53 |
54 | // Source files that you wanna generate coverage for.
55 | // Do not include tests or libraries (these files will be instrumented by Istanbul)
56 | preprocessors: {
57 | 'dist/**/!(*spec).js': ['coverage']
58 | },
59 |
60 | coverageReporter: {
61 | reporters:[
62 | {type: 'json', subdir: '.', file: 'coverage-final.json'}
63 | ]
64 | },
65 |
66 | singleRun: true
67 | })
68 | };
69 |
--------------------------------------------------------------------------------
/src/components/employee-form.component.spec.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import {
4 | it,
5 | describe,
6 | expect,
7 | TestComponentBuilder,
8 | injectAsync,
9 | setBaseTestProviders,
10 | beforeEachProviders,
11 | resetBaseTestProviders
12 | } from "angular2/testing";
13 | import {
14 | Component,
15 | provide,
16 | ApplicationRef
17 | } from "angular2/core";
18 | import {
19 | TEST_BROWSER_PLATFORM_PROVIDERS,
20 | TEST_BROWSER_APPLICATION_PROVIDERS
21 | } from "angular2/platform/testing/browser";
22 | import {
23 | ROUTER_DIRECTIVES,
24 | ROUTER_PROVIDERS,
25 | ROUTER_PRIMARY_COMPONENT,
26 | APP_BASE_HREF,
27 | Router,
28 | RouteParams,
29 | RouteRegistry
30 | } from 'angular2/router';
31 | import {RootRouter} from "angular2/src/router/router";
32 | import {SpyLocation} from "angular2/src/mock/location_mock";
33 | import {Location} from "angular2/src/router/location/location";
34 | import {
35 | XHRBackend,
36 | HTTP_PROVIDERS,
37 | Response,
38 | ResponseOptions
39 | } from "angular2/http";
40 | import { MockApplicationRef } from 'angular2/src/mock/mock_application_ref';
41 | import {
42 | MockBackend,
43 | MockConnection
44 | } from "angular2/src/http/backends/mock_backend";
45 | import { BrowserDomAdapter } from 'angular2/src/platform/browser/browser_adapter';
46 | import 'rxjs/Rx';
47 |
48 | import { AppComponent } from '../app.component';
49 | import { EmployeeFormComponent } from './employee-form.component';
50 | import { EmployeeFormServiceComponent } from '../services/employee-form-service.component';
51 |
52 |
53 | class MockEmployeeFormServiceComponent {}
54 |
55 | @Component({
56 | template: '',
57 | directives: [EmployeeFormComponent],
58 | providers: [
59 | MockEmployeeFormServiceComponent
60 | ]
61 | })
62 | class TestMyDetail {}
63 |
64 |
65 | describe('Employee Form Tests', () => {
66 | resetBaseTestProviders();
67 | setBaseTestProviders(
68 | TEST_BROWSER_PLATFORM_PROVIDERS,
69 | TEST_BROWSER_APPLICATION_PROVIDERS
70 | );
71 | beforeEachProviders(() => {
72 | return [
73 | ROUTER_DIRECTIVES,
74 | ROUTER_PROVIDERS,
75 | HTTP_PROVIDERS,
76 | EmployeeFormServiceComponent,
77 | provide(XHRBackend, {useClass: MockBackend}),
78 | provide(APP_BASE_HREF, {useValue: '/'}),
79 | provide(ROUTER_PRIMARY_COMPONENT, {useValue: AppComponent}),
80 | provide(ApplicationRef, {useClass: MockApplicationRef}),
81 | RouteRegistry,
82 | provide(Location, {useClass: SpyLocation}),
83 | provide(Router, {useClass: RootRouter})
84 | ]
85 | });
86 |
87 | it('Should display the list of employees',
88 | injectAsync([XHRBackend, TestComponentBuilder], (backend, tcb) => {
89 | backend.connections.subscribe(
90 | (connection:MockConnection) => {
91 | var options = new ResponseOptions({
92 | body: {
93 | "id": 1,
94 | "name": "Roshan Shrestha"
95 | }
96 | });
97 |
98 | var response = new Response(options);
99 |
100 | connection.mockRespond(response);
101 | }
102 | );
103 |
104 | return tcb
105 | .createAsync(TestMyDetail)
106 | .then((fixture) => {
107 | fixture.detectChanges();
108 | var compiled = fixture.nativeElement;
109 |
110 | expect(compiled.innerHTML).toContain('Employee Form');
111 | });
112 | })
113 | );
114 | });
115 |
--------------------------------------------------------------------------------
/src/components/employee-edit-form.component.spec.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import {
4 | it,
5 | describe,
6 | expect,
7 | TestComponentBuilder,
8 | injectAsync,
9 | setBaseTestProviders,
10 | beforeEachProviders,
11 | resetBaseTestProviders
12 | } from "angular2/testing";
13 | import {
14 | Component,
15 | provide,
16 | ApplicationRef
17 | } from "angular2/core";
18 | import {
19 | TEST_BROWSER_PLATFORM_PROVIDERS,
20 | TEST_BROWSER_APPLICATION_PROVIDERS
21 | } from "angular2/platform/testing/browser";
22 | import {
23 | ROUTER_DIRECTIVES,
24 | ROUTER_PROVIDERS,
25 | ROUTER_PRIMARY_COMPONENT,
26 | APP_BASE_HREF,
27 | Router,
28 | RouteParams,
29 | RouteRegistry
30 | } from 'angular2/router';
31 | import {RootRouter} from "angular2/src/router/router";
32 | import {SpyLocation} from "angular2/src/mock/location_mock";
33 | import {Location} from "angular2/src/router/location/location";
34 | import {
35 | XHRBackend,
36 | HTTP_PROVIDERS,
37 | Response,
38 | ResponseOptions
39 | } from "angular2/http";
40 | import { MockApplicationRef } from 'angular2/src/mock/mock_application_ref';
41 | import {
42 | MockBackend,
43 | MockConnection
44 | } from "angular2/src/http/backends/mock_backend";
45 | import { BrowserDomAdapter } from 'angular2/src/platform/browser/browser_adapter';
46 | import 'rxjs/Rx';
47 |
48 | import { AppComponent } from '../app.component';
49 | import { EmployeeEditFormComponent } from './employee-edit-form.component';
50 | import { EmployeeDetailServiceComponent } from '../services/employee-detail-service.component';
51 | import { EmployeeEditFormServiceComponent } from '../services/employee-edit-form-service.component';
52 |
53 |
54 | class MockEmployeeDetailServiceComponent {}
55 |
56 | class MockEmployeeEditFormServiceComponent {}
57 |
58 |
59 | @Component({
60 | template: '',
61 | directives: [EmployeeEditFormComponent]
62 | })
63 | class TestMyEditForm{}
64 |
65 |
66 | describe('Employee Edit Form Tests', () => {
67 | resetBaseTestProviders();
68 | setBaseTestProviders(
69 | TEST_BROWSER_PLATFORM_PROVIDERS,
70 | TEST_BROWSER_APPLICATION_PROVIDERS
71 | );
72 | beforeEachProviders(() => {
73 | return [
74 | ROUTER_DIRECTIVES,
75 | ROUTER_PROVIDERS,
76 | HTTP_PROVIDERS,
77 | EmployeeEditFormComponent,
78 | EmployeeDetailServiceComponent,
79 | EmployeeEditFormServiceComponent,
80 | provide(XHRBackend, {useClass: MockBackend}),
81 | provide(APP_BASE_HREF, {useValue: '/'}),
82 | provide(ROUTER_PRIMARY_COMPONENT, {useValue: AppComponent}),
83 | provide(ApplicationRef, {useClass: MockApplicationRef}),
84 | RouteRegistry,
85 | provide(Location, {useClass: SpyLocation}),
86 | provide(Router, {useClass: RootRouter}),
87 | provide(RouteParams, { useValue: new RouteParams({ id: '1' }) })
88 | ]
89 | });
90 |
91 | it('Should display the edit form of employees',
92 | injectAsync([XHRBackend, TestComponentBuilder], (backend, tcb) => {
93 | backend.connections.subscribe(
94 | (connection:MockConnection) => {
95 | var options = new ResponseOptions({
96 | body: {
97 | "id": 1,
98 | "name": "Roshan Shrestha"
99 | }
100 | });
101 |
102 | var response = new Response(options);
103 |
104 | connection.mockRespond(response);
105 | }
106 | );
107 |
108 | return tcb
109 | .createAsync(TestMyEditForm)
110 | .then((fixture) => {
111 | fixture.detectChanges();
112 | var compiled = fixture.nativeElement;
113 | expect(compiled.innerHTML).toContain('Employee Edit Form');
114 | });
115 | })
116 | );
117 | });
118 |
--------------------------------------------------------------------------------
/src/components/employee-detail.component.spec.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import {
4 | it,
5 | describe,
6 | expect,
7 | TestComponentBuilder,
8 | injectAsync,
9 | setBaseTestProviders,
10 | beforeEachProviders,
11 | resetBaseTestProviders
12 | } from "angular2/testing";
13 | import {
14 | Component,
15 | provide,
16 | ApplicationRef
17 | } from "angular2/core";
18 | import {
19 | TEST_BROWSER_PLATFORM_PROVIDERS,
20 | TEST_BROWSER_APPLICATION_PROVIDERS
21 | } from "angular2/platform/testing/browser";
22 | import {
23 | ROUTER_DIRECTIVES,
24 | ROUTER_PROVIDERS,
25 | ROUTER_PRIMARY_COMPONENT,
26 | APP_BASE_HREF,
27 | Router,
28 | RouteParams,
29 | RouteRegistry
30 | } from 'angular2/router';
31 | import {RootRouter} from "angular2/src/router/router";
32 | import {SpyLocation} from "angular2/src/mock/location_mock";
33 | import {Location} from "angular2/src/router/location/location";
34 | import {
35 | XHRBackend,
36 | HTTP_PROVIDERS,
37 | Response,
38 | ResponseOptions
39 | } from "angular2/http";
40 | import { MockApplicationRef } from 'angular2/src/mock/mock_application_ref';
41 | import {
42 | MockBackend,
43 | MockConnection
44 | } from "angular2/src/http/backends/mock_backend";
45 | import { BrowserDomAdapter } from 'angular2/src/platform/browser/browser_adapter';
46 | import 'rxjs/Rx';
47 |
48 | import { AppComponent } from '../app.component';
49 | import { EmployeeDetailComponent } from './employee-detail.component';
50 | import { EmployeeDetailServiceComponent } from '../services/employee-detail-service.component';
51 | import { EmployeeDeleteServiceComponent } from '../services/employee-delete-service.component';
52 | import { EmployeeEditFormComponent } from './employee-edit-form.component';
53 |
54 |
55 | class MockEmployeeDetailServiceComponent {}
56 |
57 | class MockEmployeeDeleteServiceComponent {}
58 |
59 |
60 | @Component({
61 | template: '',
62 | directives: [EmployeeDetailComponent],
63 | providers: [
64 | MockEmployeeDetailServiceComponent,
65 | MockEmployeeDeleteServiceComponent
66 | ]
67 | })
68 | class TestMyDetail {}
69 |
70 |
71 | describe('Employee Detail Tests', () => {
72 | resetBaseTestProviders();
73 | setBaseTestProviders(
74 | TEST_BROWSER_PLATFORM_PROVIDERS,
75 | TEST_BROWSER_APPLICATION_PROVIDERS
76 | );
77 | beforeEachProviders(() => {
78 | return [
79 | ROUTER_DIRECTIVES,
80 | ROUTER_PROVIDERS,
81 | HTTP_PROVIDERS,
82 | EmployeeDetailServiceComponent,
83 | EmployeeDeleteServiceComponent,
84 | provide(XHRBackend, {useClass: MockBackend}),
85 | provide(APP_BASE_HREF, {useValue: '/'}),
86 | provide(ROUTER_PRIMARY_COMPONENT, {useValue: AppComponent}),
87 | provide(ApplicationRef, {useClass: MockApplicationRef}),
88 | RouteRegistry,
89 | provide(Location, {useClass: SpyLocation}),
90 | provide(Router, {useClass: RootRouter}),
91 | provide(RouteParams, { useValue: new RouteParams({ id: '1' }) })
92 | ]
93 | });
94 |
95 | it('Should display the list of employees',
96 | injectAsync([XHRBackend, TestComponentBuilder], (backend, tcb) => {
97 | backend.connections.subscribe(
98 | (connection:MockConnection) => {
99 | var options = new ResponseOptions({
100 | body: {
101 | "id": 1,
102 | "name": "Roshan Shrestha"
103 | }
104 | });
105 |
106 | var response = new Response(options);
107 |
108 | connection.mockRespond(response);
109 | }
110 | );
111 |
112 | return tcb
113 | .createAsync(TestMyDetail)
114 | .then((fixture) => {
115 | fixture.detectChanges();
116 | var compiled = fixture.nativeElement;
117 | expect(compiled.innerHTML).toContain('Roshan Shrestha');
118 |
119 | var src = (new BrowserDomAdapter()).getProperty(compiled.querySelector('a'), 'href');
120 |
121 | // Employee link expectation
122 | expect(src).toBe('http://localhost:9876/employee/1/edit');
123 | });
124 | })
125 | );
126 | });
127 |
--------------------------------------------------------------------------------
/src/components/list.component.spec.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | import {
4 | it,
5 | describe,
6 | expect,
7 | TestComponentBuilder,
8 | injectAsync,
9 | setBaseTestProviders,
10 | beforeEachProviders,
11 | resetBaseTestProviders
12 | } from "angular2/testing";
13 | import {
14 | Component,
15 | provide,
16 | ApplicationRef
17 | } from "angular2/core";
18 | import {
19 | TEST_BROWSER_PLATFORM_PROVIDERS,
20 | TEST_BROWSER_APPLICATION_PROVIDERS
21 | } from "angular2/platform/testing/browser";
22 | import {
23 | ROUTER_DIRECTIVES,
24 | ROUTER_PROVIDERS,
25 | ROUTER_PRIMARY_COMPONENT,
26 | APP_BASE_HREF,
27 | Router,
28 | RouteRegistry
29 | } from 'angular2/router';
30 | import {RootRouter} from "angular2/src/router/router";
31 | import {SpyLocation} from "angular2/src/mock/location_mock";
32 | import {Location} from "angular2/src/router/location/location";
33 | import {
34 | XHRBackend,
35 | HTTP_PROVIDERS,
36 | Response,
37 | ResponseOptions
38 | } from "angular2/http";
39 | import { MockApplicationRef } from 'angular2/src/mock/mock_application_ref';
40 | import {
41 | MockBackend,
42 | MockConnection
43 | } from "angular2/src/http/backends/mock_backend";
44 | import { BrowserDomAdapter } from 'angular2/src/platform/browser/browser_adapter';
45 | import 'rxjs/Rx';
46 |
47 | import { AppComponent } from '../app.component';
48 | import { EmployeeListComponent } from './list.component';
49 | import { EmployeeListServiceComponent } from '../services/employee-list-service.component';
50 |
51 | class MockEmployeeListServiceComponent {}
52 |
53 | @Component({
54 | template: '',
55 | directives: [EmployeeListComponent],
56 | providers: [MockEmployeeListServiceComponent]
57 | })
58 | class TestMyList {}
59 |
60 |
61 | describe('Employee List Tests', () => {
62 | resetBaseTestProviders();
63 | setBaseTestProviders(
64 | TEST_BROWSER_PLATFORM_PROVIDERS,
65 | TEST_BROWSER_APPLICATION_PROVIDERS
66 | );
67 | //resetBaseTestProviders();
68 | beforeEachProviders(() => {
69 | return [
70 | ROUTER_DIRECTIVES,
71 | ROUTER_PROVIDERS,
72 | HTTP_PROVIDERS,
73 | EmployeeListServiceComponent,
74 | provide(XHRBackend, {useClass: MockBackend}),
75 | provide(APP_BASE_HREF, {useValue: '/'}),
76 | provide(ROUTER_PRIMARY_COMPONENT, {useValue: AppComponent}),
77 | provide(ApplicationRef, {useClass: MockApplicationRef}),
78 | RouteRegistry,
79 | provide(Location, {useClass: SpyLocation}),
80 | provide(Router, {useClass: RootRouter})
81 | ]
82 | });
83 |
84 | it('Should display the list of employees',
85 | injectAsync([XHRBackend, TestComponentBuilder], (backend, tcb) => {
86 | backend.connections.subscribe(
87 | (connection:MockConnection) => {
88 | var options = new ResponseOptions({
89 | body: [
90 | {
91 | "id": 1,
92 | "name": "Abhinav Mishra"
93 | },
94 | {
95 | "id": 2,
96 | "name": "Roshan Shrestha"
97 | }
98 | ]
99 | });
100 |
101 | var response = new Response(options);
102 |
103 | connection.mockRespond(response);
104 | }
105 | );
106 |
107 | return tcb
108 | .createAsync(TestMyList)
109 | .then((fixture) => {
110 | fixture.detectChanges();
111 | var compiled = fixture.nativeElement;
112 |
113 | var listCount = compiled.querySelectorAll('a').length;
114 |
115 | // Employee count expectation
116 | expect(listCount).toBe(2);
117 |
118 | // Employee name expectation
119 | expect(compiled.innerHTML).toContain('Abhinav Mishra');
120 |
121 | var src = (new BrowserDomAdapter()).getProperty(compiled.querySelector('a'), 'href');
122 |
123 | // Employee link expectation
124 | expect(src).toBe('http://localhost:9876/employee/1');
125 | });
126 | })
127 | );
128 | });
129 |
--------------------------------------------------------------------------------