Skip to content

Commit

Permalink
improve assert messages
Browse files Browse the repository at this point in the history
  • Loading branch information
nathancahill committed Nov 1, 2015
1 parent 81123b9 commit 2b5e157
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 74 deletions.
101 changes: 64 additions & 37 deletions lib/eminent.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,31 @@ var _assert2 = _interopRequireDefault(_assert);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var getNodeHTML = function getNodeHTML(node, children) {
if (!children) {
node.innerHTML = '';
} else {
for (var i = 0; i < node._childNodes.length; i++) {
node._childNodes[i].innerHTML = '';
};
}

return node.outerHTML;
};

var getTreeHTML = function getTreeHTML(tree, children) {
var abbr = tree.abbreviation;

if (children) {
var childrenAbbrs = tree.children.map(function (child) {
return child.abbreviation;
}).join('+');
abbr = abbr + '>' + childrenAbbrs;
}

return _abbreviation2.default.expand(abbr, { profile: 'plain' });
};

/**
* Compare a jsdom node and a Emmet tree.
*
Expand All @@ -31,23 +56,25 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
* @param {boolean} hasAttrs - Compare attribute names
* @param {boolean} isAttrs - Compare attribute values
* @param {boolean} isContent - Compare content
* @return {boolean}
*/
var compareNode = function compareNode(node, tree, hasAttrs, isAttrs, isContent) {
var i = undefined,
nodeChildren = node._childNodes,
treeChildren = tree.children,
isText = node._localName === undefined,
match = true;
isText = node._localName === undefined;

if (hasAttrs || isAttrs) {
for (i = 0; i < tree._attributes.length; i++) {
var attrName = tree._attributes[i].name,
attrValue = tree._attributes[i].value;

if (hasAttrs) {
if (!node.hasAttribute(tree._attributes[i].name)) {
return false;
if (!node.hasAttribute(attrName)) {
_assert2.default.fail(getNodeHTML(node, false), getTreeHTML(tree, false), 'Attribute \'' + attrName + '\' does not exist', '!=');
}
} else if (isAttrs) {
if (node.getAttribute(tree._attributes[i].name) !== tree._attributes[i].value) {
return false;
if (node.getAttribute(attrName) !== attrValue) {
_assert2.default.fail(getNodeHTML(node, false), getTreeHTML(tree, false), 'Value of attribute \'' + attrName + '\' is not \'' + attrValue + '\'', '!=');
}
}
};
Expand All @@ -60,33 +87,46 @@ var compareNode = function compareNode(node, tree, hasAttrs, isAttrs, isContent)
* text as a child node. To compare the two trees, prepend a text node to
* Emmet tree children.
*/
if (tree.content !== '' && tree._name !== '') {
if (isContent && tree.content !== '' && tree._name !== '') {
treeChildren.unshift({
content: tree.content,
children: [],
_name: ''
});
}

/*
* Discard text child nodes if not checking for content.
*/
if (!isContent) {
nodeChildren = nodeChildren.filter(function (child) {
return child._localName !== undefined;
});
}

/*
* If the node is a text node, there's no need to compare any further down
* the tree.
*/
if (isContent && isText) {
return node.textContent.trim() == tree.content.trim();
if (node.textContent.trim() === tree.content.trim()) {
return;
} else {
_assert2.default.fail(node.textContent.trim(), tree.content.trim(), 'DOM element content does not match', '!=');
}
}

/*
* If there are different numbers of children, stop comparing before
* starting a recursive loop.
*/
if (node._childNodes.length !== treeChildren.length) return false;
if (nodeChildren.length !== treeChildren.length) {
_assert2.default.fail(getNodeHTML(node, true), getTreeHTML(tree, true), 'Different number of DOM child nodes', '!=');
}

for (i = 0; i < node._childNodes.length; i++) {
match = match && compareNode(node._childNodes[i], treeChildren[i], hasAttrs, isAttrs, isContent);
for (i = 0; i < nodeChildren.length; i++) {
compareNode(nodeChildren[i], treeChildren[i], hasAttrs, isAttrs, isContent);
};

return match;
};

/**
Expand All @@ -97,10 +137,9 @@ var compareNode = function compareNode(node, tree, hasAttrs, isAttrs, isContent)
* @return {boolean}
*/
var domIs = exports.domIs = function domIs(dom, abbr) {
var tree = _abbreviation2.default.expand(abbr, { profile: 'plain' }),
result = dom === tree;
var tree = _abbreviation2.default.expand(abbr, { profile: 'plain' });

if (!result) {
if (dom !== tree) {
_assert2.default.fail(dom, tree, 'DOM does not match Emmet abbreviation', '=');
}
};
Expand All @@ -115,12 +154,9 @@ var domIs = exports.domIs = function domIs(dom, abbr) {
*/
var domIsLike = exports.domIsLike = function domIsLike(dom, abbr) {
var node = _domWhitespace2.default.remove(_jsdom2.default.jsdom(dom)).body,
tree = _abbreviation2.default.parse(abbr, { profile: 'plain' }),
result = compareNode(node, tree, false, false, false);
tree = _abbreviation2.default.parse(abbr, { profile: 'plain' });

if (!result) {
_assert2.default.fail(dom, tree, 'DOM does not match Emmet abbreviation', '=');
}
compareNode(node, tree, false, false, false);
};

/**
Expand All @@ -133,12 +169,9 @@ var domIsLike = exports.domIsLike = function domIsLike(dom, abbr) {
*/
var domAttrsIs = exports.domAttrsIs = function domAttrsIs(dom, abbr) {
var node = _domWhitespace2.default.remove(_jsdom2.default.jsdom(dom)).body,
tree = _abbreviation2.default.parse(abbr, { profile: 'plain' }),
result = compareNode(node, tree, false, true, false);
tree = _abbreviation2.default.parse(abbr, { profile: 'plain' });

if (!result) {
_assert2.default.fail(dom, tree, 'DOM does not match Emmet abbreviation', '=');
}
compareNode(node, tree, false, true, false);
};

/**
Expand All @@ -151,12 +184,9 @@ var domAttrsIs = exports.domAttrsIs = function domAttrsIs(dom, abbr) {
*/
var domAttrsIsLike = exports.domAttrsIsLike = function domAttrsIsLike(dom, abbr) {
var node = _domWhitespace2.default.remove(_jsdom2.default.jsdom(dom)).body,
tree = _abbreviation2.default.parse(abbr, { profile: 'plain' }),
result = compareNode(node, tree, true, false, false);
tree = _abbreviation2.default.parse(abbr, { profile: 'plain' });

if (!result) {
_assert2.default.fail(dom, tree, 'DOM does not match Emmet abbreviation', '=');
}
compareNode(node, tree, true, false, false);
};

/**
Expand All @@ -169,10 +199,7 @@ var domAttrsIsLike = exports.domAttrsIsLike = function domAttrsIsLike(dom, abbr)
*/
var domContentIs = exports.domContentIs = function domContentIs(dom, abbr) {
var node = _domWhitespace2.default.remove(_jsdom2.default.jsdom(dom)).body,
tree = _abbreviation2.default.parse(abbr, { profile: 'plain' }),
result = compareNode(node, tree, false, false, true);
tree = _abbreviation2.default.parse(abbr, { profile: 'plain' });

if (!result) {
_assert2.default.fail(dom, tree, 'DOM does not match Emmet abbreviation', '=');
}
compareNode(node, tree, false, false, true);
};
97 changes: 60 additions & 37 deletions src/eminent.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,29 @@ import jsdom from 'jsdom'
import assert from 'assert'


let getNodeHTML = (node, children) => {
if (!children) {
node.innerHTML = '';
} else {
for (var i = 0; i < node._childNodes.length; i++) {
node._childNodes[i].innerHTML = '';
};
}

return node.outerHTML;
}

let getTreeHTML = (tree, children) => {
let abbr = tree.abbreviation;

if (children) {
let childrenAbbrs = tree.children.map(child => child.abbreviation).join('+');
abbr = abbr + '>' + childrenAbbrs;
}

return parser.expand(abbr, {profile: 'plain'});
}

/**
* Compare a jsdom node and a Emmet tree.
*
Expand All @@ -13,23 +36,25 @@ import assert from 'assert'
* @param {boolean} hasAttrs - Compare attribute names
* @param {boolean} isAttrs - Compare attribute values
* @param {boolean} isContent - Compare content
* @return {boolean}
*/
let compareNode = (node, tree, hasAttrs, isAttrs, isContent) => {
let i,
nodeChildren = node._childNodes,
treeChildren = tree.children,
isText = node._localName === undefined,
match = true;
isText = node._localName === undefined;

if (hasAttrs || isAttrs) {
for (i = 0; i < tree._attributes.length; i++) {
let attrName = tree._attributes[i].name,
attrValue = tree._attributes[i].value;

if (hasAttrs) {
if (!node.hasAttribute(tree._attributes[i].name)) {
return false
if (!node.hasAttribute(attrName)) {
assert.fail(getNodeHTML(node, false), getTreeHTML(tree, false), `Attribute '${attrName}' does not exist`, '!=')
}
} else if (isAttrs) {
if (node.getAttribute(tree._attributes[i].name) !== tree._attributes[i].value) {
return false
if (node.getAttribute(attrName) !== attrValue) {
assert.fail(getNodeHTML(node, false), getTreeHTML(tree, false), `Value of attribute '${attrName}' is not '${attrValue}'`, '!=')
}
}
};
Expand All @@ -42,33 +67,44 @@ let compareNode = (node, tree, hasAttrs, isAttrs, isContent) => {
* text as a child node. To compare the two trees, prepend a text node to
* Emmet tree children.
*/
if (tree.content !== '' && tree._name !== '') {
if (isContent && tree.content !== '' && tree._name !== '') {
treeChildren.unshift({
content: tree.content,
children: [],
_name: ''
});
}

/*
* Discard text child nodes if not checking for content.
*/
if (!isContent) {
nodeChildren = nodeChildren.filter(child => child._localName !== undefined);
}

/*
* If the node is a text node, there's no need to compare any further down
* the tree.
*/
if (isContent && isText) {
return node.textContent.trim() == tree.content.trim();
if (node.textContent.trim() === tree.content.trim()) {
return
} else {
assert.fail(node.textContent.trim(), tree.content.trim(), `DOM element content does not match`, '!=')
}
}

/*
* If there are different numbers of children, stop comparing before
* starting a recursive loop.
*/
if (node._childNodes.length !== treeChildren.length) return false;
if (nodeChildren.length !== treeChildren.length) {
assert.fail(getNodeHTML(node, true), getTreeHTML(tree, true), `Different number of DOM child nodes`, '!=')
}

for (i = 0; i < node._childNodes.length; i++) {
match = match && compareNode(node._childNodes[i], treeChildren[i], hasAttrs, isAttrs, isContent);
for (i = 0; i < nodeChildren.length; i++) {
compareNode(nodeChildren[i], treeChildren[i], hasAttrs, isAttrs, isContent);
};

return match
}

/**
Expand All @@ -79,10 +115,9 @@ let compareNode = (node, tree, hasAttrs, isAttrs, isContent) => {
* @return {boolean}
*/
export var domIs = (dom, abbr) => {
let tree = parser.expand(abbr, {profile: 'plain'}),
result = dom === tree;
let tree = parser.expand(abbr, {profile: 'plain'});

if (!result) {
if (dom !== tree) {
assert.fail(dom, tree, 'DOM does not match Emmet abbreviation', '=')
}
}
Expand All @@ -97,12 +132,9 @@ export var domIs = (dom, abbr) => {
*/
export var domIsLike = (dom, abbr) => {
let node = whitespace.remove(jsdom.jsdom(dom)).body,
tree = parser.parse(abbr, {profile: 'plain'}),
result = compareNode(node, tree, false, false, false);
tree = parser.parse(abbr, {profile: 'plain'});

if (!result) {
assert.fail(dom, tree, 'DOM does not match Emmet abbreviation', '=')
}
compareNode(node, tree, false, false, false);
}

/**
Expand All @@ -115,12 +147,9 @@ export var domIsLike = (dom, abbr) => {
*/
export var domAttrsIs = (dom, abbr) => {
let node = whitespace.remove(jsdom.jsdom(dom)).body,
tree = parser.parse(abbr, {profile: 'plain'}),
result = compareNode(node, tree, false, true, false);
tree = parser.parse(abbr, {profile: 'plain'});

if (!result) {
assert.fail(dom, tree, 'DOM does not match Emmet abbreviation', '=')
}
compareNode(node, tree, false, true, false);
}

/**
Expand All @@ -133,12 +162,9 @@ export var domAttrsIs = (dom, abbr) => {
*/
export var domAttrsIsLike = (dom, abbr) => {
let node = whitespace.remove(jsdom.jsdom(dom)).body,
tree = parser.parse(abbr, {profile: 'plain'}),
result = compareNode(node, tree, true, false, false);
tree = parser.parse(abbr, {profile: 'plain'});

if (!result) {
assert.fail(dom, tree, 'DOM does not match Emmet abbreviation', '=')
}
compareNode(node, tree, true, false, false);
}

/**
Expand All @@ -151,10 +177,7 @@ export var domAttrsIsLike = (dom, abbr) => {
*/
export var domContentIs = (dom, abbr) => {
let node = whitespace.remove(jsdom.jsdom(dom)).body,
tree = parser.parse(abbr, {profile: 'plain'}),
result = compareNode(node, tree, false, false, true);
tree = parser.parse(abbr, {profile: 'plain'});

if (!result) {
assert.fail(dom, tree, 'DOM does not match Emmet abbreviation', '=')
}
compareNode(node, tree, false, false, true);
}
8 changes: 8 additions & 0 deletions test/eminent.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@ describe('domIsLike', () => {
eminent.domIsLike(dom, 'table>tbody>tr*2>td*3')
})
});

it('passes when dom has content but abbreviation does not', () => {
let dom = `
<div>Hello</div>
`

eminent.domIsLike(dom, 'div')
});
});

describe('domAttrsIs', () => {
Expand Down

0 comments on commit 2b5e157

Please sign in to comment.