├── .dockerignore ├── .editorconfig ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── Dockerfile ├── LICENSE ├── README.md ├── app ├── app.component.html ├── app.component.spec.ts ├── app.component.ts ├── app.module.ts ├── components │ ├── github.component.html │ └── github.component.ts ├── main.ts └── services │ └── github.service.ts ├── e2e └── app.e2e-spec.ts ├── favicon.ico ├── index.html ├── karma-test-shim.js ├── karma.conf.js ├── package.json ├── protractor.config.js ├── styles.css ├── systemjs.config.js ├── tsconfig.json ├── tslint.json ├── typings.json └── wallaby.js /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | end_of_line = lf 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | 12 | 13 | [*.md] 14 | max_line_length = 0 15 | trim_trailing_whitespace = false 16 | 17 | # Indentation override 18 | #[lib/**.js] 19 | #[{package.json,.travis.yml}] 20 | #[**/**.js] 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | typings/** 3 | node_modules 4 | jspm_packages 5 | link-checker-results.txt 6 | **/*npm-debug.log.* 7 | *.js 8 | *.js.map 9 | e2e/**/*.js 10 | e2e/**/*.js.map 11 | _test-output 12 | _temp 13 | 14 | !karma*.js 15 | !protractor*.js 16 | !systemjs.config.js 17 | !typings/typings.d.ts 18 | !wallaby.js 19 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | sudo: required 3 | language: node_js 4 | node_js: 5 | - "5" 6 | os: 7 | - linux 8 | env: 9 | global: 10 | - DBUS_SESSION_BUS_ADDRESS=/dev/null 11 | - DISPLAY=:99.0 12 | - CHROME_BIN=chromium-browser 13 | before_script: 14 | - sh -e /etc/init.d/xvfb start 15 | install: 16 | - npm install 17 | script: 18 | - npm run lint 19 | - npm run test-once 20 | - npm run e2e 21 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | # 0.2.8 (2016-09-01) 3 | * remove @angular test libraries from system.js (now in shim) 4 | * update test related files 5 | * wallaby doesn't completely work. Researching. 6 | 7 | # 0.2.7 (2016-08-31) 8 | * Angular 2 RC6 version 9 | * Updated new forms, router, angular2-in-memory-web-api, karma, core-js, rxjs and zone.js packages 10 | * Removed router-deprecated package 11 | * Updated karma.conf.js and systemjs.config.js 12 | 13 | 14 | # 0.2.6 (2016-08-09) 15 | * Angular 2 RC5 version 16 | * Updated new forms, router and angular2-in-memory-web-api 17 | 18 | 19 | # 0.2.5 (2016-06-30) 20 | * Angular 2 RC4 version 21 | * Updated new forms and router 22 | 23 | 24 | # 0.2.4 (2016-06-21) 25 | * Angular 2 RC3 version 26 | * Add new forms and router 27 | * Add support for TS e2e tests 28 | 29 | 30 | # 0.2.3 (2016-06-15) 31 | * Angular 2 RC2 version 32 | 33 | 34 | # 0.2.2 (2016-05-21) 35 | * Update to Typings 1.x 36 | 37 | 38 | # 0.2.1 (2016-05-03) 39 | * Angular 2 RC01 version 40 | 41 | 42 | # 0.2.0 (2016-05-02) 43 | * Angular 2 RC0 version 44 | 45 | 46 | # 0.1.17 (2016-04-29) 47 | * update packages 48 | * Angular 2 beta 17 49 | * RxJS 5.0.0-beta.6 50 | * a2-in-memory-web-api 0.1.17 51 | 52 | 53 | # 0.1.16 (2016-04-26) 54 | * update packages 55 | * Angular 2 beta 16 56 | * a2-in-memory-web-api 0.1.6 57 | * protractor 3.3.0 58 | * typings 0.8.1 59 | * zone.js 0.6.12 60 | 61 | * added favicon.ico 62 | 63 | * testing 64 | - updated wallaby.js and karma.conf.js 65 | - updated app.component.spec.ts 66 | 67 | 68 | 69 | # 0.1.15 (2016-04-13) 70 | * Add testing support 71 | * npm scripts 72 | * karma/jasmine 73 | * protractor 74 | 75 | * update packages 76 | * Angular 2 beta 15 77 | * lite-server 2.2.0 78 | * systemjs 0.19.26 79 | * typescript 1.8.10 80 | * typings 0.7.12 81 | 82 | * add run packages 83 | * a2-in-memory-web-api 84 | 85 | * add testing dev-dependency packages 86 | * canonical-path: 0.0.2, 87 | * http-server: ^0.9.0, 88 | * jasmine-core: ~2.4.1, 89 | * karma: ^0.13.22, 90 | * karma-chrome-launcher: ^0.2.3, 91 | * karma-cli: ^0.1.2, 92 | * karma-htmlfile-reporter: ^0.2.2, 93 | * karma-jasmine: ^0.3.8, 94 | * protractor: ^3.2.2, 95 | * rimraf: ^2.5.2 96 | 97 | 98 | # 0.1.14 (2016-04-07) 99 | * update packages 100 | * Angular 2 beta 14 101 | * lite-server 2.2.0 102 | * typings 0.7.12 103 | 104 | 105 | # 0.1.13 (2016-03-31) 106 | * update packages 107 | * Angular 2 beta 13 108 | 109 | 110 | # 0.1.12 (2016-03-23) 111 | * update packages 112 | * Angular 2 beta 12 113 | * zones 0.6.6 114 | * remove es6-promise because no longer needed. 115 | 116 | 117 | # 0.1.11 (2016-03-18) 118 | * update packages 119 | * Angular 2 beta 11 120 | * zones 0.6.4 121 | * typescript 1.8.9 122 | * typings 0.7.9 123 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # To build and run with Docker: 2 | # 3 | # $ docker build -t ng2-quickstart . 4 | # $ docker run -it --rm -p 3000:3000 -p 3001:3001 ng2-quickstart 5 | # 6 | FROM node:latest 7 | 8 | RUN mkdir -p /quickstart /home/nodejs && \ 9 | groupadd -r nodejs && \ 10 | useradd -r -g nodejs -d /home/nodejs -s /sbin/nologin nodejs && \ 11 | chown -R nodejs:nodejs /home/nodejs 12 | 13 | WORKDIR /quickstart 14 | COPY package.json typings.json /quickstart/ 15 | RUN npm install --unsafe-perm=true 16 | 17 | COPY . /quickstart 18 | RUN chown -R nodejs:nodejs /quickstart 19 | USER nodejs 20 | 21 | CMD npm start 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2014-2016 Google, Inc. 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Github Search 2 | 3 | Simple Angular 2 app that searches Github user profiles and repositories. Goes along with video tutorial at https://www.youtube.com/watch?v=u83MLQ1VsKI 4 | 5 | ### Version 6 | 1.1 - Uses Angular 2.0.0 The original version that uses RC4 is in the "rc4_old" folder, it must be removed if you want to run the app with "npm run" after installing the packages with "npm install" command. 7 | 8 | ### Usage 9 | 10 | 11 | ### Installation 12 | 13 | This app requires [Node.js](https://nodejs.org/) v4+ to run. 14 | 15 | ```sh 16 | $ npm install 17 | ``` 18 | 19 | ### Usage 20 | 21 | This app requires [Node.js](https://nodejs.org/) v4+ to run. 22 | 23 | ```sh 24 | $ npm start 25 | ``` 26 | 27 | 28 | ### npm scripts 29 | 30 | We've captured many of the most useful commands in npm scripts defined in the `package.json`: 31 | 32 | * `npm start` - runs the compiler and a server at the same time, both in "watch mode". 33 | * `npm run tsc` - runs the TypeScript compiler once. 34 | * `npm run tsc:w` - runs the TypeScript compiler in watch mode; the process keeps running, awaiting changes to TypeScript files and re-compiling when it sees them. 35 | * `npm run lite` - runs the [lite-server](https://www.npmjs.com/package/lite-server), a light-weight, static file server, written and maintained by 36 | [John Papa](https://github.com/johnpapa) and 37 | [Christopher Martin](https://github.com/cgmartin) 38 | with excellent support for Angular apps that use routing. 39 | * `npm run typings` - runs the typings tool. 40 | * `npm run postinstall` - called by *npm* automatically *after* it successfully completes package installation. This script installs the TypeScript definition files this app requires. 41 | Here are the test related scripts: 42 | * `npm test` - compiles, runs and watches the karma unit tests 43 | * `npm run e2e` - run protractor e2e tests, written in JavaScript (*e2e-spec.js) 44 | -------------------------------------------------------------------------------- /app/app.component.html: -------------------------------------------------------------------------------- 1 | 19 | 20 |
21 | 22 |
23 |
24 | 25 |
26 |
27 | 28 |
-------------------------------------------------------------------------------- /app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-unused-variable */ 2 | import { AppComponent } from './app.component'; 3 | 4 | import { TestBed } from '@angular/core/testing'; 5 | 6 | import { By } from '@angular/platform-browser'; 7 | 8 | //////// SPECS ///////////// 9 | 10 | /// Delete this 11 | describe('Smoke test', () => { 12 | it('should run a passing test', () => { 13 | expect(true).toEqual(true, 'should pass'); 14 | }); 15 | }); 16 | 17 | describe('AppComponent with TCB', function () { 18 | beforeEach(() => { 19 | TestBed.configureTestingModule({declarations: [AppComponent]}); 20 | }); 21 | 22 | it('should instantiate component', () => { 23 | let fixture = TestBed.createComponent(AppComponent); 24 | expect(fixture.componentInstance instanceof AppComponent).toBe(true, 'should create AppComponent'); 25 | }); 26 | 27 | it('should have expected

