Jasmine UI automation - jasmine

I have set up my jasmine framework using the steps mentioned here, but when I try to use jasmine keywords like browser.open to open a URL in the Browser I get an error browser not defined. When I use require to get another page, it gives Reference error: module not found.
Also, with my jasmine package, I did not get the specRunner.html.
I have tried installing protractor also and different approaches, but it's not working.
I need to set up jasmine framework for UI automation, can anyone help me with the exact set up and issues that I am facing right now?

The jasmine library is not related to browser automation. It is a library about testing. It does not define the browser object. I'm not sure which library you expect to require. Perhaps you want to use Selenium. In particular, you will want to look at the WebDriver API.
It allows you to do things like this:
var driver = new webdriver.Builder().build();
driver.get('http://www.google.com');
var element = driver.findElement(webdriver.By.name('q'));
element.sendKeys('Cheese!');
element.submit();
driver.getTitle().then(function(title) {
console.log('Page title is: ' + title);
});
driver.wait(function() {
return driver.getTitle().then(function(title) {
return title.toLowerCase().lastIndexOf('cheese!', 0) === 0;
});
}, 3000);
driver.getTitle().then(function(title) {
console.log('Page title is: ' + title);
});
driver.quit();

Related

How to set a sessionStorage in Cypress?

I need to change the value of one of the parameters in the sessionStorage but I'm not even sure if this is possible through Cypress. Couldn't find any useful information about this in their documentation.
This is the javascript code that I'm trying to run with Cypress without any success:
var data = JSON.parse(sessionStorage.getItem("vuex"))
data.country = "DE"
sessionStorage.setItem("vuex", JSON.stringify(data))
It works perfectly fine if I execute it in the console but I don't know how to make it work with Cypress.
Even if I write a simple javascript code like
console.log(sessionStorage.getItem("vuex"))
It returns Null with Cypress.
Does anyone have any idea why I am getting null for this javascript code and if this operation is even possible with Cypress?
Found the solution:
cy.window().then( win => {
var data = JSON.parse(sessionStorage.getItem("vuex"))
data.country = "DE"
sessionStorage.setItem("vuex", JSON.stringify(data))
})

How to use Jest to test React rendered async data?

I am using React for render and Jest/Jasmine for test. I have test written using old Jest/Jasmine waitsFor and runs but these are gone now in Jasmine 2 and I am not sure how to replace with new done asyncs.
In my code React renders a small page about a user. That page has an AJAX call to fetch user posts. I want to test that user posts have come back nice, and waitsFor was very, very good at this: wait until user has some post, then continue.
I looked online at lots of people talking about using AJAX calls inside Jest test which is not what I want. My Jest test has no idea about AJAX call being made, so I need a way to wait until results come back.
Here is my current code with waitsFor and runs:
it('loads user post', () => {
var page = TestUtils.renderIntoDocument(
<UserPage params={{user: 'fizzbuzz', 'pass': 'xxx'}} />
);
waitsFor(() => {
return page.state.posts.length > 0;
}, "post loaded", 10000);
runs(() => {
var posts = TestUtils.scryRenderedDOMComponentsWithClass(page, 'post');
expect(posts.length).toEqual(10);
});
});
How can I delete the waitsFor and runs and replace with Jasmine 2.0 code that works? All Jest test knows is that page.state.posts.length must be greater than 0 before expecting anything.
You should refactor this test into two unit tests that will provide a more rigorous testing of your code. It would make the tests more independent of one another and help identify errors in a more refined scope. These won't be exact as I do not know what your code is like, but here's something along the lines I would expect to see: -
it('generates the expected properties for a page', function () {
var page = TestUtils.renderIntoDocument(
<UserPage params={{user: 'fizzbuzz', 'pass': 'xxx'}} />
);
expect(page.someProperty).toBeDefined();
expect(page.user).toEqual('fizzbuzz');
});
it('generates the correct number of posts from a given page object', function () {
var fakePage = {
// put your fake mock data here that TestUtils expects
};
var posts = TestUtils.scryRenderedDOMComponentsWithClass(fakePage, 'post');
expect(posts.length).toEqual(10);
});
I am not too sure what is happening in your renderIntoDocument function so the top test may be a little broken... It looks like there is either too much going on inside the function, or you need to test the calls that function is making instead. If you elaborate on what it does I'll edit the answer.

Sinon JQuery selectors mock

I am trying to test a function using mocha/sinonjs. The function I want to test is responsible for showing or hiding some element in my DOM.
This is my function
var updateUI = function() {
$('#login').show();
$('#logout').hide();
};
I tried to mock using sinon but I'm not sure if it is possible or the correct thing to do in this case.
This is what I have tried but I keep getting an error "TypeError: undefined is not a function" during the expect call
var mockLogin = sinon.mock($);
mockLogin.withArgs('#login').expects("show").once();
I simple want to test my 2 jquery calls have been called. I tried to use spies but continue to get exceptions
Looking further into the sinon doc I found that the following worked for me.
var jQueryShow = sinon.stub($.fn, 'show');
var jQueryHide = sinon.stub($.fn, 'hide');
jQueryShow.callCount.should.be.equal(1);
jQueryShow.thisValues[0].selector.should.be.equal("#login");
jQueryHide.callCount.should.be.equal(1);
jQueryHide.thisValues[0].selector.should.be.equal("#logout");
I'm not sure if there an easier way but it checks for the selectors I need

What are the recommended ways to debug Worklight applications?

I'm finding it incredibly slow to fix issues that are specific to the iOS portion of my app. I'd like the know the recommended way to debug Worklight apps when the browser debugger isn't available.
In particular, I'm working on issues with WL.JSONStore which only works on iOS and Android. I can't use the browser debugger to see what's going on. When I do WL.Logger.debug() statements, nothing is showing up in the Xcode console, and the iPad simulator console (Cordova) only displays a few lines. There have also been periods this week that no output is printed anywhere.
I have downloaded and installed Weinre too, but none of the print statements appear to show up in its console and in general I just don't see information about the areas I need.
Thanks in advance for your suggestions.
General Worklight 5.0.6 Debugging
Look at the training module titled Debugging your applications. (Direct PDF link)
Debug Tips for JSONStore on Worklight 5.0.6
Try console.log('message') or WL.Logger.debug('message') inside jsonstore.js and your code ([app-name].js, etc.). The output should show up in Xcode's console and Android's LogCat.
Reset the Simulator or Emulator and/or call WL.JSONStore.destroy().
Make sure you're running on a supported environment:
Android >=2.2 ARM/x86 Emulator or Devices
iOS >=5.0 Simulator or Device
Try turning encryption off (ie. do not pass a password to WL.JSONStore.init or WL.JSONStore.initCollection).
Look at the SQLite Database file generated by JSONStore. This only works if encryption is off.
Android:
$ adb shell
$ cd /data/data/com.[app-name]/databases/wljsonstore
$ sqlite3 jsonstore.sqlite
iOS
$ cd ~/Library/Application Support/iPhone Simulator/6.1/Applications/[id]/Documents/wljsonstore
$ sqlite3 jsonstore.sqlite
Try looking at the searchFields with .schema and selecting data with SELECT * FROM [collection-name];. To exit sqlite3 type .exit. Take a look at this StackOverflow question for an example.
(Android Only) Enable verbose JSONStore.
adb shell setprop log.tag.jsonstore-core VERBOSE
adb shell getprop log.tag.jsonstore-core
(iOS >=6.0 and Safari >=6.0 Only) Try to use the JavaScript debugger. Set break points inside jsonstore.js. Helpful lines:
Bridge to Native code:
cdv.exec(options.onSuccess, options.onFailure, pluginName, nativeFunction, args);
Success Callbacks returning from Native code:
deferred.resolve(data, more);
Failure Callbacks returning from Native code:
deferred.reject(new ErrorObject(errorObject));
Write Proper Tests (Unit, Functional, Integration -- get test coverage). Here's a template that uses QUnit and Sinon.js to create a Sandbox environment where you can test how JSONStore handles different types of data/calls:
<!DOCTYPE HTML>
<html>
<head>
<title>JSONStore Test App</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.11.0.css">
<script src="http://code.jquery.com/qunit/qunit-1.11.0.js"></script>
<script src="http://sinonjs.org/releases/sinon-1.6.0.js"></script>
<script>
//QUnit configuration flags, no need to change it.
QUnit.config.requireExpects = true;
</script>
</head>
<body id="content" style="display: none;">
<!-- Test results will be appended to the div below, no need to make changes here. -->
<div id="qunit"></div>
<script>
//Start Worklight
WL.Client.init({connectOnStartup : false});
//Hook into the deviceready event
document.addEventListener("deviceready", onDeviceReady, false);
//onDeviceReady will be called when JSONStore/Cordova is ready
function onDeviceReady () {
//Auto executing function that holds the test
(function (jQuery) { //The variable jQuery is usable inside.
//Mock WL.Client.invokeProcedure using a Stub.
//This is only useful if you need to link a Worklight Adapter
//to a JSONStore collection to reproduce your issue or bug.
//API Doc: http://sinonjs.org/docs/#stubs
var fakeAdapter = sinon.stub(WL.Client, "invokeProcedure", function (invocationData, options) {
//DO NOT Create a real adapter, just mock the reponse here if it's relevant to the bug.
var ADAPTER_RESPONSE = {invocationResult: {fakeKey: [{fn: 'carlos'}, {fn: 'mike'}]}};
options.onSuccess(ADAPTER_RESPONSE);
});
//[**Explain your test here**]
var EXPECTED_ASSERTIONS = 2; //every assertion is a deepEqual below.
asyncTest('[**Meaningful title here**]', EXPECTED_ASSERTIONS, function () {
//Destroy first to make sure we don't depend on state
WL.JSONStore.destroy()
.then(function () {
//[**Start writting your test here**]
//The test below is an example, it does the following:
// - Initializes a collection linked to a fake adapter (see stub above).
// - Checks if initialization worked by checking the collection name.
// - Loads data from the fake adapter (see stub above).
// - Checks if load worked by checking the number of documents loaded.
var collections = {
col1 : {
searchFields : {fn: 'string'},
adapter : {name: 'fakeAdapter',
load: {
procedure: 'fakeProcedure',
params: [],
key: 'fakeKey'
}
}
}
};
return WL.JSONStore.init(collections);
})
.then(function (response) {
//Prep for your assertion
var ACTUAL_VALUE = response.col1.name;
var EXPECTED_VALUE = 'col1';
var COMMENT = 'Checking for the right collection name';
//Do your assertion using deepEqual
//API Doc: http://api.qunitjs.com/deepEqual/
deepEqual(ACTUAL_VALUE, EXPECTED_VALUE, COMMENT);
return WL.JSONStore.get('col1').load();
})
.then(function (response) {
//Prep for your assertion
var ACTUAL_VALUE = response; //load returns number of documents loaded
var EXPECTED_VALUE = 2; //two documents are returned by the fake adapter (stub)
var COMMENT = 'Checking if load worked';
//Do the assertion using deepEqual
deepEqual(ACTUAL_VALUE, EXPECTED_VALUE, COMMENT);
start();//call start() after you finish your test succesfully
})
.fail(function (error) {
deepEqual(false, true, 'Failure callback should not be called' + error.toString());
start();//call start() after you finish your test with a failure
});
});
}(WLJQ)); //end auto executing function that holds the test
} //end wlCommonInit
</script>
</body>
</html>
Expected output of the code above:
Side-note: Here's a general article about the PhoneGap/Cordova workflow for a specific developer. There's a part of debugging, just browser-based though. Some of it applies to IBM Worklight development too.
cnandreu provides great tips here. Still, visibility is pretty poor and these approaches didn't really solve my problem. I would like to also suggest what I've found to be most useful in my project (aside from WL.Logger.debug() everywhere):
JSConsole has been indispensable (http://jsconsole.com/). In reality, I don't actually use it that much like it's intended. However, I've found that it's startup warning message does something with WL.Logger.debug() (and console.log()) that enables the statements to actually print to the console so I can see what I'm doing.
In iOS 6 Safari on the Mac lets you inspect the DOM of an attached device. It's moderately useful, especially for hybrid UI issues that only are misbehaving when running natively on iOS. I don't find it super helpful otherwise. See more at https://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/DebuggingSafarioniPhoneContent/DebuggingSafarioniPhoneContent.html
The single most useful technique I've been using has been to write status messages to the UI. Yes, it's an ugly prehistoric way to do things, but everything else - including 80s error print statements to the console - have failed miserably. Here's what I do (using Dojo & JavaScript):
var v = dom.byId('audio_status');
if (v) { v.innerHTML += "recording file ["+filename+"]"; }
Where audio_status is the ID of a DIV that displays the debug content.
This stuff is ugly, but at least we can see something.

How can I dynamically change kendo.mobile.Application's loading property?

I am developing a mobile web app using Kendo UI Mobile. Whenever we make any AJAX calls, or our DataSources make them we call app.startLoading() to show the loading icon to the user. This works very well.
However, depending on the context in which the call is made we would like to change the text that is displayed along with the loading icon. I know you can define this when I create the kendo.mobile.Application instance. How can I change it afterwards?
The documentation does not suggest a way to do this, and a browse of the source code did not help me either. Is this really not possible?
EDIT: This is using Kendo UI Mobile v.2012.3.1114
I usually make a "utility" function to do this:
var _kendoApp = new kendo.mobile.Application(document.body, {});
var showLoading = function (message) {
_kendoApp.loading = "<h1>" + (message ? message : "Loading...") + "</h1>";
_kendoApp.showLoading();
};
I am also setting a default message of "Loading..." if one isn't passed in.
Edit:
I could have sworn that worked for me in a past app I did, but judging by thr source, I think you are right, my answer above shouldn't work. My best suggestion is to add a class to the message element so you can target it, and use jQuery to change the text.
var _kendoApp;
var showLoading = function (message) {
$(".loading-message").text(message ? message : "Loading...");
_kendoApp.showLoading();
};
_kendoApp = new kendo.mobile.Application(document.body, {
loading: '<h1 class="loading-message">Loading...</h1>'
});

Resources