self-signed certificate configuration in Selenium Standalone and webdriverio - selenium

How does one set in the configuration to accept insecure self-signed certificates.
I'm using Selenium Standalone and webdriverio.
https://github.com/vvo/selenium-standalone
https://github.com/webdriverio/webdriverio
I cannot read anywhere how to do this.
I'm suing the code below:
const assert = require('assert');
const { promisify } = require('util');
const exec = promisify(require('child_process').exec);
const selenium = require('selenium-standalone');
const webdriverio = require('webdriverio');
selenium.installAsync = promisify(selenium.install);
selenium.startAsync = promisify(selenium.start);
let browser;
let seleniumChild;
before(async function () {
this.timeout(10 * 1000);
try {
// Remove any previous hanging sessions
await exec('pkill -f selenium-standalone');
} catch (error) {
if (error.cmd !== 'pkill -f selenium-standalone') {
console.error(error);
process.exit(1);
}
}
await selenium.installAsync({});
seleniumChild = await selenium.startAsync({});
const options = {
desiredCapabilities: {
browserName: 'chrome',
},
port: 4444,
};
browser = webdriverio.remote(options);
await browser.init();
await browser.url('http://google.com');
const title = await browser.getTitle();
console.log('Title ->', title);
await browser.end();
});
describe('test', function () {
it('test', async function () {
assert.ok(true);
});
});

Since it's starting a Selenium server, I'm expecting to be able to specify this through capabilities:
Did you tried using:
"acceptSslCerts": "true"
More on this topic you can find on the Selenium github page.

Related

Testing authentication with Auth0 in a full stack application with Cypress

