Angular Services

Providing a singleton service

Two ways to make a service singleton in Angular

  • Declare that the service should be provided in the application root.
  • Include the service in the AppModule or in a module that is only imported by the AppModule.

Beginning with Angular 6.0, the preferred way to create a singleton services is to specify on the service that it should be provided in the application root. This is done by setting providedIn to root on the service’s @Injectable decorator:

Prefered Angular 6 Way using @Injectable decorator

  • Angular creates a single, shared instance of service and injects into any class that asks for it.
  • Registering the provider in the @Injectable metadata also allows Angular to optimize an app by removing the service if it turns out not to be used after all.
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class VoteService {
}

Register Service in providers array of @NgModule

import {VoteService} from './vote.service';
...
@NgModule({
  imports:      [ BrowserModule],
  declarations: [ AppComponent],
  bootstrap:    [ AppComponent],
  providers: [VoteService]
})

Reference

Angular 6: Using Karma for Unit Testing

×

Karma Installation

Install Karma Client on Windows 10 an run it from Command Line

D:\dev\myTestProjects\dobby-the-companion>  npm install -g karma-cli
C:\Users\Helmut\AppData\Roaming\npm\karma -> C:\Users\Helmut\AppData\Roaming\npm\node_modules\karma-cli\bin\karma
+ karma-cli@1.0.1
updated 1 package in 0.421s

D:\dev\myTestProjects\dobby-the-companion>  karma start
08 08 2018 16:03:24.227:WARN [karma]: No captured browser, open http://localhost:9876/
08 08 2018 16:03:24.232:WARN [karma]: Port 9876 in use
08 08 2018 16:03:24.233:INFO [karma]: Karma v1.7.1 server started at http://0.0.0.0:9877/

Run all Karma test

D:\dev\myTestProjects\dobby-the-companion>  ng test
 10% building modules 1/1 modules 0 active(node:25148) DeprecationWarning: Tapable.plugin is deprecated. Use new API on `.hooks` instead
10 08 2018 14:07:37.807:WARN [karma]: No captured browser, open http://localhost:9876/
10 08 2018 14:07:37.813:INFO [karma]: Karma v1.7.1 server started at http://0.0.0.0:9876/
10 08 2018 14:07:37.813:INFO [launcher]: Launching browser Chrome with unlimited concurrency
10 08 2018 14:07:37.817:INFO [launcher]: Starting browser Chrome              10 08 2018 14:07:43.581:WARN [karma]: No captured browser, open http://localhost:9876/

Missing Error Messages with Angular / Karma testing – add source-map=false parameter

D:\dev\myTestProjects\dobby-the-companion>   ng test --source-map=false
 10% building modules 1/1 modules 0 active(node:6332) DeprecationWarning: Tapable.plugin is deprecated. Use new API on `.hooks` instead
10 08 2018 14:24:47.487:WARN [karma]: No captured browser, open http://localhost:9876/
10 08 2018 14:24:47.492:INFO [karma]: Karma v1.7.1 server started at http://0.0.0.0:9876/
10 08 2018 14:24:47.492:INFO [launcher]: Launching browser Chrome with unlimited concurrency
10 08 2018 14:24:47.504:INFO [launcher]: Starting browser Chrome              10 08 2018 14:24:50.370:WARN [karma]: No captured browser, open http://localhost:9876/
10 08 2018 14:24:50.748:INFO [Chrome 67.0.3396 (Windows 10.0.0)]: Connected on socket Ml0r-gsA3JNw1F0sAAAA with id 52984303

Run ONLY a single Karma test

Change in your IDE :   
           describe('LoginComponent', () => {
        -> fdescribe('LoginComponent', () => {   

Reference

Using RouterTestingModule to test Angular Router Object

Code to be tested

import {Router} from '@angular/router';

export class myComponent  {
  constructor(   private router: Router ) { }           
  triggerMessageAction(m: Message) {
   
    if (m.messageClass === 'internal') {
      this.router.navigate([m.messageLink]);
    } 
  }

Karma/Jasmine Test Code

import {RouterTestingModule} from '@angular/router/testing';
import {Router} from '@angular/router';

describe('WarningDialogComponent', () => {
  
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      ...
      imports: [ RouterTestingModule ],     
    }).compileComponents();
  }));

  beforeEach(inject([MessagesService], (service: MessagesService) => {
   ...
  }));

  it('should close Warning Dialog after pressing on a Warning Action ', inject([MessagesService, Router],
    (service: MessagesService, router: Router) => {
      spyOn(component, 'triggerMessageAction').and.callThrough();
      spyOn(router, 'navigate').and.returnValue(true);
      expect(component.triggerMessageAction).toHaveBeenCalledWith(jasmine.objectContaining( {messageType: 'logout'}));
      expect(router.navigate).toHaveBeenCalledWith('login'); 
    }));
});

Potential Error

Error:  : Expected a spy, but got Function.
Usage: expect().toHaveBeenCalledWith(...arguments)

Fix: Add spyOn for the methode you want to spy
spyOn(router, 'navigate').and.returnValue(true)

Using SpyOn to run UNIT-tests for Angular Router Calls

  • spyOn() takes two parameters: the first parameter is the name of the object and the second parameter is the name of the method to be spied upon
  • It replaces the spied method with a stub, and does not actually execute the real method
  • The spyOn() function can however be called only on existing methods.
  • A spy only exists in the describe or it block in which it is defined, and will be removed after each spec

Sample Code

 it(`Fake Login with should set isAuthenticated Flag and finally call route: ects`,
    async(inject([AuthenticationService, HttpTestingController],
    (service: AuthenticationService, backend: HttpTestingController) => {

      spyOn(service.router, 'navigate').and.returnValue(true);

      service.login('Helmut', 'mySecret');
      // Fake a HTTP response with a Bearer Token
      // Ask the HTTP mock to return some fake data using the flush method:
      backend.match({
        method: 'POST'
      })[0].flush({ Bearer: 'A Bearer Token: XXXXXXX' });

      expect(service.router.navigate).toHaveBeenCalled();
      expect(service.router.navigate).toHaveBeenCalledWith(['ects']);
      expect(service.isAuthenticated()).toEqual(true);
    })));

Reference

My Fist Karma Sample

Screenshot Chrome Browser after running Tests Details
Image karma_img1.jpg NOT Found
  • Karma verison is v1.7.1
  • Only 1 of our 18 test was running as we use fdescribe
  • The test shows no error
  • The Screen is devided into 2 divs
  • Div with class html-report shows the test details
  • Div with class root0 shows the angular HTML components
Html Code Type Script TestCode: login.components.spec.ts
</p> <div class="text-center"> <h1>TestKarma</h1> <p> <img class="img-fluid" src="assets/th-logo.jpeg"> </div> <form (ngSubmit)="onLogin(f)" #f="ngForm"> <div class="form-group"> <label for="username">Benutzer</label><br /> <input type="text" id="username" name="username" ngModel class="form-control"> </div> <div class="form-group"> <label for="password">Passwort</label><br /> <input type="password" id="password" name="password" ngModel class="form-control"> </div> <p> <button class="btn btn-primary" type="submit">Anmelden</button><br /> </form

