Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to Unexpected 10 #38

Merged
merged 11 commits into from
Oct 9, 2015
Merged
239 changes: 138 additions & 101 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ module.exports = {
// Fake type to make it possible to build 'to satisfy' diffs to be rendered inline:
expect.addType({
name: 'attachedDOMNodeList',
base: 'array-like',
base: 'DOMNodeList',
prefix: function (output) { return output; },
suffix: function (output) { return output; },
delimiter: function (output) { return output; },
Expand All @@ -320,6 +320,16 @@ module.exports = {
}
});

function makeAttachedDOMNodeList(domNodeList, contentType) {
var attachedDOMNodeList = [];
for (var i = 0 ; i < domNodeList.length ; i += 1) {
attachedDOMNodeList.push(domNodeList[i]);
}
attachedDOMNodeList._isAttachedDOMNodeList = true;
attachedDOMNodeList.ownerDocument = { contentType: contentType };
return attachedDOMNodeList;
}

expect.addType({
name: 'HTMLDocType',
base: 'DOMNode',
Expand Down Expand Up @@ -539,29 +549,32 @@ module.exports = {
}
});

expect.addAssertion('DOMElement', 'to [only] have (class|classes)', function (expect, subject, value) {
var flags = this.flags;
if (flags.only) {
return expect(subject, 'to have attributes', {
class: function (className) {
var actualClasses = getClassNamesFromAttributeValue(className);
if (typeof value === 'string') {
value = getClassNamesFromAttributeValue(value);
}
if (flags.only) {
return topLevelExpect(actualClasses.sort(), 'to equal', value.sort());
} else {
return topLevelExpect.apply(topLevelExpect, [actualClasses, 'to contain'].concat(value));
}
expect.addAssertion('<DOMElement> to have (class|classes) <array|string>', function (expect, subject, value) {
return expect(subject, 'to have attributes', { class: value });
});

expect.addAssertion('<DOMElement> to only have (class|classes) <array|string>', function (expect, subject, value) {
return expect(subject, 'to have attributes', {
class: function (className) {
var actualClasses = getClassNamesFromAttributeValue(className);
if (typeof value === 'string') {
value = getClassNamesFromAttributeValue(value);
}
});
} else {
return expect(subject, 'to have attributes', { class: value });
}
return topLevelExpect(actualClasses.sort(), 'to equal', value.sort());
}
});
});

expect.addAssertion('<DOMTextNode> to [exhaustively] satisfy <DOMTextNode>', function (expect, subject, value) {
return expect(subject.nodeValue, 'to equal', value.nodeValue);
});

expect.addAssertion('<DOMTextNode> to [exhaustively] satisfy <object>', function (expect, subject, value) {
expect.fail();
});

expect.addAssertion('DOMTextNode', 'to [exhaustively] satisfy', function (expect, subject, value) {
return expect(subject.nodeValue, 'to satisfy', expect.findTypeOf(value).name === 'DOMTextNode' ? value.nodeValue : value);
expect.addAssertion('<DOMTextNode> to [exhaustively] satisfy <any>', function (expect, subject, value) {
return expect(subject.nodeValue, 'to satisfy', value);
});

function convertDOMNodeToSatisfySpec(node, isHtml) {
Expand All @@ -586,49 +599,73 @@ module.exports = {
}
}

expect.addAssertion('DOMDocumentFragment', 'to [exhaustively] satisfy', function (expect, subject, value) {
var isHtml = isInsideHtmlDocument(subject);
var valueType = expect.findTypeOf(value);
if (valueType.name === 'string') {
var originalValue = value;
this.argsOutput = function (output) {
output.code(originalValue, isHtml ? 'html' : 'xml');
};
value = isHtml ? parseHtml(value, true, this.testDescription) : parseXml(value, this.testDescription);
}
expect.addAssertion('<DOMNodeList> to [exhaustively] satisfy <string>', function (expect, subject, value) {
var isHtml = subject.ownerDocument.contentType === 'text/html';
expect.argsOutput = function (output) {
output.code(value, isHtml ? 'html' : 'xml');
};
return expect(subject, 'to [exhaustively] satisfy', (isHtml ? parseHtml(value, true, expect.testDescription) : parseXml(value, expect.testDescription)).childNodes);
});

if (value && value.nodeType === 11) {
value = Array.prototype.map.call(value.childNodes, function (childNode) {
return convertDOMNodeToSatisfySpec(childNode, isHtml);
});
expect.addAssertion('<DOMNodeList> to [exhaustively] satisfy <DOMNodeList>', function (expect, subject, value) {
var isHtml = subject.ownerDocument.contentType === 'text/html';
var satisfySpecs = [];
for (var i = 0 ; i < value.length ; i += 1) {
satisfySpecs.push(convertDOMNodeToSatisfySpec(value[i], isHtml));
}
return expect(subject, 'to [exhaustively] satisfy', satisfySpecs);
});

expect.addAssertion('<DOMDocumentFragment> to [exhaustively] satisfy <string>', function (expect, subject, value) {
var isHtml = isInsideHtmlDocument(subject);
expect.argsOutput = function (output) {
output.code(value, isHtml ? 'html' : 'xml');
};
return expect(subject, 'to [exhaustively] satisfy', isHtml ? parseHtml(value, true, expect.testDescription) : parseXml(value, expect.testDescription));
});

expect.addAssertion('<DOMDocumentFragment> to [exhaustively] satisfy <DOMDocumentFragment>', function (expect, subject, value) {
var isHtml = subject.ownerDocument.contentType === 'text/html';
return expect(subject, 'to [exhaustively] satisfy', Array.prototype.map.call(value.childNodes, function (childNode) {
return convertDOMNodeToSatisfySpec(childNode, isHtml);
}));
});

expect.addAssertion('<DOMDocumentFragment> to [exhaustively] satisfy <object|array>', function (expect, subject, value) {
return expect(subject.childNodes, 'to [exhaustively] satisfy', value);
});

expect.addAssertion('DOMElement', 'to [exhaustively] satisfy', function (expect, subject, value) {
expect.addAssertion('<DOMElement> to [exhaustively] satisfy <string>', function (expect, subject, value) {
var isHtml = isInsideHtmlDocument(subject);
if (typeof value === 'string') {
var documentFragment = isHtml ? parseHtml(value, true, this.testDescription) : parseXml(value, this.testDescription);
if (documentFragment.childNodes.length !== 1) {
throw new Error('HTMLElement to satisfy string: Only a single node is supported');
}
var originalValue = value;
value = documentFragment.childNodes[0];
this.argsOutput = function (output) {
output.code(originalValue, isHtml ? 'html' : 'xml');
};
var documentFragment = isHtml ? parseHtml(value, true, this.testDescription) : parseXml(value, this.testDescription);
if (documentFragment.childNodes.length !== 1) {
throw new Error('HTMLElement to satisfy string: Only a single node is supported');
}
if (expect.findTypeOf(value).name === 'DOMElement') {
value = convertDOMNodeToSatisfySpec(value, isHtml);
}
if (value && typeof value === 'object') {
var unsupportedOptions = Object.keys(value).filter(function (key) {
return key !== 'attributes' && key !== 'name' && key !== 'children' && key !== 'onlyAttributes' && key !== 'textContent';
});
if (unsupportedOptions.length > 0) {
throw new Error('Unsupported option' + (unsupportedOptions.length === 1 ? '' : 's') + ': ' + unsupportedOptions.join(', '));
}
expect.argsOutput = function (output) {
output.code(value, isHtml ? 'html' : 'xml');
};
return expect(subject, 'to [exhaustively] satisfy', documentFragment.childNodes[0]);
});

expect.addAssertion('<DOMElement> to [exhaustively] satisfy <DOMElement>', function (expect, subject, value) {
return expect(subject, 'to [exhaustively] satisfy', convertDOMNodeToSatisfySpec(value, subject.ownerDocument.contentType === 'text/html'));
});

expect.addAssertion('<DOMElement> to [exhaustively] satisfy <DOMTextNode>', function (expect, subject, value) {
expect.fail();
});

expect.addAssertion('<DOMTextNode> to [exhaustively] satisfy <DOMElement>', function (expect, subject, value) {
expect.fail();
});

expect.addAssertion('<DOMElement> to [exhaustively] satisfy <object>', function (expect, subject, value) {
var isHtml = subject.ownerDocument.contentType === 'text/html';
var unsupportedOptions = Object.keys(value).filter(function (key) {
return key !== 'attributes' && key !== 'name' && key !== 'children' && key !== 'onlyAttributes' && key !== 'textContent';
});
if (unsupportedOptions.length > 0) {
throw new Error('Unsupported option' + (unsupportedOptions.length === 1 ? '' : 's') + ': ' + unsupportedOptions.join(', '));
}

var promiseByKey = {
Expand All @@ -642,20 +679,15 @@ module.exports = {
if (typeof value.textContent !== 'undefined') {
throw new Error('The children and textContent properties are not supported together');
}
var nodeListForDiffing = [];
for (var i = 0 ; i < subject.childNodes.length ; i += 1) {
nodeListForDiffing.push(subject.childNodes[i]);
}
nodeListForDiffing._isAttachedDOMNodeList = true;
return topLevelExpect(nodeListForDiffing, 'to satisfy', value.children);
return topLevelExpect(makeAttachedDOMNodeList(subject.childNodes, subject.ownerDocument.contentType), 'to satisfy', value.children);
} else if (typeof value.textContent !== 'undefined') {
return topLevelExpect(subject.textContent, 'to satisfy', value.textContent);
}
}),
attributes: {}
};

var onlyAttributes = value && value.onlyAttributes || this.flags.exhaustively;
var onlyAttributes = value && value.onlyAttributes || expect.flags.exhaustively;
var attrs = getAttributes(subject);
var expectedAttributes = value && value.attributes;
var expectedAttributeNames = [];
Expand Down Expand Up @@ -834,73 +866,78 @@ module.exports = {
});
});

expect.addAssertion('DOMElement', 'to [only] have (attribute|attributes)', function (expect, subject, value) {
if (typeof value === 'string') {
if (arguments.length > 3) {
value = Array.prototype.slice.call(arguments, 2);
}
} else if (!value || typeof value !== 'object') {
throw new Error('to have attributes: Argument must be a string, an array, or an object');
}
return expect(subject, 'to satisfy', { attributes: value, onlyAttributes: this.flags.only });
expect.addAssertion('<DOMElement> to [only] have (attribute|attributes) <string+>', function (expect, subject, value) {
return expect(subject, 'to [only] have attributes', Array.prototype.slice.call(arguments, 2));
});

expect.addAssertion('DOMElement', 'to have [no] (child|children)', function (expect, subject, query, cmp) {
if (this.flags.no) {
this.errorMode = 'nested';
return expect(Array.prototype.slice.call(subject.childNodes), 'to be an empty array');
} else {
var children = Array.prototype.slice.call(subject.querySelectorAll(query));
throw children;
}
expect.addAssertion('<DOMElement> to [only] have (attribute|attributes) <array|object>', function (expect, subject, value) {
return expect(subject, 'to satisfy', { attributes: value, onlyAttributes: expect.flags.only });
});

expect.addAssertion('DOMElement', 'to have text', function (expect, subject, value) {
expect.addAssertion('<DOMElement> to have no (child|children)', function (expect, subject) {
expect.errorMode = 'nested';
return expect(Array.prototype.slice.call(subject.childNodes), 'to be an empty array');
});

expect.addAssertion('<DOMElement> to have (child|children)', function (expect, subject) {
return expect(subject.childNodes, 'not to be empty');
});

expect.addAssertion('<DOMElement> to have (child|children) <string>', function (expect, subject, query) {
expect.errorMode = 'nested';
expect(subject.querySelectorAll(query), 'not to be empty');
});

expect.addAssertion('<DOMElement> to have text <any>', function (expect, subject, value) {
return expect(subject.textContent, 'to satisfy', value);
});

expect.addAssertion(['DOMDocument', 'DOMElement'], 'queried for [first]', function (expect, subject, value) {
expect.addAssertion('<DOMDocument|DOMElement|DOMDocumentFragment> [when] queried for [first] <string> <assertion?>', function (expect, subject, query) {
var queryResult;

this.errorMode = 'nested';
expect.argsOutput[0] = function (output) {
return output.green(query);
};

expect.errorMode = 'nested';

if (this.flags.first) {
queryResult = subject.querySelector(value);
if (expect.flags.first) {
queryResult = subject.querySelector(query);
if (!queryResult) {
expect.fail(function (output) {
output.error('The selector').sp().jsString(value).sp().error('yielded no results');
output.error('The selector').sp().jsString(query).sp().error('yielded no results');
});
}
} else {
queryResult = subject.querySelectorAll(value);
queryResult = subject.querySelectorAll(query);
if (queryResult.length === 0) {
expect.fail(function (output) {
output.error('The selector').sp().jsString(value).sp().error('yielded no results');
output.error('The selector').sp().jsString(query).sp().error('yielded no results');
});
}
}
return this.shift(expect, queryResult, 1);
return expect.shift(queryResult);
});

expect.addAssertion(['DOMDocument', 'DOMElement'], 'to contain [no] elements matching', function (expect, subject, value) {
if (this.flags.no) {
return expect(subject.querySelectorAll(value), 'to satisfy', []);
expect.addAssertion('<DOMDocument|DOMElement|DOMDocumentFragment> to contain [no] elements matching <string>', function (expect, subject, query) {
if (expect.flags.no) {
return expect(subject.querySelectorAll(query), 'to satisfy', []);
}
return expect(subject.querySelectorAll(value), 'not to satisfy', []);
return expect(subject.querySelectorAll(query), 'not to satisfy', []);
});

expect.addAssertion(['DOMDocument', 'DOMElement'], '[not] to match', function (expect, subject, value) {
return expect(matchesSelector(subject, value), 'to be', (this.flags.not ? false : true));
expect.addAssertion('<DOMDocument|DOMElement|DOMDocumentFragment> [not] to match <string>', function (expect, subject, query) {
return expect(matchesSelector(subject, query), 'to be', (expect.flags.not ? false : true));
});

expect.addAssertion('string', 'when parsed as (html|HTML) [fragment]', function (expect, subject) {
this.errorMode = 'nested';
return this.shift(expect, parseHtml(subject, this.flags.fragment, this.testDescription), 0);
expect.addAssertion('<string> [when] parsed as (html|HTML) [fragment] <assertion?>', function (expect, subject) {
expect.errorMode = 'nested';
return expect.shift(parseHtml(subject, expect.flags.fragment, expect.testDescription));
});

expect.addAssertion('string', 'when parsed as (xml|XML)', function (expect, subject) {
this.errorMode = 'nested';
return this.shift(expect, parseXml(subject, this.testDescription), 0);
expect.addAssertion('<string> [when] parsed as (xml|XML) <assertion?>', function (expect, subject) {
expect.errorMode = 'nested';
return expect.shift(parseXml(subject, expect.testDescription));
});
}
};
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,15 @@
"mocha-lcov-reporter": "1.0.0",
"sinon": "^1.15.4",
"uglifyjs": "^2.4.10",
"unexpected": "9.16.1",
"unexpected-sinon": "6.4.1"
"unexpected": "10.0.1",
"unexpected-sinon": "8.0.0"
},
"dependencies": {
"array-changes": "1.0.3",
"extend": "^3.0.0",
"magicpen-prism": "^2.1.2"
},
"peerDependencies": {
"unexpected": "^8.0.0 || ^9.0.0"
"unexpected": "^10.0.1"
}
}
Loading