sails lifecycle - custom service and config.log - sails.js

I defined a l.js under /api/services
exports.i = sails.log.info;
exports.v = sails.log.verbose;
exports.err = sails.log.error;
exports.w = sails.log.warn;
exports.d = sails.log.debug;
It works fine but when I want to define custom logger in /config/log.js
let customLogger = new (winston.Logger)({
transports: [
new (winston.transports.Console, winston.transports.File)({
name: 'file.info',
level: 'info',
filename: logPath + '/server-info.log',
json: true
}),
new (winston.transports.Console, winston.transports.File)({
name: 'file.warning',
level: 'warning',
filename: logPath + '/server-warning.log',
json: true
}),
new (winston.transports.File)({
name: 'file.error',
level: 'error',
filename: logPath + '/server-error.log',
json: true
})
]
});
module.exports.log = {
level: 'info',
custom: customLogger,
};
When I use sails.log.error("123"); l.err("456") in controller, only "123" showed in server-error.log file. "456" only print to console.
When I check sails doc about lifecycle, it seems /config/log.js loaded before /api/services. How should I modify my code?
Thanks

Although config/log.js is loaded before api/services/l.js, (my feeling is) assignment of custom logger defined in log.js to sails.log.<level> happens after the service is loaded.
Hence the behavior.
Re-assigning on lifted event fixes this. Use this code in l.js:
exports.err = sails.log.error;
sails.on('lifted', function() {
console.log('lifted event');
// Re-assign here
exports.err = sails.log.error;
});
Do similarly for other methods of the service.

Related

Error attempting to retrieve CODE sent to gmail account using MailListener Protractor/Jasmine end to end Test

I have already installed MailListener
npm install mail-listener2 --save-dev
In My Config.js file, I have
exports.config = {
directConnect: true,
capabilities: {
browserName: 'chrome',
},
framework: 'jasmine2',
onPrepare: function () {
var AllureReporter = require('jasmine-allure-reporter');
var AllureReporter = require('../index');
jasmine.getEnv().addReporter(new AllureReporter({
resultsDir: 'allure-results'
}));
// Mail Listener
var MailListener = require("mail-listener2");
// here goes your email connection configuration
var mailListener = new MailListener({
username: "myemail#gmail.com",
password: "mygmailpassword!",
host: "imap.gmail.com",
port: 993, // imap port
tls: true,
tlsOptions: { rejectUnauthorized: false },
mailbox: "INBOX", // mailbox to monitor
searchFilter: ["UNSEEN", "FLAGGED"], // the search filter being used after an IDLE notification has been retrieved
markSeen: true, // all fetched email willbe marked as seen and not fetched next time
fetchUnreadOnStart: true, // use it only if you want to get all unread email on lib start. Default is `false`,
mailParserOptions: { streamAttachments: true }, // options to be passed to mailParser lib.
attachments: true, // download attachments as they are encountered to the project directory
attachmentOptions: { directory: "attachments/" } // specify a download directory for attachments
});
mailListener.start();
mailListener.on("server:connected", function () {
console.log("... Mail listener initialized");
});
global.mailListener = mailListener;
},
onCleanUp: function () {
mailListener.stop();
},
// Spec patterns are relative to the current working directory when
// protractor is called.
specs: [
'../e2e/login_spec.js'
],
// Options to be passed to Jasmine.
jasmineNodeOpts: {
defaultTimeoutInterval: 30000
}
};
in my login_spec.js file i have the function
function getLastEmail() {
var deferred = protractor.promise.defer();
console.log("Waiting for an email...");
mailListener.on("mail", function(mail){
deferred.fulfill(mail);
});
return deferred.promise;
};
In the Same login_spec.js
i am trying
var loginData = require('../data.json');
var Login_Objects = require('../page_objects/login_objects');
describe('2Factor Login:', function () {
dataProvider(loginData, function (data) {
Login_Objects.EnterUserName(data.username)
Login_Objects.EnterUserName(data.password)
Login_Objects.ClickLogin()
//Code is sent to email
browser.controlFlow().wait(getLastEmail()).then(function (email){
var pattern = /Code for your transfer (\w+)/g;
var regCode = pattern.exec(email.text)[1];
console.log("Registration code : = "+regCode);
//Pass the code to my methods in the objects file.
//Login_Objects.Enter2FactorCode(regCode)
//Login_Objects.ClickVerify()
})
})
})
here my Login_Objects.Enter2FactorCode(regCode) method will just send keys to the 2factor webelement [but i am not yet at that stage]
At this point i am expecting the email to be printed by the function
console.log("Registration code : = "+regCode);
On the Console I am Getting the message :
... Mail listener initialized
NOTE: I have already allowed unsecure apps to access that gmail account
Findings:
I am getting an error
Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
My reference is this >> Fetching values from email in protractor test case

