htmlchecker
Think about it as unit-test applied to HTML. We use CSS selector to get DOM elements and then we can execute tests if we find them.
This tool can have multiple applications, including:
- Checking if your HTML respect basic rules for accessibility (for attribute, alt attribute on img etc.).
- Checking if your HTML respect the requirements of your javascript components (no missing elements or no missing attributes).
- Ensure that code changes done in the HTML are done everywhere in your project (not just on the page you are working).
- Ensure that HTML pattern that you don't want are not in your projects (no more .l-left, .l-right in a mobile first project).
installation
npm install --save-dev htmlchecker
Usage
In your package.json, you can create a script
{ scripts: { "test:html": "HTMLChecker" } }
Then you need to create a module to set up your tests in htmlChecker.js:
var config = { "specs": function(suite, check){ suite.add('label', function(selector){ check.hasAttr(selector , 'for'); check.hasMatchingFor(selector); }); }, "pages": [ { "name": "My example", "url": "http://localhost:5001" } ], "forbiddenSelectors": [ ".test1", ".test2" ] } module.exports = config;
specs
Function that registers the tests. When called, it passes 2 arguments:
- suite: The suite object where the test is registered.
- check: The testing framework.
Pages
An array of locations. Each location has 2 properties:
- name: the name of the page.
- url: the url of the page.
Ex:
{ "name": "My example", "url": "http://localhost:5001" }
ForbiddenSelectors
An array of selectors you DO NOT want to see on your pages (ex: mispelled classes, deprecated classes or combination of classes).
Ex:
"forbiddenSelectors": [ ".test1", ".test2" ]
Will fail the test with:
Blah <!-- Fails -->
or:
Blah <!-- Fails -->
You can also have more complex selectors:
"forbiddenSelectors": [ ".test1 .test2" ]
Will fail if you have:
Blah <!-- Fails -->
Alternate configuration.
You may have several configuration files in your project. Here is what you can do in your package.json:
{ scripts: { "test:html": "HTMLChecker --config=alternateConfig.js" } }
Where alternateConfig.js could be:
var config = { "specs": function(suite, check){ suite.add('label', function(selector){ check.hasAttr(selector , 'for'); check.hasMatchingFor(selector); }); }, "pages": [ { "name": "My example", "url": "http://staging.myProject.com" } ] } module.exports = config;
Docs
Writing a test
In the htmlChecker.js, all tests should be written in the specs section:
var config = { "specs": function(suite, check){ suite.add('<selector>', function(moduleSelector){ // tests matching the selector are written here }); }, ... } module.exports = config;
Example of tests
Testing children
check.testHasChildren(moduleSelector, childSelector);
Ex:
suite.add('.my-selector', function(moduleSelector){ check.testHasChildren(moduleSelector, '.my-child-selector'); });
Returns true if:
Testing only one child
check.testHasOnlyOneChild(moduleSelector, childSelector);
Ex:
suite.add('.my-selector', function(moduleSelector){ check.testHasOnlyOneChild(moduleSelector, '.my-child-selector'); });
Returns true if:
Returns false if:
Testing empty attribute
check.testHasEmptyAttribute(moduleSelector, attributeName);
Ex:
suite.add('.my-img-selector', function(moduleSelector){ check.testHasEmptyAttribute(moduleSelector, 'alt'); });
Returns true if:
Testing attribute value
check.testOneOfAttributeValue(selector, attributeName, arrayAttributesValue);
Ex:
suite.add('input.my-input', function(moduleSelector){ check.testHasAttributeNotMatching(moduleSelector, 'type', ['checkbox', 'radio']); });
Testing attribute not matching regex
check.testHasAttributeNotMatching(selector, attributeName, regularExpression)
Ex:
suite.add('.my-selector', function(moduleSelector){ check.testHasAttributeNotMatching(moduleSelector, 'my-attr', /^\[.*\]$/); });
Testing attribute matching regex
check.testHasAttributeMatching(selector, attributeName, regularExpression)
Ex:
suite.add('.my-selector', function(moduleSelector){ check.testHasAttributeMatching(moduleSelector, 'my-attr', /^\[.*\]$/); });
Testing class
check.testHasClass(selector, className);
Ex:
suite.add('button', function(moduleSelector){ check.testHasClass(moduleSelector, 'btn'); });
Returns true if:
Ready
Testing one of class
check.testHasOneOfThoseClass(selector, classList);
Ex:
suite.add('.my-selector', function(moduleSelector){ check.testHasOneOfThoseClass(selector, ['class1','class2','class3']); });
Returns true for all the example below: