html-inspector
Advanced tools
Comparing version 0.4.1 to 0.5.0
// Safe to assume arguments here | ||
var basePath = phantom.args[0], | ||
baseVersion = phantom.args[1], | ||
inspectLocation = phantom.args[2], | ||
configFile = phantom.args[3] | ||
var basePath = phantom.args[0] | ||
, inspectLocation = phantom.args[1] | ||
, configFile = phantom.args[2] | ||
var system = require('system'), | ||
page = require('webpage').create() | ||
var system = require('system') | ||
, page = require('webpage').create() | ||
var injectVersions = { | ||
full: [''], | ||
core: ['.core'], | ||
convention: ['.core', '.convention'], | ||
'best-practices': ['.core', '.best-practices'], | ||
validation: ['.core', '.validation'] | ||
page.onCallback = function(data) { | ||
if (data && data.sender && data.sender == "HTMLInspector") { | ||
console.log(data.message) | ||
} | ||
} | ||
page.onAlert = system.stdout.write | ||
page.onClosing = function() { | ||
phantom.exit() | ||
} | ||
page.onError = function(msg) { | ||
console.error(msg) | ||
phantom.exit() | ||
} | ||
page.onLoadFinished = function(status) { | ||
@@ -28,27 +32,30 @@ | ||
var hasInspectorScript = page.evaluate(function() { | ||
return 'HTMLInspector' in this | ||
return window.HTMLInspector | ||
}) | ||
if(!hasInspectorScript) { | ||
injectVersions[baseVersion].forEach(function(version) { | ||
page.injectJs(basePath + '/dist/html-inspector' + version + '.js') | ||
}) | ||
if (!hasInspectorScript) { | ||
page.injectJs(basePath + '/dist/html-inspector.js') | ||
} | ||
if(configFile) { | ||
page.evaluate(function() { | ||
HTMLInspector.defaults.onComplete = function(errors) { | ||
window.callPhantom({ | ||
sender: "HTMLInspector", | ||
message: errors.map(function(error) { | ||
return "[" + error.rule + "] " + error.message | ||
}).join("\n") | ||
}) | ||
window.close() | ||
} | ||
}) | ||
if (configFile) { | ||
page.injectJs(configFile) | ||
} else { | ||
page.evaluate(function() { | ||
HTMLInspector.inspect() | ||
}) | ||
} | ||
page.injectJs(basePath + '/bin/phantom-bridge.js') | ||
page.evaluate(function() { | ||
HTMLInspector.inspect({ | ||
onComplete: function onComplete(errors) { | ||
sendMessage('htmlinspector.complete', errors) | ||
} | ||
}) | ||
}) | ||
phantom.exit() | ||
} | ||
page.open(inspectLocation) |
{ | ||
"name": "html-inspector", | ||
"version": "0.4.1", | ||
"version": "0.5.0", | ||
"main": "dist/html-inspector.js", | ||
@@ -15,2 +15,2 @@ "ignore": [ | ||
] | ||
} | ||
} |
@@ -1,8 +0,11 @@ | ||
### 0.5.0 (Unreleased) | ||
### 0.5.0 (August 31, 2013) | ||
* Add `excludeRules` option. | ||
* Convert HTML Inspector to be built with Browserify. | ||
* Rename the `exclude` option to `excludeElements`. | ||
* Rename the `excludeSubtree` option to `excludeSubtrees`. | ||
* Remove the setConfig method as it was overwriting previous setConfigs if there were multiple calls. | ||
* Improve the CLI and allow for async error reporting via the config file. | ||
* Convert HTML Inspector to be built with Browserify and released as a UMD module. | ||
* Convert tests from Jasmine to Mocha, Sinon, and Chai. | ||
* Use Mout for JavaScript utility functions. | ||
* Abstract DOM utility functions to dom-utils package. | ||
* Remove the custom builds in favor better rule inclusion/exclusion options. | ||
@@ -9,0 +12,0 @@ ### 0.4.1 (July 10, 2013) |
{ | ||
"name": "html-inspector", | ||
"title": "HTML Inspector", | ||
"version": "0.4.1", | ||
"version": "0.5.0", | ||
"description": "HTML Inspector is a code quality tool to help you and your team write better markup. It's written in JavaScript and runs in the browser, so testing your HTML has never been easier.", | ||
@@ -6,0 +6,0 @@ "license": "MIT", |
112
README.md
@@ -10,7 +10,6 @@ # HTML Inspector | ||
5. [Overriding Rules Configurations](#overriding-rule-configurations) | ||
6. [Custom Builds](#custom-builds) | ||
7. [Browser Support](#browser-support) | ||
8. [Running the Tests](#running-the-tests) | ||
9. [Contributing](#contributing) | ||
10. [FAQs](#faqs) | ||
6. [Browser Support](#browser-support) | ||
7. [Running the Tests](#running-the-tests) | ||
8. [Contributing](#contributing) | ||
9. [FAQs](#faqs) | ||
@@ -31,5 +30,12 @@ HTML Inspector is a highly-customizable, code quality tool to help you (and your team) write better markup. It aims to find a balance between the uncompromisingly strict W3C validator and having absolutely no rules at all (the unfortunate reality for most of us). | ||
Alternatively, [Bower](https://github.com/bower/bower) users can install HTML Inspector with the following command: | ||
It can also be install via [NPM](https://npmjs.org/) or [Bower](https://github.com/bower/bower): | ||
```sh | ||
# NPM (for command line usage) | ||
npm install -g html-inspector | ||
# View the CLI options | ||
htmlinspector --help | ||
# Bower (for browser usage) | ||
bower install html-inspector | ||
@@ -58,6 +64,7 @@ ``` | ||
- **useRules**: (Array) a list of rule names to run when inspecting | ||
- **domRoot**: (selector | element) the DOM element to start traversing from | ||
- **exclude**: (selector | element | Array) any DOM element that matches the selector, element, or list of selectors/elements will be excluded from traversal (note: its descendants will still be traversed). | ||
- **excludeSubTree**: (selector } element | Array) the descendants of any DOM element that matches the selector, element, or list of selectors/elements will be excluded from traversal. | ||
- **useRules**: (Array) a list of rule names to run when inspecting. Defaults to running all rules not excluded via `excludeRules` | ||
- **excludeRules**: (Array) a list of rule names **not** to run when inspecting. If `useRules` and `excludeRules` are both set, the excluded rules are removed from the list of rules to use. | ||
- **excludeElements**: (selector | element | Array) any DOM element that matches the selector, element, or list of selectors/elements will be excluded from traversal (note: its descendants will still be traversed). | ||
- **excludeSubTrees**: (selector | element | Array) the descendants of any DOM element that matches the selector, element, or list of selectors/elements will be excluded from traversal. | ||
- **onComplete**: (Function) the callback to be invoked when the inspection is finished. The function is passed an array of errors that were reported by individual rules. | ||
@@ -69,6 +76,7 @@ | ||
config: { | ||
domRoot: "html", | ||
useRules: null, | ||
domRoot: "html", | ||
exclude: "svg", | ||
excludeSubTree: ["svg", "iframe"], | ||
excludeRules: null, | ||
excludeElements: "svg", | ||
excludeSubTrees: ["svg", "iframe"], | ||
onComplete: function(errors) { | ||
@@ -86,6 +94,5 @@ errors.forEach(function(error) { | ||
HTMLInspector.inspect({ | ||
useRules: ["some-rule-name", "some-other-rule-name"], | ||
domRoot: "body", | ||
exclude: "iframe", | ||
excludeSubTree: ["svg", "template"], | ||
excludeRules: ["some-rule-name", "some-other-rule-name"], | ||
excludeElements: ["svg", "iframe"], | ||
onComplete: function(errors) { | ||
@@ -120,2 +127,26 @@ errors.forEach(function(error) { | ||
Each rule is registered via a unique string identifier that can be used to include or exclude it at inspection time. | ||
Here is the full list of built in rules by their identifiers: | ||
```sh | ||
# validation rules | ||
validate-elements | ||
validate-element-location | ||
validate-attributes | ||
duplicate-ids | ||
unique-elements | ||
# best-practices | ||
inline-event-handlers | ||
script-placement | ||
unused-classes | ||
unnecessary-elements | ||
# convention | ||
bem-conventions | ||
``` | ||
The following is a more in-depth explanation of each rule: | ||
### Validation | ||
@@ -312,47 +343,2 @@ | ||
## Custom Builds | ||
HTML Inspector comes with a number of pre-built options to use directly in your projects. | ||
- **html-inspector.js**: The full HTML Inspector code with all built-in rules prepackaged. | ||
- **html-inspector.core.js**: The core library with none of the rules. | ||
- **html-inspector.validation.js**: A package containing only the validation rules | ||
- **html-inspector.best-practices.js**: A package containing only the best practice rules | ||
- **html-inspector.convention.js**: A package containing only the convention rules | ||
If the full version of HTML Inspector and all the built-in rules is too much, you can mix and match the core library with any combination of the packaged rule libraries as well as your own rules. | ||
The build options for each of these is as follows: | ||
```sh | ||
# build everything | ||
grunt | ||
# build the core library | ||
grunt dist:core | ||
# build the validation ruleset | ||
grunt dist:validation | ||
# build the best-practices ruleset | ||
grunt dist:best-practices | ||
# build the convention ruleset | ||
grunt dist:convention | ||
``` | ||
To alter the custom builds, simply add or remove files from the directories inside of `src/rules`. But keep in mind that rules can be excluded both at build time and at runtime. In other words, you don't need a custom build to exclude certain rules. You also don't need a custom build to add new rules. It's perfectly OK to add new rules directly to the HTML source as separate files. | ||
HTML Inspector uses [Grunt](http://gruntjs.com) which runs on [Node](http://nodejs.org/) to build and lint its source files as well as to run the [Jasmine](http://pivotal.github.io/jasmine/) tests. | ||
If you don't have Node, NPM, and Grunt installed, refer to their documentation for installation instructions. Once they're installed, you can install the rest of the dependencies with the following commands: | ||
```sh | ||
# Install Node packages | ||
npm install | ||
# Install script dependencies | ||
bower install | ||
``` | ||
## Browser Support | ||
@@ -373,3 +359,3 @@ | ||
If Grunt and all the dependencies are installed, you can run the Jasmine tests with the following command. | ||
If Grunt and all the dependencies are installed, you can run the tests with the following command. | ||
@@ -380,4 +366,6 @@ ```sh | ||
This creates a `spec-runner.html` file in the root directory and uses [PhantomJS](http://phantomjs.org/) to run the tests. If you prefer to run the tests in the browser, you can always fire up a local server and load `spec-runner.html` in the browser manually. | ||
HTML Inspector has two test suites, one that runs in pure Node and one that uses [Mocha](http://visionmedia.github.io/mocha/) and [PhantomJS](http://phantomjs.org/) because it needs a browser. | ||
If you want to run the browser tests in a real browser (instead of via PhantomJS) simply fire up a local server and load the `tests/html-inspector-test.html` file. Make sure to run `grunt test` beforehand as it builds the tests. | ||
## Contributing | ||
@@ -384,0 +372,0 @@ |
@@ -21,7 +21,12 @@ var Listener = require("./listener") | ||
*/ | ||
function setup(useRules, listener, reporter) { | ||
useRules = useRules == null | ||
function setup(listener, reporter, useRules, excludeRules) { | ||
var rules = useRules == null | ||
? Object.keys(HTMLInspector.rules) | ||
: useRules | ||
useRules.forEach(function(rule) { | ||
if (excludeRules) { | ||
rules = rules.filter(function(rule) { | ||
return excludeRules.indexOf(rule) < 0 | ||
}) | ||
} | ||
rules.forEach(function(rule) { | ||
if (HTMLInspector.rules[rule]) { | ||
@@ -38,3 +43,3 @@ HTMLInspector.rules[rule].func.call( | ||
function traverseDOM(node, listener, options) { | ||
function traverseDOM(listener, node, excludeElements, excludeSubTrees) { | ||
@@ -47,3 +52,3 @@ // only deal with element nodes | ||
// trigger events for this element unless it's been excluded | ||
if (!matches(node, options.exclude)) { | ||
if (!matches(node, excludeElements)) { | ||
listener.trigger("element", node, [node.nodeName.toLowerCase(), node]) | ||
@@ -62,5 +67,5 @@ if (node.id) { | ||
// recurse through the subtree unless it's been excluded | ||
if (!matches(node, options.excludeSubTree)) { | ||
if (!matches(node, excludeSubTrees)) { | ||
toArray(node.childNodes).forEach(function(node) { | ||
traverseDOM(node, listener, options) | ||
traverseDOM(listener, node, excludeElements, excludeSubTrees) | ||
}) | ||
@@ -70,15 +75,23 @@ } | ||
function processConfig(config) { | ||
function mergeOptions(options) { | ||
// allow config to be individual properties of the defaults object | ||
if (config) { | ||
if (typeof config == "string" || config.nodeType == 1) { | ||
config = { domRoot: config } | ||
} else if (Array.isArray(config)) { | ||
config = { useRules: config } | ||
} else if (typeof config == "function") { | ||
config = { onComplete: config } | ||
if (options) { | ||
if (typeof options == "string" || options.nodeType == 1) { | ||
options = { domRoot: options } | ||
} else if (Array.isArray(options)) { | ||
options = { useRules: options } | ||
} else if (typeof options == "function") { | ||
options = { onComplete: options } | ||
} | ||
} | ||
// merge config with the defaults | ||
return mixIn({}, HTMLInspector.config, config) | ||
// merge options with the defaults | ||
options = mixIn({}, HTMLInspector.defaults, options) | ||
// set the domRoot to an HTMLElement if it's not | ||
options.domRoot = typeof options.domRoot == "string" | ||
? document.querySelector(options.domRoot) | ||
: options.domRoot | ||
return options | ||
} | ||
@@ -111,3 +124,3 @@ | ||
) | ||
return "(can't display iframe with cross-origin source)" | ||
return "(can't display iframe with cross-origin source: " + el.src + ")" | ||
else | ||
@@ -123,6 +136,7 @@ return el | ||
defaults: { | ||
domRoot: "html", | ||
useRules: null, | ||
domRoot: "html", | ||
exclude: "svg", | ||
excludeSubTree: ["svg", "iframe"], | ||
excludeRules: null, | ||
excludeElements: "svg", | ||
excludeSubTrees: ["svg", "iframe"], | ||
onComplete: function(errors) { | ||
@@ -135,18 +149,2 @@ errors.forEach(function(error) { | ||
config: {}, | ||
setConfig: function(config) { | ||
// allow config to be individual properties of the defaults object | ||
if (config) { | ||
if (typeof config == "string" || config.nodeType == 1) { | ||
config = { domRoot: config } | ||
} else if (Array.isArray(config)) { | ||
config = { useRules: config } | ||
} else if (typeof config == "function") { | ||
config = { onComplete: config } | ||
} | ||
} | ||
mixIn(this.config, this.defaults, config) | ||
}, | ||
rules: new Rules(), | ||
@@ -156,19 +154,14 @@ | ||
inspect: function(config) { | ||
var domRoot | ||
inspect: function(options) { | ||
var config = mergeOptions(options) | ||
, listener = new Listener() | ||
, reporter = new Reporter() | ||
this.setConfig(config) | ||
domRoot = typeof this.config.domRoot == "string" | ||
? document.querySelector(this.config.domRoot) | ||
: this.config.domRoot | ||
setup(listener, reporter, config.useRules, config.excludeRules) | ||
setup(this.config.useRules, listener, reporter) | ||
listener.trigger("beforeInspect", config.domRoot) | ||
traverseDOM(listener, config.domRoot, config.excludeElements, config.excludeSubTrees) | ||
listener.trigger("afterInspect", config.domRoot) | ||
listener.trigger("beforeInspect", domRoot) | ||
traverseDOM(domRoot, listener, this.config) | ||
listener.trigger("afterInspect", domRoot) | ||
this.config.onComplete(reporter.getWarnings()) | ||
config.onComplete(reporter.getWarnings()) | ||
} | ||
@@ -175,0 +168,0 @@ } |
@@ -16,4 +16,3 @@ module.exports = { | ||
var css = HTMLInspector.modules.css | ||
, classes = css.getClassSelectors() | ||
var classes = this.modules.css.getClassSelectors() | ||
, foundIn = require("../../utils/string-matcher") | ||
@@ -20,0 +19,0 @@ |
@@ -7,3 +7,3 @@ module.exports = { | ||
var validation = HTMLInspector.modules.validation | ||
var validation = this.modules.validation | ||
@@ -10,0 +10,0 @@ listener.on("element", function(name) { |
@@ -7,3 +7,3 @@ module.exports = { | ||
var validation = HTMLInspector.modules.validation | ||
var validation = this.modules.validation | ||
@@ -10,0 +10,0 @@ listener.on("element", function(name) { |
@@ -31,43 +31,18 @@ describe("HTMLInspector", function() { | ||
describe(".setConfig", function() { | ||
describe(".inspect", function() { | ||
it("merges the passed config options with the defaults", function() { | ||
var useRules = ["foo", "bar"] | ||
, domRoot = "body" | ||
, exclude = "svg, iframe" | ||
, onComplete = function() {} | ||
HTMLInspector.setConfig({ | ||
useRules: useRules, | ||
domRoot: domRoot, | ||
exclude: exclude, | ||
onComplete: onComplete | ||
it("inspects the HTML starting from the specified domRoot", function() { | ||
var events = [] | ||
HTMLInspector.rules.add("traverse-test", function(listener, reporter) { | ||
listener.on("element", function(name) { | ||
events.push(name) | ||
}) | ||
}) | ||
expect(HTMLInspector.config.useRules).to.equal(useRules) | ||
expect(HTMLInspector.config.domRoot).to.equal(domRoot) | ||
expect(HTMLInspector.config.exclude).to.equal(exclude) | ||
expect(HTMLInspector.config.onComplete).to.equal(onComplete) | ||
expect(HTMLInspector.config.excludeSubTree).to.equal(HTMLInspector.defaults.excludeSubTree) | ||
HTMLInspector.inspect() | ||
expect(events[0]).to.equal("html") | ||
events = [] | ||
HTMLInspector.inspect({ domRoot: html }) | ||
expect(events[0]).to.equal("section") | ||
}) | ||
it("accepts a variety of options for the config paramter", function() { | ||
var div = document.createElement("div") | ||
, fn = function() { } | ||
// if it's an array, assume it's the useRules options | ||
HTMLInspector.setConfig(["dom"]) | ||
expect(HTMLInspector.config.useRules).to.deep.equal(["dom"]) | ||
// if it's a string, assume it's a selector for the domRoot option | ||
HTMLInspector.inspect("body") | ||
expect(HTMLInspector.config.domRoot).to.equal("body") | ||
// if it's a DOM element, assume it's the domRoot option | ||
HTMLInspector.inspect(div) | ||
expect(HTMLInspector.config.domRoot).to.equal(div) | ||
// if it's a function, assume it's the onComplete option | ||
HTMLInspector.inspect(fn) | ||
expect(HTMLInspector.config.onComplete).to.equal(fn) | ||
}) | ||
}) | ||
describe(".inspect", function() { | ||
it("only runs the specified rules (or all rules if none are specified)", function() { | ||
@@ -100,22 +75,28 @@ var rules = [] | ||
it("invokes the onComplete callback passing in an array of errors", function() { | ||
var log | ||
HTMLInspector.rules.add("one-two", function(listener, reporter) { | ||
reporter.warn("one-two", "This is the `one` error message", document) | ||
reporter.warn("one-two", "This is the `two` error message", document) | ||
it("excludes rules specifically mentioned in the `excludeRules` options", function() { | ||
var rules = [] | ||
HTMLInspector.rules.add("one", function(listener, reporter) { | ||
listener.on("beforeInspect", function(name) { rules.push("one") }) | ||
}) | ||
HTMLInspector.rules.add("two", function(listener, reporter) { | ||
listener.on("beforeInspect", function(name) { rules.push("two") }) | ||
}) | ||
HTMLInspector.rules.add("three", function(listener, reporter) { | ||
reporter.warn("three", "This is the `three` error message", document) | ||
listener.on("beforeInspect", function(name) { rules.push("three") }) | ||
}) | ||
HTMLInspector.inspect(function(errors) { | ||
log = errors | ||
HTMLInspector.inspect({ | ||
excludeRules: ["one", "two"] | ||
}) | ||
expect(log.length).to.equal(3) | ||
expect(log[0].message).to.equal("This is the `one` error message") | ||
expect(log[1].message).to.equal("This is the `two` error message") | ||
expect(log[2].message).to.equal("This is the `three` error message") | ||
expect(rules.length).to.equal(1) | ||
expect(rules[0]).to.equal("three") | ||
rules = [] | ||
HTMLInspector.inspect({ | ||
useRules: ["one", "two"], | ||
excludeRules: ["two"] | ||
}) | ||
expect(rules.length).to.equal(1) | ||
expect(rules[0]).to.equal("one") | ||
}) | ||
it("ignores elements matching the `exclude` config option", function() { | ||
it("ignores elements matching the `excludeElements` config option", function() { | ||
var events = [] | ||
@@ -129,3 +110,3 @@ HTMLInspector.rules.add("traverse-test", function(listener, reporter) { | ||
domRoot: html, | ||
exclude: ["h1", "p"] | ||
excludeElements: ["h1", "p"] | ||
}) | ||
@@ -136,3 +117,3 @@ expect(events).to.deep.equal(["section", "a", "blockquote", "em"]) | ||
domRoot: html, | ||
exclude: html.querySelector("blockquote") | ||
excludeElements: html.querySelector("blockquote") | ||
}) | ||
@@ -142,3 +123,3 @@ expect(events).to.deep.equal(["section", "h1", "p", "p", "a", "p", "p", "em"]) | ||
it("ignores elements that descend from the `excludeSubTree` config option", function() { | ||
it("ignores elements that descend from the `excludeSubTrees` config option", function() { | ||
var events = [] | ||
@@ -152,3 +133,3 @@ HTMLInspector.rules.add("traverse-test", function(listener, reporter) { | ||
domRoot: html, | ||
excludeSubTree: "p" | ||
excludeSubTrees: "p" | ||
}) | ||
@@ -159,3 +140,3 @@ expect(events).to.deep.equal(["section", "h1", "p", "p", "blockquote", "p", "p"]) | ||
domRoot: html, | ||
excludeSubTree: [html.querySelector("p:not(.first)"), html.querySelector("blockquote")] | ||
excludeSubTrees: [html.querySelector("p:not(.first)"), html.querySelector("blockquote")] | ||
}) | ||
@@ -165,14 +146,61 @@ expect(events).to.deep.equal(["section", "h1", "p", "p", "blockquote"]) | ||
it("inspects the HTML starting from the specified domRoot", function() { | ||
var events = [] | ||
HTMLInspector.rules.add("traverse-test", function(listener, reporter) { | ||
it("invokes the onComplete callback passing in an array of errors", function() { | ||
var log | ||
HTMLInspector.rules.add("one-two", function(listener, reporter) { | ||
reporter.warn("one-two", "This is the `one` error message", document) | ||
reporter.warn("one-two", "This is the `two` error message", document) | ||
}) | ||
HTMLInspector.rules.add("three", function(listener, reporter) { | ||
reporter.warn("three", "This is the `three` error message", document) | ||
}) | ||
HTMLInspector.inspect(function(errors) { | ||
log = errors | ||
}) | ||
expect(log.length).to.equal(3) | ||
expect(log[0].message).to.equal("This is the `one` error message") | ||
expect(log[1].message).to.equal("This is the `two` error message") | ||
expect(log[2].message).to.equal("This is the `three` error message") | ||
}) | ||
it("accepts a variety of types for the options paramter", function() { | ||
var log = [] | ||
, div = document.createElement("div") | ||
HTMLInspector.rules.add("dom", function(listener, reporter) { | ||
listener.on("element", function(name) { | ||
events.push(name) | ||
log.push(this) | ||
}) | ||
}) | ||
HTMLInspector.inspect() | ||
expect(events[0]).to.equal("html") | ||
events = [] | ||
HTMLInspector.inspect({ domRoot: html }) | ||
expect(events[0]).to.equal("section") | ||
HTMLInspector.rules.add("rules", function() { | ||
log.push("rules") | ||
}) | ||
// if it's an object, assume it's the full config object | ||
HTMLInspector.inspect({ | ||
useRules: ["dom"], | ||
domRoot: parseHTML("<p>foobar</p>"), | ||
onComplete: function(errors) { | ||
log.push("done") | ||
} | ||
}) | ||
expect(log.length).to.equal(2) | ||
expect(log[0].innerHTML).to.equal("foobar") | ||
expect(log[1]).to.equal("done") | ||
log = [] | ||
// if it's an array, assume it's a list of rules | ||
HTMLInspector.inspect(["dom"]) | ||
expect(log.indexOf("rules")).to.equal(-1) | ||
log = [] | ||
// if it's a string, assume it's a selector | ||
HTMLInspector.inspect("body") | ||
expect(log[1]).to.equal(document.body) | ||
log = [] | ||
// if it's a DOM element, assume it's the domRoot | ||
HTMLInspector.inspect(div) | ||
expect(log[1]).to.equal(div) | ||
log = [] | ||
// if it's a function, assume it's complete | ||
HTMLInspector.inspect(function(errors) { | ||
log = "func" | ||
}) | ||
expect(log).to.equal("func") | ||
}) | ||
@@ -337,3 +365,3 @@ | ||
expect(console.warn.callCount).to.equal(3) | ||
expect(console.warn.getCall(1).args[1]).to.equal("(can't display iframe with cross-origin source)") | ||
expect(console.warn.getCall(1).args[1]).to.equal("(can't display iframe with cross-origin source: http://example.com/)") | ||
expect(console.warn.getCall(2).args[1]).to.equal(iframe2) | ||
@@ -340,0 +368,0 @@ console.warn.restore() |
@@ -31,43 +31,18 @@ describe("HTMLInspector", function() { | ||
describe(".setConfig", function() { | ||
describe(".inspect", function() { | ||
it("merges the passed config options with the defaults", function() { | ||
var useRules = ["foo", "bar"] | ||
, domRoot = "body" | ||
, exclude = "svg, iframe" | ||
, onComplete = function() {} | ||
HTMLInspector.setConfig({ | ||
useRules: useRules, | ||
domRoot: domRoot, | ||
exclude: exclude, | ||
onComplete: onComplete | ||
it("inspects the HTML starting from the specified domRoot", function() { | ||
var events = [] | ||
HTMLInspector.rules.add("traverse-test", function(listener, reporter) { | ||
listener.on("element", function(name) { | ||
events.push(name) | ||
}) | ||
}) | ||
expect(HTMLInspector.config.useRules).to.equal(useRules) | ||
expect(HTMLInspector.config.domRoot).to.equal(domRoot) | ||
expect(HTMLInspector.config.exclude).to.equal(exclude) | ||
expect(HTMLInspector.config.onComplete).to.equal(onComplete) | ||
expect(HTMLInspector.config.excludeSubTree).to.equal(HTMLInspector.defaults.excludeSubTree) | ||
HTMLInspector.inspect() | ||
expect(events[0]).to.equal("html") | ||
events = [] | ||
HTMLInspector.inspect({ domRoot: html }) | ||
expect(events[0]).to.equal("section") | ||
}) | ||
it("accepts a variety of options for the config paramter", function() { | ||
var div = document.createElement("div") | ||
, fn = function() { } | ||
// if it's an array, assume it's the useRules options | ||
HTMLInspector.setConfig(["dom"]) | ||
expect(HTMLInspector.config.useRules).to.deep.equal(["dom"]) | ||
// if it's a string, assume it's a selector for the domRoot option | ||
HTMLInspector.inspect("body") | ||
expect(HTMLInspector.config.domRoot).to.equal("body") | ||
// if it's a DOM element, assume it's the domRoot option | ||
HTMLInspector.inspect(div) | ||
expect(HTMLInspector.config.domRoot).to.equal(div) | ||
// if it's a function, assume it's the onComplete option | ||
HTMLInspector.inspect(fn) | ||
expect(HTMLInspector.config.onComplete).to.equal(fn) | ||
}) | ||
}) | ||
describe(".inspect", function() { | ||
it("only runs the specified rules (or all rules if none are specified)", function() { | ||
@@ -100,22 +75,28 @@ var rules = [] | ||
it("invokes the onComplete callback passing in an array of errors", function() { | ||
var log | ||
HTMLInspector.rules.add("one-two", function(listener, reporter) { | ||
reporter.warn("one-two", "This is the `one` error message", document) | ||
reporter.warn("one-two", "This is the `two` error message", document) | ||
it("excludes rules specifically mentioned in the `excludeRules` options", function() { | ||
var rules = [] | ||
HTMLInspector.rules.add("one", function(listener, reporter) { | ||
listener.on("beforeInspect", function(name) { rules.push("one") }) | ||
}) | ||
HTMLInspector.rules.add("two", function(listener, reporter) { | ||
listener.on("beforeInspect", function(name) { rules.push("two") }) | ||
}) | ||
HTMLInspector.rules.add("three", function(listener, reporter) { | ||
reporter.warn("three", "This is the `three` error message", document) | ||
listener.on("beforeInspect", function(name) { rules.push("three") }) | ||
}) | ||
HTMLInspector.inspect(function(errors) { | ||
log = errors | ||
HTMLInspector.inspect({ | ||
excludeRules: ["one", "two"] | ||
}) | ||
expect(log.length).to.equal(3) | ||
expect(log[0].message).to.equal("This is the `one` error message") | ||
expect(log[1].message).to.equal("This is the `two` error message") | ||
expect(log[2].message).to.equal("This is the `three` error message") | ||
expect(rules.length).to.equal(1) | ||
expect(rules[0]).to.equal("three") | ||
rules = [] | ||
HTMLInspector.inspect({ | ||
useRules: ["one", "two"], | ||
excludeRules: ["two"] | ||
}) | ||
expect(rules.length).to.equal(1) | ||
expect(rules[0]).to.equal("one") | ||
}) | ||
it("ignores elements matching the `exclude` config option", function() { | ||
it("ignores elements matching the `excludeElements` config option", function() { | ||
var events = [] | ||
@@ -129,3 +110,3 @@ HTMLInspector.rules.add("traverse-test", function(listener, reporter) { | ||
domRoot: html, | ||
exclude: ["h1", "p"] | ||
excludeElements: ["h1", "p"] | ||
}) | ||
@@ -136,3 +117,3 @@ expect(events).to.deep.equal(["section", "a", "blockquote", "em"]) | ||
domRoot: html, | ||
exclude: html.querySelector("blockquote") | ||
excludeElements: html.querySelector("blockquote") | ||
}) | ||
@@ -142,3 +123,3 @@ expect(events).to.deep.equal(["section", "h1", "p", "p", "a", "p", "p", "em"]) | ||
it("ignores elements that descend from the `excludeSubTree` config option", function() { | ||
it("ignores elements that descend from the `excludeSubTrees` config option", function() { | ||
var events = [] | ||
@@ -152,3 +133,3 @@ HTMLInspector.rules.add("traverse-test", function(listener, reporter) { | ||
domRoot: html, | ||
excludeSubTree: "p" | ||
excludeSubTrees: "p" | ||
}) | ||
@@ -159,3 +140,3 @@ expect(events).to.deep.equal(["section", "h1", "p", "p", "blockquote", "p", "p"]) | ||
domRoot: html, | ||
excludeSubTree: [html.querySelector("p:not(.first)"), html.querySelector("blockquote")] | ||
excludeSubTrees: [html.querySelector("p:not(.first)"), html.querySelector("blockquote")] | ||
}) | ||
@@ -165,14 +146,61 @@ expect(events).to.deep.equal(["section", "h1", "p", "p", "blockquote"]) | ||
it("inspects the HTML starting from the specified domRoot", function() { | ||
var events = [] | ||
HTMLInspector.rules.add("traverse-test", function(listener, reporter) { | ||
it("invokes the onComplete callback passing in an array of errors", function() { | ||
var log | ||
HTMLInspector.rules.add("one-two", function(listener, reporter) { | ||
reporter.warn("one-two", "This is the `one` error message", document) | ||
reporter.warn("one-two", "This is the `two` error message", document) | ||
}) | ||
HTMLInspector.rules.add("three", function(listener, reporter) { | ||
reporter.warn("three", "This is the `three` error message", document) | ||
}) | ||
HTMLInspector.inspect(function(errors) { | ||
log = errors | ||
}) | ||
expect(log.length).to.equal(3) | ||
expect(log[0].message).to.equal("This is the `one` error message") | ||
expect(log[1].message).to.equal("This is the `two` error message") | ||
expect(log[2].message).to.equal("This is the `three` error message") | ||
}) | ||
it("accepts a variety of types for the options paramter", function() { | ||
var log = [] | ||
, div = document.createElement("div") | ||
HTMLInspector.rules.add("dom", function(listener, reporter) { | ||
listener.on("element", function(name) { | ||
events.push(name) | ||
log.push(this) | ||
}) | ||
}) | ||
HTMLInspector.inspect() | ||
expect(events[0]).to.equal("html") | ||
events = [] | ||
HTMLInspector.inspect({ domRoot: html }) | ||
expect(events[0]).to.equal("section") | ||
HTMLInspector.rules.add("rules", function() { | ||
log.push("rules") | ||
}) | ||
// if it's an object, assume it's the full config object | ||
HTMLInspector.inspect({ | ||
useRules: ["dom"], | ||
domRoot: parseHTML("<p>foobar</p>"), | ||
onComplete: function(errors) { | ||
log.push("done") | ||
} | ||
}) | ||
expect(log.length).to.equal(2) | ||
expect(log[0].innerHTML).to.equal("foobar") | ||
expect(log[1]).to.equal("done") | ||
log = [] | ||
// if it's an array, assume it's a list of rules | ||
HTMLInspector.inspect(["dom"]) | ||
expect(log.indexOf("rules")).to.equal(-1) | ||
log = [] | ||
// if it's a string, assume it's a selector | ||
HTMLInspector.inspect("body") | ||
expect(log[1]).to.equal(document.body) | ||
log = [] | ||
// if it's a DOM element, assume it's the domRoot | ||
HTMLInspector.inspect(div) | ||
expect(log[1]).to.equal(div) | ||
log = [] | ||
// if it's a function, assume it's complete | ||
HTMLInspector.inspect(function(errors) { | ||
log = "func" | ||
}) | ||
expect(log).to.equal("func") | ||
}) | ||
@@ -337,3 +365,3 @@ | ||
expect(console.warn.callCount).to.equal(3) | ||
expect(console.warn.getCall(1).args[1]).to.equal("(can't display iframe with cross-origin source)") | ||
expect(console.warn.getCall(1).args[1]).to.equal("(can't display iframe with cross-origin source: http://example.com/)") | ||
expect(console.warn.getCall(2).args[1]).to.equal(iframe2) | ||
@@ -340,0 +368,0 @@ console.warn.restore() |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
2
0
351972
61
6833
372