UNPKG

unexpected-preact

Version:

Assertion library for preact.js - sister project to unexpected-react

480 lines (400 loc) 23.7 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var _unexpectedHtmllike = require('unexpected-htmllike'); var _unexpectedHtmllike2 = _interopRequireDefault(_unexpectedHtmllike); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var PENDING_TEST_EVENT_TYPE = { dummy: 'Dummy object to identify a pending event on the test renderer' }; function getDefaultOptions(flags) { return { diffWrappers: flags.exactly || flags.withAllWrappers, diffExtraChildren: flags.exactly || flags.withAllChildren, diffExtraAttributes: flags.exactly || flags.withAllAttributes, diffExactClasses: flags.exactly, diffExtraClasses: flags.exactly || flags.withAllClasses }; } /** * * @param options {object} * @param options.ActualAdapter {function} constructor function for the HtmlLike adapter for the `actual` value (usually the renderer) * @param options.ExpectedAdapter {function} constructor function for the HtmlLike adapter for the `expected` value * @param options.QueryAdapter {function} constructor function for the HtmlLike adapter for the query value (`queried for` and `on`) * @param options.actualTypeName {string} name of the unexpected type for the `actual` value * @param options.expectedTypeName {string} name of the unexpected type for the `expected` value * @param options.queryTypeName {string} name of the unexpected type for the query value (used in `queried for` and `on`) * @param options.actualRenderOutputType {string} the unexpected type for the actual output value * @param options.getRenderOutput {function} called with the actual value, and returns the `actualRenderOutputType` type * @param options.getDiffInputFromRenderOutput {function} called with the value from `getRenderOutput`, result passed to HtmlLike diff * @param options.rewrapResult {function} called with the `actual` value (usually the renderer), and the found result * @param options.wrapResultForReturn {function} called with the `actual` value (usually the renderer), and the found result * from HtmlLike `contains()` call (usually the same type returned from `getDiffInputFromRenderOutput`. Used to create a * value that can be passed back to the user as the result of the promise. Used by `queried for` when no further assertion is * provided, therefore the return value is provided as the result of the promise. If this is not present, `rewrapResult` is used. * @param options.triggerEvent {function} called the `actual` value (renderer), the optional target (or null) as the result * from the HtmlLike `contains()` call target, the eventName, and optional eventArgs when provided (undefined otherwise) * @constructor */ function AssertionGenerator(options) { this._options = Object.assign({}, options); this._PENDING_EVENT_IDENTIFIER = options.mainAssertionGenerator && options.mainAssertionGenerator.getEventIdentifier() || { dummy: options.actualTypeName + 'PendingEventIdentifier' }; this._actualPendingEventTypeName = options.actualTypeName + 'PendingEvent'; } AssertionGenerator.prototype.getEventIdentifier = function () { return this._PENDING_EVENT_IDENTIFIER; }; AssertionGenerator.prototype.installInto = function installInto(expect) { this._installEqualityAssertions(expect); this._installQueriedFor(expect); this._installPendingEventType(expect); this._installWithEvent(expect); this._installWithEventOn(expect); this._installEventHandlerAssertions(expect); }; AssertionGenerator.prototype.installAlternativeExpected = function (expect) { this._installEqualityAssertions(expect); this._installEventHandlerAssertions(expect); }; AssertionGenerator.prototype._installEqualityAssertions = function (expect) { var _options = this._options, actualTypeName = _options.actualTypeName, expectedTypeName = _options.expectedTypeName, getRenderOutput = _options.getRenderOutput, actualRenderOutputType = _options.actualRenderOutputType, getDiffInputFromRenderOutput = _options.getDiffInputFromRenderOutput, ActualAdapter = _options.ActualAdapter, ExpectedAdapter = _options.ExpectedAdapter; expect.addAssertion(['<' + actualTypeName + '> to have [exactly] rendered <' + expectedTypeName + '>', '<' + actualTypeName + '> to have rendered [with all children] [with all wrappers] [with all classes] [with all attributes] <' + expectedTypeName + '>'], function (expect, subject, renderOutput) { var actual = getRenderOutput(subject); return expect(actual, 'to have [exactly] rendered [with all children] [with all wrappers] [with all classes] [with all attributes]', renderOutput); }); expect.addAssertion(['<' + actualRenderOutputType + '> to have [exactly] rendered <' + expectedTypeName + '>', '<' + actualRenderOutputType + '> to have rendered [with all children] [with all wrappers] [with all classes] [with all attributes] <' + expectedTypeName + '>'], function (expect, subject, renderOutput) { var exactly = this.flags.exactly; var withAllChildren = this.flags['with all children']; var withAllWrappers = this.flags['with all wrappers']; var withAllClasses = this.flags['with all classes']; var withAllAttributes = this.flags['with all attributes']; var actualAdapter = new ActualAdapter({ includeKeyProp: true }); var expectedAdapter = new ExpectedAdapter({ includeKeyProp: true }); var testHtmlLike = new _unexpectedHtmllike2.default(actualAdapter); if (!exactly) { expectedAdapter.setOptions({ concatTextContent: true }); actualAdapter.setOptions({ concatTextContent: true }); } var options = getDefaultOptions({ exactly: exactly, withAllWrappers: withAllWrappers, withAllChildren: withAllChildren, withAllClasses: withAllClasses, withAllAttributes: withAllAttributes }); var diffResult = testHtmlLike.diff(expectedAdapter, getDiffInputFromRenderOutput(subject), renderOutput, expect, options); return testHtmlLike.withResult(diffResult, function (result) { if (result.weight !== 0) { return expect.fail({ diff: function diff(output, _diff, inspect) { return { diff: output.append(testHtmlLike.render(result, output.clone(), _diff, inspect)) }; } }); } }); }); expect.addAssertion(['<' + actualTypeName + '> [not] to contain [exactly] <' + expectedTypeName + '|string>', '<' + actualTypeName + '> [not] to contain [with all children] [with all wrappers] [with all classes] [with all attributes] <' + expectedTypeName + '|string>'], function (expect, subject, renderOutput) { var actual = getRenderOutput(subject); return expect(actual, '[not] to contain [exactly] [with all children] [with all wrappers] [with all classes] [with all attributes]', renderOutput); }); expect.addAssertion(['<' + actualRenderOutputType + '> [not] to contain [exactly] <' + expectedTypeName + '|string>', '<' + actualRenderOutputType + '> [not] to contain [with all children] [with all wrappers] [with all classes] [with all attributes] <' + expectedTypeName + '|string>'], function (expect, subject, expected) { var not = this.flags.not; var exactly = this.flags.exactly; var withAllChildren = this.flags['with all children']; var withAllWrappers = this.flags['with all wrappers']; var withAllClasses = this.flags['with all classes']; var withAllAttributes = this.flags['with all attributes']; var actualAdapter = new ActualAdapter({ includeKeyProp: true }); var expectedAdapter = new ExpectedAdapter({ includeKeyProp: true }); var testHtmlLike = new _unexpectedHtmllike2.default(actualAdapter); if (!exactly) { actualAdapter.setOptions({ concatTextContent: true }); expectedAdapter.setOptions({ concatTextContent: true }); } var options = getDefaultOptions({ exactly: exactly, withAllWrappers: withAllWrappers, withAllChildren: withAllChildren, withAllClasses: withAllClasses, withAllAttributes: withAllAttributes }); var containsResult = testHtmlLike.contains(expectedAdapter, getDiffInputFromRenderOutput(subject), expected, expect, options); return testHtmlLike.withResult(containsResult, function (result) { if (not) { if (result.found) { expect.fail({ diff: function diff(output, _diff2, inspect) { return { diff: output.error('but found the following match').nl().append(testHtmlLike.render(result.bestMatch, output.clone(), _diff2, inspect)) }; } }); } return; } if (!result.found) { expect.fail({ diff: function diff(output, _diff3, inspect) { return { diff: output.error('the best match was').nl().append(testHtmlLike.render(result.bestMatch, output.clone(), _diff3, inspect)) }; } }); } }); }); // More generic assertions expect.addAssertion('<' + actualTypeName + '> to equal <' + expectedTypeName + '>', function (expect, subject, expected) { expect(getRenderOutput(subject), 'to equal', expected); }); expect.addAssertion('<' + actualRenderOutputType + '> to equal <' + expectedTypeName + '>', function (expect, subject, expected) { expect(subject, 'to have exactly rendered', expected); }); expect.addAssertion('<' + actualTypeName + '> to satisfy <' + expectedTypeName + '>', function (expect, subject, expected) { expect(getRenderOutput(subject), 'to satisfy', expected); }); expect.addAssertion('<' + actualRenderOutputType + '> to satisfy <' + expectedTypeName + '>', function (expect, subject, expected) { expect(subject, 'to have rendered', expected); }); }; AssertionGenerator.prototype._installQueriedFor = function (expect) { var _options2 = this._options, actualTypeName = _options2.actualTypeName, queryTypeName = _options2.queryTypeName, getRenderOutput = _options2.getRenderOutput, actualRenderOutputType = _options2.actualRenderOutputType, getDiffInputFromRenderOutput = _options2.getDiffInputFromRenderOutput, rewrapResult = _options2.rewrapResult, wrapResultForReturn = _options2.wrapResultForReturn, ActualAdapter = _options2.ActualAdapter, QueryAdapter = _options2.QueryAdapter; expect.addAssertion(['<' + actualTypeName + '> queried for [exactly] <' + queryTypeName + '> <assertion?>', '<' + actualTypeName + '> queried for [with all children] [with all wrapppers] [with all classes] [with all attributes] <' + queryTypeName + '> <assertion?>'], function (expect, subject, query, assertion) { return expect.apply(expect, [getRenderOutput(subject), 'queried for [exactly] [with all children] [with all wrappers] [with all classes] [with all attributes]', query].concat(Array.prototype.slice.call(arguments, 3))); }); expect.addAssertion(['<' + actualRenderOutputType + '> queried for [exactly] <' + queryTypeName + '> <assertion?>', '<' + actualRenderOutputType + '> queried for [with all children] [with all wrapppers] [with all classes] [with all attributes] <' + queryTypeName + '> <assertion?>'], function (expect, subject, query) { var exactly = this.flags.exactly; var withAllChildren = this.flags['with all children']; var withAllWrappers = this.flags['with all wrappers']; var withAllClasses = this.flags['with all classes']; var withAllAttributes = this.flags['with all attributes']; var actualAdapter = new ActualAdapter({ includeKeyProp: true }); var queryAdapter = new QueryAdapter({ includeKeyProp: true }); var testHtmlLike = new _unexpectedHtmllike2.default(actualAdapter); if (!exactly) { actualAdapter.setOptions({ concatTextContent: true }); queryAdapter.setOptions({ concatTextContent: true }); } var options = getDefaultOptions({ exactly: exactly, withAllWrappers: withAllWrappers, withAllChildren: withAllChildren, withAllClasses: withAllClasses, withAllAttributes: withAllAttributes }); options.findTargetAttrib = 'queryTarget'; var containsResult = testHtmlLike.contains(queryAdapter, getDiffInputFromRenderOutput(subject), query, expect, options); var args = arguments; return testHtmlLike.withResult(containsResult, function (result) { if (!result.found) { expect.fail({ diff: function diff(output, _diff4, inspect) { var resultOutput = { diff: output.error('`queried for` found no match.') }; if (result.bestMatch) { resultOutput.diff.error(' The best match was').nl().append(testHtmlLike.render(result.bestMatch, output.clone(), _diff4, inspect)); } return resultOutput; } }); } if (args.length > 3) { // There is an assertion continuation... expect.errorMode = 'nested'; var s = rewrapResult(subject, result.bestMatch.target || result.bestMatchItem); return expect.apply(null, [rewrapResult(subject, result.bestMatch.target || result.bestMatchItem)].concat(Array.prototype.slice.call(args, 3))); return expect.shift(rewrapResult(subject, result.bestMatch.target || result.bestMatchItem)); } // There is no assertion continuation, so we need to wrap the result for public consumption // i.e. create a value that we can give back from the `expect` promise return expect.shift((wrapResultForReturn || rewrapResult)(subject, result.bestMatch.target || result.bestMatchItem)); }); }); }; AssertionGenerator.prototype._installPendingEventType = function (expect) { var actualPendingEventTypeName = this._actualPendingEventTypeName; var PENDING_EVENT_IDENTIFIER = this._PENDING_EVENT_IDENTIFIER; expect.addType({ name: actualPendingEventTypeName, base: 'object', identify: function identify(value) { return value && (typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' && value.$$typeof === PENDING_EVENT_IDENTIFIER; }, inspect: function inspect(value, depth, output, _inspect) { return output.append(_inspect(value.renderer)).red(' with pending event \'').cyan(value.eventName).red('\''); } }); }; AssertionGenerator.prototype._installWithEvent = function (expect) { var _options3 = this._options, actualTypeName = _options3.actualTypeName, actualRenderOutputType = _options3.actualRenderOutputType, triggerEvent = _options3.triggerEvent, canTriggerEventsOnOutputType = _options3.canTriggerEventsOnOutputType; var _options$wrapResultFo = this._options.wrapResultForReturn, wrapResultForReturn = _options$wrapResultFo === undefined ? function (value) { return value; } : _options$wrapResultFo; var actualPendingEventTypeName = this._actualPendingEventTypeName; var PENDING_EVENT_IDENTIFIER = this._PENDING_EVENT_IDENTIFIER; expect.addAssertion('<' + actualTypeName + '> with event <string> <assertion?>', function (expect, subject, eventName) { for (var _len = arguments.length, assertion = Array(_len > 3 ? _len - 3 : 0), _key = 3; _key < _len; _key++) { assertion[_key - 3] = arguments[_key]; } if (arguments.length > 3) { return expect.apply(null, [{ $$typeof: PENDING_EVENT_IDENTIFIER, renderer: subject, eventName: eventName }].concat(assertion)); } else { triggerEvent(subject, null, eventName); return expect.shift(wrapResultForReturn(subject)); } }); expect.addAssertion('<' + actualTypeName + '> with event <string> <object> <assertion?>', function (expect, subject, eventName, args) { if (arguments.length > 4) { return expect.shift({ $$typeof: PENDING_EVENT_IDENTIFIER, renderer: subject, eventName: eventName, eventArgs: args }); } else { triggerEvent(subject, null, eventName, args); return expect.shift(wrapResultForReturn(subject)); } }); if (canTriggerEventsOnOutputType) { expect.addAssertion('<' + actualRenderOutputType + '> with event <string> <assertion?>', function (expect, subject, eventName) { for (var _len2 = arguments.length, assertion = Array(_len2 > 3 ? _len2 - 3 : 0), _key2 = 3; _key2 < _len2; _key2++) { assertion[_key2 - 3] = arguments[_key2]; } if (arguments.length > 3) { expect.errorMode = 'bubble'; return expect.apply(null, [{ $$typeof: PENDING_EVENT_IDENTIFIER, renderer: subject, eventName: eventName, isOutputType: true }].concat(assertion)); } else { triggerEvent(subject, null, eventName); return expect.shift(wrapResultForReturn(subject)); } }); expect.addAssertion('<' + actualRenderOutputType + '> with event <string> <object> <assertion?>', function (expect, subject, eventName, args) { if (arguments.length > 4) { return expect.shift({ $$typeof: PENDING_EVENT_IDENTIFIER, renderer: subject, eventName: eventName, eventArgs: args, isOutputType: true }); } else { triggerEvent(subject, null, eventName, args); return expect.shift(subject); } }); } expect.addAssertion('<' + actualPendingEventTypeName + '> [and] with event <string> <assertion?>', function (expect, subject, eventName) { triggerEvent(subject.renderer, subject.target, subject.eventName, subject.eventArgs); if (arguments.length > 3) { return expect.shift({ $$typeof: PENDING_EVENT_IDENTIFIER, renderer: subject.renderer, eventName: eventName }); } else { triggerEvent(subject.renderer, null, eventName); return expect.shift(wrapResultForReturn(subject.renderer)); } }); expect.addAssertion('<' + actualPendingEventTypeName + '> [and] with event <string> <object> <assertion?>', function (expect, subject, eventName, eventArgs) { triggerEvent(subject.renderer, subject.target, subject.eventName, subject.eventArgs); if (arguments.length > 4) { return expect.shift({ $$typeof: PENDING_EVENT_IDENTIFIER, renderer: subject.renderer, eventName: eventName, eventArgs: eventArgs }); } else { triggerEvent(subject.renderer, null, eventName, eventArgs); return expect.shift(wrapResultForReturn(subject.renderer)); } }); }; AssertionGenerator.prototype._installWithEventOn = function (expect) { var _options4 = this._options, actualTypeName = _options4.actualTypeName, queryTypeName = _options4.queryTypeName, expectedTypeName = _options4.expectedTypeName, getRenderOutput = _options4.getRenderOutput, getDiffInputFromRenderOutput = _options4.getDiffInputFromRenderOutput, triggerEvent = _options4.triggerEvent, wrapResultForReturn = _options4.wrapResultForReturn, ActualAdapter = _options4.ActualAdapter, QueryAdapter = _options4.QueryAdapter; var actualPendingEventTypeName = this._actualPendingEventTypeName; expect.addAssertion('<' + actualPendingEventTypeName + '> on [exactly] [with all children] [with all wrappers] [with all classes] [with all attributes]<' + queryTypeName + '> <assertion?>', function (expect, subject, target) { var _arguments = arguments; var actualAdapter = new ActualAdapter({ includeKeyProp: true, convertToString: true, concatTextContent: true }); var queryAdapter = new QueryAdapter({ includeKeyProp: true, convertToString: true, concatTextContent: true }); var testHtmlLike = new _unexpectedHtmllike2.default(actualAdapter); var exactly = this.flags.exactly; var withAllChildren = this.flags['with all children']; var withAllWrappers = this.flags['with all wrappers']; var withAllClasses = this.flags['with all classes']; var withAllAttributes = this.flags['with all attributes']; var options = getDefaultOptions({ exactly: exactly, withAllWrappers: withAllWrappers, withAllChildren: withAllChildren, withAllClasses: withAllClasses, withAllAttributes: withAllAttributes }); options.findTargetAttrib = 'eventTarget'; var containsResult = testHtmlLike.contains(queryAdapter, getDiffInputFromRenderOutput(getRenderOutput(subject.renderer)), target, expect, options); return testHtmlLike.withResult(containsResult, function (result) { if (!result.found) { return expect.fail({ diff: function diff(output, _diff5, inspect) { output.error('Could not find the target for the event. '); if (result.bestMatch) { output.error('The best match was').nl().nl().append(testHtmlLike.render(result.bestMatch, output.clone(), _diff5, inspect)); } return output; } }); } var newSubject = Object.assign({}, subject, { target: result.bestMatch.target || result.bestMatchItem }); if (_arguments.length > 3) { return expect.shift(newSubject); } else { triggerEvent(newSubject.renderer, newSubject.target, newSubject.eventName, newSubject.eventArgs); return expect.shift(wrapResultForReturn(newSubject.renderer)); } }); }); expect.addAssertion(['<' + actualPendingEventTypeName + '> queried for [exactly] <' + queryTypeName + '> <assertion?>', '<' + actualPendingEventTypeName + '> queried for [with all children] [with all wrappers] [with all classes] [with all attributes] <' + queryTypeName + '> <assertion?>'], function (expect, subject, expected) { triggerEvent(subject.renderer, subject.target, subject.eventName, subject.eventArgs); return expect.apply(expect, [subject.renderer, 'queried for [exactly] [with all children] [with all wrappers] [with all classes] [with all attributes]', expected].concat(Array.prototype.slice.call(arguments, 3))); }); }; AssertionGenerator.prototype._installEventHandlerAssertions = function (expect) { var _options5 = this._options, actualTypeName = _options5.actualTypeName, expectedTypeName = _options5.expectedTypeName, triggerEvent = _options5.triggerEvent; var actualPendingEventTypeName = this._actualPendingEventTypeName; expect.addAssertion(['<' + actualPendingEventTypeName + '> [not] to contain [exactly] <' + expectedTypeName + '|string>', '<' + actualPendingEventTypeName + '> [not] to contain [with all children] [with all wrappers] [with all classes] [with all attributes] <' + expectedTypeName + '|string>'], function (expect, subject, expected) { triggerEvent(subject.renderer, subject.target, subject.eventName, subject.eventArgs); return expect(subject.renderer, '[not] to contain [exactly] [with all children] [with all wrappers] [with all classes] [with all attributes]', expected); }); expect.addAssertion('<' + actualPendingEventTypeName + '> to have [exactly] rendered [with all children] [with all wrappers] [with all classes] [with all attributes] <' + expectedTypeName + '|string>', function (expect, subject, expected) { triggerEvent(subject.renderer, subject.target, subject.eventName, subject.eventArgs); return expect(subject.renderer, 'to have [exactly] rendered [with all children] [with all wrappers] [with all classes] [with all attributes]', expected); }); }; exports.default = AssertionGenerator; //# sourceMappingURL=AssertionGenerator.js.map