<!-- Run application specs in a browser -->
<!DOCTYPE html>
<html>
<head>
  <script>document.write('<base href="' + document.location + '" />');</script>
  <title>1st Specs</title>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="styles.css">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.4.1/jasmine.css">
</head>
<body>
  <script src="https://unpkg.com/systemjs@0.19.27/dist/system.src.js"></script>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.4.1/jasmine.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.4.1/jasmine-html.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.4.1/boot.js"></script>

  <script src="https://unpkg.com/reflect-metadata@0.1.3"></script>

  <script src="https://unpkg.com/zone.js@0.6.25?main=browser"></script>
  <script src="https://unpkg.com/zone.js/dist/long-stack-trace-zone.js?main=browser"></script>
  <script src="https://unpkg.com/zone.js/dist/proxy.js?main=browser"></script>
  <script src="https://unpkg.com/zone.js/dist/sync-test.js?main=browser"></script>
  <script src="https://unpkg.com/zone.js/dist/jasmine-patch.js?main=browser"></script>
  <script src="https://unpkg.com/zone.js/dist/async-test.js?main=browser"></script>
  <script src="https://unpkg.com/zone.js/dist/fake-async-test.js?main=browser"></script>

  <script>
    var __spec_files__ = [
      'src/item.component.spec'
    ];
  </script>
  <script src="browser-test-shim.js"></script>
</body>

</html>


<!-- 
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
-->
/* Styles go here */
/* Master Styles */
h1 {
  color: #369;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 250%;
}
h2, h3 {
  color: #444;
  font-family: Arial, Helvetica, sans-serif;
  font-weight: lighter;
}
body {
  margin: 2em;
}
body, input[text], button {
  color: #888;
  font-family: Cambria, Georgia;
}
a {
  cursor: pointer;
  cursor: hand;
}
button {
  font-family: Arial;
  background-color: #eee;
  border: none;
  padding: 5px 10px;
  border-radius: 4px;
  cursor: pointer;
  cursor: hand;
}
button:hover {
  background-color: #cfd8dc;
}
button:disabled {
  background-color: #eee;
  color: #aaa;
  cursor: auto;
}

/* Navigation link styles */
nav a {
  padding: 5px 10px;
  text-decoration: none;
  margin-top: 10px;
  display: inline-block;
  background-color: #eee;
  border-radius: 4px;
}
nav a:visited, a:link {
  color: #607D8B;
}
nav a:hover {
  color: #039be5;
  background-color: #CFD8DC;
}
nav a.active {
  color: #039be5;
}

/* items class */
.items {
  margin: 0 0 2em 0;
  list-style-type: none;
  padding: 0;
  width: 24em;
}
.items li {
  cursor: pointer;
  position: relative;
  left: 0;
  background-color: #EEE;
  margin: .5em;
  padding: .3em 0;
  height: 1.6em;
  border-radius: 4px;
}
.items li:hover {
  color: #607D8B;
  background-color: #DDD;
  left: .1em;
}
.items li.selected:hover {
  background-color: #BBD8DC;
  color: white;
}
.items .text {
  position: relative;
  top: -3px;
}
.items {
  margin: 0 0 2em 0;
  list-style-type: none;
  padding: 0;
  width: 24em;
}
.items li {
  cursor: pointer;
  position: relative;
  left: 0;
  background-color: #EEE;
  margin: .5em;
  padding: .3em 0;
  height: 1.6em;
  border-radius: 4px;
}
.items li:hover {
  color: #607D8B;
  background-color: #DDD;
  left: .1em;
}
.items li.selected {
  background-color: #CFD8DC;
  color: white;
}

.items li.selected:hover {
  background-color: #BBD8DC;
}
.items .text {
  position: relative;
  top: -3px;
}
.items .badge {
  display: inline-block;
  font-size: small;
  color: white;
  padding: 0.8em 0.7em 0 0.7em;
  background-color: #607D8B;
  line-height: 1em;
  position: relative;
  left: -1px;
  top: -4px;
  height: 1.8em;
  margin-right: .8em;
  border-radius: 4px 0 0 4px;
}
/* everywhere else */
* {
  font-family: Arial, Helvetica, sans-serif;
}


