admin管理员组

文章数量:1278978

How do I read in a page from localhost into a headless Jasmine spec so test cases can work on the DOM elements?

My Gulp task is successfully running Jasmine specs for unit testing, and now I need to build integration tests to verify full web pages served from localhost. I'm using the gulp-jasmine-browser plugin to run PhantomJS.

Example:

gulpfile.js

var gulp =           require('gulp');
var jasmineBrowser = require('gulp-jasmine-browser');

function specRunner() {
   gulp.src(['node_modules/jquery/dist/jquery.js', 'src/js/*.js', 'spec/*.js'])
      .pipe(jasmineBrowser.specRunner({ console: true }))
      .pipe(jasmineBrowser.headless());
   }

gulp.task('spec', specRunner);


spec/cart-spec.js

describe('Cart ponent', function() {

   it('displays on the gateway page', function() {
      var page = loadWebPage('http://localhost/');  //DOES NOT WORK
      var cart = page.find('#cart');
      expect(cart.length).toBe(1);
      });

   });

There is no loadWebPage() function. It's just to illustrate the functionality I believe is needed.

How do I read in a page from localhost into a headless Jasmine spec so test cases can work on the DOM elements?

My Gulp task is successfully running Jasmine specs for unit testing, and now I need to build integration tests to verify full web pages served from localhost. I'm using the gulp-jasmine-browser plugin to run PhantomJS.

Example:

gulpfile.js

var gulp =           require('gulp');
var jasmineBrowser = require('gulp-jasmine-browser');

function specRunner() {
   gulp.src(['node_modules/jquery/dist/jquery.js', 'src/js/*.js', 'spec/*.js'])
      .pipe(jasmineBrowser.specRunner({ console: true }))
      .pipe(jasmineBrowser.headless());
   }

gulp.task('spec', specRunner);


spec/cart-spec.js

describe('Cart ponent', function() {

   it('displays on the gateway page', function() {
      var page = loadWebPage('http://localhost/');  //DOES NOT WORK
      var cart = page.find('#cart');
      expect(cart.length).toBe(1);
      });

   });

There is no loadWebPage() function. It's just to illustrate the functionality I believe is needed.

Share Improve this question edited Apr 5, 2017 at 4:33 Dem Pilafian asked Nov 17, 2016 at 4:23 Dem PilafianDem Pilafian 6,0166 gold badges43 silver badges69 bronze badges 6
  • Are you looking for PhantomJS's page.open method? – Gerrit0 Commented Nov 24, 2016 at 4:52
  • 4 If what you are doing is trying to use Jasmine to navigate around and follow links, you might want to think about moving to a secondary framework, like Zombie and/or Selenium. – BobGneu Commented Nov 24, 2016 at 6:18
  • @Gerrit0 Yeah, I've seen page.open and it does the right thing, but it's a PhantomJS module with no obvious way to call it from a Jasmine spec. If you know how, please tell. – Dem Pilafian Commented Nov 24, 2016 at 7:46
  • @Bob_Gneu Selenium requires Java, so it's definitely out. PhantomJS is generally considered to be able to do everything Zombie.js can do (but the browser emulation in Zombie.js is supposed to be faster than the headless WebKit in PhantomJS). – Dem Pilafian Commented Nov 24, 2016 at 8:03
  • webdriver.io is a selenium driver for node. Pretty sure you don't need to bother with any Java code for this to be used. – BobGneu Commented Nov 24, 2016 at 8:14
 |  Show 1 more ment

3 Answers 3

Reset to default 3

End-to-End testing frameworks like a Selenium, WebdriverIO, Nightwatch.js, Protractor and so on are more suitable in such case.

The gulp-jasmine-browser plugin still is about the Unit testing in the browser environment. It is not possible to navigate between pages.

I put together the following code that appears to work. Please feel free to check out my repo and confirm in your own environment.

package.json

{
  "name": "40646680",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "gulp jasmine"
  },
  "devDependencies": {
    "gulp": "^3.9.1",
    "gulp-jasmine-browser": "^1.7.1",
    "jasmine": "^2.5.2",
    "phantomjs": "^2.1.7"
  }
}

gulpfile.js

(() => {
    "use strict";

    var gulp = require("gulp"),
        jasmineBrowser = require("gulp-jasmine-browser");

    gulp.task("jasmine", () => {
        return gulp.src("test/*.js")
            .pipe(jasmineBrowser.specRunner({
                console: true
            }))
            .pipe(jasmineBrowser.headless());
    });
})();

test/sampleJasmine.js

describe("A suite", function() {
    it("contains spec with an expectation", function() {
        expect(true).toBe(true);
    });
    it("contains failing spec with an expectation", function() {
        expect(true).toBe(false);
    });
});

Execution

Bob Chatman@CHATBAG42 F:\Development\StackOverflow\40646680
> npm test

> [email protected] test F:\Development\StackOverflow\40646680
> gulp jasmine

[21:56:44] Using gulpfile F:\Development\StackOverflow\40646680\gulpfile.js
[21:56:44] Starting 'jasmine'...
[21:56:44] Jasmine server listening on port 8000
.F
Failures:
1) A suite contains failing spec with an expectation
1.1) Expected true to be false.

2 specs, 1 failure
Finished in 0 seconds
[21:56:49] 'jasmine' errored after 4.26 s
[21:56:49] Error in plugin 'gulp-jasmine-browser'
Message:
    1 failure
npm ERR! Test failed.  See above for more details.

Dependencies

node 7.2
npm 3.9.3
jasmine 2.5.2
phantomjs 2.1.7 
gulp 3.9.1

jsdom to the rescue!

It turns out it's pretty easy to load a web page into a headless Jasmine spec... but you need to swap out PhantomJS for jsdom.

Strategy:

  1. Use Jasmine's beforeAll() to call a function that will run JSDOM.fromURL() to request the web page.
  2. Once the web page has been loaded into the DOM, expose window and jQuery for use in your test cases.
  3. Finally, call done() to indicate the tests are now ready to run.

Make sure to close the window after the tests have run.

spec.js

const url  = 'http://dnajs/';
const { JSDOM } = require('jsdom');
let window, $;
function loadWebPage(done) {
   function handleWebPage(dom) {
      function waitForScripts() {
         window = dom.window;
         $ = dom.window.jQuery;
         done();
         }
      dom.window.onload = waitForScripts;
      }
   const options = { resources: 'usable', runScripts: 'dangerously' };
   JSDOM.fromURL(url, options).then(handleWebPage);
   }
function closeWebPage() { window.close(); }

describe('The web page', () => {

   beforeAll(loadWebPage);
   afterAll(closeWebPage);

   it('has the correct URL', () => {
      expect(window.location.href).toBe(url);
      });

   it('has exactly one header, main, and footer', () => {
      const actual =   {
          header: $('body >header').length,
          main:   $('body >main').length,
          footer: $('body >footer').length
          };
      const expected = { header: 1, main: 1, footer: 1 };
      expect(actual).toEqual(expected);
      });

   });


Test output


Note: Above screenshot is from a similar Mocha spec since Mocha has a nice default reporter.

Project

It's on GitHub if you want try it out yourself:
https://github./dnajs/load-web-page-jsdom-jasmine


EDITED: Updated for jsdom 11

本文标签: javascriptLoad a web page into a headless Jasmine spec running PhantomJSStack Overflow