├── .editorconfig
├── .eslintignore
├── .eslintrc.json
├── .gitignore
├── DEVNOTES.md
├── README.md
├── TODO.md
├── app
├── app.module.ts
├── app.routes.ts
├── colors.styl
├── data
│ ├── README.md
│ ├── persons.json
│ └── persons.ts
├── favicon.ico
├── global.styl
├── index.html
├── main.ts
├── models
│ └── person.ts
├── routes
│ ├── app
│ │ ├── app.component.html
│ │ ├── app.component.spec.ts
│ │ ├── app.component.styl
│ │ └── app.component.ts
│ ├── route1
│ │ ├── detail
│ │ │ ├── route1-detail.component.html
│ │ │ ├── route1-detail.component.spec.ts
│ │ │ ├── route1-detail.component.styl
│ │ │ └── route1-detail.component.ts
│ │ ├── list
│ │ │ ├── route1-list.component.html
│ │ │ ├── route1-list.component.spec.ts
│ │ │ ├── route1-list.component.styl
│ │ │ └── route1-list.component.ts
│ │ ├── route1.component.html
│ │ ├── route1.component.spec.ts
│ │ ├── route1.component.styl
│ │ └── route1.component.ts
│ └── route2
│ │ ├── route2.component.html
│ │ ├── route2.component.spec.ts
│ │ ├── route2.component.styl
│ │ └── route2.component.ts
└── services
│ └── person.service.ts
├── git-hook-pre-push.sh
├── gulp-core.js
├── gulp.config.js
├── gulp.png
├── gulp
├── build-hard.js
├── build-soft.js
├── low-level-coverage-tasks
│ ├── coverage-clean.js
│ ├── coverage-enforcer-hard.js
│ ├── coverage-enforcer-soft.js
│ ├── coverage-main.js
│ ├── coverage-open.js
│ ├── coverage-summary-long.js
│ ├── coverage-summary-short.js
│ └── enforcer-function.js
├── low-level-misc-tasks
│ ├── build-clean.js
│ ├── copy.js
│ ├── eslint-hard.js
│ ├── karma-build-hard.js
│ ├── karma-build-soft.js
│ ├── karma-watch.js
│ ├── serve.js
│ ├── styl-2-css.js
│ ├── ts-2-js-hard.js
│ ├── ts-2-js-soft.js
│ ├── tslint-hard.js
│ ├── tslint-reporter-function.js
│ └── tslint-soft.js
├── test-npm-build.js
├── test-npm-start.js
├── test-npm-test.js
└── watch.js
├── gulpfile.js
├── karma-test-shim.js
├── karma.conf.js
├── package.json
├── systemjs.config.js
├── tsconfig.json
├── tslint.json
├── typings.json
├── typings.sh
└── update.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | end_of_line = lf
5 | insert_final_newline = true
6 |
7 | [*.js]
8 | charset = utf-8
9 | indent_style = space
10 | indent_size = 2
11 |
12 | [app/**.ts]
13 | charset = utf-8
14 | indent_style = space
15 | indent_size = 2
16 |
17 | [app/**.styl]
18 | indent_style = space
19 | indent_size = 2
20 |
21 | [app/**.html]
22 | indent_style = space
23 | indent_size = 2
24 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/danday74/angular2-coverage/a72d6e6cf40b5827ae04b9dd15f12fd39391bc2a/.eslintignore
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "es6": true,
4 | "node": true,
5 | "browser": true,
6 | "jasmine": true
7 | },
8 | "extends": "eslint:recommended",
9 | "parserOptions": {
10 | "sourceType": "module"
11 | },
12 | "rules": {
13 | "no-console": 0,
14 | "indent": [
15 | "error",
16 | 2
17 | ],
18 | "linebreak-style": [
19 | "error",
20 | "unix"
21 | ],
22 | "quotes": [
23 | "error",
24 | "single"
25 | ],
26 | "semi": [
27 | "error",
28 | "always"
29 | ]
30 | },
31 | "globals": {
32 | "window": true
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /.idea/
2 | /build/
3 | /compiler/
4 | /coverage/
5 | /node_modules/
6 | /typings/
7 | npm-debug.log
8 | *.bak
9 |
--------------------------------------------------------------------------------
/DEVNOTES.md:
--------------------------------------------------------------------------------
1 | # Third party libs
2 |
3 | To use third party libs you must follow these steps.
4 |
5 | (1) To install and save **lodash** run ..
6 |
7 | ```
8 | npm i -S lodash
9 | ```
10 |
11 | (2) To install and save **lodash** TypeScript definitions run ..
12 |
13 | ```
14 | typings install dt~lodash --global --save
15 | ```
16 |
17 | (3) Update **systemjs.config.js** to let SystemJS know where to find **lodash**
18 |
19 | ```
20 | var map = {
21 | // ...
22 | 'lodash': 'node_modules/lodash/lodash.js'
23 | };
24 | ```
25 |
26 | (4) Update **karma.conf.js** to make **lodash** available to your karma test runner browser
27 |
28 | ```
29 | {pattern: 'node_modules/lodash/**/*.js', included: false, watched: false}
30 | ```
31 |
32 | (5) Then in your TypeScript .ts file ...
33 |
34 | ```
35 | import * as _ from 'lodash';
36 | ```
37 |
38 | # Points of failure for build
39 |
40 | ## BUILD
41 |
42 | * eslint-hard: Linting JavaScript
43 | * tslint-hard: Linting TypeScript
44 | * ts-2-js-hard: Transpiling TypeScript to JavaScript
45 | * styl-2-css-hard: Transpiling Stylus to CSS
46 | * styl-2-css-stream-hard: Transpiling Stylus to CSS (streaming)
47 |
48 | ## UNIT TESTS
49 |
50 | * karma-build-hard: Running unit tests
51 | * coverage-enforcer-hard: PASSED thresholds
52 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | angular2-coverage
2 | -----------------
3 | -----------------
4 |
5 | [](https://nodejs.org)
6 | [](http://gulpjs.com)
7 |
8 | An angular 2 gulp skeleton with unit testing and remapped coverage.
9 |
10 | **Updated to Angular 2.1.0**
11 |
12 | Install
13 | -------
14 |
15 | **npm i**
16 |
17 | Commands
18 | --------
19 |
20 | * **npm start -s** - Start dev server
21 | * **npm run build -s** - Kick off a build
22 | * **npm test -s** - Run test suite
23 |
24 | * **npm run checkupdates** - Check for package updates
25 | * **npm run typingsupdate** - Update typings (see [typings.sh](typings.sh))
26 |
27 | Main features
28 | -------------
29 |
30 | * unit testing
31 | * remapped coverage
32 |
--------------------------------------------------------------------------------
/TODO.md:
--------------------------------------------------------------------------------
1 | # Gulp recipes
2 |
3 | See [Gulp recipes](https://github.com/gulpjs/gulp/tree/master/docs/recipes)
4 |
5 | * Incremental rebuilding, including operating on full file sets (TODO)
6 | * Only pass through changed files (TODO)
7 | * Sharing streams with stream factories (REVIEW)
8 | * Output both a minified and non-minified version (REVIEW)
9 |
10 | # Minify JS
11 |
12 | * Minify JS files generated by the 'ts-2-js' tasks (TODO)
13 |
14 | # Color updates
15 |
16 | * Updates to colors.styl only partially inject, some do not reflect until the server is restarted
17 |
--------------------------------------------------------------------------------
/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import {NgModule} from '@angular/core';
2 | import {HttpModule} from '@angular/http';
3 | import {BrowserModule} from '@angular/platform-browser';
4 | import {routing} from './app.routes';
5 | import {AppComponent} from './routes/app/app.component';
6 | import {Route1Component} from './routes/route1/route1.component';
7 | import {Route1DetailComponent} from './routes/route1/detail/route1-detail.component';
8 | import {Route1ListComponent} from './routes/route1/list/route1-list.component';
9 | import {Route2Component} from './routes/route2/route2.component';
10 | import {PersonService} from './services/person.service';
11 |
12 | @NgModule({
13 | imports: [BrowserModule, HttpModule, routing], // dependencies
14 | declarations: [AppComponent, Route1Component, Route1DetailComponent, Route1ListComponent, Route2Component], // components and directives
15 | bootstrap: [AppComponent], // root component
16 | providers: [PersonService] // services
17 | })
18 |
19 | export class AppModule {
20 | }
21 |
--------------------------------------------------------------------------------
/app/app.routes.ts:
--------------------------------------------------------------------------------
1 | import {RouterModule, Routes} from '@angular/router';
2 | import {Route1Component} from './routes/route1/route1.component';
3 | import {Route1DetailComponent} from './routes/route1/detail/route1-detail.component';
4 | import {Route1ListComponent} from './routes/route1/list/route1-list.component';
5 | import {Route2Component} from './routes/route2/route2.component';
6 |
7 | const routes: Routes = [
8 | {
9 | path: 'route1',
10 | component: Route1Component,
11 | children: [
12 | {path: ':id', component: Route1DetailComponent},
13 | {path: '', component: Route1ListComponent}
14 | ]
15 | },
16 | {path: 'route2', component: Route2Component},
17 | {
18 | path: '',
19 | pathMatch: 'prefix',
20 | redirectTo: '/route1'
21 | }
22 | ];
23 |
24 | export const routing = RouterModule.forRoot(routes);
25 |
--------------------------------------------------------------------------------
/app/colors.styl:
--------------------------------------------------------------------------------
1 | myPrimaryColor = #FC4C02
2 |
--------------------------------------------------------------------------------
/app/data/README.md:
--------------------------------------------------------------------------------
1 | The data folder contains up to two files for each API endpoint.
2 |
3 | (1) A TypeScript file
4 |
5 | This is imported by SystemJS during unit testing. The file:
6 |
7 | * contains mock unit test data.
8 | * should always be present.
9 | * would be present in a real application in the dev environment.
10 |
11 | (2) A JSON file
12 |
13 | This is requested over HTTP by the application. The file:
14 |
15 | * contains HTTP response data.
16 | * should be present if there is no backend API in place.
17 | * would not exist in a real application, one would use a backend API instead.
18 |
--------------------------------------------------------------------------------
/app/data/persons.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": 1,
4 | "name": "Asa Israel",
5 | "age": 6,
6 | "hobby": "running"
7 | },
8 | {
9 | "id": 10,
10 | "name": "Keziah Lewis",
11 | "age": 7,
12 | "hobby": "swimming"
13 | },
14 | {
15 | "id": 20,
16 | "name": "Winnie Lewis",
17 | "age": 10,
18 | "hobby": "swimming"
19 | }
20 | ]
21 |
--------------------------------------------------------------------------------
/app/data/persons.ts:
--------------------------------------------------------------------------------
1 | let persons = [
2 | {
3 | id: 1,
4 | name: 'Asa Israel',
5 | age: 6,
6 | hobby: 'running'
7 | },
8 | {
9 | id: 10,
10 | name: 'Keziah Lewis',
11 | age: 7,
12 | hobby: 'swimming'
13 | },
14 | {
15 | id: 20,
16 | name: 'Winnie Lewis',
17 | age: 10,
18 | hobby: 'swimming'
19 | }
20 | ];
21 |
22 | export {persons};
23 |
--------------------------------------------------------------------------------
/app/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/danday74/angular2-coverage/a72d6e6cf40b5827ae04b9dd15f12fd39391bc2a/app/favicon.ico
--------------------------------------------------------------------------------
/app/global.styl:
--------------------------------------------------------------------------------
1 | @import 'nib'
2 | @import 'colors'
3 |
4 | html
5 | height 100%
6 |
7 | body
8 | background linear-gradient(top, #A3B2B9, lighten(myPrimaryColor, 30))
9 | color #FFF
10 | margin-top 1em
11 |
12 | a:link
13 | outline 0
14 |
15 | h1, h2, h3
16 | margin-top 0
17 |
18 | h1.loading
19 | color #000
20 |
21 | header, footer, section.route
22 | border 1px dashed #000
23 | padding 1em
24 |
25 | header
26 | background-color #999
27 |
28 | footer, header.sub
29 | background-color #666
30 |
31 | footer
32 | text-align center
33 |
34 | section.route
35 | background-color darken(myPrimaryColor, 25)
36 |
37 | .main-outlet
38 | background-color darken(myPrimaryColor, 28)
39 | min-height 250px
40 |
--------------------------------------------------------------------------------
/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Angular 2 Coverage
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
23 |
24 |
25 |
26 |
27 | Loading...
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/main.ts:
--------------------------------------------------------------------------------
1 | import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
2 | import {AppModule} from './app.module';
3 |
4 | platformBrowserDynamic().bootstrapModule(AppModule);
5 |
--------------------------------------------------------------------------------
/app/models/person.ts:
--------------------------------------------------------------------------------
1 | export class Person {
2 | // noinspection JSUnusedGlobalSymbols
3 | constructor(public id: number, public name: string, public age: number, public hobby: string) {
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/app/routes/app/app.component.html:
--------------------------------------------------------------------------------
1 |
8 |
11 |
14 |
--------------------------------------------------------------------------------
/app/routes/app/app.component.spec.ts:
--------------------------------------------------------------------------------
1 | import {APP_BASE_HREF} from '@angular/common';
2 | import {async, ComponentFixture, TestBed} from '@angular/core/testing';
3 | import {By} from '@angular/platform-browser';
4 | import {AppComponent} from './app.component';
5 | import {AppModule} from '../../app.module';
6 |
7 | describe('app.component.ts', () => {
8 |
9 | let fix: ComponentFixture;
10 | let instance: AppComponent;
11 |
12 | beforeEach(async(() => {
13 | TestBed.configureTestingModule({
14 | imports: [AppModule],
15 | providers: [{provide: APP_BASE_HREF, useValue: '/'}]
16 | }).compileComponents()
17 | .then(() => {
18 | fix = TestBed.createComponent(AppComponent);
19 | instance = fix.componentInstance;
20 | });
21 | }));
22 |
23 | it('should instantiate component', () => {
24 | expect(instance).toEqual(jasmine.any(AppComponent));
25 | });
26 |
27 | it('should have expected text', () => {
28 | let el = fix.debugElement.query(By.css('h1')).nativeElement;
29 | expect(el.textContent).toMatch(/angular 2 app/i);
30 | });
31 |
32 | });
33 |
--------------------------------------------------------------------------------
/app/routes/app/app.component.styl:
--------------------------------------------------------------------------------
1 | @import 'colors'
2 |
3 | h1
4 | color myPrimaryColor
5 | text-shadow 2px 2px 3px #777
6 |
7 | a
8 | border-radius 3px
9 | color #FFF
10 | font-weight bold
11 | padding 0.2em
12 | text-decoration underline
13 |
14 | a.active
15 | background-color myPrimaryColor
16 |
--------------------------------------------------------------------------------
/app/routes/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import {Component} from '@angular/core';
2 |
3 | @Component({
4 | selector: 'my-app',
5 | templateUrl: 'build/routes/app/app.component.html',
6 | styleUrls: ['build/routes/app/app.component.css']
7 | })
8 |
9 | export class AppComponent {
10 | }
11 |
--------------------------------------------------------------------------------
/app/routes/route1/detail/route1-detail.component.html:
--------------------------------------------------------------------------------
1 |
2 | ROUTE 1 DETAIL VIEW
3 |
4 |
{{person | json}}
5 |
6 |
7 |
Can't find your man
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/routes/route1/detail/route1-detail.component.spec.ts:
--------------------------------------------------------------------------------
1 | import {APP_BASE_HREF} from '@angular/common';
2 | import {async, ComponentFixture, TestBed} from '@angular/core/testing';
3 | import {By} from '@angular/platform-browser';
4 | import {AppModule} from '../../../app.module';
5 | import {persons} from '../../../data/persons';
6 | import {Route1DetailComponent} from './route1-detail.component';
7 |
8 | // HTTP mocking imports
9 | import {BaseRequestOptions, Http, Response, ResponseOptions} from '@angular/http';
10 | import {MockBackend, MockConnection} from '@angular/http/testing';
11 |
12 | describe('route1-detail.component.ts', () => {
13 |
14 | let fix: ComponentFixture;
15 | let instance: Route1DetailComponent;
16 | let injector: any;
17 |
18 | beforeEach(async(() => {
19 | TestBed.configureTestingModule({
20 | imports: [AppModule],
21 | providers: [{provide: APP_BASE_HREF, useValue: '/'},
22 | MockBackend,
23 | BaseRequestOptions,
24 | {
25 | provide: Http,
26 | useFactory: (pBackend: MockBackend, pOptions: BaseRequestOptions) => {
27 | return new Http(pBackend, pOptions);
28 | },
29 | deps: [MockBackend, BaseRequestOptions]
30 | }]
31 | }).compileComponents()
32 | .then(() => {
33 | fix = TestBed.createComponent(Route1DetailComponent);
34 | instance = fix.componentInstance;
35 | injector = fix.debugElement.injector;
36 | });
37 | }));
38 |
39 | it('should instantiate component', () => {
40 | expect(instance).toEqual(jasmine.any(Route1DetailComponent));
41 | });
42 |
43 | it('should have expected text', () => {
44 | let el = fix.debugElement.query(By.css('section.route1-detail')).nativeElement;
45 | expect(el.textContent).toMatch(/route 1 detail view/i);
46 | });
47 |
48 | it('getPerson()', async(() => {
49 | let backend = injector.get(MockBackend);
50 | backend.connections.subscribe(
51 | (connection: MockConnection) => {
52 | connection.mockRespond(new Response(
53 | new ResponseOptions({
54 | body: persons
55 | }
56 | )));
57 | });
58 |
59 | instance.getPerson(instance.DEFAULT_ID);
60 | expect(instance.person.name).toBe('Asa Israel');
61 | }));
62 |
63 | it('getPerson() invalid ID', async(() => {
64 | const INVALID_ID = 9527;
65 |
66 | let backend = injector.get(MockBackend);
67 | backend.connections.subscribe(
68 | (connection: MockConnection) => {
69 | connection.mockRespond(new Response(
70 | new ResponseOptions({
71 | body: persons
72 | }
73 | )));
74 | });
75 |
76 | instance.getPerson(INVALID_ID);
77 | expect(instance.person).toBeUndefined();
78 | }));
79 |
80 | it('getPerson() failure', async(() => {
81 | let backend = injector.get(MockBackend);
82 | backend.connections.subscribe(
83 | (connection: MockConnection) => {
84 | connection.mockError(new Error('error'));
85 | });
86 |
87 | instance.getPerson(instance.DEFAULT_ID);
88 | expect(instance.person).toBeUndefined();
89 | }));
90 |
91 | });
92 |
--------------------------------------------------------------------------------
/app/routes/route1/detail/route1-detail.component.styl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/danday74/angular2-coverage/a72d6e6cf40b5827ae04b9dd15f12fd39391bc2a/app/routes/route1/detail/route1-detail.component.styl
--------------------------------------------------------------------------------
/app/routes/route1/detail/route1-detail.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit} from '@angular/core';
2 | import {ActivatedRoute} from '@angular/router';
3 | import {Person} from '../../../models/person';
4 | import {PersonService} from '../../../services/person.service';
5 | import 'rxjs/add/operator/mergeMap';
6 | import 'rxjs/add/operator/publish';
7 |
8 | @Component({
9 | templateUrl: 'build/routes/route1/detail/route1-detail.component.html',
10 | styleUrls: ['build/routes/route1/detail/route1-detail.component.css']
11 | })
12 |
13 | export class Route1DetailComponent implements OnInit {
14 | public DEFAULT_ID: number = 1;
15 | public person: Person;
16 |
17 | constructor(public route: ActivatedRoute, private personService: PersonService) {
18 | }
19 |
20 | /* istanbul ignore next */
21 | // noinspection JSUnusedGlobalSymbols
22 | ngOnInit() {
23 |
24 | let paramsStream = this.route.params
25 | .map((params) => parseInt(params['id'], 10))
26 | .map((id) => !isNaN(id) ? id : this.DEFAULT_ID);
27 |
28 | // We use flatMap instead of map to prevent this stream being a metastream - i.e. stream of streams
29 | let responseStream = paramsStream.flatMap((id) => {
30 | // noinspection UnnecessaryLocalVariableJS
31 | let personStream = this.personService.getPerson(id);
32 | return personStream;
33 | }).publish().refCount();
34 |
35 | responseStream.subscribe((person: Person) => {
36 | this.person = person;
37 | },
38 | (err) => console.error('oops', err)
39 | );
40 | }
41 |
42 | // For testing purposes only since ngOnInit() is currently ignored
43 | // The correct RXJS approach is seen above
44 | getPerson(id: number): void {
45 | this.personService.getPerson(id)
46 | .subscribe(
47 | (person) => {
48 | this.person = person;
49 | },
50 | (err) => console.error('oops', err));
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/app/routes/route1/list/route1-list.component.html:
--------------------------------------------------------------------------------
1 |
2 | ROUTE 1 LIST VIEW
3 |
4 | -
5 | {{person.name}}
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/routes/route1/list/route1-list.component.spec.ts:
--------------------------------------------------------------------------------
1 | import {APP_BASE_HREF} from '@angular/common';
2 | import {async, ComponentFixture, TestBed} from '@angular/core/testing';
3 | import {By} from '@angular/platform-browser';
4 | import {AppModule} from '../../../app.module';
5 | import {persons} from '../../../data/persons';
6 | import {Route1ListComponent} from './route1-list.component';
7 |
8 | // HTTP mocking imports
9 | import {BaseRequestOptions, Http, Response, ResponseOptions} from '@angular/http';
10 | import {MockBackend, MockConnection} from '@angular/http/testing';
11 |
12 | describe('route1-list.component.ts', () => {
13 |
14 | let fix: ComponentFixture;
15 | let instance: Route1ListComponent;
16 | let injector: any;
17 |
18 | beforeEach(async(() => {
19 | TestBed.configureTestingModule({
20 | imports: [AppModule],
21 | providers: [{provide: APP_BASE_HREF, useValue: '/'},
22 | MockBackend,
23 | BaseRequestOptions,
24 | {
25 | provide: Http,
26 | useFactory: (pBackend: MockBackend, pOptions: BaseRequestOptions) => {
27 | return new Http(pBackend, pOptions);
28 | },
29 | deps: [MockBackend, BaseRequestOptions]
30 | }]
31 | }).compileComponents()
32 | .then(() => {
33 | fix = TestBed.createComponent(Route1ListComponent);
34 | instance = fix.componentInstance;
35 | injector = fix.debugElement.injector;
36 | });
37 | }));
38 |
39 | it('should instantiate component', () => {
40 | expect(instance).toEqual(jasmine.any(Route1ListComponent));
41 | });
42 |
43 | it('should have expected text', () => {
44 | let el = fix.debugElement.query(By.css('section.route1-list')).nativeElement;
45 | expect(el.textContent).toMatch(/route 1 list view/i);
46 | });
47 |
48 | it('ngOnInit()', async(() => {
49 | let backend = injector.get(MockBackend);
50 | backend.connections.subscribe(
51 | (connection: MockConnection) => {
52 | connection.mockRespond(new Response(
53 | new ResponseOptions({
54 | body: persons
55 | }
56 | )));
57 | });
58 |
59 | fix.detectChanges(); // Calls instance.ngOnInit()
60 | expect(instance.persons.length).toBe(3);
61 | }));
62 |
63 | it('ngOnInit() failure', async(() => {
64 | let backend = injector.get(MockBackend);
65 | backend.connections.subscribe(
66 | (connection: MockConnection) => {
67 | connection.mockError(new Error('error'));
68 | });
69 |
70 | fix.detectChanges(); // Calls instance.ngOnInit()
71 | expect(instance.persons).toBeUndefined();
72 | }));
73 |
74 | });
75 |
--------------------------------------------------------------------------------
/app/routes/route1/list/route1-list.component.styl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/danday74/angular2-coverage/a72d6e6cf40b5827ae04b9dd15f12fd39391bc2a/app/routes/route1/list/route1-list.component.styl
--------------------------------------------------------------------------------
/app/routes/route1/list/route1-list.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit} from '@angular/core';
2 | import {Person} from '../../../models/person';
3 | import {PersonService} from '../../../services/person.service';
4 |
5 | @Component({
6 | templateUrl: 'build/routes/route1/list/route1-list.component.html',
7 | styleUrls: ['build/routes/route1/list/route1-list.component.css']
8 | })
9 |
10 | export class Route1ListComponent implements OnInit {
11 | // noinspection JSMismatchedCollectionQueryUpdate
12 | public persons: Person[];
13 |
14 | constructor(private personService: PersonService) {
15 | console.log('Look at me in Chrome, sourcemaps are working!');
16 | }
17 |
18 | // noinspection JSUnusedGlobalSymbols
19 | ngOnInit() {
20 | this.personService.getPersons()
21 | .subscribe(
22 | (persons) => {
23 | this.persons = persons;
24 | },
25 | (err) => console.error('oops', err));
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/app/routes/route1/route1.component.html:
--------------------------------------------------------------------------------
1 |
4 |
5 |
--------------------------------------------------------------------------------
/app/routes/route1/route1.component.spec.ts:
--------------------------------------------------------------------------------
1 | import {APP_BASE_HREF} from '@angular/common';
2 | import {async, ComponentFixture, TestBed} from '@angular/core/testing';
3 | import {By} from '@angular/platform-browser';
4 | import {AppModule} from '../../app.module';
5 | import {Route1Component} from './route1.component';
6 |
7 | describe('route1.component.ts', () => {
8 |
9 | let fix: ComponentFixture;
10 | let instance: Route1Component;
11 |
12 | beforeEach(async(() => {
13 | TestBed.configureTestingModule({
14 | imports: [AppModule],
15 | providers: [{provide: APP_BASE_HREF, useValue: '/'}]
16 | }).compileComponents()
17 | .then(() => {
18 | fix = TestBed.createComponent(Route1Component);
19 | instance = fix.componentInstance;
20 | });
21 | }));
22 |
23 | it('should instantiate component', () => {
24 | expect(instance).toEqual(jasmine.any(Route1Component));
25 | });
26 |
27 | it('should have expected text', () => {
28 | let el = fix.debugElement.query(By.css('header.sub')).nativeElement;
29 | expect(el.textContent).toMatch(/route 1 header/i);
30 | });
31 |
32 | });
33 |
--------------------------------------------------------------------------------
/app/routes/route1/route1.component.styl:
--------------------------------------------------------------------------------
1 | header
2 | font-weight bold
3 | text-shadow 2px 2px 3px #333
4 |
--------------------------------------------------------------------------------
/app/routes/route1/route1.component.ts:
--------------------------------------------------------------------------------
1 | import {Component} from '@angular/core';
2 |
3 | @Component({
4 | templateUrl: 'build/routes/route1/route1.component.html',
5 | styleUrls: ['build/routes/route1/route1.component.css']
6 | })
7 |
8 | export class Route1Component {
9 | }
10 |
--------------------------------------------------------------------------------
/app/routes/route2/route2.component.html:
--------------------------------------------------------------------------------
1 |
2 | ROUTE 2 VIEW
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/routes/route2/route2.component.spec.ts:
--------------------------------------------------------------------------------
1 | import {APP_BASE_HREF} from '@angular/common';
2 | import {async, ComponentFixture, TestBed} from '@angular/core/testing';
3 | import {Router} from '@angular/router';
4 | import {AppModule} from '../../app.module';
5 | import {Route2Component} from './route2.component';
6 |
7 | describe('route2.component.ts', () => {
8 |
9 | let fix: ComponentFixture;
10 | let instance: Route2Component;
11 | let injector: any;
12 |
13 | beforeEach(async(() => {
14 | TestBed.configureTestingModule({
15 | imports: [AppModule],
16 | providers: [{provide: APP_BASE_HREF, useValue: '/'}]
17 | }).compileComponents()
18 | .then(() => {
19 | fix = TestBed.createComponent(Route2Component);
20 | instance = fix.componentInstance;
21 | injector = fix.debugElement.injector;
22 | });
23 | }));
24 |
25 | it('should instantiate component', () => {
26 | expect(instance).toEqual(jasmine.any(Route2Component));
27 | });
28 |
29 | it('should allow lodash access', () => {
30 | expect(instance.numArray).toEqual([3, 6, 9]);
31 | });
32 |
33 | it('goToRoute1()', () => {
34 | let router = injector.get(Router);
35 | router.navigate = jasmine.createSpy('navigate');
36 | instance.goToRoute1();
37 | expect(router.navigate).toHaveBeenCalledWith(['/route1']);
38 | });
39 |
40 | it('goToRoute1(id: number)', () => {
41 | let router = injector.get(Router);
42 | router.navigate = jasmine.createSpy('navigate');
43 | instance.goToRoute1(10);
44 | expect(router.navigate).toHaveBeenCalledWith(['/route1', 10]);
45 | });
46 |
47 | });
48 |
--------------------------------------------------------------------------------
/app/routes/route2/route2.component.styl:
--------------------------------------------------------------------------------
1 | .row
2 | text-align center
3 |
4 | button
5 | color #333
6 | font-weight bold
7 | padding 0.3em
8 |
--------------------------------------------------------------------------------
/app/routes/route2/route2.component.ts:
--------------------------------------------------------------------------------
1 | import {Component} from '@angular/core';
2 | import {Router} from '@angular/router';
3 | import * as _ from 'lodash';
4 |
5 | @Component({
6 | templateUrl: 'build/routes/route2/route2.component.html',
7 | styleUrls: ['build/routes/route2/route2.component.css']
8 | })
9 |
10 | export class Route2Component {
11 | public numArray: number[];
12 |
13 | constructor(private router: Router) {
14 | // numArray is an array of numbers and thus type can be inferred
15 | this.numArray = _.map([1, 2, 3], (n) => {
16 | return n * 3;
17 | });
18 | }
19 |
20 | goToRoute1(id?: number): void {
21 | if (id == null) {
22 | this.router.navigate(['/route1']);
23 | } else {
24 | this.router.navigate(['/route1', id]);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/app/services/person.service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from '@angular/core';
2 | import {Http, Response} from '@angular/http';
3 | import {Person} from '../models/person';
4 | import 'rxjs/add/operator/catch';
5 | import 'rxjs/add/operator/map';
6 | import {Observable} from 'rxjs/Observable';
7 |
8 | @Injectable()
9 | export class PersonService {
10 | private personsUrl: string = 'app/data/persons.json';
11 |
12 | static handleError(err: any): Observable {
13 | let errMsg = err.message;
14 | console.error(errMsg);
15 | return Observable.throw(errMsg);
16 | }
17 |
18 | constructor(private http: Http) {
19 | }
20 |
21 | getPersons(): Observable {
22 | return this.http.get(this.personsUrl)
23 | .map(
24 | (res: Response) => {
25 | return res.json();
26 | }
27 | )
28 | .catch(PersonService.handleError);
29 | }
30 |
31 | getPerson(id: number): Observable {
32 | return this.getPersons()
33 | .map((persons) => persons.filter((person) => person.id === id)[0]);
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/git-hook-pre-push.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # This hook will PREVENT a GIT push where ..
4 | # * The build is passing AND a commit message starts with WIP
5 | # * The build is failing AND a commit message does not start with WIP
6 | # * The build is failing AND the branch is master or develop
7 |
8 | RED='\033[0;31m';
9 | YELLOW='\033[0;33m';
10 | GREEN='\033[0;32m';
11 | NC='\033[0m'; # No color
12 |
13 | echo;
14 | echo -e "pre-push: Executing pre-push git hook";
15 | echo -e "pre-push: Before pushing lets try building ..";
16 | echo;
17 |
18 | npm run build -s;
19 | if [ $? -eq 0 ]; then
20 | build=true;
21 | echo;
22 | echo -e "pre-push: Build passed";
23 | else
24 | build=false;
25 | echo;
26 | echo -e "pre-push: Build failed";
27 | fi
28 |
29 | remote="$1";
30 | url="$2";
31 | z40=0000000000000000000000000000000000000000;
32 | wip=false;
33 | branch=`git symbolic-ref --short HEAD`;
34 | prevent=false;
35 |
36 | while read local_ref local_sha remote_ref remote_sha; do
37 | if [ "$local_sha" = ${z40} ]; then
38 | # Handle delete
39 | :
40 | else
41 | if [ "$remote_sha" = ${z40} ]; then
42 | # New branch, examine all commits
43 | range="$local_sha";
44 | else
45 | # Update to existing branch, examine new commits
46 | range="$remote_sha..$local_sha";
47 | fi
48 |
49 | # Check for WIP commit
50 | commit=`git rev-list -n 1 --grep '^WIP' "$range"`;
51 | if [ -n "$commit" ]; then
52 | echo >&2 "pre-push: Found WIP commit";
53 | wip=true;
54 | fi
55 | fi
56 | done
57 |
58 | echo -e "pre-push: SUMMARY: build=${build}, WIP=${wip}, branch=${branch}";
59 |
60 | if [ "${build}" == "true" ] && [ "${wip}" == "true" ]; then
61 | echo -e "pre-push: ${RED}Push prevented .. The build is passing AND a commit message starts with WIP";
62 | echo -e " TIP: Change your commit messages with ..";
63 | echo -e " git commit --amend -m \"new message\" OR git rebase -i (then use reword (r))${NC}";
64 | prevent=true;
65 | fi
66 |
67 | if [ "${build}" == "false" ] && [ "${wip}" == "false" ]; then
68 | echo -e "pre-push: ${RED}Push prevented .. The build is failing AND a commit message does not start with WIP";
69 | echo -e " TIP: Fix the build (preferred) OR change your commit messages with ..";
70 | echo -e " git commit --amend -m \"new message\" OR git rebase -i (then use reword (r))${NC}";
71 | prevent=true;
72 | fi
73 |
74 | if [ "${build}" == "false" ] && [ "${branch}" == "master" ]; then
75 | echo -e "pre-push: ${RED}Push prevented .. The build is failing AND the branch is master${NC}";
76 | prevent=true;
77 | fi
78 |
79 | if [ "${build}" == "false" ] && [ "${branch}" == "develop" ]; then
80 | echo -e "pre-push: ${RED}Push prevented .. The build is failing AND the branch is develop${NC}";
81 | prevent=true;
82 | fi
83 |
84 | if [ "${prevent}" == "false" ] && [ "${wip}" == "true" ]; then
85 | echo -e "pre-push: ${YELLOW}Push permitted but it is against policy to push failing code - Please fix ASAP${NC}";
86 | fi
87 |
88 | if [ "${prevent}" == "false" ] && [ "${wip}" == "false" ]; then
89 | echo -e "pre-push: ${GREEN}Push permitted${NC}";
90 | fi
91 |
92 | test "${prevent}" == "false";
93 | exitCode=$?;
94 | exit ${exitCode};
95 |
--------------------------------------------------------------------------------
/gulp-core.js:
--------------------------------------------------------------------------------
1 | const gulp = require('gulp');
2 | const gulpif = require('gulp-if');
3 | const intercept = require('gulp-intercept');
4 | const sourcemaps = require('gulp-sourcemaps');
5 | const browserSync = require('browser-sync').create();
6 | const chalk = require('chalk');
7 | const config = require('./gulp.config');
8 | const path = require('path');
9 | const runSequence = require('run-sequence');
10 | const VALID_MODES = ['build', 'start', 'test'];
11 | const DEFAULT_MODE = VALID_MODES[1];
12 | let modeCache;
13 |
14 | const getMode = () => {
15 | if (modeCache != null) return modeCache;
16 | modeCache = (process.argv.length > 2) ? process.argv[2] : DEFAULT_MODE;
17 | if (!VALID_MODES.includes(modeCache)) {
18 | modeCache = DEFAULT_MODE;
19 | }
20 | return modeCache;
21 | };
22 |
23 | const mainHeading = (taskName, msg) => {
24 | console.log(chalk.bgWhite.black(`${taskName}: ${msg}`));
25 | };
26 |
27 | const subHeading = (taskName, msg) => {
28 | taskName = chalk.cyan(taskName);
29 | console.log(`${taskName}: ${msg}`);
30 | };
31 |
32 | const link = (url) => {
33 | return chalk.bgCyan.black(url);
34 | };
35 |
36 | const serious = (msg) => {
37 | return chalk.bgRed.white(msg);
38 | };
39 |
40 | const watch = (msg) => {
41 | return chalk.bgBlue.white(msg);
42 | };
43 |
44 | module.exports = {
45 | gulp,
46 | gulpif,
47 | intercept,
48 | sourcemaps,
49 | browserSync,
50 | chalk,
51 | config,
52 | path,
53 | runSequence,
54 | getMode,
55 | mainHeading,
56 | subHeading,
57 | link,
58 | serious,
59 | watch
60 | };
61 |
--------------------------------------------------------------------------------
/gulp.config.js:
--------------------------------------------------------------------------------
1 | const GLOBAL_STYL = 'app/global.styl';
2 | const GLOBAL_THRESHOLD = 50;
3 | // noinspection JSUnusedGlobalSymbols
4 | const config = {
5 | browserSyncPort: 4000,
6 | apiPhp: 'http://localhost:7777',
7 | vmPhp: 'https://10.20.14.108:9100',
8 | files: {
9 | js: ['*.js', 'gulp/**/*.js'],
10 | ts: ['app/**/*.ts'],
11 | tsd: ['typings/**/*.d.ts'],
12 | styl: ['app/**/*.styl', '!' + GLOBAL_STYL],
13 | stylStream: [GLOBAL_STYL],
14 | copy: [
15 | 'app/**/*.html',
16 | 'app/**/*.css',
17 | 'app/**/*.jpg',
18 | 'app/**/*.png',
19 | 'app/**/*.ico',
20 | 'app/**/*.eot',
21 | 'app/**/*.svg',
22 | 'app/**/*.ttf',
23 | 'app/**/*.woff',
24 | 'app/**/*.woff2',
25 | 'app/**/*.min.js'
26 | ]
27 | },
28 | coverageThresholds: {
29 | statements: GLOBAL_THRESHOLD,
30 | branches: GLOBAL_THRESHOLD,
31 | functions: GLOBAL_THRESHOLD,
32 | lines: GLOBAL_THRESHOLD
33 | },
34 | coverageOutput: 'coverage/coverage-js.json',
35 | coverageReports: {
36 | 'html': 'coverage/html',
37 | 'json-summary': 'coverage/coverage-ts-summary.json',
38 | 'json': 'coverage/coverage-ts.json',
39 | 'text-summary': 'coverage/coverage-ts-summary.txt',
40 | 'text': 'coverage/coverage-ts.txt'
41 | },
42 | sourcemaps: {
43 | dir: '.',
44 | options: {
45 | includeContent: false,
46 | // Returns 'app' file relative to 'build' file
47 | // Used for locating the original file
48 | sourceRoot: () => {
49 | return '../app';
50 | }
51 | }
52 | }
53 | };
54 |
55 | module.exports = config;
56 |
--------------------------------------------------------------------------------
/gulp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/danday74/angular2-coverage/a72d6e6cf40b5827ae04b9dd15f12fd39391bc2a/gulp.png
--------------------------------------------------------------------------------
/gulp/build-hard.js:
--------------------------------------------------------------------------------
1 | const TASK = 'build-hard';
2 | const core = require('../gulp-core');
3 |
4 | core.gulp.task(TASK, (done) => {
5 | core.mainHeading(TASK, 'Starting build');
6 | core.runSequence(
7 | 'eslint-hard',
8 | 'build-clean',
9 | 'tslint-hard',
10 | 'ts-2-js-hard',
11 | 'styl-2-css-hard',
12 | 'styl-2-css-stream-hard',
13 | 'copy',
14 | done);
15 | });
16 |
--------------------------------------------------------------------------------
/gulp/build-soft.js:
--------------------------------------------------------------------------------
1 | const TASK = 'build-soft';
2 | const core = require('../gulp-core');
3 |
4 | core.gulp.task(TASK, (done) => {
5 | core.mainHeading(TASK, 'Starting build');
6 | core.runSequence(
7 | 'eslint-hard',
8 | 'build-clean',
9 | 'tslint-soft',
10 | 'ts-2-js-soft',
11 | 'styl-2-css-soft',
12 | 'styl-2-css-stream-soft',
13 | 'copy',
14 | done);
15 | });
16 |
--------------------------------------------------------------------------------
/gulp/low-level-coverage-tasks/coverage-clean.js:
--------------------------------------------------------------------------------
1 | const TASK = 'coverage-clean';
2 | const core = require('../../gulp-core');
3 | const del = require('del');
4 |
5 | core.gulp.task(TASK, () => {
6 | core.subHeading(TASK, 'Deleting coverage folder');
7 | return del(['coverage']);
8 | });
9 |
--------------------------------------------------------------------------------
/gulp/low-level-coverage-tasks/coverage-enforcer-hard.js:
--------------------------------------------------------------------------------
1 | const TASK = 'coverage-enforcer-hard';
2 | const core = require('../../gulp-core');
3 | const enforcer = require('./enforcer-function');
4 |
5 | core.gulp.task(TASK, () => {
6 | return core.gulp
7 | .src([core.config.coverageReports['json-summary']])
8 | .pipe(core.intercept((file) => {
9 | let result = enforcer(file);
10 | core.subHeading(TASK, result.message);
11 | if (result.success === false) {
12 | process.exit(1);
13 | }
14 | }));
15 | });
16 |
--------------------------------------------------------------------------------
/gulp/low-level-coverage-tasks/coverage-enforcer-soft.js:
--------------------------------------------------------------------------------
1 | const TASK = 'coverage-enforcer-soft';
2 | const core = require('../../gulp-core');
3 | const enforcer = require('./enforcer-function');
4 |
5 | core.gulp.task(TASK, () => {
6 | return core.gulp
7 | .src([core.config.coverageReports['json-summary']])
8 | .pipe(core.intercept((file) => {
9 | let result = enforcer(file);
10 | core.subHeading(TASK, result.message);
11 | }));
12 | });
13 |
--------------------------------------------------------------------------------
/gulp/low-level-coverage-tasks/coverage-main.js:
--------------------------------------------------------------------------------
1 | const TASK = 'coverage-main';
2 | const core = require('../../gulp-core');
3 | const remapIstanbul = require('remap-istanbul/lib/gulpRemapIstanbul');
4 |
5 | core.gulp.task(TASK, () => {
6 | core.subHeading(TASK, 'Generating remapped coverage reports');
7 | return core.gulp
8 | .src(core.config.coverageOutput)
9 | .pipe(remapIstanbul({
10 | reports: core.config.coverageReports
11 | }));
12 | });
13 |
--------------------------------------------------------------------------------
/gulp/low-level-coverage-tasks/coverage-open.js:
--------------------------------------------------------------------------------
1 | const TASK = 'coverage-open';
2 | const core = require('../../gulp-core');
3 |
4 | core.gulp.task(TASK, () => {
5 | return core.gulp
6 | .src(core.config.coverageReports['html'] + '/index.html')
7 | .pipe(core.intercept((file) => {
8 | let link = core.link(`file:///${file.path.replace(/\\/g, '/')}`);
9 | core.subHeading(TASK, `CTRL CLICK to open ${link}`);
10 | }));
11 | });
12 |
--------------------------------------------------------------------------------
/gulp/low-level-coverage-tasks/coverage-summary-long.js:
--------------------------------------------------------------------------------
1 | const TASK = 'coverage-summary-long';
2 | const core = require('../../gulp-core');
3 |
4 | core.gulp.task(TASK, () => {
5 | core.subHeading(TASK, '...');
6 | return core.gulp
7 | .src([core.config.coverageReports['text'], core.config.coverageReports['text-summary']])
8 | .pipe(core.intercept((file) => {
9 | console.log(file.contents.toString());
10 | }));
11 | });
12 |
--------------------------------------------------------------------------------
/gulp/low-level-coverage-tasks/coverage-summary-short.js:
--------------------------------------------------------------------------------
1 | const TASK = 'coverage-summary-short';
2 | const core = require('../../gulp-core');
3 |
4 | core.gulp.task(TASK, () => {
5 | core.subHeading(TASK, '...');
6 | return core.gulp
7 | .src([core.config.coverageReports['text-summary']])
8 | .pipe(core.intercept((file) => {
9 | console.log(file.contents.toString());
10 | }));
11 | });
12 |
--------------------------------------------------------------------------------
/gulp/low-level-coverage-tasks/enforcer-function.js:
--------------------------------------------------------------------------------
1 | const core = require('../../gulp-core');
2 |
3 | module.exports = (file) => {
4 |
5 | let thresholds = core.config.coverageThresholds;
6 | let failedThresholds = [];
7 | let total = JSON.parse(file.contents.toString()).total;
8 | let actuals = {
9 | statements: total.statements.pct,
10 | branches: total.branches.pct,
11 | functions: total.functions.pct,
12 | lines: total.lines.pct
13 | };
14 |
15 | for (let key of Object.keys(actuals)) {
16 | if (actuals[key] < thresholds[key]) failedThresholds.push(key);
17 | }
18 |
19 | let strThresholds = ` of ${JSON.stringify(thresholds)}`;
20 | if (failedThresholds.length > 0) {
21 | return {
22 | message: core.chalk.red('FAILED thresholds') + strThresholds,
23 | success: false
24 | };
25 | } else {
26 | return {
27 | message: core.chalk.green('PASSED thresholds') + strThresholds,
28 | success: true
29 | };
30 | }
31 | };
32 |
--------------------------------------------------------------------------------
/gulp/low-level-misc-tasks/build-clean.js:
--------------------------------------------------------------------------------
1 | const TASK = 'build-clean';
2 | const core = require('../../gulp-core');
3 | const del = require('del');
4 |
5 | core.gulp.task(TASK, () => {
6 | core.subHeading(TASK, 'Deleting build folder');
7 | return del(['build']);
8 | });
9 |
--------------------------------------------------------------------------------
/gulp/low-level-misc-tasks/copy.js:
--------------------------------------------------------------------------------
1 | const TASK = 'copy';
2 | const core = require('../../gulp-core');
3 |
4 | core.gulp.task(TASK, () => {
5 | core.subHeading(TASK, 'Copying from \'app\' to \'build\'');
6 | return core.gulp
7 | .src(core.config.files.copy)
8 | .pipe(core.gulp.dest('build'));
9 | });
10 |
--------------------------------------------------------------------------------
/gulp/low-level-misc-tasks/eslint-hard.js:
--------------------------------------------------------------------------------
1 | const TASK = 'eslint-hard';
2 | const core = require('../../gulp-core');
3 | const eslint = require('gulp-eslint');
4 |
5 | core.gulp.task(TASK, () => {
6 | core.subHeading(TASK, 'Linting JavaScript');
7 | //noinspection JSCheckFunctionSignatures
8 | return core.gulp
9 | .src(core.config.files.js)
10 | .pipe(eslint())
11 | .pipe(eslint.format('stylish', process.stdout))
12 | .pipe(eslint.failAfterError())
13 | .on('error', () => {
14 | process.exit(1);
15 | });
16 | });
17 |
--------------------------------------------------------------------------------
/gulp/low-level-misc-tasks/karma-build-hard.js:
--------------------------------------------------------------------------------
1 | const TASK = 'karma-build-hard';
2 | const core = require('../../gulp-core');
3 | const Server = require('karma').Server;
4 |
5 | core.gulp.task(TASK, (done) => {
6 | core.subHeading(TASK, 'Running unit tests');
7 | new Server({
8 | configFile: core.path.join(__dirname, '../../karma.conf.js'),
9 | reporters: ['mocha', 'coverage']
10 | }, (exitCode) => {
11 | if (exitCode > 0) {
12 | process.exit(exitCode);
13 | }
14 | done();
15 | }).start();
16 | });
17 |
--------------------------------------------------------------------------------
/gulp/low-level-misc-tasks/karma-build-soft.js:
--------------------------------------------------------------------------------
1 | const TASK = 'karma-build-soft';
2 | const core = require('../../gulp-core');
3 | const Server = require('karma').Server;
4 |
5 | core.gulp.task(TASK, (done) => {
6 | core.subHeading(TASK, 'Running unit tests');
7 | new Server({
8 | configFile: core.path.join(__dirname, '../../karma.conf.js'),
9 | reporters: ['mocha', 'coverage']
10 | }, () => {
11 | done();
12 | }).start();
13 | });
14 |
--------------------------------------------------------------------------------
/gulp/low-level-misc-tasks/karma-watch.js:
--------------------------------------------------------------------------------
1 | const TASK = 'karma-watch';
2 | const core = require('../../gulp-core');
3 | const Server = require('karma').Server;
4 |
5 | core.gulp.task(TASK, (done) => {
6 | core.subHeading(TASK, 'Running unit tests');
7 | new Server({
8 | configFile: core.path.join(__dirname, '../../karma.conf.js'),
9 | reporters: ['super-dots', 'coverage']
10 | }, () => {
11 | console.log();
12 | done();
13 | }).start();
14 | });
15 |
--------------------------------------------------------------------------------
/gulp/low-level-misc-tasks/serve.js:
--------------------------------------------------------------------------------
1 | const TASK = 'serve';
2 | const core = require('../../gulp-core');
3 | const rewrite = require('connect-modrewrite');
4 |
5 | core.gulp.task(TASK, () => {
6 | core.browserSync.init({
7 | port: core.config.browserSyncPort,
8 | server: {
9 | baseDir: ['build', '.'],
10 | middleware: [
11 | rewrite([
12 | '^/api/(.*)$ ' + core.config.apiPhp + '/$1 [P]',
13 | '^/vm/(.*)$ ' + core.config.vmPhp + '/$1 [P]',
14 | '^[^\\.]*$ /index.html [L]'
15 | ])
16 | ]
17 | },
18 | open: false
19 | });
20 | core.browserSync.emitter.on('init', () => {
21 | // TODO: Should reload be here or inside timeout?
22 | core.browserSync.reload();
23 | setTimeout(() => {
24 | let link = core.link(`http://localhost:${core.config.browserSyncPort}`);
25 | core.mainHeading(TASK, `CTRL CLICK to open ${link}`);
26 | }, 1000);
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/gulp/low-level-misc-tasks/styl-2-css.js:
--------------------------------------------------------------------------------
1 | const core = require('../../gulp-core');
2 | const stylus = require('gulp-stylus');
3 | const nib = require('nib');
4 | const BASEMSG = 'Transpiling Stylus to CSS';
5 |
6 | const taskFunc = (TASK) => {
7 | let isStream = TASK.includes('stream');
8 | let msg = isStream ? `${BASEMSG} (streaming)` : BASEMSG;
9 | let srcFiles = isStream ? core.config.files.stylStream : core.config.files.styl;
10 | let isSoft = TASK.includes('soft');
11 |
12 | core.subHeading(TASK, msg);
13 | let myStylus = stylus({
14 | 'include css': true,
15 | // 'resolve url' : true,
16 | compress: true,
17 | use: nib(),
18 | include: 'app'
19 | });
20 |
21 | return core.gulp
22 | .src(srcFiles)
23 | // TODO: Enforce sourcemaps for dev env only
24 | .pipe(core.gulpif(true, core.sourcemaps.init()))
25 | .pipe(myStylus)
26 | .on('error', (err) => {
27 | console.log();
28 | console.log(err.message);
29 | if (isSoft) {
30 | if (isStream) {
31 | console.log(core.chalk.red(`Error whilst ${msg}`));
32 | console.log();
33 | } else {
34 | let serious1 = core.serious('Errors in a component\'s external stylesheets may cause unit test \'Failed to load CSS\' failures for that component');
35 | console.log(serious1);
36 | let serious2 = core.serious('This is because errors prevent CSS file writing ');
37 | console.log(serious2);
38 | console.log();
39 | }
40 | myStylus.emit('end');
41 | } else {
42 | process.exit(1);
43 | }
44 | })
45 | // TODO: Enforce sourcemaps for dev env only
46 | .pipe(core.gulpif(true, core.sourcemaps.write(
47 | core.config.sourcemaps.dir,
48 | core.config.sourcemaps.options)))
49 | .pipe(core.gulp.dest('build'))
50 | // Passing the match CSS object to browserSync.stream supports CSS injection and sourcemaps
51 | // However, the sourcemaps do not update on change without a manual refresh
52 | // Not passing the match CSS object to browserSync.stream fixes this but causes CSS injection failure
53 | .pipe(core.gulpif(isStream, core.browserSync.stream({match: '**/*.css'})));
54 | };
55 |
56 | const TASK1 = 'styl-2-css-soft';
57 | const TASK2 = 'styl-2-css-stream-soft';
58 | const TASK3 = 'styl-2-css-hard';
59 | const TASK4 = 'styl-2-css-stream-hard';
60 |
61 | core.gulp.task(TASK1, () => {
62 | return taskFunc(TASK1);
63 | });
64 |
65 | core.gulp.task(TASK2, () => {
66 | return taskFunc(TASK2);
67 | });
68 |
69 | core.gulp.task(TASK3, () => {
70 | return taskFunc(TASK3);
71 | });
72 |
73 | core.gulp.task(TASK4, () => {
74 | return taskFunc(TASK4);
75 | });
76 |
--------------------------------------------------------------------------------
/gulp/low-level-misc-tasks/ts-2-js-hard.js:
--------------------------------------------------------------------------------
1 | const TASK = 'ts-2-js-hard';
2 | const core = require('../../gulp-core');
3 | const typescript = require('gulp-typescript');
4 | let tscConfig = require('../../tsconfig.json');
5 | delete tscConfig.compilerOptions.outDir;
6 |
7 | core.gulp.task(TASK, () => {
8 | core.subHeading(TASK, 'Transpiling TypeScript to JavaScript');
9 | return core.gulp
10 | .src(core.config.files.ts.concat(core.config.files.tsd))
11 | // TODO: Enforce sourcemaps for dev env only
12 | .pipe(core.gulpif(true, core.sourcemaps.init()))
13 | .pipe(typescript(tscConfig.compilerOptions))
14 | .on('error', () => {
15 | process.exit(1);
16 | })
17 | // TODO: Enforce sourcemaps for dev env only
18 | .pipe(core.gulpif(true, core.sourcemaps.write(
19 | core.config.sourcemaps.dir,
20 | core.config.sourcemaps.options)))
21 | .pipe(core.gulp.dest('build'));
22 | });
23 |
--------------------------------------------------------------------------------
/gulp/low-level-misc-tasks/ts-2-js-soft.js:
--------------------------------------------------------------------------------
1 | const TASK = 'ts-2-js-soft';
2 | const core = require('../../gulp-core');
3 | const typescript = require('gulp-typescript');
4 | let tscConfig = require('../../tsconfig.json');
5 | delete tscConfig.compilerOptions.outDir;
6 |
7 | core.gulp.task(TASK, () => {
8 | core.subHeading(TASK, 'Transpiling TypeScript to JavaScript');
9 | return core.gulp
10 | .src(core.config.files.ts.concat(core.config.files.tsd))
11 | // TODO: Enforce sourcemaps for dev env only
12 | .pipe(core.gulpif(true, core.sourcemaps.init()))
13 | .pipe(typescript(tscConfig.compilerOptions))
14 | // TODO: Enforce sourcemaps for dev env only
15 | .pipe(core.gulpif(true, core.sourcemaps.write(
16 | core.config.sourcemaps.dir,
17 | core.config.sourcemaps.options)))
18 | .pipe(core.gulp.dest('build'));
19 | });
20 |
--------------------------------------------------------------------------------
/gulp/low-level-misc-tasks/tslint-hard.js:
--------------------------------------------------------------------------------
1 | const TASK = 'tslint-hard';
2 | const core = require('../../gulp-core');
3 | const tslint = require('gulp-tslint');
4 | const reporter = require('./tslint-reporter-function');
5 |
6 | core.gulp.task(TASK, () => {
7 | core.subHeading(TASK, 'Linting TypeScript');
8 | return core.gulp
9 | .src(core.config.files.ts)
10 | .pipe(tslint())
11 | .pipe(tslint.report(reporter, {
12 | emitError: true,
13 | summarizeFailureOutput: true
14 | }))
15 | .on('error', (err) => {
16 | console.log(err.message);
17 | process.exit(1);
18 | });
19 | });
20 |
--------------------------------------------------------------------------------
/gulp/low-level-misc-tasks/tslint-reporter-function.js:
--------------------------------------------------------------------------------
1 | const core = require('../../gulp-core');
2 | const DIR = 'app';
3 |
4 | module.exports = (errors, file) => {
5 | let temp = file.path.split(`${core.path.sep}${DIR}${core.path.sep}`)[1];
6 | let filePath = `${DIR}/${temp}`;
7 | console.log(filePath);
8 | for (let err of errors) {
9 | let line = err.startPosition.line + 1;
10 | let char = err.startPosition.character + 1;
11 | line = (` ${line}`).slice(-3);
12 | char = (` ${char}`).slice(-3);
13 | let strPos = `${line}:${char}`;
14 | let strChalk = core.chalk.red('error');
15 | let strErr = `${err.failure} (${err.ruleName})`;
16 | console.log(` ${strPos} ${strChalk} ${strErr}`);
17 | }
18 | };
19 |
--------------------------------------------------------------------------------
/gulp/low-level-misc-tasks/tslint-soft.js:
--------------------------------------------------------------------------------
1 | const TASK = 'tslint-soft';
2 | const core = require('../../gulp-core');
3 | const tslint = require('gulp-tslint');
4 | const reporter = require('./tslint-reporter-function');
5 |
6 | core.gulp.task(TASK, () => {
7 | core.subHeading(TASK, 'Linting TypeScript');
8 | return core.gulp
9 | .src(core.config.files.ts)
10 | .pipe(tslint())
11 | .pipe(tslint.report(reporter, {
12 | emitError: false,
13 | summarizeFailureOutput: true
14 | }));
15 | });
16 |
--------------------------------------------------------------------------------
/gulp/test-npm-build.js:
--------------------------------------------------------------------------------
1 | const TASK = 'test-npm-build';
2 | const core = require('../gulp-core');
3 |
4 | core.gulp.task(TASK, (done) => {
5 | core.mainHeading(TASK, 'Starting test run');
6 | core.runSequence(
7 | 'coverage-clean',
8 | 'karma-build-hard',
9 | 'coverage-main',
10 | 'coverage-summary-long',
11 | 'coverage-open',
12 | 'coverage-enforcer-hard',
13 | done);
14 | });
15 |
--------------------------------------------------------------------------------
/gulp/test-npm-start.js:
--------------------------------------------------------------------------------
1 | const TASK = 'test-npm-start';
2 | const core = require('../gulp-core');
3 |
4 | core.gulp.task(TASK, (done) => {
5 | core.mainHeading(TASK, 'Starting test run');
6 | core.runSequence(
7 | 'coverage-clean',
8 | 'karma-watch', // brief output
9 | 'coverage-main',
10 | 'coverage-summary-short', // brief summary
11 | 'coverage-open',
12 | 'coverage-enforcer-soft',
13 | done);
14 | });
15 |
--------------------------------------------------------------------------------
/gulp/test-npm-test.js:
--------------------------------------------------------------------------------
1 | const TASK = 'test-npm-test';
2 | const core = require('../gulp-core');
3 |
4 | core.gulp.task(TASK, (done) => {
5 | core.mainHeading(TASK, 'Starting test run');
6 | core.runSequence(
7 | 'coverage-clean',
8 | 'karma-build-soft',
9 | 'coverage-main',
10 | 'coverage-summary-long',
11 | 'coverage-open',
12 | 'coverage-enforcer-soft',
13 | done);
14 | });
15 |
--------------------------------------------------------------------------------
/gulp/watch.js:
--------------------------------------------------------------------------------
1 | const TASK = 'watch';
2 | const core = require('../gulp-core');
3 |
4 | core.gulp.task(TASK, () => {
5 | core.mainHeading(TASK, 'Watching files');
6 |
7 | core.gulp.task('reload', (done) => {
8 | // TODO: Should reload be here or inside timeout?
9 | core.browserSync.reload();
10 | setTimeout(() => {
11 | done();
12 | }, 1000);
13 | });
14 |
15 | core.gulp.task('xxwatchxx-copy', (done) => {
16 | console.log(core.watch('WATCH: copy'));
17 | core.runSequence(
18 | 'copy',
19 | 'reload',
20 | 'test-npm-start',
21 | done);
22 | });
23 |
24 | core.gulp.task('xxwatchxx-ts-2-js', (done) => {
25 | console.log(core.watch('WATCH: ts-2-js'));
26 | core.runSequence(
27 | 'tslint-soft',
28 | 'ts-2-js-soft',
29 | 'reload',
30 | 'test-npm-start',
31 | done);
32 | });
33 |
34 | core.gulp.task('xxwatchxx-styl-2-css', (done) => {
35 | console.log(core.watch('WATCH: styl-2-css'));
36 | core.runSequence(
37 | 'styl-2-css-soft',
38 | 'reload',
39 | 'test-npm-start',
40 | done);
41 | });
42 |
43 | core.gulp.watch(core.config.files.copy, ['xxwatchxx-copy']);
44 | core.gulp.watch(core.config.files.ts, ['xxwatchxx-ts-2-js']);
45 | core.gulp.watch(core.config.files.styl, ['xxwatchxx-styl-2-css']);
46 | core.gulp.watch(core.config.files.stylStream, ['styl-2-css-stream-soft']);
47 | });
48 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | const core = require('./gulp-core');
2 | const requireDir = require('require-dir');
3 | requireDir('gulp', {recurse: true});
4 |
5 | console.log('mode =', core.getMode());
6 |
7 | core.gulp.task('build', (done) => {
8 | core.runSequence(
9 | 'build-hard',
10 | 'test-npm-build',
11 | done);
12 | });
13 |
14 | core.gulp.task('start', (done) => {
15 | core.runSequence(
16 | 'build-soft',
17 | 'test-npm-start',
18 | ['serve', 'watch'],
19 | done);
20 | });
21 |
22 | core.gulp.task('test', (done) => {
23 | core.runSequence(
24 | 'build-soft',
25 | 'test-npm-test',
26 | done);
27 | });
28 |
29 | core.gulp.task('default', (done) => {
30 | core.runSequence(
31 | 'start',
32 | done);
33 | });
34 |
--------------------------------------------------------------------------------
/karma-test-shim.js:
--------------------------------------------------------------------------------
1 | /* global __karma__ */
2 | Error.stackTraceLimit = 0; // "No stacktrace"" is usually best for app testing.
3 |
4 | // Uncomment to get full stacktrace output. Sometimes helpful, usually not.
5 | // Error.stackTraceLimit = Infinity; //
6 |
7 | jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
8 |
9 | var builtPath = '/base/build/';
10 |
11 | __karma__.loaded = function () {
12 | };
13 |
14 | function isJsFile(path) {
15 | return path.slice(-3) == '.js';
16 | }
17 |
18 | function isSpecFile(path) {
19 | return /\.spec\.(.*\.)?js$/.test(path);
20 | }
21 |
22 | function isBuiltFile(path) {
23 | return isJsFile(path) && (path.substr(0, builtPath.length) == builtPath);
24 | }
25 |
26 | var allSpecFiles = Object.keys(window.__karma__.files)
27 | .filter(isSpecFile)
28 | .filter(isBuiltFile);
29 |
30 | // noinspection ES6ModulesDependencies, NodeModulesDependencies
31 | System.config({
32 | baseURL: '/base',
33 | // Extend usual application package list with test folder
34 | packages: {'testing': {main: 'index.js', defaultExtension: 'js'}},
35 |
36 | // Assume npm: is set in `paths` in systemjs.config
37 | // Map the angular testing umd bundles
38 | map: {
39 | '@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js',
40 | '@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js',
41 | '@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js',
42 | '@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js',
43 | '@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',
44 | '@angular/http/testing': 'npm:@angular/http/bundles/http-testing.umd.js',
45 | '@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js',
46 | '@angular/forms/testing': 'npm:@angular/forms/bundles/forms-testing.umd.js',
47 | },
48 | });
49 |
50 | System.import('systemjs.config.js')
51 | .then(initTestBed)
52 | .then(initTesting);
53 |
54 | function initTestBed() {
55 | // noinspection JSFileReferences
56 | return Promise.all([
57 | System.import('@angular/core/testing'),
58 | System.import('@angular/platform-browser-dynamic/testing')
59 | ])
60 |
61 | .then(function (providers) {
62 | var coreTesting = providers[0];
63 | var browserTesting = providers[1];
64 |
65 | coreTesting.TestBed.initTestEnvironment(
66 | browserTesting.BrowserDynamicTestingModule,
67 | browserTesting.platformBrowserDynamicTesting());
68 | });
69 | }
70 |
71 | // Import all spec files and start karma
72 | function initTesting() {
73 | return Promise.all(
74 | allSpecFiles.map(function (moduleName) {
75 | return System.import(moduleName);
76 | })
77 | )
78 | .then(__karma__.start, __karma__.error);
79 | }
80 |
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | module.exports = (config) => {
2 |
3 | config.set({
4 | basePath: '',
5 | frameworks: ['jasmine'],
6 | plugins: [
7 | require('karma-jasmine'),
8 | require('karma-phantomjs-launcher'),
9 | require('karma-coverage'),
10 | require('karma-mocha-reporter'),
11 | require('karma-super-dots-reporter')
12 | ],
13 |
14 | files: [
15 | // System.js for module loading
16 | 'node_modules/systemjs/dist/system.src.js',
17 |
18 | // Polyfills
19 | 'node_modules/core-js/client/shim.js',
20 | 'node_modules/reflect-metadata/Reflect.js',
21 |
22 | // zone.js
23 | 'node_modules/zone.js/dist/zone.js',
24 | 'node_modules/zone.js/dist/long-stack-trace-zone.js',
25 | 'node_modules/zone.js/dist/proxy.js',
26 | 'node_modules/zone.js/dist/sync-test.js',
27 | 'node_modules/zone.js/dist/jasmine-patch.js',
28 | 'node_modules/zone.js/dist/async-test.js',
29 | 'node_modules/zone.js/dist/fake-async-test.js',
30 |
31 | // RxJs
32 | {pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false},
33 | {pattern: 'node_modules/rxjs/**/*.js.map', included: false, watched: false},
34 |
35 | // Paths loaded via module imports:
36 | // Angular itself
37 | {pattern: 'node_modules/@angular/**/*.js', included: false, watched: false},
38 | {pattern: 'node_modules/@angular/**/*.js.map', included: false, watched: false},
39 | {pattern: 'systemjs.config.js', included: false, watched: false},
40 | 'karma-test-shim.js',
41 |
42 | // lodash
43 | {pattern: 'node_modules/lodash/**/*.js', included: false, watched: false},
44 |
45 | // Transpiled application & spec code paths loaded via module imports
46 | {pattern: 'build/**/*.js', included: false, watched: true},
47 | // Asset (HTML & CSS) paths loaded via Angular's component compiler
48 | // (these paths need to be rewritten, see proxies section)
49 | {pattern: 'build/**/*.html', included: false, watched: true},
50 | {pattern: 'build/**/*.css', included: false, watched: true},
51 | {pattern: 'node_modules/systemjs/dist/system-polyfills.js', included: false, watched: false}, // PhantomJS2 (and possibly others) might require it
52 | // Paths for debugging with source maps in dev tools
53 | {pattern: 'app/**/*.ts', included: false, watched: false},
54 | {pattern: 'build/**/*.js.map', included: false, watched: false}
55 | ],
56 |
57 | proxies: {
58 | '/build/': '/base/build/'
59 | },
60 | exclude: [],
61 | preprocessors: {
62 | 'build/**/!(*spec).js': ['coverage']
63 | },
64 |
65 | reporters: ['mocha', 'coverage'],
66 | mochaReporter: {},
67 | coverageReporter: {
68 | reporters: [
69 | {type: 'json', subdir: '.', file: 'coverage-js.json'}
70 | ]
71 | },
72 |
73 | client: {
74 | captureConsole: false
75 | },
76 |
77 | port: 9876,
78 | colors: true,
79 | logLevel: config.LOG_INFO,
80 | browsers: ['PhantomJS'],
81 | singleRun: true,
82 | autoWatch: false
83 | });
84 | };
85 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular2-coverage",
3 | "version": "7.0.0",
4 | "private": true,
5 | "//": "dev'd on v6.2.2 prob works on lesser versions too",
6 | "engine": "node >= 6.2.2",
7 | "scripts": {
8 | "ncu": "ncu",
9 | "typings": "typings",
10 | "preinstall": "npm list -g gulp-cli || npm i -g gulp-cli",
11 | "postinstall": "typings install && test -d .git && cp git-hook-pre-push.sh .git/hooks/pre-push || true",
12 | "checkupdates": "ncu",
13 | "typingsupdate": "sh typings.sh",
14 | "build": "gulp build --silent",
15 | "start": "gulp start --silent",
16 | "test": "gulp test --silent"
17 | },
18 | "dependencies": {
19 | "@angular/common": "^2.1.0",
20 | "@angular/compiler": "^2.1.0",
21 | "@angular/core": "^2.1.0",
22 | "@angular/forms": "^2.1.0",
23 | "@angular/http": "^2.1.0",
24 | "@angular/platform-browser": "^2.1.0",
25 | "@angular/platform-browser-dynamic": "^2.1.0",
26 | "@angular/router": "^3.1.0",
27 | "@angular/router-deprecated": "^2.0.0-rc.2",
28 | "bootstrap": "^3.3.7",
29 | "core-js": "^2.4.1",
30 | "lodash": "^4.16.4",
31 | "reflect-metadata": "^0.1.8",
32 | "rxjs": "5.0.0-beta.12",
33 | "systemjs": "^0.19.39",
34 | "zone.js": "^0.6.25"
35 | },
36 | "devDependencies": {
37 | "browser-sync": "^2.17.5",
38 | "chalk": "^1.1.3",
39 | "connect-modrewrite": "^0.9.0",
40 | "del": "^2.2.2",
41 | "eslint": "^3.8.1",
42 | "gulp": "^3.9.1",
43 | "gulp-eslint": "^3.0.1",
44 | "gulp-if": "^2.0.1",
45 | "gulp-intercept": "^0.1.0",
46 | "gulp-sourcemaps": "^2.1.1",
47 | "gulp-stylus": "^2.5.0",
48 | "gulp-tslint": "^6.1.2",
49 | "gulp-typescript": "^3.0.2",
50 | "jasmine-core": "^2.5.2",
51 | "karma": "^1.3.0",
52 | "karma-coverage": "^1.1.1",
53 | "karma-jasmine": "^1.0.2",
54 | "karma-mocha-reporter": "^2.2.0",
55 | "karma-phantomjs-launcher": "^1.0.2",
56 | "karma-super-dots-reporter": "^0.1.0",
57 | "nib": "^1.1.2",
58 | "node-cmd": "^1.1.1",
59 | "npm-check-updates": "^2.8.5",
60 | "phantomjs-prebuilt": "^2.1.13",
61 | "remap-istanbul": "^0.7.0",
62 | "require-dir": "^0.3.1",
63 | "run-sequence": "^1.2.2",
64 | "tslint": "^3.15.1",
65 | "typings": "^1.4.0"
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/systemjs.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * System configuration for Angular samples
3 | * Adjust as necessary for your application needs.
4 | */
5 | (function () {
6 | var config = {
7 | paths: {
8 | // paths serve as alias
9 | 'npm:': 'node_modules/'
10 | },
11 | // map tells the System loader where to look for things
12 | map: {
13 | // our app is within the app folder
14 | // app: 'app',
15 | app: 'build',
16 |
17 | // angular bundles
18 | '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
19 | '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
20 | '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
21 | '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
22 | '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
23 | '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
24 | '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
25 | '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
26 | '@angular/upgrade': 'npm:@angular/upgrade/bundles/upgrade.umd.js',
27 |
28 | // other libraries
29 | 'rxjs': 'npm:rxjs',
30 | 'lodash': 'npm:lodash/lodash.js'
31 | },
32 |
33 | // packages tells the System loader how to load when no filename and/or no extension
34 | packages: {
35 | app: {main: './main.js', defaultExtension: 'js'},
36 | rxjs: {defaultExtension: 'js'}
37 | }
38 | };
39 | // noinspection ES6ModulesDependencies, NodeModulesDependencies
40 | System.config(config);
41 | })();
42 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "commonjs",
5 | "moduleResolution": "node",
6 | "sourceMap": true,
7 | "emitDecoratorMetadata": true,
8 | "experimentalDecorators": true,
9 | "removeComments": false,
10 | "noImplicitAny": true,
11 | "suppressImplicitAnyIndexErrors": true,
12 | "outDir": "compiler"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "class-name": true,
4 | "comment-format": [
5 | true,
6 | "check-space"
7 | ],
8 | "curly": true,
9 | "eofline": true,
10 | "forin": true,
11 | "indent": [
12 | true,
13 | "spaces"
14 | ],
15 | "label-position": true,
16 | "label-undefined": true,
17 | "max-line-length": [
18 | true,
19 | 140
20 | ],
21 | "member-access": false,
22 | "member-ordering": [
23 | true,
24 | "static-before-instance",
25 | "variables-before-functions"
26 | ],
27 | "no-arg": true,
28 | "no-bitwise": true,
29 | "no-console": [
30 | true,
31 | "debug",
32 | "info",
33 | "time",
34 | "timeEnd",
35 | "trace"
36 | ],
37 | "no-construct": true,
38 | "no-debugger": true,
39 | "no-duplicate-key": true,
40 | "no-duplicate-variable": true,
41 | "no-empty": false,
42 | "no-eval": true,
43 | "no-inferrable-types": true,
44 | "no-shadowed-variable": true,
45 | "no-string-literal": false,
46 | "no-switch-case-fall-through": true,
47 | "no-trailing-whitespace": false,
48 | "no-unused-expression": true,
49 | "no-unused-variable": true,
50 | "no-unreachable": true,
51 | "no-use-before-declare": true,
52 | "no-var-keyword": true,
53 | "object-literal-sort-keys": false,
54 | "one-line": [
55 | true,
56 | "check-open-brace",
57 | "check-catch",
58 | "check-else",
59 | "check-whitespace"
60 | ],
61 | "quotemark": [
62 | true,
63 | "single"
64 | ],
65 | "radix": true,
66 | "semicolon": [
67 | true,
68 | "always"
69 | ],
70 | "triple-equals": [
71 | true,
72 | "allow-null-check"
73 | ],
74 | "typedef-whitespace": [
75 | true,
76 | {
77 | "call-signature": "nospace",
78 | "index-signature": "nospace",
79 | "parameter": "nospace",
80 | "property-declaration": "nospace",
81 | "variable-declaration": "nospace"
82 | }
83 | ],
84 | "variable-name": false,
85 | "whitespace": [
86 | true,
87 | "check-branch",
88 | "check-decl",
89 | "check-operator",
90 | "check-separator"
91 | ]
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/typings.json:
--------------------------------------------------------------------------------
1 | {
2 | "globalDependencies": {
3 | "core-js": "registry:dt/core-js#0.0.0+20160914114559",
4 | "jasmine": "registry:dt/jasmine#2.5.0+20161003201800",
5 | "lodash": "registry:dt/lodash#4.14.0+20161004174455",
6 | "node": "registry:dt/node#6.0.0+20161010101523"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/typings.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # This script updates typings and removes the following warning
4 | # typings WARN deprecated 6/2/2016: "registry:dt/core-js#0.0.0+20160317120654" is deprecated (updated, replaced or removed)
5 | # An entry should exist here for each entry in typings.json
6 | # This script assumes that the NodeJS module 'typings' is installed locally
7 | # I do not know how to revert changes so this script backs up typings.json
8 |
9 | echo "Backing up typings.json";
10 | cp typings.json typings.json.bak &>/dev/null;
11 |
12 | echo "Updating typings.json";
13 | npm run typings -- install dt~core-js --global --save
14 | npm run typings -- install dt~jasmine --global --save
15 | npm run typings -- install dt~lodash --global --save
16 | npm run typings -- install dt~node --global --save
17 |
18 | echo "Update complete";
19 |
--------------------------------------------------------------------------------
/update.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | const cmd = require('node-cmd');
3 |
4 | fs.readFile('./package.json', 'utf8', (err, data) => {
5 | let pkg = JSON.parse(data);
6 | for (let dep in pkg.dependencies) {
7 | console.log(`Updating dev package ${dep}`);
8 | cmd.run(`npm i -S ${dep}@latest`); // You may need sudo here
9 | }
10 | for (let devDep in pkg.devDependencies) {
11 | console.log(`Updating devDep package ${devDep}`);
12 | cmd.run(`npm i -SD ${devDep}@latest`); // You may need sudo here
13 | }
14 | console.log('Please wait, updates in progress');
15 | });
16 |
--------------------------------------------------------------------------------