NightmareJS: how to set cookie? - node.js

var Nightmare = require('nightmare');
var nightmare = Nightmare({
show: true
})
nightmare
.goto('https://mail.yandex.ru')
.type('input[name=login]', 'mylogin')
.type('input[name=passwd]', 'mypassword')
.click('button.nb-button._nb-action-button.nb-group-start')
.wait('.mail-User-Name')
.cookies.get()
.then(function (cookies) {
//actions
})
I am getting cookies after authorization, but I don't know where I must set them and how I must set them. I've tried to do .cookie.set() at the beginning, but this doesn't work.
How I can use saved cookie? Thanks.

I did the following from the node terminal:
> var Nightmare = require('nightmare')
undefined
> var nightmare = Nightmare({show:true})
undefined
> nightmare.
... goto('https://google.com').
... cookies.set('foo', 'bar').
... cookies.get().
... then((cookies) => {
... console.log(JSON.stringify(cookies, null, 4))
... })
Promise { <pending> }
> [
{
"name": "NID",
"value": "96=qo1qY9LTKh1np4OSgiyJTi7e79-_OIoIuc71hnrKWvN1JUnDLJqZlE8u2ij_4mW0-JJhWOCafo5J0j-YkZCFt8H2VHzYUom4cfEd2QLOEsHmAcT2ACx4a5xSvO0SZGZp",
"domain": ".google.de",
"hostOnly": false,
"path": "/",
"secure": false,
"httpOnly": true,
"session": false,
"expirationDate": 1502733434.077271
},
{
"name": "CONSENT",
"value": "WP.25d07b",
"domain": ".google.de",
"hostOnly": false,
"path": "/",
"secure": false,
"httpOnly": false,
"session": false,
"expirationDate": 2145916800.077329
},
{
"name": "foo",
"value": "bar",
"domain": "www.google.de",
"hostOnly": true,
"path": "/",
"secure": false,
"httpOnly": false,
"session": true
}
]
nightmare.cookies.set('key', 'value') is indeed the correct way to use it, as you can see in my result object. Perhaps https://mail.yandex.ru does not accept your cookie, because it's invalid. Please do the same and edit your question to include your results.
Edit: Apparently, OP needs to store the cookies so he can use them in another Nightmare instance. This can be achieved like this:
var Nightmare = require('nightmare')
var storedCookies // This is where we will store the cookies. It could be stored in a file or database to make it permanent
// First instance:
var nightmare1 = Nightmare({show: true})
nightmare1.
goto('https://google.com').
cookies.get().
then((cookies) => {
storedCookies = cookies
})
// Second instance:
var nightmare2 = Nightmare({show: true})
for(var i = 0; i < storedCookies.length; i++)
nightmare2.
cookies.set(storedCookies[i].name, storedCookies[i].value)
nightmare2.
goto('https://google.com')

Related

Problem with app update yml files is not generated in electron?

