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

JUNIT and Java

×

Overview Versions

  • Netbeans 8.2
  • JUNIT 4
  • JUNIT uses Java Reflection API to run Object Methods

Java IO sample

package fileio;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;

public class FileIO {
    private static final Logger LOGGER = Logger.getLogger( 
            Thread.currentThread().getStackTrace()[0].getClassName() );
    
    /** FileOutputStream Descriptor */        
    private FileOutputStream fos = null;
    /** OS-FileName */
    final private String fileName ;
    public FileOutputStream getFileOutputStream() { return fos; }
    public String getFileName() { return fileName; }
    
    public static void main(String[] args) {
        String writeContent = "This is my Data which needs" +
	        " to be written into the file";
        String fileName = "C:/myfile.txt";
        //LOGGER.setLevel(Level.FINEST);
        //LOGGER.setLevel(Level.SEVERE);              
        LOGGER.setLevel(Level.INFO);                  // Setting current Logger Level
        
        Locale.setDefault(new Locale("en", "EN"));  // Change Logger Language to English 
        FileIO fileIO = new FileIO(fileName);
        fileIO.doIO(fileName, writeContent);
    }
       
    public FileIO(String fileName) {
        this.fileName = fileName;
        LOGGER.info("FileIO constructor for fileName: " + fileName);
    }
/**
 * Opens, writes and closes FileOutputStream fos.
 * 

* If open was successfull both fileName and FileOutputStream Object are * stored in the related class attributes fileName, fos for later access * @param fName The fileName at OS Level * @param writeContent The message to be written to our FileOutputStream * @return true If write was successfull else return false */ public boolean doIO(String fName,String writeContent) { try { openStream(fName); // Got an excpetion if open failse int bytesWritten = writeToStream( writeContent); boolean ret = closeStream(); String loggerString = new StringBuilder("Byte written to File ") .append( this.fileName ).append(": " ).append(bytesWritten).toString(); LOGGER.info(loggerString); return true; } catch ( IOException ioe) { // Only log the Exception Message - stacktrace should be printed by low level // Exception handler. Close the stream when there is am Exception ! LOGGER.log( Level.SEVERE, ioe.toString() ); return false; } finally{ closeStream(); } } /** * Opens a FileOutputStream fos. *

* If open was successfull both fileName and FileOutputStream Object are * stored in the related class attributes fileName, fos for later access * @param fileName The fileName at OS Level * @throws IOException If stream can't be opened at OS level * @return true If Stream was opened sucessfully */ public boolean openStream (String fileName) throws IOException { String fName = fileName; FileOutputStream lfos; File file; try { if ( fName == null ) { throw new IOException("fileName can't be null"); } //Specify the file path here file = new File(fileName); lfos = new FileOutputStream(file); /* This logic will check whether the file exists or not. If the file * is not found at the specified location it would createa new file */ if (!file.exists()) { file.createNewFile(); } this.fos = lfos; // save the FileOutputStream Descriptor for later usage return true; } catch ( IOException ioe) { String errorMesg = "Error open File-Stream " + fileName; LOGGER.log( Level.SEVERE, ioe.toString(), ioe ); this.fos = null; throw new IOException(errorMesg); } } /** * Writes a String Message to already opened FileOutputStream fos. *

* Note: This methode will convert a potenial NullPointerExceptions tiggered * by either message=null or FileOutputStream fos=null to an IOExeption. * @param message The String to be written to the Stream Descriptor fos * @throws IOException If stream is not already opened at OS level or If messsage is null * @return byteCnt The number of bytes written to our opened Stream */ public int writeToStream( String message) throws IOException { try { /*String content cannot be directly written into * a file. It needs to be converted into bytes */ if (message == null ) { throw new IOException("Message should NOT be null ! "); } // don't need to check for null ! if (!(fos instanceof FileOutputStream)) { throw new IOException("FileOutputStream fos should NOT be null ! "); } byte[] bytesArray = message.getBytes(); int byteCnt = bytesArray.length; fos.write(bytesArray); fos.flush(); String loggerString = new StringBuilder("Successfully written " ) .append( byteCnt ).append(" Bytes to File: ").append(fileName).toString(); LOGGER.info(loggerString); return byteCnt; } catch (IOException ioe) { String errorMesg = "Error writing to File: " + fileName + "\n " + ioe.toString(); LOGGER.log( Level.SEVERE, ioe.toString(), ioe ); throw new IOException(errorMesg); } } /** * Closes FileOutputStream fos. *

* Note: Closing an alreday closed FileOutputStream will not throw any error * Even we get an error during close operation closeStream() methode will only log an error * without re-throwing the underlying Exception. * @return true if Stream was closed successfully */ public boolean closeStream() { try { if (fos != null) { fos.close(); } fos = null; return true; } catch (IOException ioe) { String errorMesg = "Error closing Stream " + fileName; LOGGER.log( Level.SEVERE, ioe.toString(), ioe ); return false; } } }

JUnit test for above IO sample

  • Create JUNIT test with Netbeans 8.2: Right Click on Java File -> Tools -> Create/Update Tests


    @AfterClass
    public static void tearDownClass() {
    }
    
    @Before
    public void setUp() {
         String fName = "c:/myFileTest";
        instance = new FileIO(fName);
    }
    
    @After
    public void tearDown() {
    }

    /**
     * Test of main method, of class FileIO.
     */
    @Test
    public void testMain() {
        System.out.println("-> Start Test main()");
        String[] args = null;
        FileIO.main(args);
        System.out.println("   Test main() OK");
    }

    /**
     * Test of openStream method, of class FileIO.
     */
    @Test
    public void testOpenStream() {
        System.out.println("-> Start Test openStream()");
        String fName = "c:/myFileTest";
        boolean result = false;
        // FileIO instance = new FileIO();
        boolean expResult = true;
        try {
            result = instance.openStream(fName);
        } catch ( IOException iex) {}
        
        assertTrue("Expected Test Result " + expResult +  " - Got: " +  result,  expResult==result);
        System.out.println("   Test openStream() OK!");
    }
    
       /*
        *  Open a Non-Existing File - Should fail with an IOException    
        */
    @Test (expected=IOException.class)
    public void testOpenStreamFailed() throws IOException{
        System.out.println("-> Start Test testOpenStreamFailed() - Fails with an IOException !");
        String fName = "X:/myFileTestFailed";
        boolean result = false;
        FileOutputStream expResult = null;
        result = instance.openStream(fName);
    }
    
    /**
     * Test of writeToStream method, of class FileIO.
     */
    @Test 
    public void testWriteToStream() {
        String fName = "c:/myFileTest";
        FileOutputStream fos;
        int bytesWritten = 0;
        System.out.println("-> Start Test writeToStream()");
        String message = "This is just a Test";
        int bytesToBeWritten = message.getBytes().length ;
        try {
            instance.openStream(fName);
            bytesWritten = instance.writeToStream(message);
        } catch ( IOException iex) {}
        assertTrue("Error::  Expected bytesToBeWritten: " +  bytesToBeWritten 
                + " - GOT bytesWritten " + bytesWritten ,bytesWritten == bytesToBeWritten );
        System.out.println("   Test writeToStream() OK! - bytesWritten: " + bytesWritten);

    }

    /*
        In this test we simulate a write to a Not initialized Stream Desriptor
        This Test should fail with an IOExecption     
    */
    @Test (expected=IOException.class)
    public void testWriteToStreamFailed() throws IOException {
        String fName = "c:/myFileTest";
        FileOutputStream fos = null;

        System.out.println("-> Start testWriteToStreamFailed() - Fails with IOException !");
        String message = "This is just a Test";
        int bytesToBeWritten = message.getBytes().length ;
        // instance.writeToStream should trigger an IOException
        int bytesWritten = instance.writeToStream( message);
    }
    
    /**
     * Test of closeStream method, of class FileIO.
     * We also test that closing a closed Stream doesn't throw any Exception lile in socket opes
     */
    @Test
    public void testCloseStream() {
        String fName = "c:/myFileTest";
        FileOutputStream fos = null;
        System.out.println("-> Start Test closeStream()");
        String message = "This is just a Test";
        boolean result = false;
         
        // FileIO instance = new FileIO();
        try {
            instance.openStream(fName);
            result = instance.closeStream();
          } catch ( IOException iex) {}
        assertTrue("Error: Expected true in first close !", result);
            // Now closing an alreay closed Stream
        result = instance.closeStream();
        assertTrue("Error: Expected true in 2.nd close !", result);
        System.out.println("   Test closeStream() - 2.nd Close OK No Exception !" +
            " - ret Status: " + result );
    }

    /**
     * Test of doIO method, of class FileIO.
     * Should Work and return true !
     */
    @Test
    public void testDoIO() {
        System.out.println("-> Start Test doIO()");
        String fName = "c:/myFileTest";
         String writeContent = "This is my Data which needs" +
	        " to be written into the file";
        //FileIO instance = new FileIO();
        boolean result = instance.doIO(fName,writeContent);
        assertTrue("Error: Expected true !", result);
        System.out.println("   Test doIO() OK - result " + result );
    }    
    
    /**
     * Test of doIO method, of class FileIO. 
     * This test is the most important ONE as we will test that a failed Write closes fos 
     * descriptor to avoid a resource leak. To test this does we issue an add. write after calling 
     * doIO(). This add write should fail indicating that fos descriptor was already closed
     * TestString : null
     *              -> doIO() should return false but close fos
     *              -> An addition Write Test using the closed fos shoud fail too   
     */

    @Test
    public void testDoIOFailed() throws IOException {
        System.out.println("-> Start Test testDoIOFailed() - Fails with an Assert !");
        String fName = "c:/myFileTest";
        String writeContent = null;
        //FileIO instance = new FileIO();
        boolean result = instance.doIO(fName,writeContent);
        assertFalse("Error: Expected false !", result);
            // As we can get the Stream closed status form FileOutputStream object we start a test
            // write. Note: 
            // After a failure the Stream should be closed - we expect the the next write to fail !
        writeContent = "This WRITE should NOT Work";
        int bytesToBeWritten = writeContent.getBytes().length;
        int bytesWritten = -1;
        try {
            bytesWritten = instance.writeToStream( writeContent);
        } catch ( IOException e) {}
        assertFalse("This Write should fail - as the FOS descpriptor should be closed before!", bytesToBeWritten == bytesWritten );
    }    
    
    /* 
        Writing a null Message should reurn an IOException and Not a java.lang.NullPointerException 
    */
    @Test
    public void testWriteFailed() throws IOException{
        String fName = "c:/myFileTest";
        FileOutputStream fd;
        String message = null;
        int bytesToBeWritten = -1;
        int bytesWritten = -1;
        System.out.println("-> Start Test testWriteFailed() - Catches IOException !");
       
        instance.openStream(fName);
        fd = instance.getFileOutputStream();
        assertTrue(fd instanceof FileOutputStream);
     
        try {
            bytesWritten = instance.writeToStream( message);
        } catch ( IOException iex) {} 
        
        //  This Test raises an java.io.IOException: Message should NOT be null at all -
        // > bytesWritten remain unchanged 
        assertTrue("Error::  Expected bytesToBeWritten: " +  bytesToBeWritten 
                + " - GOT bytesWritten " + bytesWritten ,bytesWritten == bytesToBeWritten );
 
        boolean closeResult = instance.closeStream();
        assertTrue("Error: Expected true !", closeResult);       
        System.out.println("   Test testWriteFailed()  OK "  );
    }    
}

JUNIT Test Output

-> Start Test writeToStream()
   Test writeToStream() OK! - bytesWritten: 19
-> Start testWriteToStreamFailed() - Fails with IOException !
-> Start Test doIO()
   Test doIO() OK - result true
-> Start Test main()
   Test main() OK
-> Start Test closeStream()
   Test closeStream() - 2.nd Close OK No Exception ! - ret Status: true
-> Start Test openStream()
   Test openStream() OK!
-> Start Test testDoIOFailed() - Fails with an Assert !
-> Start Test testWriteFailed() - Catches IOException !
   Test testWriteFailed()  OK 
-> Start Test testOpenStreamFailed() - Fails with an IOException !
Mär 30, 2018 1:52:42 PM fileio.FileIO 
INFORMATION: FileIO constructor for fileName: c:/myFileTest
Mär 30, 2018 1:52:42 PM fileio.FileIO writeToStream
INFORMATION: Successfully written 19 Bytes to File: c:/myFileTest
Mär 30, 2018 1:52:42 PM fileio.FileIO 
INFORMATION: FileIO constructor for fileName: c:/myFileTest
Mär 30, 2018 1:52:42 PM fileio.FileIO writeToStream
SCHWERWIEGEND: java.io.IOException: FileOutputStream fos should NOT be null ! 
java.io.IOException: FileOutputStream fos should NOT be null ! 
	at fileio.FileIO.writeToStream(FileIO.java:122)
	at fileio.FileIOTest.testWriteToStreamFailed(FileIOTest.java:114)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	...

Mär 30, 2018 1:52:42 PM fileio.FileIO 
INFORMATION: FileIO constructor for fileName: c:/myFileTest
Mär 30, 2018 1:52:42 PM fileio.FileIO writeToStream
INFORMATION: Successfully written 55 Bytes to File: c:/myFileTest
Mär 30, 2018 1:52:42 PM fileio.FileIO doIO
INFORMATION: Byte written to File  c:/myFileTest: 55
Mär 30, 2018 1:52:42 PM fileio.FileIO 
INFORMATION: FileIO constructor for fileName: c:/myFileTest
Mar 30, 2018 1:52:42 PM fileio.FileIO 
INFO: FileIO constructor for fileName: C:/myfile.txt
Mar 30, 2018 1:52:42 PM fileio.FileIO writeToStream
INFO: Successfully written 55 Bytes to File: C:/myfile.txt
Mar 30, 2018 1:52:42 PM fileio.FileIO doIO
INFO: Byte written to File  C:/myfile.txt: 55
Mar 30, 2018 1:52:42 PM fileio.FileIO 
INFO: FileIO constructor for fileName: c:/myFileTest
Mar 30, 2018 1:52:42 PM fileio.FileIO 
INFO: FileIO constructor for fileName: c:/myFileTest
Mar 30, 2018 1:52:42 PM fileio.FileIO 
INFO: FileIO constructor for fileName: c:/myFileTest
Mar 30, 2018 1:52:42 PM fileio.FileIO writeToStream
SEVERE: java.io.IOException: Message should NOT be null ! 
java.io.IOException: Message should NOT be null ! 
	at fileio.FileIO.writeToStream(FileIO.java:119)
	at fileio.FileIO.doIO(FileIO.java:51)
	at fileio.FileIOTest.testDoIOFailed(FileIOTest.java:173)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	...

Mar 30, 2018 1:52:42 PM fileio.FileIO doIO
SEVERE: java.io.IOException: Error writing to File: c:/myFileTest
  java.io.IOException: Message should NOT be null ! 
Mar 30, 2018 1:52:42 PM fileio.FileIO writeToStream
SEVERE: java.io.IOException: FileOutputStream fos should NOT be null ! 
java.io.IOException: FileOutputStream fos should NOT be null ! 
	at fileio.FileIO.writeToStream(FileIO.java:122)
	at fileio.FileIOTest.testDoIOFailed(FileIOTest.java:182)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	..

Mar 30, 2018 1:52:42 PM fileio.FileIO 
INFO: FileIO constructor for fileName: c:/myFileTest
Mar 30, 2018 1:52:42 PM fileio.FileIO writeToStream
SEVERE: java.io.IOException: Message should NOT be null ! 
java.io.IOException: Message should NOT be null ! 
	at fileio.FileIO.writeToStream(FileIO.java:119)
	at fileio.FileIOTest.testWriteFailed(FileIOTest.java:204)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	...

Mar 30, 2018 1:52:42 PM fileio.FileIO 
INFO: FileIO constructor for fileName: c:/myFileTest
Mar 30, 2018 1:52:42 PM fileio.FileIO openStream
SEVERE: java.io.FileNotFoundException: X:\myFileTestFailed (Das System kann den angegebenen Pfad nicht finden)
java.io.FileNotFoundException: X:\myFileTestFailed (Das System kann den angegebenen Pfad nicht finden)
	at java.io.FileOutputStream.open0(Native Method)
	at java.io.FileOutputStream.open(FileOutputStream.java:270)
	at java.io.FileOutputStream.(FileOutputStream.java:213)
	at java.io.FileOutputStream.(FileOutputStream.java:162)
	at fileio.FileIO.openStream(FileIO.java:87)
	at fileio.FileIOTest.testOpenStreamFailed(FileIOTest.java:77)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        ...

Using PHPUnit

×

Installation Directories and Software Versions

  • PHP was used from our XAMPP installation at: d:\xampp\php;
  • PHPUnit Installation Direcotory: D:\PHP\phpunit;
  • Windows 7
  • NetBeans 8.2
  • PHP 5.5.15
  • PHPUnit 4.8.36
  • phpunit-skelgen-1.2.1.

Install PHPUnit on Windows7

Verify your PHP version from your XAMPP install on Windows

D:\PHP\phpunit>  d:\xampp\php\php.exe --version
PHP 5.5.15 (cli) (built: Jul 23 2014 15:05:09)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies
    with Xdebug v2.2.3, Copyright (c) 2002-2013, by Derick Rethans

Download PHPUnit and phpunit-skelgen package

Packages selected for download based on my PHP 5.5.15 version

  • phpunit-4.8.36.phar
  • phpunit-skelgen-1.2.1.phar
  • Directory location for PHPUnit files: D:\PHP\phpunit

Rename/Copy files

  • phpunit-4.8.36.phar -> phpunit.phar
  • phpunit-skelgen-1.2.1.phar -> phpunit-skelgen.phar

Create a new PHPUnit Command File

  • D:\PHP\phpunit> echo @php “%~dp0phpunit.phar” %* > phpunit.cmd

Modify your Windows Path varaible and verify your installation

Add to your windows PATH:   D:\PHP\phpunit;d:\xampp\php; ....

Finally verify the PHPUnit installation 
D:\Users\helmut> phpunit --version
PHPUnit 4.8.36 by Sebastian Bergmann and contributors.

Run a PHPUnit Sample from the Command Line

Directory structure matches Netbeans Project structure

 * Directory structure:
 * ├── PhpUnitTest
 *         ├── Calculator.php
 *         ├── tests
 *               ├── bootstrap.php
 *               ├── CalculatorTest.php

Calculator.php our PHP test class

class Calculator
{
    /**
     * @assert (0, 0) == 0
     * @assert (0, 1) == 1
     * @assert (1, 0) == 1
     * @assert (1, 1) == 2
     * @assert (1, 2) == 4
     */
    public function add($a, $b)
    {
        return $a + $b;
    }
}

bootstrap.php our PHP class to autoload PHP classes for testing

chdir("..");                // Note our tests directory is located just below our real PHP files  
echo "Current Working Directory:: " . getcwd() . "\n";
class Autoloader{
    public static function register(){
        //echo "Inside Register ..\n";
        spl_autoload_register(function ($class) {
            $file = str_replace('\\', DIRECTORY_SEPARATOR, $class).'.php';
            if (file_exists($file)) {
                require $file;
                echo "+++ Autoload of PHP File:: " . $file . "\n";
                return true;
            }
            return false;
        });
    }
}
Autoloader::register();

Create the test class using phpunit-skelgen.phar

D:\xampp\htdocs\tc\PhpUnitTest> php \php\phpunit\phpunit-skelgen.phar --test Calculator
PHPUnit Skeleton Generator 1.2.1 by Sebastian Bergmann.
Wrote skeleton for "CalculatorTest" to "D:\xampp\htdocs\tc\PhpUnitTest\CalculatorTest.php".

Copy CalculatorTest.php  to the tests directory 
D:\xampp\htdocs\tc\PhpUnitTest> copy CalculatorTest.php tests
tests\CalculatorTest.php überschreiben? (Ja/Nein/Alle): ja

Test class generated by phpunit-skelgen.phar

/**
 * Generated by PHPUnit_SkeletonGenerator 1.2.1 on 2018-03-04 at 12:37:11.
 */
class CalculatorTest extends PHPUnit_Framework_TestCase
{
    /**
     * @var Calculator
     */
    protected $object;

    /**
     * Sets up the fixture, for example, opens a network connection.
     * This method is called before a test is executed.
     */
    protected function setUp()
    {
        $this->object = new Calculator;
    }

    /**
     * Tears down the fixture, for example, closes a network connection.
     * This method is called after a test is executed.
     */
    protected function tearDown()
    {
    }

    /**
     * Generated from @assert (0, 0) == 0.
     *
     * @covers Calculator::add
     */
    public function testAdd()
    {
        $this->assertEquals(
          0,
          $this->object->add(0, 0)
        );
    }

    /**
     * Generated from @assert (0, 1) == 1.
     *
     * @covers Calculator::add
     */
    public function testAdd2()
    {
        $this->assertEquals(
          1,
          $this->object->add(0, 1)
        );
    }

    /**
     * Generated from @assert (1, 0) == 1.
     *
     * @covers Calculator::add
     */
    public function testAdd3()
    {
        $this->assertEquals(
          1,
          $this->object->add(1, 0)
        );
    }

    /**
     * Generated from @assert (1, 1) == 2.
     *
     * @covers Calculator::add
     */
    public function testAdd4()
    {
        $this->assertEquals(
          2,
          $this->object->add(1, 1)
        );
    }

    /**
     * Generated from @assert (1, 2) == 4.
     *
     * @covers Calculator::add
     */
    public function testAdd5()
    {
        $this->assertEquals(
          4,
          $this->object->add(1, 2)
        );
    }
}

Run the php Unit test

D:\xampp\htdocs\tc\PhpUnitTest\tests> phpunit --bootstrap bootstrap.php CalculatorTest.php 
Current Working Directory:: D:\xampp\htdocs\tc\PhpUnitTest
PHPUnit 4.8.36 by Sebastian Bergmann and contributors.

.
+++ Autoload of PHP File:: Calculator.php
...F

Time: 237 ms, Memory: 9.50MB

There was 1 failure:

1) CalculatorTest::testAdd5
Failed asserting that 3 matches expected 4.

D:\xampp\htdocs\tc\PhpUnitTest\tests\CalculatorTest.php:91

FAILURES!
Tests: 5, Assertions: 5, Failures: 1.

Return Codes from phpUnit

* PHPUnit Return Codes:   
 * .   Printed when the test succeeds.
 * F   Printed when an assertion fails while running the test method.
 * E   Printed when an error occurs while running the test method.
 * R   Printed when the test has been marked as risky (see Chapter 6).
 * S   Printed when the test has been skipped (see Chapter 7).
 * I   Printed when the test is marked as being incomplete or not yet implemented (see Chapter 7).      

PHPUnit and Netbeans Integration

Generic setup for PHPUnit within NetBeans IDE

Tools -> Option -> PHP -> PHP Framework -> PHPUnit
Image phpunit_img1.jpg  NOT Found

Create a new PHP project with the above Source for calcualater.php

Setup PHPUnit as test Provider

Right Click Project [ PhpUnitTest3] -> Properties -> Testing -> Add Folder
Image phpunit_img2.jpg  NOT Found

Create the PHP Test Classes

Right Click on Calculator.php -> Tools -> Create/Update Tests
Image phpunit_img3.jpg  NOT Found
 
Netbeans should create  CalculatorTest.php in out tests directory by running: 
"D:\xampp\php\php.exe" "D:\PHP\phpunit\phpunit-skelgen.phar" "--test" "--" "Calculator" 
    "D:\xampp\htdocs\PhpUnitTest3\Calculator.php" "CalculatorTest" "D:\xampp\htdocs\PhpUnitTest3\tests\CalculatorTest.php"
PHPUnit Skeleton Generator 1.2.1 by Sebastian Bergmann.

Wrote skeleton for "CalculatorTest" to "D:\xampp\htdocs\PhpUnitTest3\tests\CalculatorTest.php".  

Copy above bootstrap.php to our test folder and modify PHPUnit settings

Right Click Project [ PhpUnitTest3] -> Properties -> PHPUnit
Image phpunit_img4.jpg  NOT Found
Project Files and Directories sould now look like: 
* Directory structure:
 * ├── PhpUnitTest
 *         ├── Calculator.php
 *         ├── tests
 *               ├── bootstrap.php
 *               ├── CalculatorTest.php

Finally run PHPUnit tests

Right Click Calculator.php -> Test
Image phpunit_img5.jpg  NOT Found

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;

Running my first Node.js project with Netbeans

×

Node.js Overview

Node.js processing model

  • Follows single threaded even loop processing model which can handle more and more concurrent requests easily
  • Another important point to keep in mind that Node.js architecture has two types of threads

Main Thread (Single Thread)

  • Called as internal thread as well, all the non I/O blocking requests are assigned using Main thread

Worker Thread(s)

  • Used for assigning blocking I/O heavy requests

Here are the details on how the single threaded event loop based processing works

  • Client sends the request to web sever
  • Node.js web server receives client requests from different clients, puts them into a queue. This queue is called event queue
  • Node.js has an internal component called event loop which runs the loop on event queue, assigns the request to a single thread if the request is non-blocking
  • In case of blocking (I/O heavy) request, event loop will assign this to worker thread
  • While worker thread is processing the request, event loop will continue to process other requests available in event queue

Node.js and Standard Webserver Flow-Diagramms

Node.js Flow Diagram
Image nodejs_img1.jpg NOT Found
Standard Webserver Flow Diagram
Image nodejs_img2.jpg NOT Found

My First Node.js Web Application

How it works ?

  • Netbeans runs our Code in 2 Steps
  • Step1: Netbeans start a nodejs server process to execute HTTP server Code
  • –> Our HTTP server is now listening on port : 9900
  • Step2: Netbeans starts a Chrome Browser Windows and connects to Port 9900
  • –> Our Browser display the Content provided by our Http Server

Run a first Node.js Project

Setup a Node.js project properties within Netbeans

Step 1 : Configure Netbeans Project Run Methode Step 2 : Configure Node.js Properties
Image nodejs_img1.jpg NOT Found Image nodejs_img2.jpg NOT Found

Add the following Code to main.js

const http = require('http');
const port = 9900;

const requestHandler = (request, response) => {
    let funcName = "requestHandler";
    if (request.method === 'GET' && request.url === '/' ){
        dumpMessage(funcName, "Request Method: GET - request URL: " + request.url);
        response.writeHead(200, {"Content-Type": "text/html"});
        response.end('Hello Node.js Server - at:  ' + getTime() + '!');
    }
};

const server = http.createServer(requestHandler);

server.listen(port, (err) => {
    let funcName = "server.listen";
    if (err) {
        return console.log(funcName, 'something bad happened: ' + err);
    }

  dumpMessage(funcName, 'server is listening on port: ' + port);
});

function dumpMessage(testName, mesg) {                                       
    console.log(getTime() + testName + ":: --> " + mesg);           
};
    
function getTime() {
    var ts = new Date();
    return ts.toLocaleTimeString()+ ":" + ts.getMilliseconds() + "  ";
};

Finally run the Node.js Code

Step 3 : Run the project
Image nodejs_img3.jpg NOT Found

Run above Node.js project manaully

Start the http Server

D:\xampp\htdocs\pvdata\testNodejs> "D:\Program Files\nodejs\node.exe"  "D:\xampp\htdocs\pvdata\testNodejs\main.js"
17:14:42:536  server.listen:: --> server is listening on port: 9900

Redirect your browser to the Listening Adress of our Web Server: http://localhost:9900

Browser Output
Image nodejs_img4.jpg NOT Found

Debugging a Node.js Application with Netbeans – Currently NOT working due to Netbeans Bug 271238

"D:\Program Files\nodejs\node.exe" "--debug-brk=9292" "D:\xampp\htdocs\pvdata\testNodejs\main.js"
 (node:10116) [DEP0062] DeprecationWarning: `node --debug` and `node --debug-brk` are invalid. 
Please use `node --inspect` or `node --inspect-brk` instead. 

Done.

Debugging ourNode.js Application manually

Start the node.js process with inspect-brk option

  • Enable inspector agent
  • Listen on default address and port (127.0.0.1:9229)
  • Break before user code starts
D:\xampp\htdocs\pvdata\testNodejs> node --inspect-brk main.js
Debugger listening on ws://127.0.0.1:9229/9391ed9f-a46d-4f49-bee2-b83d6dafb055
For help see https://nodejs.org/en/docs/inspector

Attach Chrome Devtools 55+ to the Node.js Debugger process

  • Open a Chrome DevTool 55+ Browser session with following URL: chrome://inspect
  • Select : Open dedicated DevTools for Node
Attach Chrome DevTools to Node.js Inspector
Image nodejs_img50.jpg NOT Found

CLI should respond with: Debugger attached

D:\xampp\htdocs\pvdata\testNodejs> node --inspect-brk main.js
Debugger listening on ws://127.0.0.1:9229/9391ed9f-a46d-4f49-bee2-b83d6dafb055
For help see https://nodejs.org/en/docs/inspector
Debugger attached.

Start Debugging

Debug Node.js by viewing Sources and setting Breakpoint
Image nodejs_img51.jpg NOT Found

Reference

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

    Using Selenium Webdriver with Javascript

    Introduction Selenium-WebDriver

    • The WebDriverJS library uses a promise manager to ease the pain of working with a purely asynchronous API
    • Rather than writing a long chain of promises allows you to write synchronous code by using a blocking API

    Sample using a chain of promises [asynchronous Mode]

    const {Builder, By, until} = require('selenium-webdriver');
    new Builder()
        .forBrowser('firefox')
        .build()
        .then(driver => {
          return driver.get('http://www.google.com/ncr')
            .then(_ => driver.findElement(By.name('q')).sendKeys('webdriver'))
            .then(_ => driver.findElement(By.name('btnK')).click())
            .then(_ => driver.wait(until.titleIs('webdriver - Google Search'), 1000))
            .then(_ => driver.quit());
        });
    

    Sample using a chain of promises [synchronous Mode]

    const {Builder, By, until} = require('selenium-webdriver');
    
    let driver = new Builder()
        .forBrowser('firefox')
        .build();
    
    driver.get('http://www.google.com/ncr');
    driver.findElement(By.name('q')).sendKeys('webdriver');
    driver.findElement(By.name('btnK')).click();
    driver.wait(until.titleIs('webdriver - Google Search'), 1000);
    driver.quit();
    

    Understanding the Promises Chain

    Selenium Code:
    driver.sleep(4000);                       // Let the chromedriver Browser open for 4 seconds to review results
    driver.quit();
    
    Logger Output:
    [2018-01-17T09:37:13Z] [WARNING] [promise.ControlFlow] Detected scheduling of an unchained task.
        When the promise manager is disabled, unchained tasks will not wait for
        previously scheduled tasks to finish before starting to execute.
        New task: Task: WebDriver.quit()
            at thenableWebDriverProxy.schedule (D:\xampp\htdocs\pvdata\testSelenium\test\node_modules\selenium-webdriver\lib\webdriver.js:807:17)
            at thenableWebDriverProxy.quit (D:\xampp\htdocs\pvdata\testSelenium\test\node_modules\selenium-webdriver\lib\webdriver.js:840:23)
            at Object. (D:\xampp\htdocs\pvdata\testSelenium\test\testSelenium.js:31:8)
            at Module._compile (module.js:635:30)
            at Object.Module._extensions..js (module.js:646:10)
            at Module.load (module.js:554:32)
            at tryModuleLoad (module.js:497:12)
            at Function.Module._load (module.js:489:3)
            at Function.Module.runMain (module.js:676:10)
            at startup (bootstrap_node.js:187:16)
        Previous task: Task: WebDriver.sleep(4000)
            at ControlFlow.timeout (D:\xampp\htdocs\pvdata\testSelenium\test\node_modules\selenium-webdriver\lib\promise.js:2510:17)
            at thenableWebDriverProxy.sleep (D:\xampp\htdocs\pvdata\testSelenium\test\node_modules\selenium-webdriver\lib\webdriver.js:956:23)
            at Object. (D:\xampp\htdocs\pvdata\testSelenium\test\testSelenium.js:30:8)
            at Module._compile (module.js:635:30)
            at Object.Module._extensions..js (module.js:646:10)
            at Module.load (module.js:554:32)
            at tryModuleLoad (module.js:497:12)
            at Function.Module._load (module.js:489:3)
            at Function.Module.runMain (module.js:676:10)
            at startup (bootstrap_node.js:187:16)                                                                                                                                                              
    
    • The Task: WebDriver.quit() is scheduled after WebDriver.sleep(4000);
    • This is called the Promises Chain

    Logging with Webdriver-Selenium

    Selenium Code: 
    var {Builder, By, until, logging } = require('selenium-webdriver');
    //
    // Enable Logging 
    logging.installConsoleHandler();
    logging.getLogger('promise.ControlFlow').setLevel(logging.Level.ALL);
    
    Logger Output:
            at Function.Module._load (module.js:489:3)
    [2018-01-17T09:37:13Z] [WARNING] [promise.ControlFlow] Detected scheduling of an unchained task.
        When the promise manager is disabled, unchained tasks will not wait for
        previously scheduled tasks to finish before starting to execute.
        New task: Task: WebDriver.getTitle()
            at thenableWebDriverProxy.schedule (D:\xampp\htdocs\pvdata\testSelenium\test\node_modules\selenium-webdriver\lib\webdriver.js:807:17)
            at thenableWebDriverProxy.getTitle (D:\xampp\htdocs\pvdata\testSelenium\test\node_modules\selenium-webdriver\lib\webdriver.js:1000:17)
            at Object. (D:\xampp\htdocs\pvdata\testSelenium\test\testSelenium.js:12:8)
            at Module._compile (module.js:635:30)
            at Object.Module._extensions..js (module.js:646:10)
            at Module.load (module.js:554:32)
            at tryModuleLoad (module.js:497:12)
            at Function.Module._load (module.js:489:3)
            at Function.Module.runMain (module.js:676:10)
            at startup (bootstrap_node.js:187:16)
        Previous task: Task: WebDriver.navigate().to(http://www.google.com/ncr)
            at thenableWebDriverProxy.schedule (D:\xampp\htdocs\pvdata\testSelenium\test\node_modules\selenium-webdriver\lib\webdriver.js:807:17)
            at Navigation.to (D:\xampp\htdocs\pvdata\testSelenium\test\node_modules\selenium-webdriver\lib\webdriver.js:1133:25)
            at thenableWebDriverProxy.get (D:\xampp\htdocs\pvdata\testSelenium\test\node_modules\selenium-webdriver\lib\webdriver.js:988:28)
            at Object. (D:\xampp\htdocs\pvdata\testSelenium\test\testSelenium.js:11:8)
            at Module._compile (module.js:635:30)
            at Object.Module._extensions..js (module.js:646:10)
            at Module.load (module.js:554:32)
            at tryModuleLoad (module.js:497:12)
            at Function.Module._load (module.js:489:3)
            at Function.Module.runMain (module.js:676:10)
    

    Install Selenium-WebDriver /Chromedriver locally

    • npm install selenium-webdriver@3.6.0
    • npm install chromedriver@2.34.1

    Verify Installation

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

    Testing a Google Search with Selenium Webdriver

    Create a JavaScript file testSelenium.js

    require('chromedriver');
    var {Builder, By, until, logging } = require('selenium-webdriver');
    //
    // Enable Logging 
    // logging.installConsoleHandler();
    //logging.getLogger('promise.ControlFlow').setLevel(logging.Level.ALL);
    
    var  driver = new Builder()
        .forBrowser('chrome')
        .build();
    dumpMessage( "--- Script Start ---");
    
    driver.get('http://www.google.com/ncr');
    driver.getTitle().then(function (titleName ) {	dumpMessage("Initial Google Page load - Page Title: ---" + titleName + "---" ); });
    
    driver.findElement(By.name('q')).sendKeys('webdriver');            	// Fill in the  Serach String to the 
    driver.findElement(By.name('btnK')).click();					   	// Star the Google Searcht 	
    
    var searchTitle = 'webdriver - Google Search';                    	// The New Page Title  
    driver.wait(until.titleIs(searchTitle), 10000)						// Wait Google Search List becomes availabe
    	.then(function (titleName ) { console.log(getTime() + "Title Element now Visible in DOM ? : " + titleName)});
    
    var xPathElem =  '//*[@id="rso"]/div/div/div[1]/div/div/h3/a';      // xPAth to the  first Item from Google Search Results  
    driver.wait(until.elementLocated( { xpath: xPathElem }),20000)      // Wait until Goggle Search Results becomes available 
    	.then(function () { dumpMessage("XPath wait finished : Element  Found in DOM - xPath :  " + xPathElem );
    		}); 
    
    driver.findElement( { xpath: xPathElem }).click()                   // Click ON the for Search Result   
    	.then(function (  ) { dumpMessage("xPath  Element  Found in DOM: Triggering a Click Event on first Element of Google Search List !" );
    		});
    			
    driver.sleep(4000);                                               	// Let the chromedriver Browser open for 4 seconds to review results
    driver.quit();                                                    	// Finally Quit the driver 
    
    dumpMessage( "--- Script End ---");                              	// Note as all functions are async wer 
    
    															 		// 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() + "  ";
    }
    

    Run first Selenium-Webdriver Script: testSelenium.js

    D:\xampp\htdocs\pvdata\testSelenium\test> node testSelenium.js
    

    Script Output

    D:\xampp\htdocs\pvdata\testSelenium\test> node testSelenium.js
    10:40:29:745  --- Script Start ---
    10:40:29:745  --- Script End ---
    
    DevTools listening on ws://127.0.0.1:12790/devtools/browser/aa1d4440-591b-45dd-8332-f590848ec58c
    10:40:34:359  Initial Google Page load - Page Title: ---Google---
    10:40:35:173  Title Element now Visible in DOM ? : true
    10:40:35:187  XPath wait finished : Element  Found in DOM - xPath :  //*[@id="rso"]/div/div/div[1]/div/div/h3/a
    10:40:36:320  xPath  Element  Found in DOM: Triggering a Click Event on first Element of Google Search List !
    

    Understanding the Script Output

    • The Script end is reached in less then 1ms [ due to the Asyn Mode of Node.js ]
    • All driver calls are scheduled via chains of promises for later execution
    • After about 5 seconds the ChromeDriver is started and initial Google Search Mask gets displayed [ Page Title : Google ]
    • About 1 second later the Google Search List gets displayed [ Page Title: webdriver Google-Search ]
    • Again 1 second later the 1 entry of our Google Search List gets displayed

    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