I’m working on a full-stack NestJS application, integrating with Auth0 using the express-openid-connect library. I’m using Cypress for e2e tests, and I’m trying to find a way of testing my login using Cypress.
I found this article - https://auth0.com/blog/end-to-end-testing-with-cypress-and-auth0/, but it seems to be very much tied to a React application. I’m calling the /oauth/token API endpoint, and I get a response, but I’m unsure how to build out my callback URL to log me in to the application. Here’s what I have so far:
Cypress.Commands.add('login', () => {
cy.session('logged in user', () => {
const options = {
method: 'POST',
url: `${Cypress.env('OAUTH_DOMAIN')}/oauth/token`,
body: {
grant_type: 'password',
username: Cypress.env('AUTH_USERNAME'),
password: Cypress.env('AUTH_PASSWORD'),
scope: 'openid profile email',
audience: `${Cypress.env('OAUTH_DOMAIN')}/api/v2/`,
client_id: Cypress.env('OAUTH_CLIENT_ID'),
client_secret: Cypress.env('OAUTH_CLIENT_SECRET'),
},
};
cy.request(options).then((response) => {
// What do I do here?
});
});
});
Any pointers would be gratefully recieved!
I ended up sorting this out by using Puppeteer to handle my login, stopping at the point of redirection to the callback URL and returning the cookies and callback URL to Cypress, as detailed in this article:
https://sandrino.dev/blog/writing-cypress-e2e-tests-with-auth0
Things have changed a bit since then, and with the introduction of Cypress's experimentalSessionSupport it's a bit simpler. I ended up whittling the solution down to having the following in my Cypress setup:
// cypress/plugins/auth0.js
const puppeteer = require('puppeteer');
const preventApplicationRedirect = function (callbackUrl) {
return (request) => {
const url = request.url();
if (request.isNavigationRequest() && url.indexOf(callbackUrl) === 0)
request.respond({ body: url, status: 200 });
else request.continue();
};
};
const writeUsername = async function writeUsername({ page, options } = {}) {
await page.waitForSelector('#username');
await page.type('#username', options.username);
};
const writePassword = async function writeUsername({ page, options } = {}) {
await page.waitForSelector('#password', { visible: true });
await page.type('#password', options.password);
};
const clickLogin = async function ({ page } = {}) {
await page.waitForSelector('button[type="submit"]', {
visible: true,
timeout: 5000,
});
const [response] = await Promise.all([
page.waitForNavigation({ waitUntil: 'networkidle2' }),
page.click('button[type="submit"]'),
]);
return response;
};
exports.Login = async function (options = {}) {
const browser = await puppeteer.launch({
headless: options.headless,
args: options.args || ['--no-sandbox', '--disable-setuid-sandbox'],
});
const page = await browser.newPage();
try {
await page.setViewport({ width: 1280, height: 800 });
await page.setRequestInterception(true);
page.on('request', preventApplicationRedirect(options.callbackUrl));
await page.goto(options.loginUrl);
await writeUsername({ page, options });
await writePassword({ page, options });
const response = await clickLogin({ page, options });
if (response.status() >= 400) {
throw new Error(
`'Login with user ${
options.username
} failed, error ${response.status()}`,
);
}
const url = response.url();
if (url.indexOf(options.callbackUrl) !== 0) {
throw new Error(`User was redirected to unexpected location: ${url}`);
}
const { cookies } = await page._client.send('Network.getAllCookies', {});
return {
callbackUrl: url,
cookies,
};
} finally {
await page.close();
await browser.close();
}
};
// cypress/plugins/index.js
const auth0 = require('./auth0');
module.exports = (on, config) => {
require('dotenv').config({ path: '.env.test' });
config.env.AUTH0_DOMAIN = process.env.AUTH0_DOMAIN;
config.env.AUTH_USERNAME = process.env.AUTH_USERNAME;
config.env.AUTH_PASSWORD = process.env.AUTH_PASSWORD;
on('task', {
LoginPuppeteer(options) {
return auth0.Login(options);
},
});
return config;
};
// cypress/support/commands.js
const { getUnixTime } = require('date-fns');
/*
* Create the cookie expiration.
*/
function getFutureTime(minutesInFuture) {
const time = new Date(new Date().getTime() + minutesInFuture * 60000);
return getUnixTime(time);
}
/**
* Create a cookie object.
* #param {*} cookie
*/
function createCookie(cookie) {
return {
name: cookie.name,
value: cookie.value,
options: {
domain: `${cookie.domain.trimLeft('.')}`,
expiry: getFutureTime(15),
httpOnly: cookie.httpOnly,
path: cookie.path,
sameSite: cookie.sameSite,
secure: cookie.secure,
session: cookie.session,
},
};
}
/**
* Login via puppeteer and return the redirect url and cookies.
*/
function login() {
return cy.task('LoginPuppeteer', {
username: Cypress.env('AUTH_USERNAME'),
password: Cypress.env('AUTH_PASSWORD'),
loginUrl: 'http://localhost:3000/login',
callbackUrl: 'http://localhost:3000/callback',
});
}
/**
* Login with Auth0.
*/
Cypress.Commands.add('loginAuth0', () => {
cy.session('logged in user', () => {
login().then(({ cookies, callbackUrl }) => {
console.log(cookies);
cookies
.map(createCookie)
.forEach((c) => cy.setCookie(c.name, c.value, c.options));
cy.visit(callbackUrl);
});
});
});
You can then use cy.loginAuth0() in your app to login with a real Auth0 instance. Make sure you have "experimentalSessionSupport": true in your cypress.json. That way you'll only have to perform this (admittedly long winded) task only once in your test suite!

How to use basic commands in webdriver.io

I'm using webdriver.io to do some browser automation. Not really testing , just saving time by automating things. I can see examples of how to use some of the functions .. but I can't seem to access them. I'm quite new to node.js
** Important ** I realise you can use browser.getAttribute - but looking at this example: http://webdriver.io/api/property/getAttribute.html
I should be able to execute getAttribute on the element object..?
var allInputs = $$('.loginForm input')
console.log(allInputs.map(function(el) { return el.getAttribute('name'); }))
My code:
var webdriverio = require('webdriverio');
var options = {
desiredCapabilities: {
browserName: 'chrome'
}
};
var browser = webdriverio.remote(options)
async function browserTest(){
await browser
.init()
.url('http://www.google.com')
.getTitle().then(function(title) {
console.log('Title was: ' + title);
})
.catch(function(err) {
console.log(err);
});
var body = await browser.element("//body")
console.log(body)
//the following line fails
console.log(await body.getAttribute("id"))
}
browserTest()

