How to test JavaScript with DOM elements using jas

2020-07-25 10:17发布

I am trying to write a test in jasmine for JavaScript code including DOM elements which doesn't work. It works when I test only for JavaScript code (just simple functions but not for DOM elements). I have been researching for so long and can't really find the answer. I also tried to use jsdom as it's supposed to be used when testing for DOM elements, however I keep getting a bunch of errors. Is there any 'easy' way to test DOM elements only using jasmine?

JavaScript:

var result;
var adding = function(one, two) {
    var one1 = document.forms["myForm"]["one"].value;
    var two1 = document.forms["myForm"]["two"].value;
    result = parseInt(one1) + parseInt(two);
    var number = document.getElementById("number");
    number.innerHTML = result;
    return result;
}

HTML:

<html>

<head> </head>

<body>
    <form name="myForm">
        <h4>numner 1</h4> <input type="text" name="one" id="one"></input>
        <h4>number 2</h4> <input type="text" name="two" id="two"></input> <input type="submit" onclick="adding(one.value, two.value); return false;"> </form>
    <p id="number"> </p>
</body>

</html>

my test specs:

describe("additions", function() {
    it("result should add two numbers", function() {
        var final = adding(5, 1);
        expect(final).toEqual(6);
    });
})

For the test I'm getting always:

Cannot read property 'one' of undefined.

I know that

var one1 = document.forms["myForm"]["one"].value;
var two1 = document.forms["myForm"]["two"].value;

looks strange in this example, but my actual code was much bigger (I didn't want to post the entire code as it's not necessary for my question) and it was necessary so I had to include it here (perhaps it affects the testing).

2条回答
趁早两清
2楼-- · 2020-07-25 10:53

There HAS to be an environment where your js will execute.

  • Browser
  • Node

You can run your test in Browser using Karma(or you can find similar test runners). Karma executes the HTML/JS/Jasmine-Test-JS in a real browser like Chrome/IE/Firefox/Safari OR a headless browser like PhantomJS. You can also take advantage of jquery selectors here.

You can run your test in Node using JSDOM. Here a virtual DOM is created in-memory. You can use Cheerio to get a jquery like behaviour if you want to run selectors.

import {expect} from 'chai';
import jsdom from 'jsdom';
import fs from 'fs';

describe('index.html', ()=>{
  it('should have h1 that says Users', (done)=>{
    const index = fs.readFileSync('./src/index.html', "utf-8");
    jsdom.env(index, function(err, window){
      if(err){
        console.log(err);
      }
      else{
        const h1 = window.document.getElementsByTagName('h1')[0];
        expect(h1.innerHTML).to.equal("Users");
        done();
        window.close();
      }
    })
  })
})

To run test in Node, you will have to bring in the html content in a variable and initialize jsdom. Refer the example to see how a window object gets into picture by jsdom.

查看更多
走好不送
3楼-- · 2020-07-25 11:00

I had the same problem with document being 'undefined' plus problem with using ES6 (SyntaxError: Unexpected token import).

I used jasmine with babel and jsdom.

Jasmine can run test in Node or/and browser. I guess using Node version is more universal.

My solution:

jasmine.json

{
    "spec_dir": "spec",
    "spec_files": [
        "**/*[sS]pec.js"
    ],
    "helpers": [
        "../node_modules/babel-register/lib/node.js",   // load babel first to use ES6 'import' and other features
        "helpers/**/*.js"

    ],
    "stopSpecOnExpectationFailure": false,
    "random": true
}

testHelper.js

import jsdom from 'jsdom';
import fs from 'fs';

const index = fs.readFileSync('./static/index.html', 'utf-8');
const { JSDOM } = jsdom;

const { document } = (new JSDOM(index)).window;
global.document = document;

With above setup you can use 'document' in your tests.

PS: Above is not full babel setup. See babel documentation or other posts for that.

查看更多
登录 后发表回答