/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/
### Angular Starter Plunker - Typescript
var angularVersion;
if(window.AngularVersionForThisPlunker === 'latest'){
  angularVersion = ''; //picks up latest
}
else {
  angularVersion = '@' + window.AngularVersionForThisPlunker;
}

System.config({
  //use typescript for compilation
  transpiler: 'typescript',
  //typescript compiler options
  typescriptOptions: {
    emitDecoratorMetadata: true
  },
  paths: {
    'npm:': 'https://unpkg.com/'
  },
  //map tells the System loader where to look for things
  map: {
    
    'app': './src',
    '@angular/core': 'npm:@angular/core'+ angularVersion + '/bundles/core.umd.js',
    '@angular/common': 'npm:@angular/common' + angularVersion + '/bundles/common.umd.js',
    '@angular/compiler': 'npm:@angular/compiler' + angularVersion  + '/bundles/compiler.umd.js',
    '@angular/platform-browser': 'npm:@angular/platform-browser' + angularVersion + '/bundles/platform-browser.umd.js',
    '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic' + angularVersion + '/bundles/platform-browser-dynamic.umd.js',
    '@angular/http': 'npm:@angular/http' + angularVersion + '/bundles/http.umd.js',
    '@angular/router': 'npm:@angular/router' + angularVersion +'/bundles/router.umd.js',
    '@angular/forms': 'npm:@angular/forms' + angularVersion + '/bundles/forms.umd.js',
    '@angular/animations': 'npm:@angular/animations' + angularVersion + '/bundles/animations.umd.js',
    '@angular/platform-browser/animations': 'npm:@angular/platform-browser' + angularVersion + '/bundles/platform-browser-animations.umd.js',
    '@angular/animations/browser': 'npm:@angular/animations' + angularVersion + '/bundles/animations-browser.umd.js',
    
    '@angular/core/testing': 'npm:@angular/core' + angularVersion + '/bundles/core-testing.umd.js',
    '@angular/common/testing': 'npm:@angular/common' + angularVersion + '/bundles/common-testing.umd.js',
    '@angular/compiler/testing': 'npm:@angular/compiler' + angularVersion + '/bundles/compiler-testing.umd.js',
    '@angular/platform-browser/testing': 'npm:@angular/platform-browser' + angularVersion + '/bundles/platform-browser-testing.umd.js',
    '@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic' + angularVersion + '/bundles/platform-browser-dynamic-testing.umd.js',
    '@angular/http/testing': 'npm:@angular/http' + angularVersion + '/bundles/http-testing.umd.js',
    '@angular/router/testing': 'npm:@angular/router' + angularVersion + '/bundles/router-testing.umd.js',
    'tslib': 'npm:tslib@1.6.1',
    'rxjs': 'npm:rxjs',
    'typescript': 'npm:typescript@2.2.1/lib/typescript.js'
  },
  //packages defines our app package
  packages: {
    app: {
      main: './main.ts',
      defaultExtension: 'ts'
    },
    rxjs: {
      defaultExtension: 'js'
    }
  }
});
//main entry point
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {AppModule} from './app.module';

platformBrowserDynamic().bootstrapModule(AppModule)
import { Component, OnInit } from '@angular/core';
import { Item } from './item.model';

import { CartService } from './cart.service';
import { ItemService } from './item.service';

@Component({
  selector: 'my-item',
  template: `<div class="card card-block" *ngFor="let item of items">
   <h5 class="card-title">สินค้า: {{item.description}}</h5>
   <p class="card-text">ราคา: {{item.price}} บาท</p>
   
   <button type="button"
      class="btn"
      >
     ใส่รถเข็น
    <i class="fa fa-cart-plus fa-sm" aria-hidden="true"></i>
  </button>  
</div>`,
})
export class ItemComponent implements OnInit {
 items: Array<Item>;
 constructor(
    private cartService: CartService, 
    private itemService: ItemService) {}
 
 ngOnInit(): void {
   this.loadItems();
 }
 
 private loadItems(): void {
    this.items = this.itemService.getItems();
 }
 addToCart(itemId: number): void {
   this.cartService.addToCart(itemId);
 }
}
export class Item {
  constructor (
    public id: number,
    public description: string,
    public price: number,
    public comment: string
    ) {}
}
//our root app module
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouterModule } from '@angular/router';

