My log4js.js file code
'use strict';
var log4js = require('log4js');
var log4jsGen = {
getLogger: function getLogger() {
log4js.loadAppender('file');
log4js.addAppender(log4js.appenders.file('./ApplicationLogs.log'), 'logs');
var logger = log4js.getLogger('logs');
return logger;
}
};
module.exports = log4jsGen;
My conf.js file(specific to appender section only)
"appenders": [{
"type": "log4js-protractor-appender",
"append": 'false',
"maxLogSize": 20480,
"backups": 3,
"category": "relative-logger"
}],
Problem:
1) IS there a way that the logs will get overwritten in each run.
2) Why log4js-protractor-appender is not working, instead log4js is working, the merit of the previous is that it resolves the promises which is passed as an argument.
Thats a great question. Yes log4js-protractor-appender is awesome. It is built specially for Protractor based environments and it places all logger command in Protractor Control flow and resolves Protractor promises before logging.
You were using it incorrectly. The appender options are not part of Protractor config options but can be integrated. The approach you have is a little old one and I have updated by blog post
These are the steps as an answer to your question-2
Step 1: Install log4js npm module
Step 2: Install log4js-protractor-appender module
Step 3: Add the logger object creation logic in protractor beforeLaunch() and assign it onto browser protractor global object
'use strict';
var log4js = require('log4js');
beforeLaunch:function(){
if (fs.existsSync('./logs/ExecutionLog.log')) {
fs.unlink('./logs/ExecutionLog.log')
}
log4js.configure({
appenders: [
{ type: 'log4js-protractor-appender', category: 'protractorLog4js' },
{
type: "file",
filename: './logs/ExecutionLog.log',
category: 'protractorLog4js'
}
]
});
},
onPrepare: function() {
browser.logger = log4js.getLogger('protractorLog4js');
},
Step 4: Use logger object in your tests by accessing through browser.logger
describe('sample test', function(){
it('Sample Check', function(){
browser.get("http://www.protractortest.org/#/");
browser.logger.info("Testing Log4js");
browser.sleep(5000);
browser.logger.info('Displayed text is:', browser.getCurrentUrl());
var elm = element(by.css('.lead'))
browser.logger.info('Displayed text is:', elm.getText());
});
});
But one thing to note is - This appender is just an console appender and will not be able to write to file. The file will still contain unresolved promises
Sample Output:
[21:54:23] I/local - Starting selenium standalone server...
[21:54:23] I/launcher - Running 1 instances of WebDriver
[21:54:25] I/local - Selenium standalone server started at http://192.168.1.5:60454/wd/hub
Started
[2017-02-03 21:54:30.905] [INFO] protractorLog4js - Testing Log4js
[2017-02-03 21:54:35.991] [INFO] protractorLog4js - Displayed text is: http://www.protractortest.org/#/
[2017-02-03 21:54:36.143] [INFO] protractorLog4js - Displayed text is: Protractor is an end-to-end test framework for Angular and AngularJS applications. Protractor runs tests against your application running in a real browser, interacting with it as a user would.
.
Answer to your Question 1: How to overwrite logs each run. I added a simple logic in beforeLaunch() to delete old logs if they exist and its part of the code snippet I pasted above
I have check this issue with and followed the steps mentioned in Answer 1 and it works for me.
Earlier I was getting log output in Console only but now I am getting log in console and file also.
I corrected the file path passing and Set type: "file" in log4js configure in conf file.
Log4js in Conf file
Log appender in file
Please let me know if you face any issue again.
Thanks
Related
I am trying out Stitch, a serverless/hosted JavaScript environment from MongoDB. My main purpose is to help me learn modern JavaScript, but I am trying to write a useful app as well.
I have written the following function, and saved it in my Stitch app. I believe this follows the documented way to write functions in Stitch, and I have tested it from the Stitch administration console:
exports = function(query){
const http = context.services.get("HTTP");
const urlBase = context.values.get("stackOverflowApiUrl");
const options = [
'order=desc',
'sort=activity',
'site=stackoverflow',
'q=' + encodeURIComponent(query),
'user=472495',
'filter=!--uPQ.wqQ0zW'
];
return http
.get({ url: urlBase + '?' + options.join('&') })
.then(response => {
// The response body is encoded as raw BSON.Binary. Parse it to JSON.
const ejson_body = EJSON.parse(response.body.text());
return ejson_body.total;
});
};
This code is pretty simple - it obtains an http object for making external API fetches, and obtains a configuration value for a URL urlBase to contact (resolving to https://api.stackexchange.com/2.2/search/excerpts) and then makes a call to the Stack Overflow Data API. This runs a search query against my user and returns the number of results.
So far so good. Now, I want to call this function locally, in Jest. To do this, I have installed Node and Jest in a local Docker container, and have written the following test function:
const callApi = require('./source');
test('Simple fetch with no user', () => {
expect(callApi('hello')).toBe(123);
});
This fails, with the following error:
~ # jest
FAIL functions/callApi/source.test.js
✕ Simple fetch with no user (3ms)
● Simple fetch with no user
TypeError: callApi is not a function
2 |
3 | test('Simple fetch with no user', () => {
> 4 | expect(callApi('hello')).toBe(123);
| ^
5 | });
6 |
at Object.<anonymous>.test (functions/callApi/source.test.js:4:12)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 1.418s
Ran all test suites.
(In fact I was expecting it to fail, since it contains a global object context that Jest does not have access to. I will work out how to mock that later, but for now Jest cannot even see the function at all).
I suspect I can see the reason - in the Jest introduction docs, one has to do this for the SUT:
module.exports = function() { ... }
However the Stitch docs seem to require functions to be defined as:
exports = function() { ... }
I do not have a background in JavaScript to understand the difference. I could try module.exports in Stitch, but I would rather not, since this would either not work now, or cause a breakage in the future. Can Jest be instructed to "see" bare exports without the module prefix?
Incidentally, I have picked Jest because it is popular, and because some of my JavaScript colleagues vouch for it. However, I am not wedded to it, and would be happy to use something else if it is known to be better for Stitch development.
Update
Following the useful answer from jperl below, I find that the following construction is not possible in Stitch:
module.exports = exports = function() {}
I also cannot do this:
exports = function() {}
module.exports = exports
If I try either, I get the following error:
runtime error during function validation
So it looks like I have to get Jest to work without module.exports, or create a glue file that imports the exports version into module.exports, with the main file being used by Stitch, and the glue importer being used by Jest.
I suggest you to read this thread. And you're right in thinking it has to do with modules.exports vs exports. The thing is that module.exports and exports first point to the same thing. So something like this works:
//modify the same object that modules.exports is pointing to
exports.a = {}
exports.b = {}
but this won't:
exports = {}
Why? Because now exports points to something else than module.exports so what you're doing has no effect at all.
Update
Following some updates in the comments, we came to the view that Stitch does not seem to support the export format that Jest requires.
This is an addendum to jperl's answer, to show how I got Jest working while respecting Stitch's limitations.
Firstly, it is worth noting how a Stitch application is laid out. This is determined by the import/export format.
auth_providers/
functions/
function_name_1/
config.json
source.js
function_name_2/
config.json
source.js
...
services/
values/
The config.json file is created by Stitch remotely, and is obtained through a export. This contains ID information to uniquely identify the function in the same folder.
I believe it is common JavaScript practice to mix tests with source code, so I am following that style (I am new to modern JS, and I confess I find this style untidy, but I am running with it nevertheless). Thus I add a source.test.js file in each function folder.
Finally, since there is a discrepancy between what Stitch requires and what Jest requires, I have written a script to create a source code file under _source.js in each function folder.
So, each folder will contain these files (the underscore files will probably be ignored by Git, as they will always be generated):
_source.js
config.json
source.js
source.test.js
In order to create the underscored copies, I am using this shell script:
#!/bin/bash
# Copy all source.js files as _source.js
for f in $(find functions/ -name source.js); do cp -- "$f" "$(dirname $f)/_$(basename $f)"; done
# Search and replace in all _source.js files
for f in $(find functions/ -name _source.js); do sed -i -e 's/exports =/module.exports =/g' $f; done
A bit hacky perhaps, but it works!
There are a few third party libraries that are using log4js to output their logs. I know it sounds counter-intuitive but I would like to disable these logs temporarily to be able to investigate an issue that I have.
How do I temporarily disable log4js logs temporarily in code in javascript? Specifically nodejs.
In log4js 5.3.0 (not sure how many versions back it's the same) you can do this by turning everything off temporarily at the root logger, which affects every other logger:
log4js.getLogger().level = 'off';
A full example:
#!/bin/env node
const log4js = require('log4js');
log4js.configure({
appenders: {
out: { type: "stdout" }
},
categories: {
default: {
appenders: [ "out" ],
level: "info"
}
}
});
const rootLogger = log4js.getLogger();
const log = log4js.getLogger('foo');
log.info('this is on - turning off');
rootLogger.level = 'off';
log.info('this is off - turning back on');
rootLogger.level = 'info';
log.info('this is back on');
Which gives you:
[2019-11-13T22:00:37.541] [INFO] foo - this is on - turning off
[2019-11-13T22:00:37.544] [INFO] foo - this is back on
In the app.js file of my nodejs application I place the following code to temporarily disable log4js logs from thirdparty libraries.
const log4js = require('log4js')
log4js.configure({})
This works for disabling the logs.
I've been refactoring an existing site towards using gulp and npm more efficiently. I'd like to incorporate inquirer into my tasks to define some build alternatives. For now I'm starting simple.
Here is my current gulpfile:
//Define our required components
var gulp = require('gulp');
var inq = require('inquirer');
var plugins = require('gulp-load-plugins')({ scope: ['dependencies', 'devDependencies'] });
//Function that retrieves the file for the specifically names task
function getTask(task) {
return require('./gulp-tasks/' + task)(gulp, plugins);
};
//Call for our tasks
gulp.task('thirdPartyComponents', getTask('ThirdPartyComponents'));
gulp.task('thirdPartyComponents.css', getTask('ThirdPartyComponentsCss'));
gulp.task('buyer.app', getTask('Buyer.App'));
gulp.task('buyer.controllers', getTask('Buyer.Controllers'));
gulp.task('buyer.directives', getTask('Buyer.Directives'));
gulp.task('buyer.filters', getTask('Buyer.Filters'));
//CODE NOTE: Dependent tasks are case-sensitive
gulp.task('default', function () {
var questions =
[
{
type: 'confirm',
name: 'minimize',
message: 'Do you want to minimize the files?',
default: true
}
];
inq.prompt(questions).then(function (answers) {
console.log(answers);
});
});
When I run the task I get this in the output window in the task explorer
[16:21:21] Using gulpfile ....
[16:21:21] Starting 'default'...
[16:21:21] 'default' errored after 185 ms
[16:21:21] Error: Implement me. Unknown stdin file type!
at process.stdin (node.js:740:17)
at setupReadlineOptions (C:\Projects\BuyerSupplier\BuyerSupplier\Main\Source\BuyerSupplier.site-dev\src\BuyerSupplier.site\node_modules\inquirer\lib\ui\baseUI.js:57:35)
at module.exports (C:\Projects\BuyerSupplier\BuyerSupplier\Main\Source\BuyerSupplier.site-dev\src\BuyerSupplier.site\node_modules\inquirer\lib\ui\baseUI.js:14:40)
at new module.exports (C:\Projects\BuyerSupplier\BuyerSupplier\Main\Source\BuyerSupplier.site-dev\src\BuyerSupplier.site\node_modules\inquirer\lib\ui\prompt.js:15:8)
at Object.promptModule [as prompt] (C:\Projects\BuyerSupplier\BuyerSupplier\Main\Source\BuyerSupplier.site-dev\src\BuyerSupplier.site\node_modules\inquirer\lib\inquirer.js:26:14)
at Gulp.<anonymous> (C:\Projects\BuyerSupplier\BuyerSupplier\Main\Source\BuyerSupplier.site-dev\src\BuyerSupplier.site\Gulpfile.js:31:9)
at module.exports (C:\Projects\BuyerSupplier\BuyerSupplier\Main\Source\BuyerSupplier.site-dev\src\BuyerSupplier.site\node_modules\orchestrator\lib\runTask.js:34:7)
at Gulp.Orchestrator._runTask (C:\Projects\BuyerSupplier\BuyerSupplier\Main\Source\BuyerSupplier.site-dev\src\BuyerSupplier.site\node_modules\orchestrator\index.js:273:3)
at Gulp.Orchestrator._runStep (C:\Projects\BuyerSupplier\BuyerSupplier\Main\Source\BuyerSupplier.site-dev\src\BuyerSupplier.site\node_modules\orchestrator\index.js:214:10)
at Gulp.Orchestrator.start (C:\Projects\BuyerSupplier\BuyerSupplier\Main\Source\BuyerSupplier.site-dev\src\BuyerSupplier.site\node_modules\orchestrator\index.js:134:8)
Process terminated with code 1.
I'm not sure why something this straightforward doesnt want to fire off....any help is really appreciated.
Found the issue, and its nothing to do with the code directly. I am running inside Visual Studio and was using the Task Runner Explorer to call the default task. This was where I was seeing the issue.
After doing more research, and on a whim, I ran the gulp task from a command window. It completed as expected. Therefore there are still issues within the Task runner with commands that use process.stdin command.
I am quite new to nodeJS.
I am using the nodeJS module node-workflow
Basically, this module is an orchestrator that takes a custom javascript script (=workflow definition), then serialize it and store it in a REDIS db (for example), and execute on-demand later on by the node-workflow module.
A workflow definition is composed of task, like this:
var my_external_module = require('my_external_module');
var workflow = module.exports = {
name: 'Workflow Test',
chain: [{
name: 'TASK 1',
timeout: 30,
retry: 1,
body: function(job, cb) {
// Execute external function
my_external_module.hello("Monkey");
return cb(null)
},
},
...
First I put my function my_external_module.hello() in a .js file beside the workflow script.
When I run the node-workflow module I get the following error:
Error initializing runner:
[ReferenceError: my_external_module is not defined]
So I have created a module my_external_module,
and in: ./node_modules/my_external_module/index.js
module.exports = {
hello: function(name) {
console.log("Hello, " + name);
}
};
When I run the node-workflow module I get the same error:
Error initializing runner:
[ReferenceError: my_external_module is not defined]
It seems that the require(...) shall stands in one of the .js files of the node-workflow module, so I would have to hack one of the files of the module, but it is a bit dirty.
Is there something I missed?
Or is there a way to define a $PATH like in Python in order to my function to be accessible from everywhere.
You have to require it as:
var my_external_module = require('./my_external_module');
Notice the ./ this means Node should search for a file like ./my_external_module.js
If you omit the ./ Node looks at the installed modules on (usually) node_modules directory
I am using Jasmine (BDD Testing Framework for JavaScript) in my firefox add-on to test the functionality of my code.
The problem is that jasmine is outputing the test results to an HTML file,what I need is to Firebug Console or other solution to output the results.
Have you tried the ConsoleReporter?
jasmine.getEnv().addReporter(new jasmine.ConsoleReporter(console.log));
According to the code Jasmine has the ConsoleReporter class that executes a print function (in this case console.log) that should do what you need.
If all else fails you could just use this as a starting point to implement your own console.log reporter.
UPDATE
In newer versions of jasmine, ConsoleReporter was removed. You can either use the built-in jsApiReporter, or write your own (console) reporter, as shown in the following link: https://jasmine.github.io/tutorials/custom_reporter
In newest version of Jasmine (2.0) if you want to get test output to console you need to add following lines.
var ConsoleReporter = jasmineRequire.ConsoleReporter();
var options = {
timer: new jasmine.Timer,
print: function () {
console.log.apply(console,arguments)
}};
consoleReporter = new ConsoleReporter(options); // initialize ConsoleReporter
jasmine.getEnv().addReporter(consoleReporter); //add reporter to execution environment
Output to html is included by default however so if you don't want html output at all you have to edit your boot.js file and remove relevant lines from there. If you want to customize how output is displayed in console edit file console.js.
Source
jasmineRequire.ConsoleReporter did not exist in 2.3.0 so I used the following code:
//create a console.log reporter
var MyReporter = function(){jasmineRequire.JsApiReporter.apply(this,arguments);};
MyReporter.prototype = jasmineRequire.JsApiReporter.prototype;
MyReporter.prototype.constructor = MyReporter;
MyReporter.prototype.specDone=function(o){
o=o||{};
if(o.status!=="passed"){
console.warn("Failed:" + o.fullName + o.failedExpectations[0].message);
}
};
var env = jasmine.getEnv();
env.addReporter(new MyReporter());
For the sake of completeness here's the full configuration:
First of all run the npm install command:
npm install jasmine-console-reporter --save-dev
Then check your Jasmine configuration to make sure you got the helpers setting there:
spec/support/jasmine.json
{
"spec_dir": "spec",
"spec_files": [
"**/*[sS]pec.js"
],
"helpers": [
"helpers/**/*.js"
],
"stopSpecOnExpectationFailure": false,
"random": false
}
Since helpers are executed before specs the only thing you have to do is to create a console reporter helper.
spec/helpers/reporter/consoleReporter.js
const JasmineConsoleReporter = require('jasmine-console-reporter');
let consoleReporter = new JasmineConsoleReporter({
colors: 1, // (0|false)|(1|true)|2
cleanStack: 1, // (0|false)|(1|true)|2|3
verbosity: 4, // (0|false)|1|2|(3|true)|4
listStyle: 'indent', // "flat"|"indent"
activity: false
});
jasmine.getEnv().addReporter(consoleReporter);
jasmine-console-reporter on npmjs.com
Jasmine custom reporter docs
Jasmine configuration reference