requirejs shim deps not working in zombie #555

Closed
ShijunK opened this Issue Aug 1, 2013 · 5 comments

Projects

None yet

6 participants

ShijunK commented Aug 1, 2013

I am using cumber-js with zombie to test a web app. The web app itself uses requirejs to load Raphael and gRapael for vector graph. Everything works well in the browsers I tested (safari 6.0.5, firefox 20.0). However, when I run my cucumber feature to drive zombie browser, I got exception log from zombie "Raphael is not defined ReferenceError: Raphael is not defined".

Zombie: Opened window http://localhost:8080 
Zombie: GET http://localhost:8080/ => 200
Zombie: Loaded document http://localhost:8080/
Zombie: GET http://localhost:8080/js/plugins.js => 200
Zombie: GET http://localhost:8080/js/vendor/modernizr-2.6.2.min.js => 200
Zombie: GET http://localhost:8080/js/require.js => 200
Zombie: GET http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js => 200
Zombie: Fired timeout after 4ms delay
Zombie: Fired timeout after 4ms delay
Zombie: Fired timeout after 4ms delay
Zombie: GET http://localhost:8080/js/main.js => 200
Zombie: Fired timeout after 4ms delay
Zombie: Fired timeout after 4ms delay
Zombie: Fired timeout after 4ms delay
Zombie: Fired timeout after 4ms delay
Zombie: Fired timeout after 4ms delay
Zombie: GET http://localhost:8080/js/lib/raphael.js => 200
Zombie: Fired timeout after 50ms delay
Zombie: GET http://localhost:8080/js/vendor/raphaeljs/g.raphael.js => 200
Raphael is not defined ReferenceError: Raphael is not defined
    at <anonymous>:26:1

Per the debug logging, it seems that Zombie honors the order of loading from requirejs (please see the dependency defined vis shim config below), however, the interpret and execution does not, the "g.raphael.js" seems be interpreted and executed before raphael.js. Though, it is only my guess.

questions:

  • does Zombie execute javascripts in the same order of loading?
  • is there a way to make Zombie more verbose, i.e. tells the order of javascripts execution?
require.config({
    baseUrl: 'js/lib', //including raphael.js ver 2.1.0 
    paths: {
        "graphael": "../vendor/raphaeljs/g.raphael",
        "gbar": "../vendor/raphaeljs/g.bar",
        "gline": "../vendor/raphaeljs/g.line"
    },
    shim: {
        "graphael": {
            deps: ['raphael'],
            exports: 'gRaphael'
        },
        "gbar": {
            deps: ['graphael'],
            exports: 'gBar'
        },
        "gline": {
            deps: ['graphael'],
            exports: 'gLine'
        }
    }
});

Reproduction, in three lines or less

var zombie = require('zombie');
var browser = new zombie();
browser.visit("http://helmetrevolution.com/en/science")

Stack Trace

Cannot read property 'svg' of undefined TypeError: Cannot read property 'svg' of undefined
    at <anonymous>:10:54539
    at Contextify.sandbox.run (/myrepo/node_modules/zombie/node_modules/jsdom/node_modules/contextify/lib/contextify.js:12:24)
    at Object.window._evaluate (/myrepo/node_modules/zombie/lib/zombie/window.js:187:25)
    at Object.HTML.languageProcessors.javascript (/myrepo/node_modules/zombie/lib/zombie/scripts.js:23:21)
    at Object.define.proto._eval (/myrepo/node_modules/zombie/node_modules/jsdom/lib/jsdom/level2/html.js:1475:47)
    at Object.loaded (/myrepo/node_modules/zombie/lib/zombie/scripts.js:74:23)
    at /myrepo/node_modules/zombie/node_modules/jsdom/lib/jsdom/level2/html.js:73:20
    at Object.item.check (/myrepo/node_modules/zombie/node_modules/jsdom/lib/jsdom/level2/html.js:345:11)
    at Object.item.check (/myrepo/node_modules/zombie/node_modules/jsdom/lib/jsdom/level2/html.js:348:23)
    at Object.item.check (/myrepo/node_modules/zombie/node_modules/jsdom/lib/jsdom/level2/html.js:348:23)
Raphael is not defined ReferenceError: Raphael is not defined
    at <anonymous>:302:1
    at Contextify.sandbox.run (/myrepo/node_modules/zombie/node_modules/jsdom/node_modules/contextify/lib/contextify.js:12:24)
    at Object.window._evaluate (/myrepo/node_modules/zombie/lib/zombie/window.js:187:25)
    at Object.HTML.languageProcessors.javascript (/myrepo/node_modules/zombie/lib/zombie/scripts.js:23:21)
    at Object.define.proto._eval (/myrepo/node_modules/zombie/node_modules/jsdom/lib/jsdom/level2/html.js:1475:47)
    at Object.loaded (/myrepo/node_modules/zombie/lib/zombie/scripts.js:74:23)
    at /myrepo/node_modules/zombie/node_modules/jsdom/lib/jsdom/level2/html.js:73:20
    at Object.item.check (/myrepo/node_modules/zombie/node_modules/jsdom/lib/jsdom/level2/html.js:345:11)
    at Object.item.check (/myrepo/node_modules/zombie/node_modules/jsdom/lib/jsdom/level2/html.js:348:23)
    at Object.item.check (/myrepo/node_modules/zombie/node_modules/jsdom/lib/jsdom/level2/html.js:348:23)
slickmb commented Dec 10, 2013

Problem is that zombie fails Rapheal's tests for SVG and VML, so it breaks early (before window.Raphael is set) with a semi-silent error.

//from raphael.js -- in zombie, this doesn't pass, so type gets set to "VML"
R.type = (g.win.SVGAngle || g.doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") ? "SVG" : "VML");
    if (R.type == "VML") {
        var d = g.doc.createElement("div"),
            b;
        d.innerHTML = '<v:shape adj="1"/>';
        b = d.firstChild;
        b.style.behavior = "url(#default#VML)";

        //in zombie, this doesn't pass either, so Raphael breaks out early without setting the window.Raphael object.
        if (!(b && typeof b.adj == "object")) {
            return (R.type = E);
        }
        d = null;
    }
slickmb commented Dec 10, 2013

The following horrible hack got my test working again. Keep in mind that Raphael was not a critical component of the test I was working on. This hack just gets Raphael to load and does not guarantee proper functionality.

var path = require('path'),
    browser = require(path.resolve(require.resolve("zombie"), "../../../node_modules/jsdom/lib/jsdom/browser/index")),
    jsdom = require(path.resolve(require.resolve("zombie"), "../../../node_modules/jsdom/lib/jsdom")),
    createWindow = browser.createWindow;

jsdom.createWindow = browser.createWindow = function () {
    var window = createWindow.apply(this, arguments);
    window.window.SVGAngle = {};
    return window;
};
Sorbing commented Jan 21, 2014

My site is also used a RequireJS (of client-side). Could this be the reason that the event domReady does not fire on site page?

@assaf assaf closed this Sep 25, 2014

I have the same problem. How to fix this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment