I want to write all tests in module and import into a main test js file for execution. How to achieve this? Below is my code snippet.
module.exports = (function(settings) {
settings.test_workers = false;
return settings;
})(require('./nightwatch.json'));
var testPage = (require('./test.js'));
var myTest;
module.exports = {
myTest = new testPage(browser)
myTest.Login(browser) -> Giving error on this line.
}
Test.js
module.exports = {
'Login' : function Login (browser) {
browser
.url('http://localhost:63916/Login/Login')
.useXpath()
.maximizeWindow()
.pause(3000)
}
Why giving this error? Thanks.
Related
I am new to Cypress. How to read data from excel files using Cypress? Searched in google but could not find useful answers.
In cypress you can create cypress task to read xlsx file with SheetJS library.
Usage
cypress\integration\read-xlsx.spec.js
context('Xlsx file', () => {
it('Read excel file', () => {
cy.task('readXlsx', { file: 'my-excel.xlsx', sheet: "Sheet1" }).then((rows) => {
expect(rows.length).to.equal(543)
// expect(rows[0]["column name"]).to.equal(11060)
})
})
})
Need to install xlsx
$ npm install xlsx
Create read excel fuction
cypress\plugins\read-xlsx.js
const fs = require('fs');
const XLSX = require('xlsx');
const read = ({file, sheet}) => {
const buf = fs.readFileSync(file);
const workbook = XLSX.read(buf, { type: 'buffer' });
const rows = XLSX.utils.sheet_to_json(workbook.Sheets[sheet]);
return rows
}
module.exports = {
read,
}
Use function as Cypress task (plugin)
cypress\plugins\index.js
const readXlsx = require('./read-xlsx')
module.exports = (on, config) => {
on('task', {
'readXlsx': readXlsx.read
})
}
Here is an instruction how to use excel as source for cypress tests https://medium.com/#you54f/dynamically-generate-data-in-cypress-from-csv-xlsx-7805961eff55
First you need to conver your xlsx file to json with Xlsx
import { writeFileSync } from "fs";
import * as XLSX from "xlsx";
try {
const workBook = XLSX.readFile("./testData/testData.xlsx");
const jsonData = XLSX.utils.sheet_to_json(workBook.Sheets.testData);
writeFileSync(
"./cypress/fixtures/testData.json",
JSON.stringify(jsonData, null, 4),
"utf-8"
);
} catch (e) {
throw Error(e);
}
Then import json file and loop over each row and use the data in the way you want. In this example it tries to log in to a system.
import { login } from "../support/pageObjects/login.page";
const testData = require("../fixtures/testData.json");
describe("Dynamically Generated Tests", () => {
testData.forEach((testDataRow: any) => {
const data = {
username: testDataRow.username,
password: testDataRow.password
};
context(`Generating a test for ${data.username}`, () => {
it("should fail to login for the specified details", () => {
login.visit();
login.username.type(data.username);
login.password.type(`${data.password}{enter}`);
login.errorMsg.contains("Your username is invalid!");
login.logOutButton.should("not.exist");
});
});
});
});
For me the first answer pretty much worked. But i had to make a small fix.
Use function as Cypress task (plugin)
cypress/plugins/index.js
const readXlsx = require('./read-xlsx')
module.exports = (on, config) => {
on('task', {
'readXlsx': readXlsx.read
})
}
when i used this code i got the below error in cypress.
CypressError
cy.task('log') failed with the following error:
The task 'log' was not handled in the plugins file. The following tasks are registered: readXlsx
and the below fix worked
const readXlsx = require('./read-xlsx')
module.exports = (on, config) => {
on('task', {
'readXlsx': readXlsx.read,
log (message) {
console.log(message)
return null
}
})
}
I'm trying to write to console the network log after a test failure as part of my protractor suite. The code works fine when in an afterEach() block but fails to execute the promise when inside of a custom jasmine reporter. As far as I can tell the promise never executes, but there are no known/shown errors.
protractor config (simplified):
exports.config = {
specs: ['./e2e/**/*.spec.ts'],
capabilities: {
browserName: 'chrome',
chromeOptions: {
perfLoggingPrefs: {
enableNetwork: true,
enablePage: false,
}
},
loggingPrefs: {
performance: 'ALL',
browser: 'ALL'
},
},
onPrepare() {
jasmine.getEnv().addReporter({
specDone: result => {
new ErrorReporter(browser).logNetworkError(result);
}
});
},
};
ErrorReporter:
class ErrorReporter {
constructor(browser) {
this.browser = browser;
}
logNetworkError(result) {
if(result.status === 'failed') {
// execution makes it in here
this.browser.manage().logs().get('performance').then(function(browserLogs) {
// execution DOES NOT make it here
browserLogs.forEach(function(log) {
const message = JSON.parse(log.message).message;
if(message.method === 'Network.responseReceived') {
const status = message.params.response.status;
const url = message.params.response.url;
if(status !== 200 && status !== 304) {
console.log(`----E2E NETWORK ERROR----`);
console.log(`STATUS: [${status}]`);
console.log(`URL: [${url}]`);
console.log(`RESPONSE: [${log.message}]`);
}
}
});
});
}
}
}
module.exports = ErrorReporter;
The code inside the logNetworkError() method works completely fine when executed in an afterEach() block but never writes out any logs when executed as a custom reporter. I would expect that this would work as a jasmine reporter as well.
If it's not possible to execute this as a jasmine reporter is there some way to access the executed test's results in the afterEach() block? I do not want to log on successful test execution.
I figured out the solution. There was 2 main problems. The first was that I needed to use async and await inside of the function that was creating the log:
async logNetworkError(result) {
if(result.status === 'failed') {
const logs = await this.browser.manage().logs().get('performance');
logs.forEach((log) => {
const message = JSON.parse(log.message).message;
if(message.method === 'Network.responseReceived') {
const status = message.params.response.status;
const url = message.params.response.url;
if(status !== 200 && status !== 304) {
console.log(`-----E2E NETWORK ERROR-----`);
console.log(`TEST NAME: ${result.fullName}`);
console.log(`STATUS: [${status}]`);
console.log(`URL: [${url}]`);
console.log(`RESPONSE: [${log.message}]`);
}
}
});
}
}
the second part of the problem was that another reporter which was saving screenshots did not have async and await which was stopping other reporters from completing. Adding async/await to both reporters solved this issue.
i want to implement the page object pattern in my nightwatch tests and use mocha at the same time.
My test class looks like this
module.exports = {
'Create Subscription' : function (browser) {
var createPage= browser.page.createSubscriptionPage();
var subscriptionName = '_test_nightWatch',
subscriptionDescription = 'description';
it('should create a subscription', function(browser){
createPage.navigate()
.waitForElementVisible('#nameField', 20000)
.setValue('#nameField', subscriptionName)
.setValue('#descriptionField', subscriptionDescription)
.expect.element('#nameField').to.have.value.that.equals(subscriptionName)
browser.expect.element('#descriptionField').to.have.value.that.equals(subscriptionDescription)
browser.end();
});
}
};
i updated my json file to
"test_runner" : {
"type" : "mocha",
"options" : {
"ui" : "bdd",
"reporter" : "list"
}
}
it starts the server but nothing runs
I've seen issue on this online but none that have been resolved
Figured it out ...
var expect = require('chai').expect;
var nightwatch = require('nightwatch');
describe('Create Subscription', function() {
var subscriptionName = '_test_nightWatch',
subscriptionDescription = 'description';
it('should create a subscription', function(browser){
var createPage= browser.page.createSubscriptionPage();
createPage.navigate()
.waitForElementVisible('#nameField', 20000)
.setValue('#nameField', subscriptionName)
.setValue('#descriptionField', subscriptionDescription)
.expect.element('#nameField').to.have.value.that.equals(subscriptionName)
browser.end();
});
});
EDIT: Formatted text properly
Currently I use addon sdk to develop a firefox extension,which can redirect some request without loading them.
For example, a page refer a.js (maybe have something like this <script src='example.com/a.js'>),
then, I want to redirect this request to example2.com/b.js
Now,with nsIContentPolicy I can block example.com/a.js,
But I don't know how to load example2.com/b.js at the time when a.js is blocked.
my codes now look like this:
const { Cc, Ci } = require("chrome");
const xpcom = require("sdk/platform/xpcom");
const { Class } = require("sdk/core/heritage");
exports.gcleaner = Class({
extends: xpcom.Unknown,
interfaces: ["nsIContentPolicy"],
shouldLoad: function (contType, contLoc, reqOrig, ctx, typeGuess, extra) {
//https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIContentPolicy#shouldLoad()
if (contType === 2) //2 means js
{
var blockReg = new RegExp('example.com/a.js');
if (contLoc['spec'].match(blockReg))
{
return Ci.nsIContentPolicy.REJECT;
};
};
return Ci.nsIContentPolicy.ACCEPT;
},
shouldProcess: function (contType, contLoc, reqOrig, ctx, mimeType, extra) {
return Ci.nsIContentPolicy.ACCEPT;
}
});
let factory = xpcom.Factory({
Component: exports.gcleaner,
description: "hello world",
contract: "#liujiacai.net/gcleaner"
});
var catman = Cc["#mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
catman.addCategoryEntry("content-policy", "speeding.gcleaner", factory.contract, false, true);
Thanks!
I have a sdk module which does this here
https://github.com/jetpack-labs/pathfinder/blob/master/lib/redirect.js
I am trying to run Jasmine inside PhantomJS. After a lot of effort I am down to:
page.injectJs("/jasmine-standalone-2.0.0/lib/jasmine-2.0.0/jasmine.js");
page.injectJs("/jasmine-standalone-2.0.0/lib/jasmine-2.0.0/jasmine-html.js");
page.injectJs("/jasmine-standalone-2.0.0/lib/jasmine-2.0.0/boot.js");
page.injectJs("/jasmine-standalone-2.0.0/lib/jasmine-2.0.0/console.js");
var result = page.evaluate(function (done) {
var ConsoleReporter = jasmineRequire.ConsoleReporter();
var options = {
timer: new jasmine.Timer,
print: function () {
console.log.apply(console, arguments)
}
};
consoleReporter = new ConsoleReporter(options);
jasmine.getEnv().addReporter(consoleReporter);
describe("test1", function () {
console.log("in test 1");
it("should do something", function () {
console.log("NEVER GETS HERE"); // <-- never gets there
});
});
});
The code executes all the way up to it() but the callback never executes :|
[edit]
I'm trying to use phantom with jasmine for end to end testing. I already have an app server and I'm using Karma for unit tests. So I don't think a testRunner.html is going to help. PhantomJS should login to my app and do some stuff, which I will test with Jasmine.
Got it with the dumb luck brute force approach. I never found helpful documentation but this helped a little
My files are like this:
testrunner.js
var system = require("system");
var page = require("webpage").create();
var loginUrl = system.args[1];
page.onConsoleMessage = function (msg) {
console.log("FROM PAGE: " + msg);
};
page.onError = function (err) {
console.log("ERR FROM PAGE: " + JSON.stringify(err));
}
var loggedIn = false;
function onLogin_atHomePage() {
if (loggedIn)
return; // dont run twice if a developer is programatically logging in
page.injectJs("/jasmine-standalone-2.0.0/lib/jasmine-2.0.0/jasmine.js");
page.injectJs("/jasmine-standalone-2.0.0/lib/jasmine-2.0.0/boot.js");
page.injectJs("/jasmine-standalone-2.0.0/lib/jasmine-2.0.0/console.js");
var result = page.evaluate(function (done) {
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
describe("test1", function () {
console.log("in test 1");
it("should do something", function () {
console.log("NEV");
});
});
jasmine.getEnv().execute();
});
}
page.open(loginUrl, function () {
console.log("LOGGING IN...");
page.onLoadFinished = onLogin_atHomePage;
page.evaluate(function () {
$(document).ready(function () {
var $u = $("#login_id");
var $p = $("[name='password']");
$u.val("me");
$p.val("666");
submitForm();
});
});
});
boot.js
/**
Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project.
If a project is using Jasmine via the standalone distribution, this file can be customized directly. If a project is using Jasmine via the [Ruby gem][jasmine-gem], this file can be copied into the support directory via `jasmine copy_boot_js`. Other environments (e.g., Python) will have different mechanisms.
The location of `boot.js` can be specified and/or overridden in `jasmine.yml`.
[jasmine-gem]: http://github.com/pivotal/jasmine-gem
*/
(function() {
/**
* ## Require & Instantiate
*
* Require Jasmine's core files. Specifically, this requires and attaches all of Jasmine's code to the `jasmine` reference.
*/
window.jasmine = jasmineRequire.core(jasmineRequire);
/**
* Since this is being run in a browser and the results should populate to an HTML page, require the HTML-specific Jasmine code, injecting the same reference.
*/
//jasmineRequire.html(jasmine);
/**
* Create the Jasmine environment. This is used to run all specs in a project.
*/
var env = jasmine.getEnv();
/**
* ## The Global Interface
*
* Build up the functions that will be exposed as the Jasmine public interface. A project can customize, rename or alias any of these functions as desired, provided the implementation remains unchanged.
*/
var jasmineInterface = {
describe: function(description, specDefinitions) {
return env.describe(description, specDefinitions);
},
xdescribe: function(description, specDefinitions) {
return env.xdescribe(description, specDefinitions);
},
it: function(desc, func) {
return env.it(desc, func);
},
xit: function(desc, func) {
return env.xit(desc, func);
},
beforeEach: function(beforeEachFunction) {
return env.beforeEach(beforeEachFunction);
},
afterEach: function(afterEachFunction) {
return env.afterEach(afterEachFunction);
},
expect: function(actual) {
return env.expect(actual);
},
pending: function() {
return env.pending();
},
spyOn: function(obj, methodName) {
return env.spyOn(obj, methodName);
},
jsApiReporter: new jasmine.JsApiReporter({
timer: new jasmine.Timer()
})
};
/**
* Add all of the Jasmine global/public interface to the proper global, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`.
*/
if (typeof window == "undefined" && typeof exports == "object") {
extend(exports, jasmineInterface);
} else {
extend(window, jasmineInterface);
}
/**
* Expose the interface for adding custom equality testers.
*/
jasmine.addCustomEqualityTester = function(tester) {
env.addCustomEqualityTester(tester);
};
/**
* Expose the interface for adding custom expectation matchers
*/
jasmine.addMatchers = function(matchers) {
return env.addMatchers(matchers);
};
/**
* Expose the mock interface for the JavaScript timeout functions
*/
jasmine.clock = function() {
return env.clock;
};
/**
* ## Runner Parameters
*
* More browser specific code - wrap the query string in an object and to allow for getting/setting parameters from the runner user interface.
*/
/*var queryString = new jasmine.QueryString({
getWindowLocation: function() { return window.location; }
});
var catchingExceptions = queryString.getParam("catch");
env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions);
*/
/**
* ## Reporters
* The `HtmlReporter` builds all of the HTML UI for the runner page. This reporter paints the dots, stars, and x's for specs, as well as all spec names and all failures (if any).
*/
/*
var htmlReporter = new jasmine.HtmlReporter({
env: env,
onRaiseExceptionsClick: function() { queryString.setParam("catch", !env.catchingExceptions()); },
getContainer: function() { return document.body; },
createElement: function() { return document.createElement.apply(document, arguments); },
createTextNode: function() { return document.createTextNode.apply(document, arguments); },
timer: new jasmine.Timer()
});
*/
/**
* The `jsApiReporter` also receives spec results, and is used by any environment that needs to extract the results from JavaScript.
*/
env.addReporter(jasmineInterface.jsApiReporter);
//env.addReporter(htmlReporter);
/**
* Filter which specs will be run by matching the start of the full name against the `spec` query param.
*/
/*var specFilter = new jasmine.HtmlSpecFilter({
filterString: function() { return queryString.getParam("spec"); }
});
env.specFilter = function(spec) {
return specFilter.matches(spec.getFullName());
};*/
/**
* Setting up timing functions to be able to be overridden. Certain browsers (Safari, IE 8, phantomjs) require this hack.
*/
window.setTimeout = window.setTimeout;
window.setInterval = window.setInterval;
window.clearTimeout = window.clearTimeout;
window.clearInterval = window.clearInterval;
/**
* ## Execution
*
* Replace the browser window's `onload`, ensure it's called, and then run all of the loaded specs. This includes initializing the `HtmlReporter` instance and then executing the loaded Jasmine environment. All of this will happen after all of the specs are loaded.
*/
var currentWindowOnload = window.onload;
window.onload = function() {
if (currentWindowOnload) {
currentWindowOnload();
}
htmlReporter.initialize();
env.execute();
};
/**
* Helper function for readability above.
*/
function extend(destination, source) {
for (var property in source) destination[property] = source[property];
return destination;
}
}());