import { AppComponent } from './app.component';
import { ItemComponent } from './item.component';
import { CartComponent } from './cart.component';
import { OrderComponent } from './order.component';
import { CartService } from './cart.service';
import { ItemService } from './item.service';

import { AppRouteModule } from './app-route.module';

@NgModule({
  imports: [ 
        BrowserModule,
        AppRouteModule
  ],
  declarations: [ 
    AppComponent, 
    ItemComponent, 
    CartComponent,
    OrderComponent
  ],
  providers: [
    CartService,
    ItemService
  ],
  bootstrap: [ AppComponent ]
})
export class AppModule {}
<div class="card card-block" *ngFor="let item of items">
   <h5 class="card-title">สินค้า: {{item.description}}</h5>
   <p class="card-text">ราคา: {{item.price}} บาท</p>
   
   <button type="button"
      class="btn"
      [routerLink] = "['/order', item.id]"
      >
     ใส่รถเข็น
    <i class="fa fa-cart-plus fa-sm" aria-hidden="true"></i>
  </button>  
</div>
<div class="card card-block">
  <h4 class="card-title">รายการที่ซื้อ</h4>
  <table width="100%">
    <tr>
      <th>รายการ</th>
      <th>ราคา</th>
      <th>จำนวน</th>
      <th>รวม</th>
    </tr>
    <tr *ngFor="let cart of carts">
      <td>{{cart.cart.item.description}}</td>
      <td>{{cart.cart.item.price}}</td>
      <td>{{cart.cart.quantity}}</td>
      <td>{{cart.cart.total}}</td>
    </tr>
    <tr>
      <td>รวมทั้งสิ้น</td>
      <td></td>
      <td>{{noOfItem}}</td>
      <td>{{grandTotal}}</td>
    </tr>
  </table>

</div>
<p></p>
<button type="button" class="btn" (click)="goBack()">
  <i class="fa fa-arrow-left" aria-hidden="true">Back</i>
</button>  
import { Component, OnInit }  from '@angular/core';
import { Location } from '@angular/common';

import { CartService } from './cart.service';
@Component({
  selector: 'my-cart',
  template: `<div class="card card-block">
  <h4 class="card-title">รายการที่ซื้อ</h4>
  <table width="100%">
    <tr>
      <th>รายการ</th>
      <th>ราคา</th>
      <th>จำนวน</th>
      <th>รวม</th>
    </tr>
    <tr *ngFor="let cart of carts">
      <td>{{cart.cart.item.description}}</td>
      <td>{{cart.cart.item.price}}</td>
      <td>{{cart.cart.quantity}}</td>
      <td>{{cart.cart.total}}</td>
    </tr>
    <tr>
      <td>รวมทั้งสิ้น</td>
      <td></td>
      <td>{{noOfItem}}</td>
      <td>{{grandTotal}}</td>
    </tr>
  </table>

</div>
<p></p>
<button type="button" class="btn" (click)="goBack()">
  <i class="fa fa-arrow-left" aria-hidden="true">Back</i>
</button>  `,
})
export class CartComponent implements OnInit{
  
  carts: Array<Cart>;
  noOfItem: number;
  grandTotal: number;
  
  constructor(
    private location: Location,
    private cartService: CartService) {}
  
  ngOnInit(): void {
    this.carts = this.cartService.getCarts();
    this.noOfItem = this.cartService.getNoOfItem();
    this.grandTotal = this.cartService.getGrandTotal();
  }
  
  goBack() : void {
   this.location.back();
 }
}
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription, Observable } from 'rxjs/Rx';
import { CartService } from './cart.service'

@Component({
  selector: 'my-app',
  templateUrl: "src/app.component.html"
})
export class AppComponent implements OnInit, OnDestroy {
  
  subscription: Subscription;
  cartInfo: any;
  
  constructor(private cartService: CartService) {}
  
  ngOnInit() {
    this.cartInfo = {noOfItem: 0, grandTotal: 0};
    
    this.subscription = this.cartService.getCartObservable().subscribe((cartInfo) => 
      { this.cartInfo = cartInfo; });  
  }
  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}
<div>
  <button type="button"
      [routerLink]="['/cart']"
     
      class="btn btn-primary">
    <i class="fa fa-shopping-cart fa-lg" aria-hidden="true"></i>
    <span class="badge badge-secondary">@{{cartInfo.noOfItem}}, {{cartInfo.grandTotal}}.-</span>
  </button>  
