Search code examples
jasmineprotractorwinstonjasmine2.0

Test fails with Winston logger implemention in protractor


Background: I'm using Jasmine2 as my test framework for Protractor and trying to implement a logger mechanism in the framework using winston package for better logging.

Problem: Test fails with below Non-Zero error in cmd which was working fine before including winston in the script. Could you please help me in implementing it correct.

Non-Zero Error:

Report destination:   target\e2e\screenshots\my-report.html
[20:28:52] I/launcher - Running 1 instances of WebDriver
[20:28:52] I/hosted - Using the selenium server at http://127.0.0.1:4444/wd/hub

[20:28:56] I/launcher - 0 instance(s) of WebDriver still running
[20:28:56] I/launcher - chrome #01 failed 1 test(s)
[20:28:56] I/launcher - overall: 1 failed spec(s)
[20:28:56] E/launcher - Process exited with error code 1

Below are the corresponding files for reference:

Scenario_01.js:

describe('Scenario_01', function() {

 var Logging = require('./scripts/LoggingMech.js');
 var common = require('./scripts/CloseBrowsers.js');    
 var Login = require('./scripts/Login.js'); 


 it('Login', function() {
         browser.waitForAngularEnabled(false); 
         Login.login('admin','Adminpwd')
          .catch(error => Logging.Logger.log(error));
     });

afterAll(function(){
    common.closeBrowsers();
});
});

Login.js:

var Login = function() {

     this.login = async function(username, passwordKey){
     await browser.get('http://testwebsite.com/showCust');
     await element(by.name('USER')).sendKeys(username);
     await element(by.name('PASSWORD')).sendKeys(passwordKey);
     await element(by.xpath('/html/body/table/tbody/tr[2]/td/table/tbody/tr/td/table/tbody/tr[3]/td/form/input[9]')).click();
     await element(by.name('YES')).click();
     //browser.sleep(10000);

};
}
module.exports = new Login();

LoggingMech.js

const winston = require('winston');
var Logging = function() {

     this.Logger = function(){
      const logger = winston.createLogger({

           level: 'info',
           format: format.simple(),
            transports: [
                new winston.transports.Console(),
                new winston.transports.File({ filename: 'TodaysLog.log' })
                        ]
});

};
}
module.exports = new Logging();

Solution

  • Problem

    const logger = winston.createLogger...You are creating a winston reference but it's never passed anywhere. You are just storing it in a constant. You would have to make it a property of Logger attribute and then create a new instance of Logging.Logger and call log() on it.

    Fix

    You would have to make it a property of Logger attribute.

    In LoggingMech.js you do this.logger = winston.createLogger instead of const logger = winston.createLogger

    and then create a new instance of Logging.Logger and call log() on it.

    var Logging = require('./scripts/LoggingMech.js');
    // logs foo
    (new Logging.Logger()).log('foo');
    

    But I think you are doing it more complex as it is needed. For implementing the logger you could simply change your LoggingMech.js file to the following:

    const winston = require('winston');
    module.exports = winston.createLogger({
        level: 'info',
        format: format.simple(),
        transports: [
            new winston.transports.Console(),
            new winston.transports.File({
                filename: 'TodaysLog.log'
            })
        ]
    });
    

    And call it like:

    var Logging = require('./scripts/LoggingMech.js');
    Logging.log('foo');
    

    The configuration of the logger still is encapsulated within LoggingMech.js and it's way simpler to call. The code is also easier to maintain.

    Update 1: Logging with winston

    The winston.log() method accepts only a log object and not a string.

    // logs "I am a log message."
    winston.log({
      level: 'info',
      message: 'I am a log message.'
    }
    

    For logging plain strings you can use logger.info().

    Update 2: Full winston logging example

    A working log example. Following code works for me on my machinde:

    winston.js

    var winston = require('winston');
    module.exports = winston.createLogger({
        level: 'info',
        transports: [
            new winston.transports.Console(),
            new winston.transports.File({
                filename: 'TodaysLog.log'
            })
        ]
    });
    

    index.js

    var Logging = require('./winston');
    var message = {
        level: 'info',
        message: 'Hello distributed log files!'
      };
    
      Logging.log(message);
      Logging.info('sdf');
      Logging.error(message);
      Logging.warn(message);
    

    logged content in TodaysLog.log

    {"level":"info","message":"Hello distributed log files!"}
    {"message":"sdf","level":"info"}
    {"level":"error","message":"Hello distributed log files!"}
    {"level":"warn","message":"Hello distributed log files!"}