I have a problem with the auto-update of electron app,
After I finished all the app parts and I am trying to push it to my custom update server , I found this error message in my logger :
Error unknown ENOENT: no such file or directory, open
'C:\{appPath}\{appName}\resources\app-update.yml'
and here is my package.json build configuration
"build": {
"appId": "com.server.app",
"copyright": "Copyright company name",
"generateUpdatesFilesForAllChannels": true,
"win": {
"target": "nsis",
"icon": "build/icon.ico"
},
"mac": {
"target": "dmg",
"artifactName": "appName.dmg",
"icon": "build/icon.icns"
},
"dmg": {
"background": "build/i-bg.tif",
"icon": "build/setup.icns",
"iconSize": 80,
"title": "${productName}-${version}",
"window": {
"width": 540,
"height": 380
}
},
"nsis": {
"artifactName": "${productName}-Setup-${version}.${ext}",
"oneClick": false,
"perMachine": false,
"allowToChangeInstallationDirectory": true,
"installerIcon": "build/setup.ico",
"uninstallerIcon": "build/setup.ico",
"installerHeader": "build/installerHeader.bmp",
"installerSidebar": "build/installerSidebar.bmp",
"runAfterFinish": true,
"deleteAppDataOnUninstall": true,
"createDesktopShortcut": "always",
"createStartMenuShortcut": true,
"shortcutName": "AppName",
"publish": [{
"provider": "generic",
"url": "https://my-update-server/path"
}]
},
"extraFiles": [
"data",
"templates"
]
},
"publish": [{
"provider": "generic",
"url": "https://my-update-server/path"
}],
and here is the code for triggering the auto-update
//-----------------------------------------------
// Auto-Update event listening
//-----------------------------------------------
autoUpdater.on('checking-for-update', () => {
splashLoadingStatus(`Checking for ${appName} update ...`);
})
autoUpdater.on('update-available',(info) => {
splashLoadingStatus(`${appName} new update available.`);
})
autoUpdater.on('update-progress',(progInfo) => {
splashLoadingStatus(`Download speed: ${progInfo.bytesPerSecond} - Download ${progInfo.percent}% (${progInfo.transferred}/${progInfo.total})`);
})
autoUpdater.on('error' , (error) => {
dialog.showErrorBox('Error', error.message);
})
autoUpdater.on('update-downloaded', (info) => {
const message = {
type: 'info',
buttons: ['Restart', 'Update'],
title: `${appName} Update`,
detail: `A new version has been downloaded. Restart ${appName} to apply the updates.`
}
dialog.showMessageBox(message, (res) => {
if(res === 0) {
autoUpdater.quitAndInstall();
}
})
})
.....
autoUpdater.setFeedURL('https://my-update-server/path');
autoUpdater.checkForUpdatesAndNotify();
.....
then when I am pushing the build it will do everything correct with the latest.yml file generating but after installing I found the app-update.yml is not there ...
If you have a problem with missing app-update.yml and dev-app-update.yml then paste the following code into index.js:
import path from "path"
import fs from "fs"
const feed = 'your_site/update/windows_64'
let yaml = '';
yaml += "provider: generic\n"
yaml += "url: your_site/update/windows_64\n"
yaml += "useMultipleRangeRequest: false\n"
yaml += "channel: latest\n"
yaml += "updaterCacheDirName: " + app.getName()
let update_file = [path.join(process.resourcesPath, 'app-update.yml'), yaml]
let dev_update_file = [path.join(process.resourcesPath, 'dev-app-update.yml'), yaml]
let chechFiles = [update_file, dev_update_file]
for (let file of chechFiles) {
if (!fs.existsSync(file[0])) {
fs.writeFileSync(file[0], file[1], () => { })
}
}
I fixed it by using autoUpdater.setFeedURL() before autoUpdater.checkForUpdates(). Below is the code snippet that works for github releases. Also, please make sure there is existing release in Github before running this code.
import { autoUpdater } from "electron-updater";
// ...
autoUpdater.setFeedURL({
provider: "github",
owner: "org",
repo: "repo",
});

Jest's globalSetup make my tests to not being recognized