</div>
<p></p>
<router-outlet></router-outlet>
import { NgModule }             from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

import { ItemComponent } from './item.component';
import { CartComponent } from './cart.component';
import { OrderComponent } from './order.component';

const routes: Routes = [
  { path: '', redirectTo '/item', pathMatch: 'full' },
  { path: 'item', component: ItemComponent },
  { path: 'cart', component: CartComponent },
  { path: 'order/:id', component: OrderComponent }
];


@NgModule({
  imports: [ RouterModule.forRoot(routes,  {useHash: true}) ],
  exports: [ RouterModule ]
})
export class AppRouteModule {}
export class Cart {
  constructor (
    public item: Item,
    public quantity: number,
    public total: number
    ) {}
}
import { Injectable, Component } from '@angular/core';
import { Observable } from 'rxjs/Rx';
import { Subject } from 'rxjs/Subject';
import { Cart } from './cart.model';
import { Item } from './item.model';

@Injectable()
export class CartService {

 private cache: Map<number, Cart> = new Map<string, Cart>();
 private cartSubject: Subject<any> = new Subject<any>();
 private itemSubject: Subject<any> = new Subject<any>();
 private noOfItem: number = 0;
 private grandTotal: number = 0;
 
  addToCart(item: Item): void {
    const cart = new Cart();
    if (this.cache.has(item.id)) {
      console.log(`%cUp quantity and total for itemId: ${item.id}`,
                    'color: green');
      cart = this.cache.get(item.id);
      cart.quantity += 1;
      cart.total = cart.quantity * cart.item.price;
      this.cache.set(item.id, cart);
    } else {
      console.log(`%cCache set for item id: ${item.id}`, 'color: blue');
      cart.item = item;
      cart.quantity = 1;
      cart.total = cart.quantity * cart.item.price;
      this.cache.set(item.id, cart);
    }
    this.setItemTotal(cart);
    this.updateCartTotal();
  }
  
  removeFromCart(item: Item): void {
     if (this.cache.has(item.id)) {
        const cart = this.cache.get(item.id);
        cart.quantity -= 1;
        if (cart.quantity > 0) {
          console.log(`%cDown quantity and total for itemId: ${item.id}`,
                      'color: purple');
          cart.total = cart.quantity * cart.item.price;
          this.cache.set(item.id, cart);
          this.setItemTotal(cart);
        } else {
          console.log(`%cItem removed for itemId: ${item.id}`,'color: red');
          cart.quantity = 0;
          cart.total = 0;
          this.cache.delete(item.id);
          this.setItemTotal(cart);
        }
        this.updateCartTotal();
     } else {
        console.log(`%cNo item found in cart: ${item.id}`,'color: blue');
     }
  }

  getCarts(): Array<Cart> {
    const arr = Array.from(this.cache, ([key, cart]) => {
      return {cart};
    });
    return arr;
  } 
  
  getCartObservable(): Observable<any> {
    return this.cartSubject.asObservable();
  }
  
  getItemObservable():Observable<any> {
    return this.itemSubject.asObservable();
  }
  
  getCart(id: number) : Cart {
    const cart = new Cart();
    cart = this.cache.get(id);
    return cart
  }
  
  getItemFromCart(id: number): Item {
    return this.getCarts()
          .map(cart => cart.cart.item)
          .find(item => item.id === id);
  }
  
  isItemInCart(id: number): boolean {
    return this.cache.has(id);
  }
  
  getNoOfItem(): number {
    return this.noOfItem;
  }
  
  getGrandTotal(): number {
    return this.grandTotal;
  }
  
  private updateCartTotal(): void {
    this.noOfItem = this.getCarts()
                      .map(cart => cart.cart.quantity)
                      .reduce((total,quantity) => total + quantity, 0);
    
    this.grandTotal = this.getCarts()
                        .map(cart => cart.cart.total)
                        .reduce((grandTotal,total) => grandTotal + total, 0);

    this.cartSubject.next({noOfItem: this.noOfItem, grandTotal: this.grandTotal});  
  }

  private setItemTotal(cart: Cart): void {
     this.itemSubject.next({quantity: cart.quantity, total: cart.total});  
  }

}
import { Component, Injectable }  from '@angular/core';
import { Item } from './item.model';
import { Observable } from 'rxjs/Rx';

