Why does the zombie.js browser return empty HTML when using Bootstrap?
Asked Answered
Q

1

11

I'm trying to test my Node.js/Express.js application using Mocha and Zombie. I can get simple tests to pass, but as soon as I add the script tags for Twitter Bootstrap to my views, the browser object returns empty HTML.

Here is my test code:

process.env.NODE_ENV = 'test';

var app = require('../app');
var assert = require('assert');
var Browser = require('zombie');

describe('home page', function() {
before(function() {
    this.server = app.listen(3000);
    this.browser = new Browser({site: 'http://localhost:3000', debug : true});
});

it('should show welcome', function(done) {
    var browser = this.browser;
    browser
        .visit("/")
        .then(function() {
            console.log(browser.html());
        })
        .fail(function(error) {
            console.log("Error: ", error);
        })
        .then(done);
});

after(function(done) {
    this.server.close(done);
});
});

The view code (my layout.jade file):

doctype 5
html
  head
    title= title
    link(rel='stylesheet', href='/stylesheets/style.css')
    script(src='/javascripts/jquery-2.0.3.min.js')
    script(src='/javascripts/bootstrap.min.js')
  body
    .navbar.navbar-inverse.navbar-fixed-top
      .container
        .navbar-header
          button.navbar-toggle(type='button', data-toggle='collapse', data-target='.navbar-collapse')
            span.icon-bar
            span.icon-bar
            span.icon-bar
          a.navbar-brand(href='/') Contact Database
        .collapse.navbar-collapse
          ul.nav.navbar-nav
            li.active
              a(href='/') Home
            li.active
              a(href='/contacts') Contacts
  block content

If I remove the script tags, the HTML is logged to the console as expected. Otherwise, I get empty HTML returned.

The debug output:

home page
◦ should show welcome: Zombie: Opened window http://localhost:3000/ 
GET / 200 283ms - 1018b
Zombie: GET http://localhost:3000/ => 200
Zombie: Loaded document http://localhost:3000/
GET /javascripts/bootstrap.min.js 200 4ms - 27.08kb
Zombie: GET http://localhost:3000/javascripts/jquery-2.0.3.min.js => 200
Zombie: GET http://localhost:3000/javascripts/bootstrap.min.js => 200
GET /javascripts/jquery-2.0.3.min.js 200 41ms - 81.65kb
<html></html>
Zombie: Event loop is empty
✓ should show welcome (414ms)

It appears that the problem might have to do with timing. The document is loaded, then the Javascript files are loaded. I'm wondering if zombie is executing my callback function before the Javascript is loaded, therefore the DOM is empty at that point. Any ideas?

Update:

This was solved by wprl's suggestion below.

Here is the test that works, after adding a wait function:

it('should show welcome', function(done) {

    // Wait until page is loaded
    function pageLoaded(window) {
        return window.document.querySelector(".container");
    }

    var browser = this.browser;
    browser.visit("/");
    browser.wait(pageLoaded, function() {
        console.log(browser.html());
    });
    done();
});

I'll have to rewrite my test logic a bit now, but the key to getting it to work was the wait function.

Queenstown answered 30/9, 2013 at 18:31 Comment(0)
K
9

It does sound like timing might be an issue. On the other hand, Zombie is good about giving you control only after JavaScript events have stopped when using visit.

A good strategy to use is to browser.wait for a certain DOM element to appear before proceeding with your tests. That way you know e.g. Bootstrap has loaded and shown element #widget-view.

Might want to adjust maxWait/waitFor as well.

At least then you could rule out the timing issue.

Kinin answered 30/9, 2013 at 19:22 Comment(1)
That worked great! I'll edit my post to show the updated test code. Thanks!Queenstown

© 2022 - 2024 — McMap. All rights reserved.