import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { LoginComponent } from './login.component';
import {FormsModule} from '@angular/forms';
import {RouterTestingModule} from '@angular/router/testing';
import {AuthenticationService} from '../authentication.service';
import {AuthGuard} from '../auth-guard.service';

fdescribe ('LoginComponent', () => {
  let component: LoginComponent;
  let fixture: ComponentFixture<LoginComponent>;
  let h1:        HTMLElement;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ LoginComponent ],
      imports: [FormsModule, RouterTestingModule ],
      providers: [AuthenticationService]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(LoginComponent);
    component = fixture.componentInstance;
    h1 = fixture.nativeElement.querySelector('h1');
    console.log(h1);

    fixture.detectChanges();
  });

  it('should have <h1> with  TestKarma', () => {
    const loginElement: HTMLElement = fixture.nativeElement;
     h1 = loginElement.querySelector('h1');
    expect(h1.textContent).toEqual('TestKarma');
  });

  it('should be created', () => {
    expect(component).toBeTruthy();
  });
});

Debug Karma Test

  • Add debugger keyword to your Java Script Code you want to debug
  • Start Karma tests with : ng test
  • Add Chrome Debugger Tools by pressing F12
  • Reload your page – Javascript code should stop on the line with debugger statement
Screenshot Chrome Browser after running Tests Details
Image karma_img3.jpg NOT Found Image karma_img3.jpg NOT Found

A more complexer Sample setting up a Karma Test Environment for Integration Tests

import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { CurrentSemesterComponent } from './current-semester.component';
import { CommonHeaderComponent } from '../common-header/common-header.component';
import { NavigationComponent } from '../navigation/navigation.component';
import { RouterTestingModule } from '@angular/router/testing';
import { MatIconModule } from '@angular/material';
import {MatButtonToggleModule} from '@angular/material/button-toggle';
import {AuthenticationService} from '../auth/authentication.service';


fdescribe('CurrentSemesterComponent', () => {
  let component: CurrentSemesterComponent;
  let fixture: ComponentFixture;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ CurrentSemesterComponent,CommonHeaderComponent, NavigationComponent ],
      providers: [AuthenticationService,],
      imports: [RouterTestingModule, MatIconModule, MatButtonToggleModule ],
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(CurrentSemesterComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});

Jasmine Test Order

  • Currently (v2.x) Jasmine runs tests in the order they are defined
  • However, there is a new (Oct 2015) option to run specs in a random order, which is still off by default
  • According to the project owner, in Jasmine 3.x it will be converted to be the default.

Reference

Jasmine and Timeout

Reference

https://makandracards.com/makandra/32477-testing-settimeout-and-setinterval-with-jasmine

Error: router-outlet’ is not a known element:

Error Details

'router-outlet' is not a known element:
1. If 'router-outlet' is an Angular component, then verify that it is part of this module.
2. If 'router-outlet' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message. 

"<app-navigation></app-navigation>
<div class="container">
  [ERROR ->]<router-outlet></router-outlet>
</div>
"): ng:///DynamicTestModule/AppComponent.html@2:2

Fix – import RouterTestingModule

import {RouterTestingModule} from '@angular/router/testing'

describe('AppComponent', () => {
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
        AppComponent
      ],
      imports: [ RouterTestingModule ]
    }).compileComponents();
  }));

Reference

Error: app-navigation’ is not a known element:

Error Details

AppComponent should create the app
Failed: Template parse errors:
'app-navigation' is not a known element:
1. If 'app-navigation' is an Angular component, then verify that it is part of this module.
2. If 'app-navigation' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message. ("

<title>app</title>
[ERROR ->]<app-navigation></app-navigation>


Angular code

app.component.html 

<app-navigation></app-navigation>
<div class="container">
  <router-outlet></router-outlet>
</div>


navigation.component.ts 
import {Component, OnInit} from '@angular/core';
import {AuthenticationService} from '../auth/authentication.service';

@Component({
  selector: 'app-navigation',
  templateUrl: './navigation.component.html',
  styleUrls: ['./navigation.component.css']
})
...

Fix – Add a stubbing Object

import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
import {RouterTestingModule} from '@angular/router/testing'
import {Component} from '@angular/core';

@Component({selector: 'app-navigation', template: ''})
class NavigationStubComponent {}

describe('AppComponent', () => {
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
        AppComponent,
        NavigationStubComponent
      ],
      imports: [ RouterTestingModule ]
    }).compileComponents();
  })

Reference

Error Injecting a service

Error Datails: NullInjectorError: No provider for AuthenticationService!

NavigationComponent should create
Error: StaticInjectorError(DynamicTestModule)[NavigationComponent -> AuthenticationService]: 
  StaticInjectorError(Platform: core)[NavigationComponent -> AuthenticationService]: 
    NullInjectorError: No provider for AuthenticationService!

Fix add AuthenticationService to the provider Array

import {AuthenticationService} from '../auth/authentication.service';

describe('NavigationComponent', () => {
  let component: NavigationComponent;
  let fixture: ComponentFixture;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ NavigationComponent ],
      providers: [
        MatSnackBar,
        Overlay,
        AuthenticationService,
        SnackBarComponent,
        DatePipe],
    })
    .compileComponents();
  }));

Error: Failed: Template parse errors

Error Datails: There is no directive with “exportAs” set to “ngForm”

LoginComponent should create
Failed: Template parse errors:
There is no directive with "exportAs" set to "ngForm" ("

<form (ngSubmit)="onLogin(f)" [ERROR ->]#f="ngForm">
  <div class="form-group">
    <label for="username">Benutzer</label>
"): ng:///DynamicTestModule/LoginComponent.html@5:30

Fix: Add FormsModule Import

describe('LoginComponent', () => {
  let component: LoginComponent;
  let fixture: ComponentFixture;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ LoginComponent ],
      imports: [FormsModule ],
      providers: [AuthenticationService]
    })

Reference

Error: StaticInjectorError(DynamicTestModule)[AuthGuard -> Router]:

Error Datails: NullInjectorError: No provider for Router!

Error: StaticInjectorError(DynamicTestModule)[AuthGuard -> Router]: 
  StaticInjectorError(Platform: core)[AuthGuard -> Router]: 
    NullInjectorError: No provider for Router!
Error: StaticInjectorError(DynamicTestModule)[AuthGuard -> Router]: 
  StaticInjectorError(Platform: core)[AuthGuard -> Router]: 
    NullInjectorError: No provider for Router

Fix: Add RouterTesting Module

import { TestBed, async, inject } from '@angular/core/testing';
import { AuthGuard } from './auth-guard.service';
import {AuthenticationService} from '../auth/authentication.service';

import {RouterTestingModule} from '@angular/router/testing';
describe('AuthGuard', () => {
  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [AuthGuard,
         AuthenticationService,
      ],
      imports: [
        RouterTestingModule
      ],
    });
  });

Setup for NGXLogger

Note: the setup below should use a single logger instance for both : Code Base and for Karma/Jasmine Tests!

import { TestBed, inject } from '@angular/core/testing';
import {LoggerConfig, LoggerTestingModule, NGXLogger} from 'ngx-logger';

fdescribe('InterceptService', () => {
  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [
        LoggerTestingModule
      ],
      providers: [   NGXLogger, LoggerConfig, 
       ... ]
    });
  });

