Frontend headless browser testing using CasperJS and configuration-files? - frameworks

I tried to use CasperJS for headless browser testing using PhantomJS and wanted to have a config file or something to change Website URL, Username passwords etc. So finally I found NuclearJS. Do you guys know any other perfect way to do this? If I wanted to write a one from the scratch would like to know about as well.

I got a solution (not perfect ;) ) that is using multiple configfiles (for selector, execution, desktop, mobile, etc).
I include a in the execution of my casperjs tests a file that offers me all configs i need (i include also global functions there).
Lets guess the test execution looks like that:
casperjs test --includes=loadGlobals.js test_1.js
In the that example loadGlobals.js contains functions like that:
var fs = require('fs');
var config = {},
configFile = fs.read('config.json');
config = JSON.parse(configFile);
Probalby the config.json is looking like that:
{
"url": "http://www.yourTestUrl.com",
"variable_1": "bla",
"variable_2": "blub",
"nextTier": {
"variable_1": "blablub"
}
}
Now you can call in the test_1.js the variables of the config.json:
casper.start(config.url, function() {
casper.then(function() {
casper.echo(config.variable_1);
casper.echo(config.variable_2);
casper.echo(config.nextTier.variable_1);
});
})
casper.run();
You can use like that different configurationfiles, even to override it during tests if nessacary.
The tests should be written in the page object pattern style so they are highly maintable, espacially with a outsourced configuration.
NuclearJS i didn't know, but i will take a look into it, too.

Related

Specifying window (global) variable type hinting in VSCode from external JS file without typescript

This may be a silly question but I really don't know where to look.
I'm creating a browser testing environment for a pretty large-scale API written in typescript. This API uses esbuild to build the typescript files into a /dist/ folder with a single index.js entry-point and its appropriate d.ts file.
I've created a /tests/ folder to hold some browser files that includes an index.html file with Mocha and Chai imported. It also imports /dist/index.js which is set globally to a window.myAPI variable.
In /tests/index.html:
import * as myAPI from "./dist/index.js"
Alongside index.html in the tests folder, there are separate JS files included for different tests that run things on window.myAPI... to do assertion tests.
search.test.js
book.test.js
navigate.test.js
I then run a server to host at the root. These separate tests are then imported from /tests/index.html. The separate tests look like this inside:
const { chai, mocha } = window;
const { assert } = chai;
describe("Search", function() {
describe("Setup", function() {
it("Setting URL should work", function() {
const call = myAPI.someCall()
assert.ok(call);
});
});
});
mocha.run();
Everything works, but I have no code hinting for myAPI. I'd like to be able to see what functions are available when I type myAPI, and what parameters they take, and what they should return - along with all my comments on each function.
In typescript you can do things like ambient declarations, but I don't want to make my tests typescript because then I add an unnecessary build step to the tests. But it would be as easy as:
/// <reference path = "/dist/index.d.ts" />
How can I tell VSCode that window.myAPI is an import of /dist/index.js and should import the types as well so I can see them ?
I'm open to different solutions to this, but I feel like this should be pretty simple. I don't know if ESLint is capable of doing something like this, but I tagged it because I feel it's relevant.
Thanks!

Protractor Custom Locator: Not available in production, but working absolutely fine on localhost

I have added a custom locator in protractor, below is the code
const customLocaterFunc = function (locater: string, parentElement?: Element, rootSelector?: any) {
var using = parentElement || (rootSelector && document.querySelector(rootSelector)) || document;
return using.querySelector("[custom-locater='" + locater + "']");
}
by.addLocator('customLocater', customLocaterFunc);
And then, I have configured it inside protractor.conf.js file, in onPrepare method like this:
...
onPrepare() {
require('./path-to-above-file/');
...
}
...
When I run my tests on the localhost, using browser.get('http://localhost:4200/login'), the custom locator function works absolutely fine. But when I use browser.get('http://11.15.10.111/login'), the same code fails to locate the element.
Please note, that the test runs, the browser gets open, user input gets provided, the user gets logged-in successfully as well, but the element which is referred via this custom locator is not found.
FYI, 11.15.10.111 is the remote machine (a virtual machine) where the application is deployed. So, in short the custom locator works as expected on localhost, but fails on production.
Not an answer, but something you'll want to consider.
I remember adding this custom locator, and encounter some problems with it and realised it's just an attribute name... nothing fancy, so I thought it's actually much faster to write
let elem = $('[custom-locator="locator"]')
which is equivalent to
let elem = element(by.css('[custom-locator="locator"]'))
than
let elem = element(by.customLocator('locator'))
And I gave up on this idea. So maybe you'll want to go this way too
I was able to find a solution to this problem, I used data- prefix for the custom attribute in the HTML. Using which I can find that custom attribute on the production build as well.
This is an HTML5 principle to prepend data- for any custom attribute.
Apart from this, another mistake that I was doing, is with the selector's name. In my code, the selector name is in camelCase (loginBtn), but in the production build, it was replaced with loginbtn (all small case), that's why my custom locater was not able to find it on the production build.