WebdriverIO - Get browser logs

I want to get the browser logs (console.logs) from chrome with WebdriverIO's log functionality but all I get is, that the function log is not a function.
var WebdriverIO = require('webdriverio');
var chai = require('chai');
var _ = require('lodash');
var chaiAsPromised = require('chai-as-promised');
var expect = chai.expect;
chai.use(chaiAsPromised);
var browser = {
host: '127.0.0.1',
port: 4444,
desiredCapabilities: {
browserName : 'chrome',
chromeOptions: {
args: [
'no-sandbox',
'use-fake-device-for-media-stream',
'use-fake-ui-for-media-stream',
'mute-audio',
]
},
loggingPrefs: {
'driver': 'INFO',
'browser': 'INFO'
}
},
};
var matrix = WebdriverIO.multiremote({
browserA: browser,
browserB: browser,
});
chaiAsPromised.transferPromiseness = matrix.transferPromiseness;
var browserA = matrix.select('browserA');
var browserB = matrix.select('browserB');
it('should initialize browsers', function() {
return matrix.init();
});
it('should open two browsers', function(done) {
browserA.url('https://127.0.0.1:3000/');
browserB.url('https://127.0.0.1:3000/');
matrix.timeouts('implicit', 15000);
matrix.sync().call(done);
});
it('should return logs', function(done) {
browserA
.log('browser', function(err, msg, a) {
console.log(msg);
})
.call(done);
});
Does someone know how to use this function properly? It also doesnt work when I just use one browser and not creating a Matrix like I did in the code snippet.
You are using the API wrong. You can not pass in a callback to the log method. The command returns a promise (if you use a standalone script like that) so you need to do:
browserA
.log('browser').then(function(msg) {
console.log(msg);
})

Node Promises with webdriver.io

I am trying to run selenium web scraping and failing. Please look at the code snippet.
var webdriverio = require('webdriverio');
var client = webdriverio
.remote({
desiredCapabilities: {
browserName:'chrome'
}
});
module.exports = function(some_url) {
return new Promise(function(resolve) {
client
.init()
.newWindow(some_url)
.getHTML('html')
.then(function(html) {
var some_data = someFactory(html); // do some data scraping
Promise
.all(
some_data
.some_array
.map(function (data) {
return new Promise(function(resolve) {
client
.newWindow(data.other_link)
.getHTML('html')
.then(function (html) {
var $ = cheerio.load(html); // do some more scraping
resolve(html);
})
.end();
});
})
)
.then(function (data) {
// execution never comes here while I get html in
// the mapped function
resolve(some_data, data);
});
).end();
});
This above execution never completes. It never comes out of the inner block.
Any help would be greatly appreciated.

Issues testing hapijs plugin

Here's my test
'use strict';
var assert = require('assert');
var sinon = require('sinon');
var proxyquire = require('proxyquire');
var Lab = require('lab');
var lab = exports.lab = Lab.script();
lab.experiment("src.mysql", function () {
var server = {
settings: {
app: {
mysql: {
connectionLimit: 10,
host: "none",
user: "me",
password: "nope",
database: "db"
}
}
},
expose: sinon.stub()
};
var mysql = sinon.stub();
var next = sinon.stub();
var plugin = proxyquire('../../src/mysql', {
mysql: mysql
});
lab.test("successful loads", function(done) {
plugin.register(server, {}, next, function(err) {
assert(err === 'hello');
});
done();
});
});
I'm not getting an error, but the test is passing, which is a false positive. Not sure what I am doing wrong
The latest version of hapi 8.x.x uses a new method for loading plugins, you should call server.register with arguments described here http://hapijs.com/api#serverregisterplugins-options-callback.