@Injectable()
export class ItemService {
  private items: Array<Item>;
  
  constructor() {
    this.items = [
        new Item(1,'ไม้จิ้มฟัน',20),
        new Item(3,'สากกระเบือ',300),
        new Item(2,'เรือรบ', 150) ,
        new Item(4,'Kinder egg', 45) 
      ];
  }
  
  getItems(): Array<Item> {
    return Observable.of(this.items);
  }
  
  getItem(id: number): Item {
    return this.items.find(item => item.id === id);
  }
}
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, ParamMap } from '@angular/router';
import { Location }                 from '@angular/common';
import { Subscription, Observable } from 'rxjs/Rx';

import 'rxjs/add/operator/switchMap';
import { Item } from './item.model';
import { CartService } from './cart.service'
import { ItemService } from './item.service';

@Component({
  selector: 'order-item',
  template: `<div class="card card-block">
   <h5 class="card-title">สั่งซื้อสินค้า: {{item.description}}</h5>
   <p class="card-text">ราคา: {{item.price}} บาท</p>
   <table width="100%">
     <tr>
       <td>
         <button type="button" class="btn" (click)="addToCart(item)" >
          <i class="fa fa-plus" aria-hidden="true"></i>
         </button> 
         <button type="button" class="btn" (click)="removeFromCart(item)">
          <i class="fa fa-minus" aria-hidden="true"></i>
         </button>
       </td>
       <td>จำนวน: {{itemInfo.quantity}}</td>
       <td>เป็นเงิน: {{itemInfo.total}} บาท</td>
     </tr>
   </table>
</div>
<button type="button" class="btn" (click)="goBack()">
  <i class="fa fa-arrow-left" aria-hidden="true">Back</i>
</button>  `
})
export class OrderComponent implements OnInit {
  
  item: Item;
  subscription: Subscription;
  itemSubscription: Subscription;
  cartInfo: any;
  itemInfo: any;
  cart: Cart;

 constructor(
    private cartService: CartService, 
    private itemService: ItemService,
    private route: ActivatedRoute,
    private location: Location
    ) {
      this.itemInfo = {quantity: 0, total: 0};
      
    }
 
 ngOnInit(): void {
   this.route.paramMap.subscribe((p) => {
    this.loadItem(+p.params.id);
   });
  
  this.cartInfo = {noOfItem: 0, grandTotal: 0};
    
  this.subscription = this.cartService.getCartObservable().subscribe((cartInfo) => 
    { this.cartInfo = cartInfo; });  
  //this.itemSubscription = this.cartService.getItemObservable().subscribe((itemInfo) => 
  //  { this.itemInfo = itemInfo; });
 }
 
  ngOnDestroy() {
    this.subscription.unsubscribe();
    this.itemSubscription.unsubscribe();
  }
 
 private loadItem(id: number): void {
   if (this.cartService.isItemInCart(id)) {
     this.item = this.cartService.getCart(id).item;
     this.itemInfo.quantity = this.cartService.getCart(id).quantity;
     this.itemInfo.total = this.cartService.getCart(id).total;
   } else {
    this.item = this.itemService.getItem(id);  
   }
 }
 
 addToCart(): void {
   this.cartService.addToCart(this.item);
 }
 
 removeFromCart(): void {
   this.cartService.removeFromCart(this.item);
 }
 
 goBack(): void {
  this.location.back();
 }
}
<div class="card card-block">
   <h5 class="card-title">สั่งซื้อสินค้า: {{item.description}}</h5>
   <p class="card-text">ราคา: {{item.price}} บาท</p>
   <table width="100%">
     <tr>
       <td>
         <button type="button" class="btn" (click)="addToCart(item)" >
          <i class="fa fa-plus" aria-hidden="true"></i>
         </button> 
         <button type="button" class="btn" (click)="removeFromCart(item)">
          <i class="fa fa-minus" aria-hidden="true"></i>
         </button>
       </td>
       <td>จำนวน: {{itemInfo.quantity}}</td>
       <td>เป็นเงิน: {{itemInfo.total}} บาท</td>
     </tr>
   </table>
</div>
<button type="button" class="btn" (click)="goBack()">
  <i class="fa fa-arrow-left" aria-hidden="true">Back</i>