SAP UIveri5 Minimum example

I am trying to understand how UIveri5 works and how to apply it to my own projects, but due to the minimal documentation I am unable to create a minimal working example.
I tried to apply the code from https://github.com/SAP/ui5-uiveri5/blob/master/README.md to "my" minimal app ( https://ui5.sap.com/1.62.0/#/sample/sap.m.sample.Button/code/ ), but the IDE VS Code marks errors, since i.e. the commands export or define are not known and I don't see where UIveri5 loads them from. Also if I just execute uiveri5 in my command line as is, I am getting an error ( I guess from selenium ) that my Chrome binary is missing, but don't the drivers get downloaded automatically?
conf.js
exports.config = {
profile: 'integration',
baseUrl: 'localhost:8080/.../sap.m.sample.Button',
};
page.spec.js
describe('Page', function () {
it('should display the page',function() {
element(by.control({
viewName: 'sap.m.sample.Button.Page',
controlType: 'sap.m.Page',
properties: {
title: "Page"
}}));
});
});
It would be awesome if someone already build a minimal example and can share it. It would help me very much in understanding how everything works together.
The minimum example is right in the readme.md. The only problem I see here is with the baseUrl - this should be a valid URL to an existing app. If this is a sample app on your localhost, you need a dev server.

How we can make cypress scripts easily maintainable like POM in other tools like selenium

This is just a general clarification about building framework using cypress.io.
In cypress can we write a test framework like page object model in selenium?
These model make our life easy to maintain tests.
For eg if ID or class of a particular element which is used across multiple tests /files has changed with a new version of Application-In cypress it is hard to go to multiple test files/tests and change the ID right?
Can we follow the same page object model concept like declaring all elements as variables in each page and use the variable names in tests/functions?
Also can we reuse these variables across different test .js files ?
If yes - can you please give a sample
Thanks
I have seen only a few people using POM concept while creating an automation framework using Cypress. Is that advisable to follow POM model, it depends on reading the following link from team. I would say this may depend upon automation tools/ architecture. According to Cypress team this is not recommendable, may be a debatable topic, read this: https://www.cypress.io/blog/2019/01/03/stop-using-page-objects-and-start-using-app-actions/#
We can declare the variable names in Cypress.env.json file or cypress.json file like below:
{
"weight": "85",
"height": "180",
"age": "35"
}
Then if you want to use them in a test-spec, create a new variable and receive it like below in test-spec.
const t_weight = Cypress.env('weight');
const t_height = Cypress.env('height');
Now you can use the variable in respective textbox input of pages as below:
cy.get('#someheighttextfieldID').type(t_weight);
cy.get('#someweighttextfieldID').type(t_height);
or receive it directly;
cy.get('#someweighttextfieldID').type(Cypress.env('weight'));
example:
/* declare varaibles in 'test-spec.js' file*/
const t_weight = Cypress.env('weight');
const t_height = Cypress.env('height');
//Cypress test - assume below test to test some action and receive the variable to text box
describe('Cypress test to receive variable', function(){
it('Cypress test to receive variable', function(){
cy.visit('/')
cy.get('#someweighttextfieldID').type(t_weight);
cy.get('#someheighttextfieldID').type(t_height);
//even receive the variable straight away
cy.get('#someweighttextfieldID').type(Cypress.env('weight'));
})
});

Is there any way to pass multiple browser via protractor cli

Just wanted to know is it possible to specify cli args to protractor like
--multiCapabilities.0.browserName chrome --multiCapabilities.1.browserName firefox
so that it overrides the multiCapabilities defined in protractor conf file.
A concrete example of Isaac Lyman's first suggestion:
CLI:
protractor ... --params.browsers="chrome,firefox"
conf.js:
var capabilities = {
chrome: {
browserName: 'chrome'
},
firefox: {
browserName: 'firefox'
}
};
...
getMultiCapabilities: function() {
var browsers = this.params.browsers.split(',');
// Using lodash to select the keys in `capabilities` corresponding
// to the browsers param.
return _( capabilities )
.pick(browsers)
.values()
.value();
},
There are a couple of things you could try.
How can I use command line arguments in Angularjs Protractor? explains how to pass in a "params" variable, which if you were totally pro you could reference later in the config file, with the multiCapabilities section (maybe use a helper function or an if statement so you don't have to pass in a complex object from the command line). Not easy to do, but possible.
https://sourcegraph.com/github.com/teerapap/grunt-protractor-runner (see the Options section) is a utility that lets you pass in these things from the command line without any trouble. It's open-source and seems like it would be easy to mod if it doesn't quite meet your needs.
The easiest option, assuming you just need a couple of different options, would just be to use two different config files, "protractor.chrome.conf.js" and "protractor.firefox.conf.js" and run whichever one you need at the moment.
This is a reasonable request. I've created a PR for this here: https://github.com/angular/protractor/pull/1770. For now, you can patch this PR to your local protractor to use this feature.