fit(' should create and test NGXLogger  !',
    inject([NGXLogger], (logger: NGXLogger) => {
        // config the Logger
      logger.updateConfig({ level: NgxLoggerLevel.DEBUG });
        // send a Test message from our Karma Code to the
      logger.log('Logger Message from Karma Testing Module !');
        // Override the logger instance from our production code
      component.logger = logger;
        // Invoke a function to test  NGXLogger functionality works for our Code Base too !
      component.syncSemsterData();
      expect(component).toBeTruthy();
    }));
});

Logger Output : 
2019-08-13T11:37:46.298Z LOG [semester-goal-setting.component.spec.ts:95] Logger Message from Karma Testing Module !
2019-08-13T11:37:46.743Z LOG [semester-goal-setting.component.ts:130] syncSemsterData():: Subjects: 3 - all Marks Valid : true - saveButtonIsDisabled false

A complexer Sample mocking Services and Components

@Component({selector: 'app-semester-header', template: ''})
class SemesterHeaderStubComponent {}

@Component({selector: 'app-navigation', template: ''})
class NavigationStubComponent {}

export class MockDataService {
  public isReady = true;
  getIsReady(): boolean {
    return this.isReady;
  }
  setAppStatusFailed(): void  {}

  getSemesterById(): Semester {
  return new Semester(1, 20, 30 , false, true,
    [ new Module('Mathematik', 8, 2.2, 2.0, 3.0, true),
               new Module('JAVA Programming 2', 7, 2.2, 2.0, 3.0, true),
    ]);
  }
}

describe('CurrentSemesterComponent', () => {
  let component: CurrentSemesterComponent;
  let fixture: ComponentFixture;
  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [ CurrentSemesterComponent, SemesterHeaderStubComponent, NavigationStubComponent],
      imports: [
        LoggerTestingModule,
        RouterTestingModule,
        NoopAnimationsModule
      ],
      schemas:  [NO_ERRORS_SCHEMA],
      providers: [
        NGXLogger,
        LoggerConfig,
        {provide: DataService, useValue: new MockDataService() } ]
    });
    fixture = TestBed.createComponent(CurrentSemesterComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  /*
      Whenever dataService is not ready  setAppStatusFailed() should be called with systemError param
   */
  it('if dataService not READY setAppStatusFailed() should be called with param \'systemError\' ', () => {
    let dataService: MockDataService;
    dataService = TestBed.get(DataService);
    const spy = spyOn(dataService, 'setAppStatusFailed');
    dataService.isReady = false;
    component.ngOnInit();
    expect(component).toBeTruthy();
    expect(dataService.setAppStatusFailed).toHaveBeenCalledWith('systemError');
  });
  /*
        Whenever dataService is READY setAppStatusFailed() should NOT be called anyway
     */
  it('if dataService is READY setAppStatusFailed() should not have been called', () => {
    let dataService: MockDataService;
    dataService = TestBed.get(DataService);
    const spy = spyOn(dataService, 'setAppStatusFailed');
    dataService.isReady = true;
    component.ngOnInit();
    expect(component).toBeTruthy();
    expect(dataService.setAppStatusFailed).not.toHaveBeenCalled();
  });

});

Mock a Service Object

export class MockDataService {
  public isReady = true;

  getSemesterById(semId: number): Semester {
    return new Semester(  '20192' , 30, 0,  '', 0,
      [
        new Mark( 4.5, 5, new Exam ( '6', 'Mathematik S1'), 3, true ),
        new Mark( 2.5, 7, new Exam ( '5', 'JAVA Programming II S1'), 2, true ),
        new Mark( 1.5, 8, new Exam ( '4', 'C ++ Programming II S1'), 2.7, true ),
      ])
  }

}

fdescribe('SemesterGoalSettingComponent', () => {
  let component: SemesterGoalSettingComponent;
  let fixture: ComponentFixture;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ SemesterGoalSettingComponent ],
      schemas: [NO_ERRORS_SCHEMA],
      imports: [ MatTableModule, MatDialogModule, RouterTestingModule, LoggerTestingModule ,  HttpClientModule,
        HttpClientTestingModule, MatSnackBarModule],
      providers: [ NGXLogger, LoggerConfig, MatSnackBar, MatDialog,
        { provide: DataService, useValue: new MockDataService() } ]
    })
    .compileComponents();
  }));
...

Simulate a Button Press Action

Karma/Jasmine Test Code:
beforeEach(() => {
    fixture = TestBed.createComponent(SemesterHeaderComponent);
    component = fixture.componentInstance;
    // 'autoDetectChanges' will continually check for changes until the test is complete.
    // This is slower, but necessary for certain UI changes as changes triggered by ngFor Ops
    fixture.autoDetectChanges(true);
  });

it('Button Press should redirect to Central ECTS Page  ', () => {
    spyOn(component, 'navigateTop');
    const el1 =   fixture.debugElement.query(By.css('#return-to-top-level-page')).nativeElement;
    el1.click();
    expect(component.navigateTop).toHaveBeenCalled();
  });

HTML Code:

    <button id="return-to-top-level-page" class="mat-button-study-progress" mat-button  (click)="navigateTop()" > <mat-icon class="button-navigate-back color_white" >arrow_back_ios</mat-icon> </button>


JavaScript Code:

 navigateTop() {
    this.logger.warn('SemesterHeaderComponent::navigate  to ECTS Page !: ');
    this.router.navigate(['ects']);
  }

JEE7: Using Logging with SLF4j

×

Generic SLF4l Logging Overview

Overview SLf4j logging with jcl-over-slf4j

SLf4j logging with jcl-over-slf4j
Image slf4j_logging_img1.jpg  NOT Found

pom.xml


       <!-- Logging -->
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-classic</artifactId>
                <version>1.0.13</version>
            </dependency>
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>jcl-over-slf4j</artifactId>
                <version>1.7.5</version>
            </dependency>

Downloaded External Libraries by MAVEN

  • logback-classic-1.0.13.jar
  • logback-core-1.0.13.jar
  • jcl-over-slf4j-1.7.5.jar
  • slf4j-api-1.7.5.jar

Jee7 Code Sample for SLF4j Logging

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

// The Java class will be hosted at the URI path "/helloworld"
@Path("/helloworld")
public class HelloWorld {
    private static final Logger LOGGER
            = LoggerFactory.getLogger(HelloWorld.class);

