Jasmine compatibility with jQuery Mobile - javascript

I'm just in the middle of implementing some Jasmine tests for a jQuery mobile application I'm working on, I've run into an error that I managed to track down to adding the jQuery mobile library, the error is as follows:
Jasmine.js:1769 TypeError: Cannot read property 'abort' of undefined.
As soon as I remove the jQM dependency, the error goes away.
This is my code:
<!DOCTYPE html>
<html>
<head>
<title>HTML5/Common/Tests</title>
<!-- LOAD STYLES FIRST -->
<link type="text/css" rel="stylesheet" href="libs/jasmine.css" media="screen">
<link type="text/css" rel="stylesheet" href="../../Common/libs/jquery.mobile-1.0.1.css" />
<!-- LOAD JASMINE LIBRARIES -->
<script type="text/javascript" src="libs/jasmine.js"></script>
<script type="text/javascript" src="libs/jasmine-html.js"></script>
<!-- LOAD DEPENDENCIES -->
<script type="text/javascript" src="../../Common/libs/jquery-1.7.1.min.js"></script>
<script type="text/javascript" src="../../Common/libs/jquery.mobile-1.0.1.min.js"></script>
<!-- LOAD CODE TO TEST -->
<script type="text/javascript" src="../../Common/libs/myLib.js"></script>
<!-- LOAD ACTUAL TESTS -->
<script type="text/javascript">
describe("Suite 1", function() {
it("Should be that 1 equals 0", function() {
expect(0).toEqual(1);
});
});
</script>
</head>
<body>
<script type="text/javascript">
jasmine.getEnv().addReporter(new jasmine.TrivialReporter());
jasmine.getEnv().execute();
</script>
</body>
</html>
I'd prefer to use Jasmine for this application instead of qUnit as I think its more flexible and easier to implement in CI and explain to the BA's and PM's.. however after tinkering with this problem for a couple of hours and some futile searches on google I still havent been able to solve it so I'm starting to consider moving on.
Before I do though, has anyone experienced this same problem and found a solution for it?
Thanks and Regards.
UPDATE 20 March:
Ticket is in github Jasmine project:
https://github.com/pivotal/jasmine/issues/204