</button>  
// BROWSER TESTING SHIM
// Keep it in-sync with what karma-test-shim does
/*global jasmine, __karma__, window*/
(function () {

Error.stackTraceLimit = 0; // "No stacktrace"" is usually best for app testing.

// Uncomment to get full stacktrace output. Sometimes helpful, usually not.
// Error.stackTraceLimit = Infinity; //

jasmine.DEFAULT_TIMEOUT_INTERVAL = 3000;

var baseURL = document.baseURI;
baseURL = baseURL + baseURL[baseURL.length-1] ? '' : '/';

System.config({
  baseURL: baseURL,
  // Extend usual application package list with test folder
  packages: { 'testing': { main: 'index.js', defaultExtension: 'js' } },

  // Assume npm: is set in `paths` in systemjs.config
  // Map the angular testing umd bundles
  map: {
    '@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js',
    '@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js',
    '@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js',
    '@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js',
    '@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',
    '@angular/http/testing': 'npm:@angular/http/bundles/http-testing.umd.js',
    '@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js',
    '@angular/forms/testing': 'npm:@angular/forms/bundles/forms-testing.umd.js',
  },
});

System.import('systemjs.config.js')
  .then(importSystemJsExtras)
  .then(initTestBed)
  .then(initTesting);

/** Optional SystemJS configuration extras. Keep going w/o it */
function importSystemJsExtras(){
  return System.import('systemjs.config.extras.js')
  .catch(function(reason) {
    console.log(
      'Warning: System.import could not load the optional "systemjs.config.extras.js". Did you omit it by accident? Continuing without it.'
    );
    console.log(reason);
  });
}

function initTestBed(){
  return Promise.all([
    System.import('@angular/core/testing'),
    System.import('@angular/platform-browser-dynamic/testing')
  ])

  .then(function (providers) {
    var coreTesting    = providers[0];
    var browserTesting = providers[1];

    coreTesting.TestBed.initTestEnvironment(
      browserTesting.BrowserDynamicTestingModule,
      browserTesting.platformBrowserDynamicTesting());
  })
}

// Import all spec files defined in the html (__spec_files__)
// and start Jasmine testrunner
function initTesting () {
  console.log('loading spec files: '+__spec_files__.join(', '));
  return Promise.all(
    __spec_files__.map(function(spec) {
      return System.import(spec);
    })
  )
  //  After all imports load,  re-execute `window.onload` which
  //  triggers the Jasmine test-runner start or explain what went wrong
  .then(success, console.error.bind(console));

  function success () {
    console.log('Spec files loaded; starting Jasmine testrunner');
    window.onload();
  }
}

})();


/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/
import { ActivatedRoute } from '@angular/router';
import { Observable } from 'rxjs';

export class MockActivatedRoute extends ActivatedRoute {

    constructor(parameters?: any) {
        super();
        this.queryParams = Observable.of(parameters);
        this.params = Observable.of(parameters);
    }
}
/**
 * WEB ANGULAR VERSION
 * (based on systemjs.config.js in angular.io)
 * System configuration for Angular samples
 * Adjust as necessary for your application needs.
 */