So I was following this example to make a test with mongodb on jest, but after configuring everything I just get this when running jest:
If I remove globalSetup from jest.config.js, the tests appear although with errors because of mongo-enviroment and teardown configs been dependents on globalSetup:
If I run jest --debug I get this:
{
"configs": [
{
"automock": false,
"browser": false,
"cache": true,
"cacheDirectory": "/tmp/jest_rs",
"clearMocks": false,
"coveragePathIgnorePatterns": [
"/node_modules/"
],
"detectLeaks": false,
"detectOpenHandles": false,
"errorOnDeprecated": false,
"filter": null,
"forceCoverageMatch": [],
"globals": {},
"haste": {
"providesModuleNodeModules": []
},
"moduleDirectories": [
"node_modules"
],
"moduleFileExtensions": [
"js",
"json",
"jsx",
"node"
],
"moduleNameMapper": {},
"modulePathIgnorePatterns": [],
"name": "9f5155d702743ad8d949d6d219c1bc22",
"prettierPath": null,
"resetMocks": false,
"resetModules": false,
"resolver": null,
"restoreMocks": false,
"rootDir": "/home/mauricio/work/growthbond/gbnd1",
"roots": [
"/home/mauricio/work/growthbond/gbnd1"
],
"runner": "jest-runner",
"setupFiles": [
"/home/mauricio/work/growthbond/gbnd1/node_modules/regenerator-runtime/runtime.js"
],
"setupTestFrameworkScriptFile": "/home/mauricio/work/growthbond/gbnd1/testConfig/setupScript.js",
"skipFilter": false,
"snapshotSerializers": [],
"testEnvironment": "/home/mauricio/work/growthbond/gbnd1/testConfig/mongo-environment.js",
"testEnvironmentOptions": {},
"testLocationInResults": false,
"testMatch": [
"**/__tests__/**/*.js?(x)",
"**/?(*.)+(spec|test).js?(x)"
],
"testPathIgnorePatterns": [
"/node_modules/"
],
"testRegex": "",
"testRunner": "/home/mauricio/work/growthbond/gbnd1/node_modules/jest-jasmine2/build/index.js",
"testURL": "http://localhost",
"timers": "real",
"transform": [
[
"^.+\\.jsx?$",
"/home/mauricio/work/growthbond/gbnd1/node_modules/babel-jest/build/index.js"
]
],
"transformIgnorePatterns": [
"/node_modules/"
],
"watchPathIgnorePatterns": []
}
],
"globalConfig": {
"bail": false,
"changedFilesWithAncestor": false,
"collectCoverage": false,
"collectCoverageFrom": null,
"coverageDirectory": "/home/mauricio/work/growthbond/gbnd1/coverage",
"coverageReporters": [
"json",
"text",
"lcov",
"clover"
],
"coverageThreshold": null,
"detectLeaks": false,
"detectOpenHandles": false,
"errorOnDeprecated": false,
"expand": false,
"filter": null,
"globalSetup": "/home/mauricio/work/growthbond/gbnd1/testConfig/setup.js",
"globalTeardown": "/home/mauricio/work/growthbond/gbnd1/testConfig/teardown.js",
"listTests": false,
"maxWorkers": 3,
"noStackTrace": false,
"nonFlagArgs": [],
"notify": false,
"notifyMode": "always",
"passWithNoTests": false,
"projects": null,
"rootDir": "/home/mauricio/work/growthbond/gbnd1",
"runTestsByPath": false,
"skipFilter": false,
"testFailureExitCode": 1,
"testPathPattern": "",
"testResultsProcessor": null,
"updateSnapshot": "new",
"useStderr": false,
"verbose": true,
"watch": false,
"watchman": true
},
"version": "23.6.0"
}
Note that
"testMatch": [
"**/__tests__/**/*.js?(x)",
"**/?(*.)+(spec|test).js?(x)"
],
looks perfectly fine.
Related files
jest.config.js:
module.exports = {
globalSetup: './testConfig/setup.js',
globalTeardown: './testConfig/teardown.js',
testEnvironment: './testConfig/mongo-environment.js',
setupTestFrameworkScriptFile: './testConfig/setupScript.js',
verbose: true
}
setup.js (globalSetup):
const path = require('path');
const fs = require('fs');
const MongodbMemoryServer = require('mongodb-memory-server');
const globalConfigPath = path.join(__dirname, 'globalConfig.json');
const mongod = new MongodbMemoryServer.default({
instance: {
dbName: 'jest'
},
binary: {
version: '3.2.18'
},
autoStart: false,
});
module.exports = async () => {
if (!mongod.isRunning) {
await mongod.start();
}
const mongoConfig = {
mongoDBName: 'jest',
mongoUri: await mongod.getConnectionString()
};
// Write global config to disk because all tests run in different contexts.
fs.writeFileSync(globalConfigPath, JSON.stringify(mongoConfig));
console.log('Config is written');
// Set reference to mongod in order to close the server during teardown.
global.__MONGOD__ = mongod;
process.env.MONGO_URL = mongoConfig.mongoUri;
};
teardown.js:
module.exports = async function() {
await global.__MONGOD__.stop();
};
mongo-environment.js:
const NodeEnvironment = require('jest-environment-node');
const path = require('path');
const fs = require('fs');
const globalConfigPath = path.join(__dirname, 'globalConfig.json');
module.exports = class MongoEnvironment extends NodeEnvironment {
constructor(config) {
super(config);
}
async setup() {
console.log('Setup MongoDB Test Environment');
const globalConfig = JSON.parse(fs.readFileSync(globalConfigPath, 'utf-8'));
this.global.__MONGO_URI__ = globalConfig.mongoUri;
this.global.__MONGO_DB_NAME__ = globalConfig.mongoDBName;
await super.setup();
}
async teardown() {
console.log('Teardown MongoDB Test Environment');
await super.teardown();
}
runScript(script) {
return super.runScript(script);
}
};
user.test.js (mongodb related test):
const MongoClient= require('mongodb');
const User = require('../../db/models/user');
let connection;
let db;
beforeAll(async () => {
connection = await MongoClient.connect(global.__MONGO_URI__);
db = await connection.db(global.__MONGO_DB_NAME__);
});
afterAll(async () => {
await connection.close();
await db.close();
});
describe('Password Encription', async () => {
const uEmail = 'test#a.com';
const uPass = '123test';
var testUser = new User({
email:uEmail ,
password: uPass
});
await testUser.save()
test('Encripted password string is different to plain password', async () => {
user = await User.findOne({ email: uEmail });
expect(user.password).not.toEqual(uPass);
});
test('ComparePassword method verify that plain password is the same that encrypted password', async () => {
rightPassword = await user.comparePassword(uPass);
expect(rightPassword).toBeTrue();
});
test('ComparePassword method verify that altered plain password is not the same that encrypted password', async () => {
wrongPassword = await user.comparePassword(uPass+'random');
expect(rightPassword).not.toBeTrue();
});
});
authService.test.js:
require('dotenv').config()
const authS = require('../../services/authService');
const jwt = require('jsonwebtoken');
describe('Auth Services',()=>{
const payload = {test:'This is a test'}
const user = {id:101}
const mockSecret = 'SECRET123HAAJAHJSoafdafda'
const token = authS.jwtSign(user,payload)
test('JWT sign', () => {
expect(authS.jwtSign(user,payload)).toBeString();
});
test('JWT verify different secret', ()=>{
badToken = jwt.sign(
payload,
mockSecret,
{ subject:String(user.id),
expiresIn:'1h'
}
);
expect(()=>authS.jwtVerify(badToken)).toThrowError(jwt.JsonWebTokenError)
})
test('JWT verify payload', ()=>{
expect(authS.jwtVerify(authS.jwtSign(user,payload))).toMatchObject(payload)
})
})
My environment:
node v11.0.0
jest 23.6.0
As a matter of fact I know that my test non mongodb related run if I comment
globalSetup: './testConfig/setup.js',
globalTeardown: './testConfig/teardown.js',
testEnvironment: './testConfig/mongo-environment.js',
from jest.config.js :
My problem was that I had another GlobalSetup file and they were conflicting. In my custom GlobalSetup I imported the #Shelf/jest-mongodb/setup and add it to mine.
const jestMongoSetup = require("#shelf/jest-mongodb/setup")
module.exports = async () => {
process.env.TZ = "UTC" //My config
await jestMongoSetup()
}