    // The Java method will process HTTP GET requests
    @GET
    // The Java method will produce content identified by the MIME Media type "text/plain"
    @Produces("text/html")
    public String getFirstMessage() {
        LOGGER.info(" ---- Inside HTTP GET Request --- ");
 ..
<

SLF4j Logger Output [ server.log payara41\glassfish\domains\domain1\logs ]

  10:43:31.058 [http-thread-pool::http-listener-1(4)] INFO  HelloWorld -  ---- Inside HTTP GET Request --- 

JSF accessing an Resource

  • #{status} translates to enum value: FEMALE
  • {backend[status] translates to backend[FEMALE]
  • backend.properties translates FEMALE to Frau

 <f:selectItem itemValue="#{null}" itemLabel="Auswahl Geschlecht" noSelectionOption="true"  itemDisabled="true" />
                <f:selectItems
                        value="#{editor.myEnumValues}"
                        var="status"
                        itemValue="#{status}"
                        itemLabel="<strong>#{backend[status]</strong>}"
                />

Runtime Logging for SLFj/Logback

Display all Classes which are avaiable for Logging via Logback

      LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
      List loggerList = loggerContext.getLoggerList();
      loggerList.stream().forEach(tmpLogger -> System.out.println(tmpLogger.toString()
                + "  Log Level:" + tmpLogger.getLevel() + "  Name:" + tmpLogger.getName() ));

An Arquillian Sample using @BeforeClass @AfterClass Annotations

 @BeforeClass
    public static void setUpClass() {
        LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
        ch.qos.logback.classic.Logger myClassLogger =  loggerContext.getLogger("de.thnuernberg.in.infohm.server.services.AccountServiceIT");
        myClassLogger.setLevel(Level.toLevel("INFO"));
    }

   @AfterClass
    public static void tearDownClass() {
        LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
        ch.qos.logback.classic.Logger myClassLogger =  loggerContext.getLogger("de.thnuernberg.in.infohm.server.services.AccountServiceIT");
        myClassLogger.setLevel(null);
    }

  @Test
    @UsingDataSet("account.xml")
    public void testRemoveAccounts()   {
...
  

Reference

wpPlanung

×

Status Heizungs-Planung

Datum Action Status Link
18-Feb-2018 Eintragen in die Sammelliste für die Geisha Bestellung done Aquarea Club Sammelbestestellung
18-Feb-2018 Auswahl Geisha Type [ Geisha-F / Geisha-H ] in progress HausTechnikDialog Thread: New Geisha-H
18-Feb-2018 Auswahl Fußboden-Heizung tbd ev Kermi ?
18-Feb-2018 Hydraulik-Planung tbd
18-Feb-2018 BAFA tbd

Haus Beschreibung

Übersicht Haus

Übersicht PV Anlagen

PV Name WR-Type kWp Vergütung Rest-Laufzeit EEG
PV I Fronius 4,73 49,21 ct/kWp 10 Jahre
PV II SMA 7,77 39,14 ct/kWp 8 Jahre
PV III Fronius 7,56 12,30 ct/kWp 20 Jahre

Übersicht Heizung / Lüftungsanlage

Heizung Lüftung
Primär-Heizung Wodtke Frank Waterplus 10 kW – wasserführend [ modulierend max. 8,6 kW im Winter ] Lüftungs-System Tecalor TVZ 171
5 Flach-Kollektoren Buderus SKN 3.0 [ ca 11qm ]
Kombispeicher Logalus P750 S

Heizungs-Verhalten Jetzt-Zustand

Heizung
Der Wodtke-Ofen wird an kalten Tagen früh morgens und abends eingeschaltet [ wenn wir auf Arbeit sind ist der Ofen aus ! ]
Wenn wir abends nach Hause komme braucht der Ofen ca. 1 – 2 Stunden bis der Heizkörper im Wohnzimmer langsam warm wird – etwas träge !
An sehr kalten Tagen ohne Sonne sinkt die Temperatur in Wohnzimmer dann bis abends auf ca. 20 Grad ab
Im Kombispeicher Logalus P750 S sinken die Temperaturen am Abend vor Zuschalten des Wodtkes auf 55 / 38 / 28 Grad
sowohl für den Wotdke Ofen als auch für Flach-Kollektoren gabs 2008 ne BAFA-Förderung

Warum Neuplanung unserer Heizung-Anlage

Gründe für Neu-Plamung
zusätzl. Wohnfläche von 51,4 qm im Nebengebäude über FBH – [ fast Passivhausstandard – aber ohne Lüftungsanlage ]
Heizungsausfall-Zeiten minimieren [ 2017 Platinenschaden am Wodte Ofen -> 2 Wochen kein warmes Wasser über Weihnachten -> nicht lustig ]

Ziele der Heizungs-Änderung

Ziele
Die Trägheit des Heizungssystems verringern
Heizen beider Wohnungen über WP auch wenn wir tagsüber außer Haus sind
Ausfallsicherheit erhöhen [ Heizung / WW-Bereitung entweder durch Wodtke bzw WP oder bestenfalls durch beide ]
In die Bestands-Heizung sollte nur sehr geringfügig eingegriffen werden
Im Winter Buffer-Temperatur auf ca. 40-45 Grad mit unserer NEUEN Geisha stabilisieren
Unser Passivhaus sollte weiter über die Wärmestrahlung des Wodtke Ofens beheizt werden, da im Passivhaus nur wenig Heizkörperfläche verfügbar ist

Hydraulik-Plan der Heizung

  • Neue Heizungs-Elemente sind ROT umrahmt !”
  • Hydraulik-Plan vom 28-Feb-2018 mit Kombispeicher Logalus P750 S
Hydraulik-Plan vom 28-Feb-2018 mit Kombispeicher Logalus P750 S
Image Hydraulik-Plan-Heizung_Neu.jpg NOT Found

Wärmepumpe Auswahl

Geisha-H [WH-MDC05H3E5] or Geisha-F [WH-MDC05F3E5] – That’s the Question

Pro Geisha-H:

  • neues Modell/wird aktiv produziert
  • mittels günstiger Zusatzplatine (ca.200€) kann die Funktion erweitert werden, die bei der F den HPM und ein Steuerkabel erfordert (ca. 500€).
  • Schnüffelmodusproblem ist nicht mehr da
  • Die Wiedereinschalthysterese kann eingestellt werden
  • Höhere Spreizung -> weniger Durchmischung, bessere Schichtung, und weniger Auskühlen [ mein LogaLux P750 S == Puffer mit FRIWA ]

Pro Geisha-F:

  • wird von der BAFA gefördert, auf die Aufnahme der H in die BAFA Liste warten wir noch

Contra Geisha-F:

  • Produktion ist aus, nur noch Lagerbestände verfügbar
  • Steuerung wie in den 80er Jahren

Reference Wärmepumpe Auswahl

Geisha-H BAFA Status

MarcoDahlhaus 	Zeit: 04.02.2018 12:26:59
  Beitrag der Redaktion melden
Der BAFA-Antrag hat mich auch interessiert.

Zusammengefasster Email-Verlauf:

BAFA: Frag die Betreiber vom JAZ-Rechner
JAZ-Rechner: Frag Panasonic
Panasonic: 
besten Dank für Ihre Anfrage.

Wir werden das genannte Produkt bei der BAFA und weiteren Datenbanken listen lassen, sobald die offiziellen Test Reports hierzu vorliegen.

Diese Test Reports sind der Nachweis der vorab zur Verfügung gestellten Werksangaben.

Als abschätzbarer Zeitraum wird dies voraussichtlich im Frühjahr 2018 sein.

Nochmal BAFA:
tragen Sie bitte im Online-Antrag bei der "Jahresarbeitszahl" die Mindestanforderung (3,5 bei Basisförderung oder 4,5 bei Innovationsförderung) ein und anstatt der JAZ-Berechnung laden Sie bitte eine Stellungnahme hoch.
Bei der Antragstellung beim Hersteller wählen Sie bitte "Sonstiges & Sonderbauform" aus und als Antragstellerunterlage noch ein Angebot über die Wärmepumpe.

So sollte der Online-Antrag durchgehen und übermittelt werden.

FBH – Fußboden-Heizung

Kermi Fußboden-Heizung

Reference

Using Promises

×

About Promise

How Promises Work

A promise is an object which can be returned synchronously from an asynchronous function.
It will be in one of 3 possible states:

  • Fulfilled: onFulfilled() will be called (e.g., resolve() was called)
  • Rejected: onRejected() will be called (e.g., reject() was called)
  • Pending: not yet fulfilled or rejected

Promises following the spec must follow a specific set of rules:

  • A promise or “thenable” is an object that supplies a standard-compliant .then() method.
  • A pending promise may transition into a fulfilled or rejected state.
  • A fulfilled or rejected promise is settled, and must not transition into any other state.
  • Once a promise is settled, it must have a value (which may be undefined). That value must not change.
  • A Promise can be resolved or rejected, exclusively and only once.
  • A call to promise.then returns a promise, so that we can call the next promise
  • A value returned by a .then handler is immediately passed to the next handler
  • If the returned value is a promise, then the further execution is suspended until it settles.
  • A fetch() promise will reject with a TypeError when a network error is encountered or CORS is misconfigured on the server side
  • By default, fetch won’t send or receive any cookies from the server

Chained Promises

Chained Promises Sample

function testMe(myUrl, test, dataError) {
    dumpMessage("Testing Promise Chaining: "  + test, false);
    let url = myUrl;
    fetch(url)                           // fetch returns a promise       
        .then(response => {              // Our Success Handler returns response Object 
            if(response.ok) {
                if ( dataError) {        // Just for testing - Mimicking a Data Proessing Error
                    throw new Error('Data Processing Error');
                }  
                return response.json();
            }
            throw new Error('Network response was not ok  at Chain Level 1');
        })  // Catches Exception for our Success Handler and for our Reject Handler 
    .catch(e => { 
        dumpMessage("Exception at Chain Level 1  : " + e,true );  
        throw new Error('Initial Fetch failed for URL: ' + url); 
    })
    .then(jsonData => { dumpMessage("ID: " + jsonData.id + " - name : " + jsonData.name,false ); return(jsonData.name);} )
    .then( (user) => {  dumpMessage("Username: " + user, false);  return fetch("https://api.github.com/users/"+user ); })
        // Load the response as json
    .then(response => response.json())     
        // Show the avatar image (githubUser.avatar_url) for 3 seconds (maybe animate it)
    .then(githubUser => {
        dumpMessage("Displaying Github Avatar Image for 3 seconds!", false);  
        let img = document.createElement('img');
        img.src = githubUser.avatar_url;
        img.className = "promise-avatar-example";
        document.body.append(img);

        setTimeout(() => {
            img.remove();
            dumpMessage("Removed Github Avatar Image !", false);
        }, 3000); // (*)
    })
    .catch(err => {             // Catch all Hanlder return true/false for retry logic 
        dumpMessage("CatchAll Error-handler: " + err, true);
        });
} 

Promises and Error Handling

Overview

Pomisess Error Handling Diagram
Image promise_img1.jpg NOT Found

Handle Errors – Pattern 1


save().then(
  handleSuccess,
  handleError
);


  • Problem Exceptions in handleSuccess() are not catched

Handle Errors – Pattern 2


save()
  .then(handleSuccess)
  .catch(handleError)


Sample:
 fetch(url)                           // fetch returns a promise       
        .then(response => {              // Our Success Handler returns response Object 
            if(response.ok) {
                if ( dataError) {        // Just for testing - Mimicking a Data Proessing Error
                    throw new Error('Data Processing Error');
                }  
                return response.json();
            }
            throw new Error('Network response was not ok  at Chain Level 1');
        })  // Catches Exception for our Success Handler and for our Reject Handler 
    .catch(e => { 
        dumpMessage("Exception at Chain Level 1  : " + e,true );  
        throw new Error('Initial Fetch failed for URL: ' + url); 
    })
    .then(jsonData => { dumpMessage("ID: " + jsonData.id + " - name : " + jsonData.name,false ); return(jsonData.name);} )
    ...

Handle Errors – Pattern 3


save()
  .then(
    handleSuccess,
    handleNetworkError    -> Handle and Fix Network Error
  )
  .catch(handleProgrammerError) -> Handle anf Fix ProgamError in handleSucessFunction


Sample:
    fetch(url)                      
        .then(response => {              // Our Success Handler 
            if(response.ok) {
                if ( dataError) {        // Mimicking a Data Proessing Error
                    throw new Error('Data Processing Error');
                }  
                return response.json();
            }
            throw new Error('Network response was not ok.');
        },      
        err => {    // Now we handle the error (rejection reason)
            dumpMessage("Handle error (rejection reason): " + err,true );  
               // Create a Dummy object
            dumpMessage("Create a Default Object to Finish Promise Chain");    
            myObj = { "name":"hhutzler", "id":999 };
            return myObj;
        } )
        .catch(e => { dumpMessage("Processing Error Chaining at Level 1  : " + e,true );  
            dumpMessage("Create a Default Object to Finish Promise Chain");    
            myObj = { "name":"hhutzler", "id":999 };
            return myObj;                   
        })
            //        ,        // Now we handle the error (rejection reason)
            //e => { dumpMessage("Initial Fetch Error: " + e,true );  throw new Error('Initial Fetch Error for URL' + url); } )
            //.then(response =>  response.json() )
    .then(jsonData => { dumpMessage("ID: " + jsonData.id + " - name : " + jsonData.name,false ); return(jsonData.name);} )
    ....

Reference

CORS Details

Setup

  • Html Page was loaded from: localhost
  • PHP file was loaded from: http://hhutzler.de

JavaScript Code

console.log("Testing Promise Chaining by Returning New Promises");
fetch("http://hhutzler.de/myID.php")
  .then(response =>  response.json() )
  .then(jsonData => { console.log("ID returned by node-fetch Module : " + jsonData.id + " - name : " + jsonData.name );} );

PHP Code


$myObj = new stdClass();
$myObj->id=999;
$myObj->name = "hhutzler";
$myObj->city = "Sattelmanmsburg";

$myJSON = json_encode($myObj);

echo $myJSON;

Expected CORS Error

 
Failed to load http://hhutzler.de/myID_NW.php: No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin 'http://localhost' is therefore not allowed access. 
If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

FIX – Add Access-Control-Allow-Origin to the PHP File

 
header('Access-Control-Allow-Origin: *'); 

$myObj = new stdClass();
$myObj->id=999;
$myObj->name = "hhutzler";
$myObj->city = "Sattelmanmsburg";

$myJSON = json_encode($myObj);

echo $myJSON;

Using JIRA

Overview JIRA

What is a Board ?

A board displays issues from one or more projects, giving you a flexible way of viewing, managing, and reporting on work in progress. There are two types of boards in Jira Software:

  • Scrum board: For teams that plan their work in sprints. Includes a backlog.
  • Kanban board: For teams that focus on managing and constraining their work-in-progress. Includes the option of a Kanban backlog.

What is a Epic ?

An epic captures a large body of work. It is essentially a large user story that can be broken down into a number of smaller stories. It may take several sprints to complete an epic.

What is a Sprint ?

A sprint — also known as an iteration — is a short (ideally two to four week) period in which the development team implements and delivers a discrete product increment, e.g. a working milestone version.

Introduction to JIRA & Agile Project Management

  • Introduction to JIRA & Agile Project Management
  • Install JIRA

    Downlaod JIRA

    Install JIRA on Windows 7

    D:\Program Files\Atlassian\JIRA\bin> dir \software
    20.01.2018  15:16       350.857.328  atlassian-jira-software-7.7.0-x64.exe
    
    As Administrator run: atlassian-jira-software-7.7.0-x64.exe
    Select: 
      Advanced Mode for installation 
      Ports 9080 9005     [ change Ports if needed ]
      Start as a service  [ Start JIRA as a service ]
    Login: 
      Email: 	   Helmut.Hutzler@gmail.com
      Benutzer:  Helmut.Hutzler
      Password:  .....it
    Config: 
      Running the Setup Wizard 
    

    Reference JIRA Installation

    Run JIRA on our local System JIRA

    • Note the Link below: http://localhost:9080/secure/Dashboard.jspa works ONLY on my local System !
    • Run JIRA Dashbaord

    Working with JIRA

    Create a Board using multiple Projects

    Create an Agile Board from Existing Projects
    Image jira_img1.jpg NOT Found
    Add multiple projects to the Board
    Image jira_img2.jpg NOT Found

    Add a new Project to an existing Board

    Boards -> View All Boards -> Configure -> Edit Filter Query -> Press Left Menu Button -> Add/Delete Projects
    Image jira_img3.jpg NOT Found

    Reconfigure JIRA by running Setup Wizard again

    Stop JIRA 
    D:\Program Files\Atlassian\JIRA\bin> stop-jira.bat
    
    Delete dbconfig.xml 
    D:\Program Files\Atlassian\Application Data\JIRA> del dbconfig.xml
    
    Delete Database Files 
    D:\Program Files\Atlassian\Application Data\JIRA\database> dir
    21.01.2018  10:16         2.838.528 h2db.mv.db
    21.01.2018  09:18            16.208 h2db.trace.db
                   2 Datei(en),      2.854.736 Bytes
                   2 Verzeichnis(se), 82.347.048.960 Bytes frei
    
    D:\Program Files\Atlassian\Application Data\JIRA\database> del *.db
    Möchten Sie "D:\Program Files\Atlassian\Application Data\JIRA\database\*" löschen (J/N)? j
    
    Open JIRA Baseurl to restart the configuration process: http://localhost:9080/
    

    Reference

    Using Mocha and Selenium

    Install Mocha, Chai, Selenium and Chromdriver

    Init local Repository

    D:\xampp\htdocs\pvdata\testSelenium\test> npm init
    ..
    package name: (test) testselenium
    version: (1.0.0)
    description: test Selenium and Mocha
    entry point: (googlePage.js) test_s5.js
    test command:
    git repository:
    keywords:
    author: Helmut
    license: (ISC)
    About to write to D:\xampp\htdocs\pvdata\testSelenium\test\package.json:
    
    {
      "name": "testselenium",
      "version": "1.0.0",
      "description": "test Selenium and Mocha",
      "main": "test_s5.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "author": "Helmut",
      "license": "ISC"
    }
    
    Is this ok? (yes)
    ..
    

    Install local Nodejs Modules

    D:\xampp\htdocs\pvdata\testSelenium\test > npm install chromedriver@2.34.1 --save
    
    > chromedriver@2.34.1 install D:\xampp\htdocs\pvdata\testSelenium\test\node_modules\chromedriver
    > node install.js
    
    Downloading https://chromedriver.storage.googleapis.com/2.34/chromedriver_win32.zip
    Saving to D:\Users\helmut\AppData\Local\Temp\chromedriver\chromedriver_win32.zip
    Received 781K...
    Received 1568K...
    Received 2352K...
    Received 3136K...
    Received 3222K total.
    Extracting zip contents
    Copying to target path D:\xampp\htdocs\pvdata\testSelenium\test\node_modules\chromedriver\lib\chromedriver
    Done. ChromeDriver binary available at D:\xampp\htdocs\pvdata\testSelenium\test\node_modules\chromedriver\lib\chromedriver\chromedriver.exe
    npm notice created a lockfile as package-lock.json. You should commit this file.
    npm WARN testselenium@1.0.0 No repository field.
    
    + chromedriver@2.34.1
    added 96 packages in 14.552s
    
    D:\xampp\htdocs\pvdata\testSelenium\test> npm install selenium-webdriver@3.6.0 --save
    npm WARN testselenium@1.0.0 No repository field.
    
    + selenium-webdriver@3.6.0
    added 14 packages in 4.256s
    
    D:\xampp\htdocs\pvdata\testSelenium\test> npm install chai --save
    npm WARN testselenium@1.0.0 No repository field.
    
    + chai@4.1.2
    added 7 packages in 2.129s
    

    Verify Local Module Status

    D:\xampp\htdocs\pvdata\testSelenium\test> npm  list --depth=0
    testselenium@1.0.0 D:\xampp\htdocs\pvdata\testSelenium\test
    +-- chai@4.1.2
    +-- chromedriver@2.34.1
    `-- selenium-webdriver@3.6.0
    

    Install Mocha as a Global Nodejs Module

    D:\xampp\htdocs\pvdata\testSelenium\test> npm -g install mocha@4.1
    D:\Users\helmut\AppData\Roaming\npm\mocha -> D:\Users\helmut\AppData\Roaming\npm\node_modules\mocha\bin\mocha
    D:\Users\helmut\AppData\Roaming\npm\_mocha -> D:\Users\helmut\AppData\Roaming\npm\node_modules\mocha\bin\_mocha
    + mocha@4.1.0
    updated 1 package in 4.61s
    

    Verify Global Package Status

    D:\xampp\htdocs\pvdata\testSelenium\test> npm  list --depth=0  -g
    D:\Users\helmut\AppData\Roaming\npm
    +-- eslint@4.16.0
    `-- mocha@4.1.0
    

    Testscripts

    Script: test_s4.js

    require('chromedriver');
    var assert = require('chai').assert;
    var selenium = require('selenium-webdriver');
    var test = require('selenium-webdriver/testing');
    var driver;
    var GooglePage = require('./googlePage.js');
    
    const timeOut = 15000;
     
    test.describe('Testing Google Search Page', function() {
      test.beforeEach(function() {
      	dumpMessage("-> beforeEach Hook");
        this.timeout(timeOut);
        driver = new selenium.Builder()
        	.forBrowser('chrome')
        	.build();
      	var googlePage = new GooglePage(driver);
        googlePage.view();
    
      });
      
      test.it( 'Working TestCase' , function(){  
        this.timeout(timeOut);
      	driver.getTitle().then(function(title){
      		dumpMessage("Found Page Title: " + title);
      		assert.equal("Google",title );
    	});
    	dumpMessage("--> Start Processing" ); 
    	driver.findElement(selenium.By.name('q')).sendKeys('webdriver');           // Fill in the  Search String for Google Search 
    	driver.findElement(selenium.By.name('btnK')).click();					   // Start the Google Search 	
        dumpMessage("--> Leaving Processing" ); 
      });
      
        test.it( 'Failing TestCase' , function(){  
        this.timeout(timeOut);
      	driver.getTitle().then(function(title){
      		dumpMessage("Found Page Title: " + title);
      		assert.equal("xGoogle",title );
    	});
    	dumpMessage("--> Start Processing" ); 
    	driver.findElement(selenium.By.name('q')).sendKeys('webdriver');           // Fill in the  Serach String to the 
    	driver.findElement(selenium.By.name('btnK')).click();					   	// Start the Google Search 	
        dumpMessage("--> Leaving Processing" ); 
      });
                
      test.afterEach(function() {
      	  var promise;
      	  var waitTime = 2000;       // Keep the browser window 2 seconds open before calling driver.quit()
      	  this.timeout(10000);       // Increase Timeout ot avoid Error: Timeout of 2000ms exceeded. 
    								 // If returning a Promise, ensure it resolves.        
        	promise = new Promise(function(resolve, reject){
            	setTimeout(function(){
               		dumpMessage("-> afterEach Hook Promise called - WaitTime: " +  waitTime );
               		driver.quit();
                	resolve();
            	}, waitTime);
     		});
        	// mocha will wait for the promise to be resolved before exiting
        	return promise;      		
      	dumpMessage("-> afterEach Hook");
      });
    
    });
    															 		// Helper Functions 							
    function dumpMessage(mesg) {                                        // console.log at top level will create a undefined message
    	console.log(getTime() + mesg);                                  // Provide a wrapper function which returns some data 
    	return "---------------------------------------------------";	
    }
    
    function getTime() {
    	var ts = new Date();
        return ts.toLocaleTimeString()+ ":" + ts.getMilliseconds() + "  ";
    }
    

    Script: googlePage.js

    var webdriver = require('selenium-webdriver');
     
    GooglePage = function GooglePage(driver) {
      this.driver = driver;
      this.url = "http://www.google.com/ncr";
    };
     
    GooglePage.prototype.view = function() {
      this.driver.get(this.url);
      return webdriver.promise.fulfilled(true);
    };
     
    module.exports = GooglePage;                     // export the module so in an be imported with the require syntax
    

    Running the Mocha/Selenium Testcase

    Testcase Overview

    • Testcase consists out of 2 tests !
    • Both tests starts and closes the Chromedriver
    • Testcase 1 should work !
    • Testcase 2 should fail !

    Testcase Details

    Command: mocha test_s5.js
    Image mocha_img4.jpg NOT Found

    A more complete Testcase

    NetBeans Output

    Press F6 in Netbeans to Start Test Scripts
    Image mocha_img10.jpg NOT Found

    Reference

    Unit Testing with Netbeans [Mocha]

    ×

    Versions used

    • Netbeans IDE 8.2
    • Mocha 4.0.1 – Our Testing Tool
    • Chai 4.1.2 – An Assert Library

    Create a HTML5 Project with Javascript Support inside Netbeans

    Create a HTML5/Javascript Project and add Javascript File main2.js to the project
    Image mocha_img0.jpg.jpg NOT Found
    • Note: exports is a node.js concept that declares the functions that your module makes available to code outside itself

    Setup Mocha as Testing Provider

    Change Project Properties for Javascript Testing
    Image mocha_img1.jpg.jpg NOT Found

    Setup Mocha/Chai [ Open a Netbeans Terminal Window]

    Initialize new Node.js Project

    
    $ cd D:\xampp\htdocs\pv\mochaTest2
    $ npm init                                                                                                                                                                                  
    This utility will walk you through creating a package.json file.
    It only covers the most common items, and tries to guess sensible defaults.
    
    See `npm help json` for definitive documentation on these fields
    and exactly what they do.
    
    Use `npm install ` afterwards to install a package and
    save it as a dependency in the package.json file.
    
    Press ^C at any time to quit.
    package name: (mochatest2) 
    version: (1.0.0) 
    description: Mocha/Chai Testing
    entry point: (index.js) main2.js
    test command: mocha
    git repository: 
    keywords: 
    author: Helmut
    license: (ISC) MIT
    About to write to D:\xampp\htdocs\pv\mochaTest2\package.json:
    
    {
      "name": "mochatest2",
      "version": "1.0.0",
      "description": "Mocha/Chai Testing",
      "main": "main2.js",
      "directories": {
        "test": "test"
      },
      "scripts": {
        "test": "mocha"
      },
      "author": "Helmut",
      "license": "MIT"
    }
    
    
    Is this ok? (yes) yes
    
    helmut@myPC /cygdrive/d/xampp/htdocs/pv/mochaTest2
    
    

    Setup Mocha and Chai in our Netbeans Project Base Directory

    helmut@myPC /cygdrive/d/xampp/htdocs/pv/mochaTest2
    $  npm install mocha                                                                                                                                                                       
    npm WARN mochatest2@1.0.0 No repository field.
    + mocha@4.0.1
    added 24 packages in 2.189s
    
    helmut@myPC /cygdrive/d/xampp/htdocs/pv/mochaTest2
    $  npm install chai                                                                                                                                                                          
    npm WARN mochatest2@1.0.0 No repository field.
    
    + chai@4.1.2
    added 7 packages in 1.304s
    

    Verify package.json – created by our previous setup steps

    helmut@myPC /cygdrive/d/xampp/htdocs/pv/mochaTest2
    $ cat   package.json 
    {
      "name": "mochatest2",
      "version": "1.0.0",
      "description": "Mocha/Chai Testing",
      "main": "main2.js",
      "directories": {
        "test": "test"
      },
      "scripts": {
        "test": "mocha"
      },
      "author": "Helmut",
      "license": "MIT",
      "dependencies": {
        "chai": "^4.1.2",
        "mocha": "^4.0.1"
      }
    }
    
    

    Create and Run Mocha testscript manually under Unit Test direcorty

    Manually run Mocha Tests via Netbeans Terminal Window
    Image mocha_img2.jpg.jpg NOT Found
    • Our test script mochaTest2.js imports the functions from Chai and main2.js via require()
    • describe()` is merely used for grouping test Tests – can be nested if needed
    • `it()` is a test case

    Finally run Neteans Unit Tests [ ALT F6]

    Open Netbeans Test Result Window to review Test Results
    Image mocha_img3.jpg.jpg NOT Found
    • Note: If Netbeans IDE hangs during Testing you may need to restart Netbeans to fix this !

    Reference

    How To Unit Testing JavaScript with Netbeans
    Mocha Homepage
    Working with package.json
    An Absolute Beginner’s Guide to Using npm
    Understanding module.exports and exports in Node.js

    Decrypt HTTPS traffic with Wireshark and Fiddler

    ×

    Using Wireshark on Windows 7 – Key Facts and Overview

    • Wireshark is a traffic analyzer, that helps you to learn how networking work and how to diagnose Network problems
    • To track SSL Traffic on Windows we use Wireshark with Session Key Logging
    • If the Browser uses the Diffie-Hellman cipher we need to disable it

    Understanding the SSL Handshake Protocol

    TLS/SSL Handshake Diagram
    Image https_img1.jpg NOT Found
    • The SSL or TLS client sends a “client hello” message that lists cryptographic information such as the SSL or TLS version and, in the client’s order of preference, the CipherSuites supported by the client
    • The SSL or TLS server responds with a “server hello” message that contains the CipherSuite chosen by the server from the list provided by the client
    • Reference:An overview of the SSL or TLS handshake
    • Note: The “server hello” is very important as it Diffie-Hellman Cipher can’t be traced !

    Disable the Diffie-Hellman Cipher for Browsers

    Disable the Diffie-Hellman Cipher for Firefox

    • Launch Firefox, navigate to “about:config” from address bar
    • Double click all the Diffie-Hellman ciphers starting with dhe or ecdhe to change the Value to false
    • Restart Firefox to take effect
    Disable the Diffie-Hellman Cipher for Firefox
    Image ssl_dh_img2.jpg NOT Found

    Disable the Diffie-Hellman Cipher for Chrome

    • View the default Cipher Suites list from the Client Hello message of Chrome
    • Append all the ciphers that contain “ECDHE” or “DHE” in hex to command line parameter:”–cipher-suite-blacklist” and launch Chrome
    • Sample: chrome.exe –cipher-suite-blacklist=0xc02b,0xc02f,0x009e,0xcc14,0xcc13,0xc00a,0xc014,0x0039,0xc009,0xc013,0x0033
    Cipher Suites (15 suites)
         Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b)
         Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
         Cipher Suite: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (0x009e)
         Cipher Suite: TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (0xcc14)
         Cipher Suite: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xcc13)
         Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a)
         Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
         Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x0039)
         Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009)
         Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)
         Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x0033)
         Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c)
         Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)
         Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
         Cipher Suite: TLS_RSA_WITH_3DES_EDE_CBC_SHA (0x000a)
    
    

    Testing SSL Decryption with Wireshark

    Setup Wireshark

    Activate Session Key Logging on Windows Action
    Image https_img1.jpg NOT Found
    • Create SSLKEYLOGFILE enviroment variable
    Image https_img2.jpg NOT Found
    • Enable SSLKEYLOGFILE for SSL Protocol
    Image https_img21.jpg NOT Found
    • If needed add add. HTTPS Ports like : Port 8443
    • Edit -> Preferences -> Protocols -> HTTP

    Run Wireshark and decrypt a TLS/SSL packet

    Run first https test against Google Website
    Image https_img3.jpg NOT Found
    • Testing against https:/gooogle.de
    • The decrypted SSL indicates that this packet was decrypted sucessfully !

    Advantages / Disadvantages using Wireshark

    Advantages Disadvantages
    A little bit complicated Very detailed Info for the complete Network Stack
    You need to know a lot of Networking Details Client must support SSLKEYLOGFILE feature
    Support only certain Browsers [ Firefox, Chrome ] and email clients [ thunderbird] No support for cURL and WordPress function like wp_get_remote() and

    Reference

    Using Fiddler

    Fiddler – How it Works

    Overview
    Image fiddler_overview.jpg NOT Found
    • To read HTTPS data Fiddler is acting like a Man-in-the-Middle
    • Fiddler is listening to following Network proxy: localhost:8888
    • On startup Fiddler registers as a WinINET-Proxy service
    • All Browsers [ like Chrrome, Firefox ] taking care of this service sends its data to the >Fiddler-Proxy first
    • Finally Fiddler sends the data to the Target Host

    Setup – Enable Decryption of SSL/HTTPS traffic

    Setup
    Image fiddler_setup.jpg NOT Found
    • Menu: Tools -> Option -> HTTPS
    • Check: X Decrypt HTTPS Traffic

    Decrypt cURL HTTPS traffic with Fiddler

    Using cUrl : add –proxy 127.0.0.1:8888 to the cUrl command
    Image fiddler_curl1.jpg NOT Found
    • Start Fiddler
      [Note Fiddler uses Portnumber: 8888 per Default ]
    • Add –proxy 127.0.0.1:8888 to your curl command
    Image fiddler_curl2.jpg NOT Found
    • Use Inspectors menu item
    • This gives as a decrypted view of the HTTPS Post Request
    • Note: Passwords and Username can now easily extracted
    • Use the RAW menu item to get details about
      HTTPS Response Request like:
      HTTP Response Code, HTTPS Header and HTTPS
      Response Body

    Decrypt WordPress HTTPS traffic for wp_remote_get()/wp_remote_post() with Fiddler

    Application Details

    Display Timelines with Fiddler

    Timeline
    Image fiddler_timeline.jpg NOT Found
    • Page load [ /pv/wr] is decoupled from the PHP processing
    • PHP processing [initWRApp.php] is triggered via Ajax Request
    • All Remote PHP processing steps [login.action, tologin.action and summaryInfo.action] runs sequentially

    Display HTTP Packet Details with Fiddler

    Step1 : Initial Page Load WebBrowser -> Local Webserver [ 192.168.1.50]
    Image fiddler_data_img1.jpg NOT Found
    • Protocal: HTTP
    • Http Get Request to load the initial Page
    Step2: Starting PHP Remote Processing WebBrowser -> Local Webserver [ 192.168.1.50]
    Image fiddler_data_img2.jpg NOT Found
    • Protocal: HTTP
    • Http Get Request to start PHP Remote Processing with wp_remote_get and wp_remote_post
    Step3: Authenticate with Username/Password against Remote Webserver Local Webserver [ 192.168.1.50] -> Remote Webserver [ 52.58.164.53:8443 ]
    Image /fiddler_data_img3.jpg NOT Found
    • Protocol: HTTPS Post
    • URL: https://52.58.164.53:8443/security!login.action
    • WordPress Function used: wp_remote_post()
    • Remote Webserver return “op.successfully” if login OK !
    • Remote Webserver return New JSESSIONID cookie if login OK !
    Step 4: Capture initial Page after Login into Remote Werbserver Local Webserver [ 192.168.1.50] -> Remote Webserver [ 52.58.164.53:8443]
    Image fiddler_data_img4.jpg NOT Found
    • Protocol: HTTPS Get
    • URL: https://52.58.164.53:8443/security!tologin.action
    • WordPress Function used: wp_remote_get()
    • Remote Webserver return Initial Webpage after successful login!
    • Remote Webserver return X-CSRF-Token which should be used for subsequent requests
    Step 5: Finally capture Data from Remote Werbserver Local Webserver [ 192.168.1.50] -> Remote Webserver [ 52.58.164.53:8443]
    Image fiddler_data_img5.jpg NOT Found
    • Protocol: HTTPS Post
    • URL: https://52.58.164.53:8443/summaryAction!querySummaryInfo.action?nodeSN=0
    • WordPress Function used: wp_remote_post()
    • Remote Webserver return Data in Json Format
    • For this request we use JSESSIONID cookie returned from Step 3
    • For this request we use X-CSRF-TOKEN returned from Step 4

    Advantages/Disadvantages using Fiddler

    Advantages Disadvantages
    Easy Setup Only HTTP/HTTP traffic can be monitored
    Support all sort of clients like cURl, PHP, Browers, Email Clients, …