(function (global) {
  System.config({
    // DEMO ONLY! REAL CODE SHOULD NOT TRANSPILE IN THE BROWSER
    transpiler: 'ts',
    typescriptOptions: {
      // Copy of compiler options in standard tsconfig.json
      "target": "es5",
      "module": "commonjs",
      "moduleResolution": "node",
      "sourceMap": true,
      "emitDecoratorMetadata": true,
      "experimentalDecorators": true,
      "noImplicitAny": true,
      "suppressImplicitAnyIndexErrors": true
    },
    meta: {
      'typescript': {
        "exports": "ts"
      }
    },
    paths: {
      // paths serve as alias
      'npm:': 'https://unpkg.com/'
    },
    // map tells the System loader where to look for things
    map: {
      // our app is within the app folder
      app: 'src',

      // angular bundles
      '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
      '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
      '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
      '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
      '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
      '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
      '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
      '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
      '@angular/upgrade': 'npm:@angular/upgrade/bundles/upgrade.umd.js',
      '@angular/upgrade/static': 'npm:@angular/upgrade/bundles/upgrade-static.umd.js',

      // other libraries
      'rxjs':                      'npm:rxjs',
      'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js',
      'ts':                        'npm:plugin-typescript@4.0.10/lib/plugin.js',
      'typescript':                'npm:typescript@2.0.3/lib/typescript.js',

    },
    // packages tells the System loader how to load when no filename and/or no extension
    packages: {
      app: {
        main: './main.ts',
        defaultExtension: 'ts'
      },
      rxjs: {
        defaultExtension: 'js'
      }
    }
  });

  if (global.autoBootstrap) { bootstrap(); }

  // Bootstrap with a default `AppModule`
  // ignore an `app/app.module.ts` and `app/main.ts`, even if present
  // This function exists primarily (exclusively?) for the QuickStart
  function bootstrap() {
    console.log('Auto-bootstrapping');

    // Stub out `app/main.ts` so System.import('app') doesn't fail if called in the index.html
    System.set(System.normalizeSync('app/main.ts'), System.newModule({ }));

    // bootstrap and launch the app (equivalent to standard main.ts)
    Promise.all([
      System.import('@angular/platform-browser-dynamic'),
      getAppModule()
    ])
    .then(function (imports) {
      var platform = imports[0];
      var app      = imports[1];
      platform.platformBrowserDynamic().bootstrapModule(app.AppModule);
    })
    .catch(function(err){ console.error(err); });
  }

  // Make the default AppModule
  // returns a promise for the AppModule
  function getAppModule() {
    console.log('Making a bare-bones, default AppModule');

    return Promise.all([
      System.import('@angular/core'),
      System.import('@angular/platform-browser'),
      System.import('app/app.component')
    ])
    .then(function (imports) {

      var core    = imports[0];
      var browser = imports[1];
      var appComp = imports[2].AppComponent;

      var AppModule = function() {}

      AppModule.annotations = [
        new core.NgModule({
          imports:      [ browser.BrowserModule ],
          declarations: [ appComp ],
          bootstrap:    [ appComp ]
        })
      ]
      return {AppModule: AppModule};
    })
  }
})(this);

/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/
// this tsconfig is used for protractor tests
// see _boilerplate/tsconfig.json for the the tsconfig used in examples
{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": true,
    "suppressImplicitAnyIndexErrors": true,
    "typeRoots": [
      "node_modules/@types"
    ]
  },
  "files": [
    "protractor-helpers.ts"
  ],
  "include": [
    "*/e2e-spec.ts"
  ]
}
/* tslint:disable:no-unused-variable */
import { TestBed, async, ComponentFixture } from '@angular/core/testing';
import { Observable } from 'rxjs/Rx';
import { By }           from '@angular/platform-browser';
import { DebugElement } from '@angular/core';


import {Item} from 'src/item.model';
import {ItemComponent} from 'src/item.component';
import {CartService} from 'src/cart.service';
import {ItemService} from 'src/item.service';

describe('Item Component', () => {
  let fixture: ComponentFixture<ItemComponent>;
  let component: ItemComponent;
  let cartService: CartService;
  let itemService: ItemService;

  beforeEach(() => {
    // refine the test module by declaring the test component
    TestBed.configureTestingModule({
      declarations: [ItemComponent],
      providers: [
        CartService, 
        ItemService
        ]
      });
    });

  beforeEach(() =>{
    // create component and test fixture
    fixture = TestBed.createComponent(ItemComponent);

    // get test component from the fixture
    component = fixture.componentInstance;

    // UserService provided to the TestBed
    cartService = TestBed.get(CartService);
    itemService = TestBed.get(ItemService);
    
  });
  
   
  it ('Should create the component', () => {
      let app = fixture.debugElement.componentInstance;
      expect(app).toBeTruthy(); 
  });

  it ('Should call itemService.loadItems() and get item when OnInit', () => {
      //GIVEN
      expect(component.items).toBeUndefined();
    
      spyOn(itemService, 'getItems').and.returnValue([new Item(1,'test description',50)]);
      
      //WHEN
      component.ngOnInit();
      
      //THEN
      expect(component.items).toBeDefined(); 
      expect(itemService.getItems).toHaveBeenCalled();
      expect(component.items).toEqual(jasmine.any(Object));
      expect(component.items[0].id).toEqual(1);
      expect(component.items[0].description).toEqual('test description');
      expect(component.items[0].price).toEqual(50);
  });

});