text', () => { 28 | let fixture = TestBed.createComponent(AppComponent); 29 | fixture.detectChanges(); 30 | 31 | let h1 = fixture.debugElement.query(el => el.name === 'h1').nativeElement; // it works 32 | 33 | h1 = fixture.debugElement.query(By.css('h1')).nativeElement; // preferred 34 | 35 | expect(h1.innerText).toMatch(/angular 2 app/i, '

should say something about "Angular 2 App"'); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | moduleId: module.id, 5 | selector: 'my-app', 6 | templateUrl: 'app.component.html' 7 | }) 8 | export class AppComponent { } 9 | -------------------------------------------------------------------------------- /app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | import {HttpModule} from '@angular/http'; 4 | import {FormsModule} from '@angular/forms'; 5 | 6 | import { AppComponent } from './app.component'; 7 | import {GithubComponent} from './components/github.component'; 8 | 9 | @NgModule({ 10 | imports: [ BrowserModule, HttpModule, FormsModule ], 11 | declarations: [ AppComponent, GithubComponent ], 12 | bootstrap: [ AppComponent ] 13 | }) 14 | export class AppModule { } 15 | -------------------------------------------------------------------------------- /app/components/github.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 | 6 |
7 |
8 |
9 |
10 | 11 |
12 |
13 |
14 |

