I'm using Jasmine to test a backbone app, which works fine in the browser, but when I run it using grunt-contrib-jasmine via phantomjs it chokes on:
var myVar = myCollection.get('myModel').get('myAttribute');
which throws an error:
Testing jasmine specs via phantom
>> TypeError: 'undefined' is not an object (evaluating 'myCollection.get('myModel').get')
but the strange thing is this works just fine if I break it up like this:
var mdl = myCollection.get('myModel');
var myVar = mdl.get('myAttribute');
Is this a bug in phantom or am I missing something in the way I'm writing the code?
Seems like since it works in the browser it's a phantom problem.
The problem turned out to be much bigger than I realize. It's rather complex to explain and frankly doesn't relate at all to this question. Consider this question dead.
Related
So, I was transitioning code from windows to linux today to make sure everything works. I managed to break casper/phantom and I'm not even sure how.
Here's my command that runs a casper script on linux (ubuntu 12.14):
/usr/bin/casperjs /var/www/tekalyze/phantom/get_site_info.js --jquery-path="/var/www/tekalyze/js/jquery-1.10.2.min.js" --uri-path=" /var/www/tekalyze/phantom/URI.js" --log-path="/var/www/tekalyze/phantom/casper.log" --data-url=http://tekalyze.com/ajax.php --id='19' --url='http://www.bk.com/?utm_source=LOCATIONiq&utm_medium=locallstgs&utm_campaign=2013' --log-level=debug
It's giving me this:
TypeError: 'undefined' is not an object (evaluating 'requireDirs.forEach')
in module (./get_all_urls:102)
/var/www/tekalyze/phantom/get_all_urls.js:102 in _require
/var/www/tekalyze/phantom:13 in anonymous
/home/casper/casperjs/bin/bootstrap.js:146 in _require
/var/www/tekalyze/phantom/get_site_info.js:8
/var/www/tekalyze/phantom/get_site_info.js:228
line 102 of get_all_urls is:
crawl.call(this, links[currentLink]);
I've tried commenting it out, and the stack trace remains the same, which leads me to believe it's not related.
The relevant file can be found here.
I'm honestly just scratching my head. I looked at bootstrap.js:146 and saw something about phantom.casperPath, but I hadn't had to set an environment variable in windows, so I'm not sure about this for linux. The relevant line is this: if (!phantom.casperPath) -- which leads me to believe I could get this to work if I re-write everything to start from phantom first, then set all of the casper variables, but I haven't verified whether or not that will work yet.
Also, I used this script to install them both, so the directories should be set up correctly.
It turns out this functionality isn't added until 1.1.0-DEV, so updating to that instead of using 1.0.0 on linux is the best solution.
I have set up jasmine tests for my app. In my app I have javascript that shouldn't work in IE8 :
var foo = Object.create(Array.prototype);
When I run mvn jasmine:bdd and I open the test page in Internet Explorer (with browserMode set to Internet Explorer 8), it fails as expected:
TypeError: Object doesn't support property or method 'create'
However, when I run:
mvn jasmine:test -DbrowserVersion=INTERNET_EXPLORER_8
All of my tests are successful. The logs specify that the browserVersion is set to INTERNET_EXPLORER_8.
I expected both to give me the same result. This is causing an issue with our ci testing since it has let out js errors that I wanted to catch.
Should this be working as I'm expecting and if not, what should I change?
Also, this is the best way I know how to test multiple browsers. Is there a better way that I'm missing?
EDIT
A coworker has tried to dash my hopes that the browserVersion wouldn't even catch such an error and suggested that it was only meant to change the header so that the tests could cover browser specific javascript as well (blocks of code that only run when the browser is a specific version). Is this accurate?
It seems very accurate that the jasmine tests browserVersion property does not change the internals of how the js is run, meaning that the quirks or each browser will not be tested. I have successfully transitioned to using js-test-driver for my tests which can run jasmine tests on actual browsers. This looks to be the right way to do this. Although if you're starting new down this path, I'd look at Karma instead (previously named testacular, and built as an improvement on js-test-driver).
I've got a project that I'd like to move the testing from rhino to nodejs for (rhino simply takes too long to start and load in envjs). This is the current blocker before being able to move forward:
ExampleSingleton = new function () {
var something = someFunction () {/*Does something*/}
$(window).bind('resize', something);
}();
This complains about window not being defined - I don't know how to get the 'window' that I made in the shell (#!/usr/bin/env node) script that I wrote (see below, and pardon the chaos, as I've gotten to that "try anything and everything" point).
var dom = require("jsdom").jsdom()
var window = global.window = dom.createWindow();
global.jQuery = require("jQuery");
global.$ = global.jQuery;
....
require("path/to/file"); //This is where it breaks, before the tests even start
I've tried reading in and eval'ing as well, but that didn't much help and of course the error was masked because it was an anonymous function.
Am I trying to do the impossible here? Or is there a very simple browser friendly thing I can do to get this working?
Have you thought about using PhantomJS instead of node?
PhantomJS is a headless WebKit with JavaScript API. It has fast and
native support for various web standards: DOM handling, CSS selector,
JSON, Canvas, and SVG.
PhantomJS is an optimal solution for fast headless testing, site
scraping, pages capture, SVG renderer, network monitoring and many
other use cases.
Because it is a real browser, you won't need jsdom or envjs. JavaScript continuous testing with QUnit, PhantomJS and Powershell might help you get started.
I just started doing some Javascript work for a project, I do mostly backend work so I'm sorry for being new at this! Also, not using a Javascript framework because I want to learn about the fundamentals before making everything very easy for myself :)
So, here is my question/confusion: I wrote a little javascript that dynamically changed forms. This is how I called the code:
// loads the initial box
window.onload = initList(environment_box);
// loads artifacts on each change to environment select box
environment_box.onchange = changeList;
This worked like magic - in CHROME that is! I never noticed it wasn't working in Firefox (its just an internal tool, so I can assume decent browsers, but I figure hey, if its working in Chrome, it will work in Firefox!). So, I did some investigation, and it seems as though the code isnt getting executed in Firefox. I whipped out firebug and wanted to see what was going on.
The interesting thing was, when I enabled Console on firebug, my code got executed! I am very confused as to why, and I would much appreciate any help I could get. Thanks!
-Shawn
You are calling some method on console in your JavaScript is my best guess. Chrome has console defined be default, so it is not a problem.
On Firefox, however, there is no such global object (not without Firebug), so when you try to call a property on an undefined object like,
console.log(..);
it throws an exception which you are not catching, so the JavaScript execution halts.
You're probably calling a method of the console object which just doesn't exist by default in most web browsers. It may be always available on webkit based browsers (like Chrome) but with firefox/IE(/opera?) it requires an external add-on, either firebug or a javascript dependency.
Checkout things like firebugx which simply defines the most common methods of a console object as no-op functions.
I just spent half an one our to find out what caused the Error-Message "Ci is not defined" in my JavaScript code. I finally found the reason:
It should be (jQuery):
$("asd").bla();
It was:
("asd").bla();
(Dollar sign gone missing)
Now after having fixed the problem I'd like to understand the message itself: What does Firefox mean when it tells me that "Ci" is not defined. What's "Ci"?
Update:
I'm using the current version of Firefox (3.0.3).
To reproduce, just use this HTML code:
<html><head><title>test</title>
<script>
("asd").bla();
</script>
</head><body></body></html>
To make it clear: I know what caused the error message. I'd just like to know what Firefox tries to tell me with "Ci"...
I don't know which version of FF you are using, but regardless, the message is probably referring to the fact that bla() is not a function available on the String object. Since you were missing the $, which means you were missing a function, ("asd") would evaluate to a string, and then the JavaScript interpreter would try to call bla() on that object. So, if you had the following code in your project:
String.prototype.bla = function() {};
// now this next line will execute without any problems:
("asd").bla();
So, it is possible that Ci is some internal Firefox symbol that simply refers to the idea of a function. That is my guess, I imagine you are going to need someone that knows something about Firefox's internals to get a better answer to this question...
UPDATE: I am running your example code in the exact same version of FF as you are, but it reports the error as:
Error: "asd".bla is not a function
Source File: file:///C:/test.html
Line: 3
Perhaps you have an extension/plug-in running that does something with this? Maybe some Greasemonkey script or something?
Jason seems to be right. Many plugins (e.g. Firebug, Geode) use Ci as a shortcut:
const Ci = Components.interfaces;
So the plugins seem to cause that strange error message.
Assuming it's CodeIngiter, it can't find the js file.