loopback redis based sessions

first i would like to say that i have already seen questions regarding related issues but did not find the answer.
I want to use redis for session in loopback, but req is not available in code.
server/server.js
var redis = require("redis");
var session = require('express-session');
var redisStore = require('connect-redis')(session);
var client = redis.createClient();
var app = module.exports = loopback();
app.use(session({
secret: '0`3VTw;hQ|3/`:95ZYu{0J82O>{}7JC/',
// create new redis store.
store: new redisStore({ host: 'localhost', port: 6379, client: client,ttl : 260}),
saveUninitialized: false,
resave: false
}));
I want to implement Redis Based express sessions on loopback application but i cant find the way to do it without writing the whole route controller myself.
I am currently extending the model and creating a remoteMethod() but i cannot access "req" in anyway.
this is my TrmptUsers Model code (see line 3)
common/models/trmpt-users.js
module.exports = function(TrmptUsers) {
TrmptUsers.login = function(username, password, cb) {
console.log(TrmptUsers.app.session); //i want access to req variable to work with redis here.
var ursalt = security.gen_salt(username);
password = security.decrypt256(password, ursalt);
TrmptUsers.findOne({fields:{usrPwd:true,usrAccessToken:true},where:{and:[{usr_username:username}]}},function(err,result){
security.verifyPassword(password, result.usrPwd, function(err, verify) {
if (verify) {
User.generateVerificationToken(username, cb)
cb(null,result.usrAccessToken);
}
else {
cb({status:401,message:"Invalid Username/Password"},null);
}
});
});
}
TrmptUsers.remoteMethod(
'login',
{
accepts: [
{arg: 'username', type: 'string', required: 'true'},
{arg: 'password', type: 'string', required: 'true'},
],
returns: {arg: 'accesstoken', type: 'string'}
}
);
};
I found a solution to all my problems above a long time ago, since someone up-voted it i think they might want an answer so I am posting one here.
server/server.js
var redis = require("redis");
var session = require('express-session');
var redisStore = require('connect-redis')(session);
app.use(session({
secret: 'hello',
store: new redisStore({ host: 'localhost', port: 6379, client: client,ttl : 3600}),//1 hour
saveUninitialized: false,
resave: false
}));
then when you create your models slc:loopback model you get an option to add req object to your parameters.
model-specific.json
...
"methods": {
"userLogin": {
"isStatic": true,
"accepts": [
{
"arg": "req",
"type": "object",
"required": true,
"description": "",
"http": {
"source": "req"
}
},
{
"arg": "username",
"type": "string",
"required": true,
"description": "Username"
},
{
"arg": "password",
"type": "string",
"required": true,
"description": "Password"
}
],
"returns": [
{
"arg": "accessToken",
"type": "string",
"root": false,
"description": ""
}
],
...
Then just use req.session in any way you want and remember to install redis-server first.

Cant configure timed out user confirmation url page in LoopbackJS

I try to configure, new registerede user's timed ot confirmation url.
When user clicks on timed out link from mail, screen looks like :
{"error":{"name":"Error","status":404,"message":"User not found: 19","statusCode":404,"code":"USER_NOT_FOUND","stack":"Error: User not found: 19\n at c:\\NodeJS\\UyguncaAdmin\\node_modules\\loopback\\common\\models\\user.js:477:19\n at c:\\NodeJS\\UyguncaAdmin\\node_modules\\loopback-datasource-juggler\\lib\\dao.js:1524:62\n at c:\\NodeJS\\UyguncaAdmin\\node_modules\\loopback-datasource-juggler\\lib\\dao.js:1456:9\n at Object.async.each (c:\\NodeJS\\UyguncaAdmin\\node_modules\\loopback-datasource-juggler\\node_modules\\async\\lib\\async.js:153:20)\n at allCb (c:\\NodeJS\\UyguncaAdmin\\node_modules\\loopback-datasource-juggler\\lib\\dao.js:1394:13)\n at c:\\NodeJS\\UyguncaAdmin\\node_modules\\loopback-connector-mysql\\node_modules\\loopback-connector\\lib\\sql.js:1071:7\n at c:\\NodeJS\\UyguncaAdmin\\node_modules\\loopback-datasource-juggler\\lib\\observer.js:166:22\n at doNotify (c:\\NodeJS\\UyguncaAdmin\\node_modules\\loopback-datasource-juggler\\lib\\observer.js:93:49)\n at MySQL.ObserverMixin._notifyBaseObservers (c:\\NodeJS\\UyguncaAdmin\\node_modules\\loopback-datasource-juggler\\lib\\observer.js:116:5)\n at MySQL.ObserverMixin.notifyObserversOf (c:\\NodeJS\\UyguncaAdmin\\node_modules\\loopback-datasource-juggler\\lib\\observer.js:91:8)"}}
I want to send more user-friendly page includes message like "Confirmation mail timed out ...".
I try to use "afterRemote" method, but it does not work. I cant get "in confirm afterRemote" message.
MyUser.afterRemote('confirm', function(ctx, inst, next) {
console.log('in confirm afterRemote...');
next(); });
Is there any way to do this? What is wrong with this afterRemote method?
Edit your server/config.json
and set "disableStackTrace": true and "disableStatusCode": true
under errorHandler section look below example
Don't forget to vote ;-)
Cheers
{
"restApiRoot": "/api",
"host": "0.0.0.0",
"port": 4000,
"remoting": {
"context": {
"enableHttpContext": false
},
"rest": {
"normalizeHttpPath": false,
"xml": false
},
"json": {
"strict": false,
"limit": "100kb"
},
"urlencoded": {
"extended": true,
"limit": "100kb"
},
"cors": {
"origin": true,
"credentials": true
},
"errorHandler": {
"disableStackTrace": true,
"disableStatusCode": true
}
}
}

Node js request get page error 500

i want to make a request to a page using request module in node js, but this have a error 500 .
This is part of the json response
{
"readable": false,
"domain": null,
"_maxListeners": 10,
"httpVersion": "1.1",
"complete": true,
"_pendingIndex": 0,
"url": "",
"method": null,
"statusCode": 500,
"_consuming": true,
"_dumped": false,
"httpVersionMajor": 1,
"httpVersionMinor": 1,
"upgrade": false,
"body": "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n<title>500 Not Found</title>\n</head><body>\n<h1>Not Found</h1>\n<p>The requested\n site HTTP/1.1 is not presently available on\n this web cluster.\n This may be a temporary issue, so please try again in a few\n moments.</p>\n\n</body></html>\n",
"_readableState": {
"highWaterMark": 16384,
"length": 0,
"pipes": null,
"pipesCount": 0,
"flowing": false,
"ended": true,
"endEmitted": true,
"reading": false,
"calledRead": true,
"sync": false,
"needReadable": true,
"emittedReadable": false,
"readableListening": false,
"objectMode": false,
"defaultEncoding": "utf8",
"ranOut": false,
"awaitDrain": 0,
"readingMore": false,
"decoder": null,
"encoding": null,
"buffer": []
},
This is the code that i use for the request
app.get('/', function(req, res){
var options = {
url: 'http://www.metallicabyrequest.com/'
}
request(options, function (error, response, html) {
/*if (!error && response.statusCode == 200) {
res.json(html);
}*/
if(error){
res.json(error);
}else{
res.json(response)
}
});
});
Is there any way to get prevent the error 500? I read that if you change the headers, is probably that the request works, but i don't know how to do ...
That site require 'Host' in request header:
var options = {
url: 'http://www.metallicabyrequest.com/',
headers: {
'Host': 'www.metallicabyrequest.com'
}
}

Resources