How can we use the On Prepare function in config File while i am trying to run multiple Spec files

In the Config File i am using the On Prepare Function for the purpose of assigning the property data test id as value
But for the first spec file execution the on prepare is picked up
but on the next execution of the Spec , the on prepare function is not getting picked up
import { Config } from "protractor/built/config";
import { by } from "protractor";
// import { encode } from "punycode";
function encode(file) {
var stream = require('fs').readFileSync(file);
return new Buffer(stream).toString('base64');
}
export let config: Config = {
// The address of a running selenium server.
//seleniumAddress: 'http://localhost:4444/wd/hub',
directConnect:true,
allScriptsTimeout:1500000,
// Capabilities to be passed to the webdriver instance.
capabilities: {
browserName: 'chrome',
'chromeOptions': {
'extensions': [encode('C:/Users/koanand/Documents/Protractor/ASR/2.2.9_0.crx')]
}
},
onPrepare: function () {
by.addLocator('testId', function(value, parentElement) {
parentElement = parentElement || document;
var nodes = parentElement.querySelectorAll('[data-test-id]');
return Array.prototype.filter.call(nodes, function(node) {
return (node.getAttribute('data-test-id') === value);
});
});
},
// Spec patterns are relative to the configuration file location passed
// to protractor (in this example conf.js).
// They may include glob patterns.
specs: ['C:/Users/anand/Documents/Protractor/ASR/TS-Output/specs/directasr.js',
'C:/Users/anand/Documents/Protractor/ASR/TS-Output/specs/products.js'
],
// Options to be passed to Jasmine-node.
jasmineNodeOpts: {
showColors: true, // Use colors in the command line report.
defaultTimeoutInterval : 150000
}
};
i am observing the below error
Message:
Failed: protractor_1.by.testID is not a function
Stack:
TypeError: protractor_1.by.testID is not a function
at new productlist (C:\Users\koanand\Documents\Protractor\ASR\pageobject\productlist.ts:19:45)
at product.selectingproductlist (C:\Users\koanand\Documents\Protractor\ASR\specs\classproductlist.ts:14:32)
at UserContext.<anonymous> (C:\Users\koanand\Documents\Protractor\ASR\specs\products.ts:21:21)
at C:\Users\koanand\Documents\Protractor\ASR\node_modules\jasminewd2\index.js:108:15
at new ManagedPromise (C:\Users\koanand\Documents\Protractor\ASR\node_modules\selenium-webdriver\lib\promise.js:1077:7)
at ControlFlow.promise (C:\Users\koanand\Documents\Protractor\ASR\node_modules\selenium-webdriver\lib\promise.js:2505:12)
at schedulerExecute (C:\Users\koanan
d\Docume
Use BeforeAll() in each spec file & write whatever you want to execute before each spec starts
May following link help you to clear your doubts for onPrepare and what to use in pace of it.
OnPrepare function in Protractor

Why is gulp-rsync not deploying?

Im trying to deploy to a staging site with gulp-rsync. I'm not receiving any errors but it's not deploying to My server. I would also expect to be asked for the password, which is not happening.
var gulp = require('gulp'),
gutil = require('gulp-util'),
sass = require('gulp-sass'),
autoprefixer = require('gulp-autoprefixer'),
minifycss = require('gulp-minify-css'),
jshint = require('gulp-jshint'),
stylish = require('jshint-stylish'),
uglify = require('gulp-uglify'),
concat = require('gulp-concat'),
rename = require('gulp-rename'),
plumber = require('gulp-plumber'),
bower = require('gulp-bower'),
sftp = require('gulp-sftp'),
rsync = require('gulp-rsync');
gulp.task('deploy', function() {
gulp.src('build/test_for_rsync')
.pipe(rsync({
root: 'build',
hostname: '*****.wpengine.com',
username: '*****',
port: 2222,
destination: '/wp-content/themes/',
incremental: true,
progress: true,
relative: true,
exclude: ['/node_modules', '/bower_components'],
recursive: true
}));
});
Try using return keyword before gulp.src:
gulp.task('deploy', function() {
return gulp.src('build/test_for_rsync')
.pipe(rsync({
root: 'build', ...

multiple logger levels for multiple files in sails.js

I want to create separate files for every log levels, and it should store respective files. says,
sails.log.info('Info log');
It should store at info.log file.
var logger = new (winston.Logger)({
transports: [
new (winston.transports.Console)({}),
new (winston.transports.File)({
name: 'info-file',
filename: 'info.log',
level: 'info',
json: false
}),
new (winston.transports.File)({
name: 'error-file',
filename: 'error.log',
level: 'error',
json: false
}),
new (winston.transports.File)({
name: 'debug-file',
filename: 'debug.log',
level: 'debug',
json: false
})
]
});
In config/log.js
custom: logger
My problem is some logs are not shows in terminal, and info.log and debug.log files has not only info and debug log respectively.
How to achieve this?
Well, looks like Winston writes to logs based on their numeric levels. So that error messages will be always written to info log, but info never to error log.
So I think it is better to separate to different instances in config/bootstrap.js:
sails.warnLog = new (winston.Logger)({
transports: [
new (winston.transports.Sentry)({
name: 'warn-Sentry',
dsn: '{my account dsn}',
patchGlobal: true
level: 'warn'
})
]});
sails.infLog = new (winston.Logger)({
transports: [
new (winston.transports.Loggly)({
name: 'info-Loggly',
subdomain: '{my subdomain}',
inputToken: '{my input token}'
level: 'info'
})
]});
sails.verbLog = new (winston.Logger)({
transports: [
new (winston.transports.Console)({
name: 'verb-console',
timestamp: true,
prettyPrint: true,
colorize: true,
level: 'verbose'
})
]});
And then you can write to log:
sails.warnLog.warn('Warning');
sails.infLog.info('Information');
sails.verbLog.verbose('Verbose');

Using Winston and Morgan to log in Sails

In the config/log.js file for Sails this is my code:
var express = require("express");
var app = express();
var winston = require('winston');
var logger = new(winston.Logger)({
transports: [
new(winston.transports.File)({
level: 'info',
timestamp: true,
filename: './logFile.log',
handleExceptions: true,
json: true,
colorize: false
}),
new(winston.transports.Console)({
level: 'debug',
timestamp: true,
handleExceptions: true,
json: false,
colorize: true
})
],
exitOnError: false
});
logger.stream = {
write: function (message, encoding) {
logger.verbose(message);
}
};
app.use(require('morgan')("combined", {"stream": logger.stream}));
module.exports.log = {
level: 'info',
custom: logger
};
I'm trying to use morgan along with winston to log all the HTTP requests. I found an example online that said to do it this way, and this makes sense to me, but for some reason my log file isn't showing any of the requests that are made. The winston part is fine as it is logging all the information that it should be, but I don't know how to get morgan to work with winston. Any advice or suggestions? Thanks!
Morgan is an express middleware so it should be loaded as a custom middleware to Sails.
To do that add the following to config/http.js:
customMiddleware: function(app) {
app.use(require('morgan')("combined", {"stream": sails.config.log.custom.stream}));
}