I was able to have jasmine test of jquery mobile scripts using jasmine-jquery.
The trick is that you need to disable the jquery mobile enhancement on DOMready because it will try to enhance the html of jasmine runner.
You can do it with this script inserted in the head of the html runner file:
<script type="text/javascript">
$(document).bind("mobileinit", function(){
$.mobile.autoInitializePage = false;
});
</script>
Then you need to trigger the enhancement of jquery mobile on the html inserted from your fixture (the jasmine-jquery functionnality):
describe('my test', function(){
beforeEach(function() {
loadFixtures("fixtures/MYFixture.html");
$("#jasmine-fixtures").attr("data-role","page").trigger("create");
}
it( ...
});

Try disabling both auto-initialization and hash-listening:
<script type="text/javascript">
$(document).bind("mobileinit", function(){
$.mobile.autoInitializePage = false;
$.mobile.hashListeningEnabled = false;
});
</script>
Then add the jqm page to the jasmine-jquery fixture, and initialize the page:
beforeEach(function() {
jasmine.getFixtures().set('<div data-role="page"></div>');
$.mobile.initializePage();
});

Related

JQuery Mobile 1.5.0 loading message

I was using Jquery Mobile 1.3.0. I decided to change and use the new version (1.5.0) due to a bug of the previous version.
When loading the page, a loading text appears on the botttom of the page. In the previous version I used this code, and it worked:
$.mobile.loadingMessage = false;
But, with the new version it doesn't work.
Thanks for your help.
Yes, this has been changed.
You can override the global default setting as below:
<!-- JQM theme shall be loaded before structure -->
<link rel="stylesheet" href="css/jquery.mobile-1.5.0.alpha.theme.css" />
<link rel="stylesheet" href="css/jquery.mobile-1.5.0.alpha.structure.css" />
<script type="application/javascript" src="js/jquery-3.2.1.js"></script>
<script>
$(document).on("mobileinit", function () {
$.mobile.loader.prototype.options.text = "";
$.mobile.loader.prototype.options.textVisible = false;
});
</script>
<script type="application/javascript" src="js/jquery.mobile-1.5.0.alpha.js"></script>
...but later on You still will have the option to show the loader along with a message text as needed:
$.mobile.loading("show", {
text: "foo",
textVisible: true
});
Reference: http://api.jquerymobile.com/loader/

Error: TypeError: $(...).dialog is not a function

I am having an issue getting a dialog to work as basic functionality. Here is my jQuery source imports:
<script type="text/javascript" src="scripts/jquery-1.9.1.js"></script>
<script type="text/javascript" src="scripts/jquery-ui-1.11.1.js"></script>
<script type="text/javascript" src="scripts/json.debug.js"></script>
Html:
<button id="opener">open the dialog</button>
<div id="dialog1" title="Dialog Title" hidden="hidden">I'm a dialog</div>
<script type="text/javascript">
$("#opener").click(function() {
$("#dialog1").dialog('open');
});
</script>
From the posts around seems like as a library import issue. I downloaded the JQuery UI Core, Widget, Mouse and Position dependencies.
Any Ideas?
Be sure to insert full version of jQuery UI. Also you should init the dialog first:
$(function () {
$( "#dialog1" ).dialog({
autoOpen: false
});
$("#opener").click(function() {
$("#dialog1").dialog('open');
});
});
<script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.1/jquery-ui.min.js"></script>
<link rel="stylesheet" href="https://code.jquery.com/ui/1.11.1/themes/smoothness/jquery-ui.css" />
<button id="opener">open the dialog</button>
<div id="dialog1" title="Dialog Title" hidden="hidden">I'm a dialog</div>
if some reason two versions of jQuery are loaded (which is not recommended), calling $.noConflict(true) from the second version will return the globally scoped jQuery variables to those of the first version.
Some times it could be issue with older version (or not stable version) of JQuery files
Solution use $.noConflict();
<script src="other_lib.js"></script>
<script src="jquery.js"></script>
<script>
$.noConflict();
jQuery( document ).ready(function( $ ) {
$("#opener").click(function() {
$("#dialog1").dialog('open');
});
});
// Code that uses other library's $ can follow here.
</script>
If you comment out the following code from the _Layout.cshtml page, the modal popup will start working:
</footer>
#*#Scripts.Render("~/bundles/jquery")*#
#RenderSection("scripts", required: false)
</body>
</html>
Change jQueryUI to version 1.11.4 and make sure jQuery is not added twice.
I just experienced this with the line:
$('<div id="editor" />').dialogelfinder({
I got the error "dialogelfinder is not a function" because another component was inserting a call to load an older version of JQuery (1.7.2) after the newer version was loaded.
As soon as I commented out the second load, the error went away.
Here are the complete list of scripts required to get rid of this problem.
(Make sure the file exists at the given file path)
<script src="#Url.Content("~/Scripts/jquery-1.8.2.js")" type="text/javascript">
</script>
<script src="#Url.Content("~/Scripts/jquery-ui-1.8.24.js")" type="text/javascript">
</script>
<script src="#Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript">
</script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript">
</script>
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript">
</script>
and also include the below css link in _Layout.cshtml for a stylish popup.
<link rel="stylesheet" type="text/css" href="../../Content/themes/base/jquery-ui.css" />
I had a similar problem and in my case, the issue was different (I am using Django templates).
The order of JS was incorrect (I know that's the first thing you check but I was almost sure that that was not the case, but it was). The js calling the dialog was called before jqueryUI library was called.
I am using Django, so was inheriting a template and using {{super.block}} to inherit code from the block as well to the template. I had to move {{super.block}} at the end of the block which solved the issue. The js calling the dialog was declared in the Media class in Django's admin.py. I spent more than an hour to figure it out. Hope this helps someone.

html/javascript sharing script lists... or doing CI with jasmine and selenium

I'm pretty new to js + html. I've set up some (extjs) js based acceptance tests using jasmine and am now looking at getting continuous integration setup for them.
Because they run in browser, there's going to be a bit of mucking about to get them running under CI. What I was thinking of doing was using selenium to run the tests (we've already got a working selenium setup so that should be easy) and using jasmine-reporters to get the results output to a file that CruiseControl.net can understand.
Jasmine is pretty straight-forward in the way it works and you end up writing a html page that looks like this:
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Jasmine Spec Runner v2.0.0</title>
<link rel="shortcut icon" type="image/png" href="lib/jasmine-2.0.0/jasmine_favicon.png">
<link rel="stylesheet" type="text/css" href="lib/jasmine-2.0.0/jasmine.css">
<script type="text/javascript" src="lib/jasmine-2.0.0/jasmine.js"></script>
<script type="text/javascript" src="lib/jasmine-2.0.0/jasmine-html.js"></script>
<script type="text/javascript" src="lib/jasmine-2.0.0/boot.js"></script>
<script type="text/javascript">
//set this a bit higher to aid debugging
jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000;
</script>
<!-- include source files here... -->
<script type="text/javascript" src="Sample/src/Player.js"></script>
<script type="text/javascript" src="Sample/src/Song.js"></script>
<script type="text/javascript" src="/native/WeatherVane.js"></script>
<script type="text/javascript" src="/native/EventCreator.js"></script>
<script type="text/javascript" src="/ext/ext-all-dev.js"></script>
<script type="text/javascript" src="/api/api.js"></script>
<script type="text/javascript">
Ext.app.REMOTING_API.maxRetries = 0;
Ext.direct.Manager.addProvider(Ext.app.REMOTING_API);
</script>
<!-- include spec files here... -->
<script type="text/javascript" src="Sample/spec/SpecHelper.js"></script>
<script type="text/javascript" src="Sample/spec/PlayerSpec.js"></script>
<script type="text/javascript" src="Tests/EventCreation.js"></script>
<!-- note this needs to be last as it fires up the tests-->
<script type="text/javascript" src="TestApp.js"></script>
I've not actually got round to stripping out the sample tests yet!
Anyway the easiest way I could see of doing this would be to another page which uses a different TestApp (the last entry) which configures jasmine to use the nunitreporter from the jasmine-reporters library and just get selenium to run that page
Obviously I dont want to just copy + paste everything in there and modify just the last bit. This is going to be a list we're going to be adding to a lot and it's going to be a real pain if the CI and local testing aren't working basically the same way.
Basically what I'd like to do is effectively split it into two documents/sets of includes like this:
Document A - the shared setup
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Jasmine Spec Runner v2.0.0</title>
<link rel="shortcut icon" type="image/png" href="lib/jasmine-2.0.0/jasmine_favicon.png">
<link rel="stylesheet" type="text/css" href="lib/jasmine-2.0.0/jasmine.css">
<script type="text/javascript" src="lib/jasmine-2.0.0/jasmine.js"></script>
<script type="text/javascript" src="lib/jasmine-2.0.0/jasmine-html.js"></script>
<script type="text/javascript" src="lib/jasmine-2.0.0/boot.js"></script>
<script type="text/javascript">
//set this a bit higher to aid debugging
jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000;
</script>
<!-- include source files here... -->
<script type="text/javascript" src="Sample/src/Player.js"></script>
<script type="text/javascript" src="Sample/src/Song.js"></script>
<script type="text/javascript" src="/native/WeatherVane.js"></script>
<script type="text/javascript" src="/native/EventCreator.js"></script>
<script type="text/javascript" src="/ext/ext-all-dev.js"></script>
<script type="text/javascript" src="/api/api.js"></script>
<script type="text/javascript">
Ext.app.REMOTING_API.maxRetries = 0;
Ext.direct.Manager.addProvider(Ext.app.REMOTING_API);
</script>
<!-- include spec files here... -->
<script type="text/javascript" src="Sample/spec/SpecHelper.js"></script>
<script type="text/javascript" src="Sample/spec/PlayerSpec.js"></script>
<script type="text/javascript" src="Tests/EventCreation.js"></script>
Document B - the current browser output method:
SomeCommandToInclude(documentA);
<!-- note this needs to be last as it fires up the tests-->
<script type="text/javascript" src="TestApp.js"></script>
Document C - the CI/xml output method:
SomeCommandToInclude(documentA);
<!-- note this needs to be last as it fires up the tests-->
<script type="text/javascript" src="XmlOutputApp.js"></script>
I've felt myself wanting to do something very similar a few times with these html script lists. How do you do this? Is it even possible? I was looking at some stuff to do with document.write a while ago but it didn't seem to do quite do the right thing.
If it's not possible to include these script lists in each other, I'm open to other approaches for getting the CI going, although I have a pretty strong preference for doing it with selenium as I dont want to learn yet another library/technology and spend ages fiddling to get it working.
Here's what I did. I didn't figure out how to include html files but I got something working.
Basic approach
I passed in a parameter in the url which says whether we are in CI mode. The client side testing library parses the url to check if it should create xml output. Because this is run in-browser by selenium it can't be saved directly to file. Instead I wrote it into a string and then query this string from Selenium and from there write it out to disc.
Jasmine-reporters
Jasmine-reporters has been forked to cope with jasmine-2.0 which I am using note that the 2.0 branch is not the main branch. I'm not familiar with git and was thrown by it hiding the other branch from you in the history. There is a compatible version of jasmine-reporters there.
I used the NUnit reporter and to faciliate use with selenium I did a massive hack and replaced the write file method with the following:
self.writeFile = function(text) {
self.output(text, totalSpecsFailed > 0);
};
I also added this to the constructor:
self.output = options.output;
My calling/config code then does this if we are in CI mode:
var jasmineEnv = jasmine.getEnv();
jasmineEnv.addReporter(new jasmineReporters.NUnitXmlReporter(
{
output: function (xmlOutput, anyFailures) {
testConfig.xmlOutput = xmlOutput;
testConfig.anyFailures = anyFailures;
}
}));
Selenium
The selenium code looks like this (note this isn't raw selenium - it's going through an API I've wrapped around the basic stuff but you should be able to get the gist)
public void PokeTheTestPage()
{
try
{
NavigateTo(WebAppUrl + "Tests/Jasmine/SpecRunner.html?outputFile=true");
var error = Driver.GetStringWith("return weatherVane.testConfig.errorText;");
if (error != "")
ExitWithError(error);
var testOutput = LongWait.Until(d => d.GetStringWith("return weatherVane.testConfig.xmlOutput;"));
var failed = Driver.GetBoolWith("return weatherVane.testConfig.anyFailures;");
using (var file = File.OpenWrite(_outputFile))
using (var writer = new StreamWriter(file))
writer.Write(testOutput);
if (failed)
ExitWithError("tests failed");
}
catch (Exception e)
{
ExitWithError(e.ToString());
}
}
private void ExitWithError(string error)
{
Console.WriteLine("got Error:");
Console.WriteLine(error);
Driver.Close();
Environment.Exit(1);
}
}

jQuery multiple versions noConflict in IE

I have a javascript widget that I wrote using jQuery 1.8 that loads on a clients website that uses jQuery 1.3. I cannot get noConflict working properly in IE without some really ugly hacks. Here is what the page looks like after my widget is rendered:
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.3.min.js"></script>
</head>
<html>
<body>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
<script>
$jq = $.noConflict();
</script>
</body>
</html>
In chrome, this works great, $jq is defined as jQuery 1.8.3, but in IE 8 this does not work, $jq is defined as jQuery 1.3. My guess is that its a timing issue, the script gets executed before the new jQuery is loaded. I put in some call back timers and it works, but I cant imagine having embedded callback timers is the right way to go.
Any ideas?
EDIT
I cannot namespace jQuery1.3, the client uses it throughout the page and does not want to upgrade.
<!-- load jQuery 1.5 -->
<script type="text/javascript" src="http://foo.com/jquery-1.5.js"></script>
<script type="text/javascript">
var jQuery_1_5 = $.noConflict(true);
</script>
<!-- load jQuery 1.6 -->
<script type="text/javascript" src="http://foo.com/jquery-1.6.js"></script>
<script type="text/javascript">
var jQuery_1_6 = $.noConflict(true);
</script>
in this case -
use
jQuery_1_6(document).ready(function($) {
// Code using $ as usual goes here.
});
instead of
jQuery(document).ready(function($) {
// Code using $ as usual goes here.
});
see here - http://blog.nemikor.com/2009/10/03/using-multiple-versions-of-jquery/
I ended up going with LABjs, which is a javascript loader. This way I can synchronously load scripts and execute code on them accordingly:
<script>
$LAB
.script("framework.js").wait()
.script("plugin.framework.js")
.script("myplugin.framework.js")
.wait(function(){
myplugin.init();
framework.init();
framework.doSomething();
});
</script>

phonegap plugin: Torch undefined, even though js file is loaded on android

I get the following error when trying to use the TorchPluging:
file:///android_asset/www/web/index.html: Line 12 : Uncaught TypeError: Cannot read property 'Torch' of undefined
I added the plugin to config.xml (I think it has changed from plugins.xml to config.xml in the newer phonegap versions?)
The following is my entire index.html
<!DOCTYPE HTML>
<html>
<head>
<title>Flashlight</title>
<script type="text/javascript" charset="utf-8" src="js/cordova-2.1.0.js"></script>
<script type="text/javascript" charset="utf-8" src="js/jquery-1.8.2.min.js"></script>
<script type="text/javascript" charset="utf-8" src="js/Torch.js"></script>
<script type="text/javascript" charset="utf-8" src="js/bootstrap.min.js"></script>
<script type="text/javascript">
function turnTorchOn(){
window.plugins.Torch.turnOn(
function() { console.log( "turnOn" ) } // success
, function() { console.log( "error" ) }); // error
}
</script>
</head>
<body>
<button id="turnOnButton" name="turnOnButton" > Turn on Flashlight</button>
<script>
$('#turnOnButton').click(function(){
alert("will turn on now");
turnTorchOn();
alert("called turnOn done");
});
</script>
</body>
</html>
It actually isn't that hard to update an older style plugin to one that will work in 2.0.0+. You would need to:
Modify the JS to the new cordova.define() style of declaring plugins.
Update the package reference to org.apache.cordova.* from com.phonegap.* in the Java code.
Make sure you are not calling any deprecated API's.
I've written a couple of blog posts that cover the topic. If you do follow them an update the Torch plugin you should submit a pull request so everyone can enjoy your work.
2.0.0 Plugin - http://simonmacdonald.blogspot.ca/2012/08/so-you-wanna-write-phonegap-200-android.html
Deprecated API's - http://simonmacdonald.blogspot.ca/2012/07/phonegap-android-plugins-sometimes-we.html

Categories

Resources