The opening shoot the breeze

Originally, I wanted to enhance pocket-tool by adding the chain writing method, but after I used the previous function, there was a bug. I just remembered that the unit test for DOM operation had not been written before, so I just made up the unit test for this part first. Indeed, it was completed, but there are still some regrets. Next, I will first analyze the ideas of this DOM module unit test, and then talk about the shortcomings.

Start with requirements

To unit test the DOM, one of the most basic requirements is to get a Document object, but Mocha runs in a Node environment and there is no Document object in Node, so to start getting document, I initially thought that someone had already implemented this feature in Node. So I followed this line of thought to find a few.

  1. jsdom
  2. cheerio
  3. mocha – browser support
  4. phantomjs

The way to find these four is to read the official documents, such as Mocha, the test of various open source projects, such as jquery, and the Cheerio I used. One of the regrets is that when I see jquery test, I just glance at it or go straight to find out how they got the Document. I always ignore their running mode and find that it is also running on the browser side. Next, we will give a brief introduction to these four.

Then the function is analyzed

jsdom

A JavaScript implementation of the WHATWG DOM and HTML Standards for use with Node.js One provides Javascript that implements WHATWG DOM and HTML standards on Node.js. WHATWG is an organization that looks like what I need, and then how the API is called

const jsdom = require("jsdom");
const { JSDOM } = jsdom;Copy the code

Yeah, it looks a little bit like that. Keep watching

const dom = new JSDOM(`<! DOCTYPE html><p>Hello world</p>`); console.log(dom.window.document.querySelector("p").textContent); // "Hello world"Copy the code
const { window } = new JSDOM(`... `); // or even const { document } = (new JSDOM(`... `)).window;Copy the code

By passing in an HTML string and then generating an instance. At this point, it doesn’t seem to meet my needs. I can’t inject window into my project because it’s actually a forgery, so the node object I get may not be the actual Document object, which will affect my final test. So, just give up.

cheerio

The official description is Fast, flexible, and lean implementation of core jQuery designed Specifically for the server. In fact, it is similar to JsDOM, except that it is jquery-centric, which means that it can be evaluated in the way jQuery operates. Now look at how the API is called

const cheerio = require('cheerio') const $ = cheerio.load('<h2 class="title">Hello world</h2>') $('h2.title').text('Hello there! ') $('h2').addClass('welcome') $.html() //=> <h2 class="title welcome">Hello there! </h2>Copy the code

It’s pretty much the same as Jsdom, well, it didn’t meet my needs either, but I used it to develop a tool for screening useless classes, which was poorly written and didn’t follow up on the features, so I won’t post it now. It works pretty well. According to the understanding of Jsdom and Cheerio above, we can find that we can’t actually use a simulated Document object, but a real document object, so we shift our thinking to the browser side.

mocha – browser support

Mocha can also be installed via Bower (Bower install Mocha), and is available at CDNJS. Mocha runs in the browser. Every release of Mocha will have new builds of./mocha.js and./mocha.css for use in the browser. This means that Mocha can run in the browser, so I don’t need to run Mocha in the Node environment. I just need to write mocha and run it in the browser

< link href = "https://cdn.rawgit.com/mochajs/mocha/2.2.5/mocha.css" rel = "stylesheet" / > < script SRC = "https://cdn.rawgit.com/jquery/jquery/2.1.4/dist/jquery.min.js" > < / script > < script SRC = "https://cdn.rawgit.com/Automattic/expect.js/0.3.1/index.js" > < / script > < script SRC = "https://cdn.rawgit.com/mochajs/mocha/2.2.5/mocha.js" > < / script >Copy the code

In view of our domestic situation, or through Bower to install the above several tools jquery, Mocha, I use the assertion library should, you can choose what you like. Then add mocha’s methods, as well as the js file of the test unit

< div id = "mocha" > < / div > < script SRC = "https://cdn.rawgit.com/jquery/jquery/2.1.4/dist/jquery.min.js" > < / script > < script SRC = "https://cdn.rawgit.com/Automattic/expect.js/0.3.1/index.js" > < / script > < script SRC = "https://cdn.rawgit.com/mochajs/mocha/2.2.5/mocha.js" > < / script > < script > mocha. Setup (' BDD) < / script > < script src="test.array.js"></script> <script src="test.object.js"></script> <script src="test.xhr.js"></script> <script> mocha.checkLeaks(); mocha.globals(['jQuery']); mocha.run(); </script>Copy the code

Here are the official call methods, my own is similar, or look at the official clearer, when you are all configured, openhtmlFile is good, so you can see a page like this



Ok, so it’s running successfullydocumentIt’s unit-tested, but that’s not good enough if I’m going to joinCIHow do I run it from the command line and exit when it doesn’t work? So I kept looking, and I found itphantomjsI’ve heard about it before, but I haven’t used it before.

phantomjs

PhantomJS is a headless WebKit scriptable with a JavaScript API. It has fast and native support for various Web pages standards: DOM handling, CSS selector, JSON, Canvas, and SVG. It, in fact is like a page in the browser, there are many powerful features, I haven’t explore, interested students can go to their official website to see here first temporarily borrow a shell, of course, this is not enough, because running is still running, no response, not because of some cases to go off and throw an error, And then mocha-PhantomJS-Core. Ok, that’s it. Let’s start integrating.

And then finally integrate

Let’s set up what we need

Bower install mocha should.js --save-dev // Install mocha and should assertion library NPM install Phantomjs -g // Install phantomjs NPM install Mocha-phantomjs-core -d install mocha-Phantomjs-coreCopy the code

Create an index.html and introduce the tools you need

<! DOCTYPE html> <html lang="en"> <head> <title>DOM DEMO</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href=".. /.. /bower_components/mocha/mocha.css" rel="stylesheet" /> </head> <body> <div id="mocha"></div> <script src=".. /.. /bower_components/should.js/should.js"></script> <script src=".. /.. /bower_components/mocha/mocha.js"></script> <script src=".. /.. /bower_components/jquery/dist/jquery.min.js"></script> <! <script SRC =".. /.. /dist/pocket-tool.js"></script> <! This is the script I want to test --> <script> mocha.setup(' BDD ') // How to use BDD </script> <! <script SRC ="./test/getElement. Js "></script> <script SRC ="./test/ addclass.js "></script> <script src="./test/removeClass.js"></script> <script src="./test/on.js"></script> <script src="./test/off.js"></script> <script  src="./test/getDataSet.js"></script> <script src="./test/chain.js"></script> <! -- / This is my use case --> <script> mocha.run(); </script> </body> </html>Copy the code

The entry is done, and the unit test cases are written the samemochaThe same if you want to supportes6Just reintroducebabel-polyfillIt’ll be ok. So once you’ve done that, how do you run it, test it on the command linephantomjs ./node_modules/mocha-phantomjs-core/mocha-phantomjs-core.js ./test/phantomjs/index.html spec '{\"useColors\":true}'Through themocha-phantomjs-coreThe way to run behindindex.htmlWhen everything goes well



All this is so familiar. At this time topackage.jsonthescriptJust add it

"scripts": {
	"test:phantomjs": "phantomjs ./node_modules/mocha-phantomjs-core/mocha-phantomjs-core.js ./test/phantomjs/index.html spec '{\"useColors\":true}'",
}Copy the code

This one is missing

Because I had two parts in my project, one was using Mocha in NodeJS and the other was phantomjs, and I wanted to combine the two to facilitate CI. So I found karma but it was hard to integrate. I don’t know if it was my posture. Finally, use the package.js script for the combination

"scripts": { "test": "npm run test:mocha && npm run test:phantomjs", "test:mocha": "npm run dist && mocha test/mocha", "test:phantomjs":"phantomjs ./node_modules/mocha-phantomjs-core/mocha-phantomjs-core.js ./test/phantomjs/index.html spec  '{\"useColors\":true}'" }Copy the code

The result is exactly what I want, but then I have to add the coverage statistics, which is a pain. I’m using Istanbul here, which works for nodeJS

istanbul cover _mocha test/mocha"Copy the code

Mocha-phantomjs + Mocha-Phantomjs-istanbul, but mocha-Phantomjs-istanbul doesn’t work. It’s a little bit complicated, and I want to find a way, Integrate the two solutions.

conclusion

This time, still can be only run on phantomjs coverage cannot be computed, and then there is no through karam will integrate the two, it seems to continue after a unit test road, I think the unit test before there is no necessary, but is a tool for the function in the upgrade, is glad before write the unit tests, There will be no serious repercussions. By the way, if you want to have a good plan, please leave a message and talk about it with me.