{{user.name}}

15 |
16 |
17 |
18 |
19 | 20 |
21 |
22 |
23 | {{user.public_repos}} Public Repos 24 | {{user.public_gists}} Public Gists 25 | {{user.followers}} Followers 26 | {{user.following}} Following 27 |
28 |
29 |
    30 |
  • Username: {{user.login}}
  • 31 |
  • Location: {{user.location}}
  • 32 |
  • Email: {{user.email}}
  • 33 |
  • Blog: {{user.blog}}
  • 34 |
  • Member Since: {{user.created_at}}
  • 35 |
36 |
37 |
38 |
39 |
40 | 41 |
42 |
43 |

Repos

44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |

{{repo.name}}

52 |

{{repo.description}}

53 |
54 |
55 | {{repo.watchers}} Watchers 56 | {{repo.forks}} Forks 57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
-------------------------------------------------------------------------------- /app/components/github.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import {GithubService} from '../services/github.service'; 3 | 4 | @Component({ 5 | moduleId:module.id, 6 | selector: 'github', 7 | templateUrl: 'github.component.html', 8 | providers:[GithubService] 9 | }) 10 | export class GithubComponent { 11 | user:any; 12 | repos:any; 13 | username:string; 14 | 15 | constructor(private _githubService:GithubService){ 16 | console.log('Github Component Init...'); 17 | } 18 | 19 | search(){ 20 | this._githubService.updateUsername(this.username); 21 | 22 | this._githubService.getUser().subscribe(user => { 23 | //console.log(user); 24 | this.user = user; 25 | }); 26 | 27 | this._githubService.getRepos().subscribe(repos => { 28 | this.repos = repos; 29 | }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/main.ts: -------------------------------------------------------------------------------- 1 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 2 | 3 | import { AppModule } from './app.module'; 4 | 5 | platformBrowserDynamic().bootstrapModule(AppModule); 6 | -------------------------------------------------------------------------------- /app/services/github.service.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import {Http, Headers} from '@angular/http'; 3 | import 'rxjs/add/operator/map'; 4 | 5 | @Injectable() 6 | export class GithubService{ 7 | private username = 'bradtraversy'; 8 | private client_id = 'd9308aacf8b204d361fd'; 9 | private client_secret='62551cc02cee983fff0bac41baf170eb5a312c1c'; 10 | 11 | constructor(private _http:Http){ 12 | console.log('Github Service Init...'); 13 | } 14 | 15 | getUser(){ 16 | return this._http.get('https://api.github.com/users/'+this.username+'?client_id='+this.client_id+'&client_secret='+this.client_secret) 17 | .map(res => res.json()); 18 | } 19 | 20 | getRepos(){ 21 | return this._http.get('https://api.github.com/users/'+this.username+'/repos?client_id='+this.client_id+'&client_secret='+this.client_secret) 22 | .map(res => res.json()); 23 | } 24 | 25 | updateUsername(username:string){ 26 | this.username = username; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /e2e/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | 2 | describe('QuickStart E2E Tests', function () { 3 | 4 | let expectedMsg = 'My First Angular 2 App'; 5 | 6 | 7 | beforeEach(function () { 8 | browser.get(''); 9 | }); 10 | 11 | it('should display: ' + expectedMsg, function () { 12 | expect(element(by.css('h1')).getText()).toEqual(expectedMsg); 13 | }); 14 | 15 | }); 16 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradtraversy/githubsearch/c3c0aad16a584e57d8260fdf11a38d8dd9060dc3/favicon.ico -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Angular 2 QuickStart 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 20 | 21 | 22 | 23 | Loading... 24 | 25 | 26 | -------------------------------------------------------------------------------- /karma-test-shim.js: -------------------------------------------------------------------------------- 1 | // #docregion 2 | // /*global jasmine, __karma__, window*/ 3 | Error.stackTraceLimit = 0; // "No stacktrace"" is usually best for app testing. 4 | 5 | // Uncomment to get full stacktrace output. Sometimes helpful, usually not. 6 | // Error.stackTraceLimit = Infinity; // 7 | 8 | jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000; 9 | 10 | var builtPath = '/base/app/'; 11 | 12 | __karma__.loaded = function () { }; 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 | System.config({ 31 | baseURL: '/base', 32 | // Extend usual application package list with test folder 33 | packages: { 'testing': { main: 'index.js', defaultExtension: 'js' } }, 34 | 35 | // Assume npm: is set in `paths` in systemjs.config 36 | // Map the angular testing umd bundles 37 | map: { 38 | '@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js', 39 | '@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js', 40 | '@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js', 41 | '@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js', 42 | '@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js', 43 | '@angular/http/testing': 'npm:@angular/http/bundles/http-testing.umd.js', 44 | '@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js', 45 | '@angular/forms/testing': 'npm:@angular/forms/bundles/forms-testing.umd.js', 46 | }, 47 | }); 48 | 49 | System.import('systemjs.config.js') 50 | .then(importSystemJsExtras) 51 | .then(initTestBed) 52 | .then(initTesting); 53 | 54 | /** Optional SystemJS configuration extras. Keep going w/o it */ 55 | function importSystemJsExtras(){ 56 | return System.import('systemjs.config.extras.js') 57 | .catch(function(reason) { 58 | console.log( 59 | 'WARNING: System.import could not load "systemjs.config.extras.js"; continuing without it.' 60 | ); 61 | console.log(reason); 62 | }); 63 | } 64 | 65 | function initTestBed(){ 66 | return Promise.all([ 67 | System.import('@angular/core/testing'), 68 | System.import('@angular/platform-browser-dynamic/testing') 69 | ]) 70 | 71 | .then(function (providers) { 72 | var coreTesting = providers[0]; 73 | var browserTesting = providers[1]; 74 | 75 | coreTesting.TestBed.initTestEnvironment( 76 | browserTesting.BrowserDynamicTestingModule, 77 | browserTesting.platformBrowserDynamicTesting()); 78 | }) 79 | } 80 | 81 | // Import all spec files and start karma 82 | function initTesting () { 83 | return Promise.all( 84 | allSpecFiles.map(function (moduleName) { 85 | return System.import(moduleName); 86 | }) 87 | ) 88 | .then(__karma__.start, __karma__.error); 89 | } 90 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // #docregion 2 | module.exports = function(config) { 3 | 4 | var appBase = 'app/'; // transpiled app JS and map files 5 | var appSrcBase = 'app/'; // app source TS files 6 | var appAssets = '/base/app/'; // component assets fetched by Angular's compiler 7 | 8 | var testBase = 'testing/'; // transpiled test JS and map files 9 | var testSrcBase = 'testing/'; // test source TS files 10 | 11 | config.set({ 12 | basePath: '', 13 | frameworks: ['jasmine'], 14 | plugins: [ 15 | require('karma-jasmine'), 16 | require('karma-chrome-launcher'), 17 | require('karma-htmlfile-reporter') 18 | ], 19 | 20 | customLaunchers: { 21 | // From the CLI. Not used here but interesting 22 | // chrome setup for travis CI using chromium 23 | Chrome_travis_ci: { 24 | base: 'Chrome', 25 | flags: ['--no-sandbox'] 26 | } 27 | }, 28 | files: [ 29 | // System.js for module loading 30 | 'node_modules/systemjs/dist/system.src.js', 31 | 32 | // Polyfills 33 | 'node_modules/core-js/client/shim.js', 34 | 'node_modules/reflect-metadata/Reflect.js', 35 | 36 | // zone.js 37 | 'node_modules/zone.js/dist/zone.js', 38 | 'node_modules/zone.js/dist/long-stack-trace-zone.js', 39 | 'node_modules/zone.js/dist/proxy.js', 40 | 'node_modules/zone.js/dist/sync-test.js', 41 | 'node_modules/zone.js/dist/jasmine-patch.js', 42 | 'node_modules/zone.js/dist/async-test.js', 43 | 'node_modules/zone.js/dist/fake-async-test.js', 44 | 45 | // RxJs 46 | { pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false }, 47 | { pattern: 'node_modules/rxjs/**/*.js.map', included: false, watched: false }, 48 | 49 | // Paths loaded via module imports: 50 | // Angular itself 51 | {pattern: 'node_modules/@angular/**/*.js', included: false, watched: false}, 52 | {pattern: 'node_modules/@angular/**/*.js.map', included: false, watched: false}, 53 | 54 | {pattern: 'systemjs.config.js', included: false, watched: false}, 55 | {pattern: 'systemjs.config.extras.js', included: false, watched: false}, 56 | 'karma-test-shim.js', 57 | 58 | // transpiled application & spec code paths loaded via module imports 59 | {pattern: appBase + '**/*.js', included: false, watched: true}, 60 | {pattern: testBase + '**/*.js', included: false, watched: true}, 61 | 62 | 63 | // Asset (HTML & CSS) paths loaded via Angular's component compiler 64 | // (these paths need to be rewritten, see proxies section) 65 | {pattern: appBase + '**/*.html', included: false, watched: true}, 66 | {pattern: appBase + '**/*.css', included: false, watched: true}, 67 | 68 | // Paths for debugging with source maps in dev tools 69 | {pattern: appSrcBase + '**/*.ts', included: false, watched: false}, 70 | {pattern: appBase + '**/*.js.map', included: false, watched: false}, 71 | {pattern: testSrcBase + '**/*.ts', included: false, watched: false}, 72 | {pattern: testBase + '**/*.js.map', included: false, watched: false} 73 | ], 74 | 75 | // Proxied base paths for loading assets 76 | proxies: { 77 | // required for component assets fetched by Angular's compiler 78 | "/app/": appAssets 79 | }, 80 | 81 | exclude: [], 82 | preprocessors: {}, 83 | reporters: ['progress', 'html'], 84 | 85 | // HtmlReporter configuration 86 | htmlReporter: { 87 | // Open this file to see results in browser 88 | outputFile: '_test-output/tests.html', 89 | 90 | // Optional 91 | pageTitle: 'Unit Tests', 92 | subPageTitle: __dirname 93 | }, 94 | 95 | port: 9876, 96 | colors: true, 97 | logLevel: config.LOG_INFO, 98 | autoWatch: true, 99 | browsers: ['Chrome'], 100 | singleRun: false 101 | }) 102 | } 103 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "githubsearch", 3 | "version": "1.0.0", 4 | "description": "QuickStart package.json from the documentation, supplemented with testing support", 5 | "scripts": { 6 | "start": "tsc && concurrently \"npm run tsc:w\" \"npm run lite\" ", 7 | "docker-build": "docker build -t ng2-quickstart .", 8 | "docker": "npm run docker-build && docker run -it --rm -p 3000:3000 -p 3001:3001 ng2-quickstart", 9 | "pree2e": "npm run webdriver:update", 10 | "e2e": "tsc && concurrently \"http-server -s\" \"protractor protractor.config.js\" --kill-others --success first", 11 | "lint": "tslint ./app/**/*.ts -t verbose", 12 | "lite": "lite-server", 13 | "postinstall": "typings install", 14 | "test": "tsc && concurrently \"tsc -w\" \"karma start karma.conf.js\"", 15 | "test-once": "tsc && karma start karma.conf.js --single-run", 16 | "tsc": "tsc", 17 | "tsc:w": "tsc -w", 18 | "typings": "typings", 19 | "webdriver:update": "webdriver-manager update" 20 | }, 21 | "keywords": [], 22 | "author": "", 23 | "license": "ISC", 24 | "dependencies": { 25 | "@angular/common": "2.0.0", 26 | "@angular/compiler": "2.0.0", 27 | "@angular/core": "2.0.0", 28 | "@angular/forms": "2.0.0", 29 | "@angular/http": "2.0.0", 30 | "@angular/platform-browser": "2.0.0", 31 | "@angular/platform-browser-dynamic": "2.0.0", 32 | "@angular/router": "3.0.0", 33 | "@angular/upgrade": "2.0.0", 34 | "core-js": "^2.4.1", 35 | "reflect-metadata": "^0.1.3", 36 | "rxjs": "5.0.0-beta.12", 37 | "systemjs": "0.19.27", 38 | "zone.js": "^0.6.23", 39 | "angular2-in-memory-web-api": "0.0.20", 40 | "bootstrap": "^3.3.6" 41 | }, 42 | "devDependencies": { 43 | "concurrently": "^2.2.0", 44 | "lite-server": "^2.2.2", 45 | "typescript": "^2.0.2", 46 | "typings": "^1.3.2", 47 | "canonical-path": "0.0.2", 48 | "http-server": "^0.9.0", 49 | "tslint": "^3.7.4", 50 | "lodash": "^4.11.1", 51 | "jasmine-core": "~2.4.1", 52 | "karma": "^1.2.0", 53 | "karma-chrome-launcher": "^0.2.3", 54 | "karma-cli": "^0.1.2", 55 | "karma-htmlfile-reporter": "^0.2.2", 56 | "karma-jasmine": "^0.3.8", 57 | "protractor": "^3.3.0", 58 | "rimraf": "^2.5.2" 59 | }, 60 | "repository": {} 61 | } 62 | -------------------------------------------------------------------------------- /protractor.config.js: -------------------------------------------------------------------------------- 1 | // FIRST TIME ONLY- run: 2 | // ./node_modules/.bin/webdriver-manager update 3 | // 4 | // Try: `npm run webdriver:update` 5 | // 6 | // AND THEN EVERYTIME ... 7 | // 1. Compile with `tsc` 8 | // 2. Make sure the test server (e.g., http-server: localhost:8080) is running. 9 | // 3. ./node_modules/.bin/protractor protractor.config.js 10 | // 11 | // To do all steps, try: `npm run e2e` 12 | 13 | var fs = require('fs'); 14 | var path = require('canonical-path'); 15 | var _ = require('lodash'); 16 | 17 | 18 | exports.config = { 19 | directConnect: true, 20 | 21 | // Capabilities to be passed to the webdriver instance. 22 | capabilities: { 23 | 'browserName': 'chrome' 24 | }, 25 | 26 | // Framework to use. Jasmine is recommended. 27 | framework: 'jasmine', 28 | 29 | // Spec patterns are relative to this config file 30 | specs: ['**/*e2e-spec.js' ], 31 | 32 | 33 | // For angular2 tests 34 | useAllAngular2AppRoots: true, 35 | 36 | // Base URL for application server 37 | baseUrl: 'http://localhost:8080', 38 | 39 | // doesn't seem to work. 40 | // resultJsonOutputFile: "foo.json", 41 | 42 | onPrepare: function() { 43 | //// SpecReporter 44 | //var SpecReporter = require('jasmine-spec-reporter'); 45 | //jasmine.getEnv().addReporter(new SpecReporter({displayStacktrace: 'none'})); 46 | //// jasmine.getEnv().addReporter(new SpecReporter({displayStacktrace: 'all'})); 47 | 48 | // debugging 49 | // console.log('browser.params:' + JSON.stringify(browser.params)); 50 | jasmine.getEnv().addReporter(new Reporter( browser.params )) ; 51 | 52 | global.sendKeys = sendKeys; 53 | 54 | // Allow changing bootstrap mode to NG1 for upgrade tests 55 | global.setProtractorToNg1Mode = function() { 56 | browser.useAllAngular2AppRoots = false; 57 | browser.rootEl = 'body'; 58 | }; 59 | }, 60 | 61 | jasmineNodeOpts: { 62 | // defaultTimeoutInterval: 60000, 63 | defaultTimeoutInterval: 10000, 64 | showTiming: true, 65 | print: function() {} 66 | } 67 | }; 68 | 69 | // Hack - because of bug with protractor send keys 70 | function sendKeys(element, str) { 71 | return str.split('').reduce(function (promise, char) { 72 | return promise.then(function () { 73 | return element.sendKeys(char); 74 | }); 75 | }, element.getAttribute('value')); 76 | // better to create a resolved promise here but ... don't know how with protractor; 77 | } 78 | 79 | // Custom reporter 80 | function Reporter(options) { 81 | var _defaultOutputFile = path.resolve(process.cwd(), './_test-output', 'protractor-results.txt'); 82 | options.outputFile = options.outputFile || _defaultOutputFile; 83 | 84 | initOutputFile(options.outputFile); 85 | options.appDir = options.appDir || './'; 86 | var _root = { appDir: options.appDir, suites: [] }; 87 | log('AppDir: ' + options.appDir, +1); 88 | var _currentSuite; 89 | 90 | this.suiteStarted = function(suite) { 91 | _currentSuite = { description: suite.description, status: null, specs: [] }; 92 | _root.suites.push(_currentSuite); 93 | log('Suite: ' + suite.description, +1); 94 | }; 95 | 96 | this.suiteDone = function(suite) { 97 | var statuses = _currentSuite.specs.map(function(spec) { 98 | return spec.status; 99 | }); 100 | statuses = _.uniq(statuses); 101 | var status = statuses.indexOf('failed') >= 0 ? 'failed' : statuses.join(', '); 102 | _currentSuite.status = status; 103 | log('Suite ' + _currentSuite.status + ': ' + suite.description, -1); 104 | }; 105 | 106 | this.specStarted = function(spec) { 107 | 108 | }; 109 | 110 | this.specDone = function(spec) { 111 | var currentSpec = { 112 | description: spec.description, 113 | status: spec.status 114 | }; 115 | if (spec.failedExpectations.length > 0) { 116 | currentSpec.failedExpectations = spec.failedExpectations; 117 | } 118 | 119 | _currentSuite.specs.push(currentSpec); 120 | log(spec.status + ' - ' + spec.description); 121 | }; 122 | 123 | this.jasmineDone = function() { 124 | outputFile = options.outputFile; 125 | //// Alternate approach - just stringify the _root - not as pretty 126 | //// but might be more useful for automation. 127 | // var output = JSON.stringify(_root, null, 2); 128 | var output = formatOutput(_root); 129 | fs.appendFileSync(outputFile, output); 130 | }; 131 | 132 | function initOutputFile(outputFile) { 133 | var header = "Protractor results for: " + (new Date()).toLocaleString() + "\n\n"; 134 | fs.writeFileSync(outputFile, header); 135 | } 136 | 137 | // for output file output 138 | function formatOutput(output) { 139 | var indent = ' '; 140 | var pad = ' '; 141 | var results = []; 142 | results.push('AppDir:' + output.appDir); 143 | output.suites.forEach(function(suite) { 144 | results.push(pad + 'Suite: ' + suite.description + ' -- ' + suite.status); 145 | pad+=indent; 146 | suite.specs.forEach(function(spec) { 147 | results.push(pad + spec.status + ' - ' + spec.description); 148 | if (spec.failedExpectations) { 149 | pad+=indent; 150 | spec.failedExpectations.forEach(function (fe) { 151 | results.push(pad + 'message: ' + fe.message); 152 | }); 153 | pad=pad.substr(2); 154 | } 155 | }); 156 | pad = pad.substr(2); 157 | results.push(''); 158 | }); 159 | results.push(''); 160 | return results.join('\n'); 161 | } 162 | 163 | // for console output 164 | var _pad; 165 | function log(str, indent) { 166 | _pad = _pad || ''; 167 | if (indent == -1) { 168 | _pad = _pad.substr(2); 169 | } 170 | console.log(_pad + str); 171 | if (indent == 1) { 172 | _pad = _pad + ' '; 173 | } 174 | } 175 | 176 | } 177 | -------------------------------------------------------------------------------- /styles.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bradtraversy/githubsearch/c3c0aad16a584e57d8260fdf11a38d8dd9060dc3/styles.css -------------------------------------------------------------------------------- /systemjs.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * System configuration for Angular 2 samples 3 | * Adjust as necessary for your application needs. 4 | */ 5 | (function (global) { 6 | System.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 | // angular bundles 16 | '@angular/core': 'npm:@angular/core/bundles/core.umd.js', 17 | '@angular/common': 'npm:@angular/common/bundles/common.umd.js', 18 | '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js', 19 | '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js', 20 | '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js', 21 | '@angular/http': 'npm:@angular/http/bundles/http.umd.js', 22 | '@angular/router': 'npm:@angular/router/bundles/router.umd.js', 23 | '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js', 24 | // other libraries 25 | 'rxjs': 'npm:rxjs', 26 | 'angular2-in-memory-web-api': 'npm:angular2-in-memory-web-api', 27 | }, 28 | // packages tells the System loader how to load when no filename and/or no extension 29 | packages: { 30 | app: { 31 | main: './main.js', 32 | defaultExtension: 'js' 33 | }, 34 | rxjs: { 35 | defaultExtension: 'js' 36 | }, 37 | 'angular2-in-memory-web-api': { 38 | main: './index.js', 39 | defaultExtension: 'js' 40 | } 41 | } 42 | }); 43 | })(this); 44 | -------------------------------------------------------------------------------- /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 | } 13 | } 14 | -------------------------------------------------------------------------------- /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": true, 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 | "always" 68 | ], 69 | "triple-equals": [ 70 | true, 71 | "allow-null-check" 72 | ], 73 | "typedef-whitespace": [ 74 | true, 75 | { 76 | "call-signature": "nospace", 77 | "index-signature": "nospace", 78 | "parameter": "nospace", 79 | "property-declaration": "nospace", 80 | "variable-declaration": "nospace" 81 | } 82 | ], 83 | "variable-name": false, 84 | "whitespace": [ 85 | true, 86 | "check-branch", 87 | "check-decl", 88 | "check-operator", 89 | "check-separator", 90 | "check-type" 91 | ] 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "globalDependencies": { 3 | "angular-protractor": "registry:dt/angular-protractor#1.5.0+20160425143459", 4 | "core-js": "registry:dt/core-js#0.0.0+20160725163759", 5 | "jasmine": "registry:dt/jasmine#2.2.0+20160621224255", 6 | "node": "registry:dt/node#6.0.0+20160909174046", 7 | "selenium-webdriver": "registry:dt/selenium-webdriver#2.44.0+20160317120654" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /wallaby.js: -------------------------------------------------------------------------------- 1 | // Configuration for the Wallaby Visual Studio Code testing extension 2 | // https://marketplace.visualstudio.com/items?itemName=WallabyJs.wallaby-vscode 3 | // Note: Wallaby is not open source and costs money 4 | 5 | module.exports = function () { 6 | return { 7 | files: [ 8 | // System.js for module loading 9 | {pattern: 'node_modules/systemjs/dist/system.js', instrument: false}, 10 | {pattern: 'systemjs.config.js', instrument: false}, 11 | {pattern: 'systemjs.config.extras.js', instrument: false}, 12 | 13 | // Polyfills 14 | {pattern: 'node_modules/core-js/client/shim.min.js', instrument: false}, 15 | {pattern: 'node_modules/reflect-metadata/Reflect.js', instrument: false}, 16 | 17 | // zone.js 18 | {pattern: 'node_modules/zone.js/dist/zone.js', instrument: false}, 19 | {pattern: 'node_modules/zone.js/dist/long-stack-trace-zone.js', instrument: false}, 20 | {pattern: 'node_modules/zone.js/dist/proxy.js', instrument: false}, 21 | {pattern: 'node_modules/zone.js/dist/sync-test.js', instrument: false}, 22 | {pattern: 'node_modules/zone.js/dist/jasmine-patch.js', instrument: false}, 23 | {pattern: 'node_modules/zone.js/dist/async-test.js', instrument: false}, 24 | {pattern: 'node_modules/zone.js/dist/fake-async-test.js', instrument: false}, 25 | 26 | // application (but not specs) loaded via module imports 27 | {pattern: 'app/**/*+(ts|html|css)', load: false}, 28 | {pattern: 'app/**/*.spec.ts', ignore: true}, 29 | 30 | {pattern: 'testing/**/*+(ts|html|css)', load: false}, 31 | ], 32 | 33 | tests: [ 34 | {pattern: 'app/**/*.spec.ts', load: false} 35 | ], 36 | 37 | middleware: function (app, express) { 38 | app.use('/node_modules', express.static(require('path').join(__dirname, 'node_modules'))); 39 | }, 40 | 41 | testFramework: 'jasmine', 42 | 43 | debug: true, 44 | 45 | bootstrap: bootstrap 46 | }; 47 | }; 48 | 49 | // Like karma-test-shim.js 50 | function bootstrap (wallaby) { 51 | wallaby.delayStart(); 52 | 53 | System.config({ 54 | // Extend usual application package list with test folder 55 | packages: { 'testing': { main: 'index.js', defaultExtension: 'js' } }, 56 | 57 | // Assume npm: is set in `paths` in systemjs.config 58 | // Map the angular testing umd bundles 59 | map: { 60 | '@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js', 61 | '@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js', 62 | '@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js', 63 | '@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js', 64 | '@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js', 65 | '@angular/http/testing': 'npm:@angular/http/bundles/http-testing.umd.js', 66 | '@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js', 67 | '@angular/forms/testing': 'npm:@angular/forms/bundles/forms-testing.umd.js', 68 | }, 69 | }); 70 | 71 | System.import('systemjs.config.js') 72 | .then(importSystemJsExtras) 73 | .then(initTestBed) 74 | .then(initTesting); 75 | 76 | /** Optional SystemJS configuration extras. Keep going w/o it */ 77 | function importSystemJsExtras(){ 78 | return System.import('systemjs.config.extras.js') 79 | .catch(function(reason) { 80 | console.log( 81 | 'WARNING: System.import could not load "systemjs.config.extras.js"; continuing without it.' 82 | ); 83 | console.log(reason); 84 | }); 85 | } 86 | 87 | function initTestBed(){ 88 | return Promise.all([ 89 | System.import('@angular/core/testing'), 90 | System.import('@angular/platform-browser-dynamic/testing') 91 | ]) 92 | 93 | .then(function (providers) { 94 | var coreTesting = providers[0]; 95 | var browserTesting = providers[1]; 96 | 97 | coreTesting.TestBed.initTestEnvironment( 98 | browserTesting.BrowserDynamicTestingModule, 99 | browserTesting.platformBrowserDynamicTesting()); 100 | }) 101 | } 102 | 103 | // Load all spec files and start wallaby 104 | function initTesting () { 105 | return Promise.all( 106 | wallaby.tests.map(function (specFile) { 107 | return System.import(specFile); 108 | }) 109 | ) 110 | .then(function () { 111 | wallaby.start(); 112 | }) 113 | .catch(function (e) { 114 | setTimeout(function () { 115 | throw e; 116 | }, 0); 117 | }); 118 | } 119 | } 120 | --------------------------------------------------------------------------------