Best JavaScript code snippet using unexpected
createTopLevelExpect.js
Source:createTopLevelExpect.js
...15const throwIfNonUnexpectedError = require('./throwIfNonUnexpectedError');16const ensureValidUseOfParenthesesOrBrackets = require('./ensureValidUseOfParenthesesOrBrackets');17const expandAssertion = require('./expandAssertion');18const nodeJsCustomInspect = require('./nodeJsCustomInspect');19function isAssertionArg({ type }) {20 return type.is('assertion');21}22const anyType = {23 _unexpectedType: true,24 name: 'any',25 level: 0,26 identify() {27 return true;28 },29 equal: utils.objectIs,30 inspect(value, depth, output) {31 if (output && output.isMagicPen) {32 return output.text(value);33 } else {34 // Guard against node.js' require('util').inspect eagerly calling .inspect() on objects35 return `type: ${this.name}`;36 }37 },38 diff(actual, expected, output, diff, inspect) {39 return null;40 },41 typeEqualityCache: {},42 is(typeOrTypeName) {43 let typeName;44 if (typeof typeOrTypeName === 'string') {45 typeName = typeOrTypeName;46 } else {47 typeName = typeOrTypeName.name;48 }49 const cachedValue = this.typeEqualityCache[typeName];50 if (typeof cachedValue !== 'undefined') {51 return cachedValue;52 }53 let result = false;54 if (this.name === typeName) {55 result = true;56 } else if (this.baseType) {57 result = this.baseType.is(typeName);58 }59 this.typeEqualityCache[typeName] = result;60 return result;61 },62};63if (nodeJsCustomInspect !== 'inspect') {64 anyType[nodeJsCustomInspect] = function () {65 return `type: ${this.name}`;66 };67}68const OR = {};69function getOrGroups(expectations) {70 const orGroups = [[]];71 expectations.forEach((expectation) => {72 if (expectation === OR) {73 orGroups.push([]);74 } else {75 orGroups[orGroups.length - 1].push(expectation);76 }77 });78 return orGroups;79}80function evaluateGroup(expect, context, subject, orGroup, forwardedFlags) {81 return orGroup.map((expectation) => {82 const args = Array.prototype.slice.call(expectation);83 args.unshift(subject);84 return {85 expectation: args,86 promise: makePromise(() => {87 if (typeof args[1] === 'function') {88 if (args.length > 2) {89 throw new Error(90 'expect.it(<function>) does not accept additional arguments'91 );92 } else {93 // expect.it(function (value) { ... })94 return args[1](args[0]);95 }96 } else {97 return expect._expect(context.child(), args, forwardedFlags);98 }99 }),100 };101 });102}103function writeGroupEvaluationsToOutput(output, groupEvaluations) {104 const hasOrClauses = groupEvaluations.length > 1;105 const hasAndClauses = groupEvaluations.some(({ length }) => length > 1);106 groupEvaluations.forEach((groupEvaluation, i) => {107 if (i > 0) {108 if (hasAndClauses) {109 output.nl();110 } else {111 output.sp();112 }113 output.jsComment('or').nl();114 }115 let groupFailed = false;116 groupEvaluation.forEach((evaluation, j) => {117 if (j > 0) {118 output.jsComment(' and').nl();119 }120 const isRejected = evaluation.promise.isRejected();121 if (isRejected && !groupFailed) {122 groupFailed = true;123 const err = evaluation.promise.reason();124 if (hasAndClauses || hasOrClauses) {125 output.error('⨯ ');126 }127 output.block((output) => {128 output.append(err.getErrorMessage(output));129 });130 } else {131 if (isRejected) {132 output.error('⨯ ');133 } else {134 output.success('â ');135 }136 const expectation = evaluation.expectation;137 output.block((output) => {138 const subject = expectation[0];139 const subjectOutput = (output) => {140 output.appendInspected(subject);141 };142 const args = expectation.slice(2);143 const argsOutput = args.map((arg) => (output) => {144 output.appendInspected(arg);145 });146 const testDescription = expectation[1];147 createStandardErrorMessage(148 output,149 subjectOutput,150 testDescription,151 argsOutput,152 {153 subject,154 }155 );156 });157 }158 });159 });160}161function createExpectIt(expect, expectations, forwardedFlags) {162 const orGroups = getOrGroups(expectations);163 function expectIt(subject, context) {164 context =165 context && typeof context === 'object' && context instanceof Context166 ? context167 : new Context();168 if (169 orGroups.length === 1 &&170 orGroups[0].length === 1 &&171 orGroups[0][0].length === 1 &&172 typeof orGroups[0][0][0] === 'function'173 ) {174 // expect.it(subject => ...)175 return oathbreaker(orGroups[0][0][0](subject));176 }177 const groupEvaluations = [];178 const promises = [];179 orGroups.forEach((orGroup) => {180 const evaluations = evaluateGroup(181 expect,182 context,183 subject,184 orGroup,185 forwardedFlags186 );187 evaluations.forEach(({ promise }) => {188 promises.push(promise);189 });190 groupEvaluations.push(evaluations);191 });192 return oathbreaker(193 makePromise.settle(promises).then(() => {194 groupEvaluations.forEach((groupEvaluation) => {195 groupEvaluation.forEach(({ promise }) => {196 if (197 promise.isRejected() &&198 promise.reason().errorMode === 'bubbleThrough'199 ) {200 throw promise.reason();201 }202 });203 });204 if (205 !groupEvaluations.some((groupEvaluation) =>206 groupEvaluation.every(({ promise }) => promise.isFulfilled())207 )208 ) {209 expect.fail((output) => {210 writeGroupEvaluationsToOutput(output, groupEvaluations);211 });212 }213 })214 );215 }216 expectIt._expectIt = true;217 expectIt._expectations = expectations;218 expectIt._OR = OR;219 expectIt.and = function (...args) {220 const copiedExpectations = expectations.slice();221 copiedExpectations.push(args);222 return createExpectIt(expect, copiedExpectations, forwardedFlags);223 };224 expectIt.or = function (...args) {225 const copiedExpectations = expectations.slice();226 copiedExpectations.push(OR, args);227 return createExpectIt(expect, copiedExpectations, forwardedFlags);228 };229 return expectIt;230}231const expectPrototype = {232 promise: makePromise,233 notifyPendingPromise,234 errorMode: 'default',235};236utils.setPrototypeOfOrExtend(expectPrototype, Function.prototype);237expectPrototype.it = function (...args) {238 return createExpectIt(this._topLevelExpect, [args], this.flags);239};240expectPrototype.equal = function (actual, expected, depth, seen) {241 depth = typeof depth === 'number' ? depth : 100;242 if (depth <= 0) {243 // detect recursive loops in the structure244 seen = seen || [];245 if (seen.indexOf(actual) !== -1) {246 throw new Error('Cannot compare circular structures');247 }248 seen.push(actual);249 }250 return this.findCommonType(actual, expected).equal(actual, expected, (a, b) =>251 this.equal(a, b, depth - 1, seen)252 );253};254expectPrototype.inspect = function (obj, depth, outputOrFormat) {255 let seen = [];256 const printOutput = (obj, currentDepth, output) => {257 const objType = this.findTypeOf(obj);258 if (currentDepth <= 0 && objType.is('object') && !objType.is('expect.it')) {259 return output.text('...');260 }261 seen = seen || [];262 if (seen.indexOf(obj) !== -1) {263 return output.text('[Circular]');264 }265 return objType.inspect(obj, currentDepth, output, (v, childDepth) => {266 output = output.clone();267 seen.push(obj);268 if (typeof childDepth === 'undefined') {269 childDepth = currentDepth - 1;270 }271 output = printOutput(v, childDepth, output) || output;272 seen.pop();273 return output;274 });275 };276 let output =277 typeof outputOrFormat === 'string'278 ? this.createOutput(outputOrFormat)279 : outputOrFormat;280 output = output || this.createOutput();281 return (282 printOutput(283 obj,284 typeof depth === 'number' ? depth : defaultDepth,285 output286 ) || output287 );288};289if (nodeJsCustomInspect !== 'inspect') {290 expectPrototype[nodeJsCustomInspect] = expectPrototype.inspect;291}292expectPrototype.expandTypeAlternations = function (assertion) {293 const createPermutations = (args, i) => {294 if (i === args.length) {295 return [];296 }297 const result = [];298 args[i].forEach((arg) => {299 const tails = createPermutations(args, i + 1);300 if (tails.length) {301 tails.forEach((tail) => {302 result.push([arg].concat(tail));303 });304 } else if (arg.type.is('assertion')) {305 result.push([306 { type: arg.type, minimum: 1, maximum: 1 },307 { type: this.getType('any'), minimum: 0, maximum: Infinity },308 ]);309 result.push([310 { type: this.getType('expect.it'), minimum: 1, maximum: 1 },311 ]);312 if (arg.minimum === 0) {313 // <assertion?>314 result.push([]);315 }316 } else {317 result.push([arg]);318 }319 });320 return result;321 };322 const result = [];323 assertion.subject.forEach((subjectRequirement) => {324 if (assertion.args.length) {325 createPermutations(assertion.args, 0).forEach((args) => {326 result.push(327 extend({}, assertion, {328 subject: subjectRequirement,329 args,330 })331 );332 });333 } else {334 result.push(335 extend({}, assertion, {336 subject: subjectRequirement,337 args: [],338 })339 );340 }341 });342 return result;343};344expectPrototype.parseAssertion = function (assertionString) {345 const tokens = [];346 let nextIndex = 0;347 const parseTypeToken = (typeToken) => {348 return typeToken.split('|').map((typeDeclaration) => {349 const matchNameAndOperator = typeDeclaration.match(350 /^([a-z_](?:|[a-z0-9_.-]*[_a-z0-9]))([+*?]|)$/i351 );352 if (!matchNameAndOperator) {353 throw new SyntaxError(354 `Cannot parse type declaration:${typeDeclaration}`355 );356 }357 const type = this.getType(matchNameAndOperator[1]);358 if (!type) {359 throw new Error(360 `Unknown type: ${matchNameAndOperator[1]} in ${assertionString}`361 );362 }363 const operator = matchNameAndOperator[2];364 return {365 minimum: !operator || operator === '+' ? 1 : 0,366 maximum: operator === '*' || operator === '+' ? Infinity : 1,367 type,368 };369 });370 };371 function hasVarargs(types) {372 return types.some(({ minimum, maximum }) => minimum !== 1 || maximum !== 1);373 }374 assertionString.replace(375 /\s*<((?:[a-z_](?:|[a-z0-9_.-]*[_a-z0-9])[?*+]?)(?:\|(?:[a-z_](?:|[a-z0-9_.-]*[_a-z0-9])[?*+]?))*)>|\s*([^<]+)/gi,376 ({ length }, $1, $2, index) => {377 if (index !== nextIndex) {378 throw new SyntaxError(379 `Cannot parse token at index ${nextIndex} in ${assertionString}`380 );381 }382 if ($1) {383 tokens.push(parseTypeToken($1));384 } else {385 tokens.push($2.trim());386 }387 nextIndex += length;388 }389 );390 const assertion = {391 subject: tokens[0],392 assertion: tokens[1],393 args: tokens.slice(2),394 };395 if (!Array.isArray(assertion.subject)) {396 throw new SyntaxError(`Missing subject type in ${assertionString}`);397 }398 if (typeof assertion.assertion !== 'string') {399 throw new SyntaxError(`Missing assertion in ${assertionString}`);400 }401 if (hasVarargs(assertion.subject)) {402 throw new SyntaxError(403 `The subject type cannot have varargs: ${assertionString}`404 );405 }406 if (assertion.args.some((arg) => typeof arg === 'string')) {407 throw new SyntaxError('Only one assertion string is supported (see #225)');408 }409 if (assertion.args.slice(0, -1).some(hasVarargs)) {410 throw new SyntaxError(411 `Only the last argument type can have varargs: ${assertionString}`412 );413 }414 if (415 [assertion.subject]416 .concat(assertion.args.slice(0, -1))417 .some((argRequirements) =>418 argRequirements.some(({ type }) => type.is('assertion'))419 )420 ) {421 throw new SyntaxError(422 `Only the last argument type can be <assertion>: ${assertionString}`423 );424 }425 const lastArgRequirements = assertion.args[assertion.args.length - 1] || [];426 const assertionRequirements = lastArgRequirements.filter(({ type }) =>427 type.is('assertion')428 );429 if (assertionRequirements.length > 0 && lastArgRequirements.length > 1) {430 throw new SyntaxError(431 `<assertion> cannot be alternated with other types: ${assertionString}`432 );433 }434 if (assertionRequirements.some(({ maximum }) => maximum !== 1)) {435 throw new SyntaxError(436 `<assertion+> and <assertion*> are not allowed: ${assertionString}`437 );438 }439 return this.expandTypeAlternations(assertion);440};441const placeholderSplitRegexp = /(\{(?:\d+)\})/g;442const placeholderRegexp = /\{(\d+)\}/;443expectPrototype._fail = function (arg) {444 if (arg instanceof UnexpectedError) {445 arg._hasSerializedErrorMessage = false;446 throw arg;447 }448 if (utils.isError(arg)) {449 throw arg;450 }451 const error = new UnexpectedError(this);452 if (typeof arg === 'function') {453 error.errorMode = 'bubble';454 error.output = arg;455 } else if (arg && typeof arg === 'object') {456 if (typeof arg.message !== 'undefined') {457 error.errorMode = 'bubble';458 }459 error.output = (output) => {460 if (typeof arg.message !== 'undefined') {461 if (arg.message.isMagicPen) {462 output.append(arg.message);463 } else if (typeof arg.message === 'function') {464 arg.message.call(output, output);465 } else {466 output.text(String(arg.message));467 }468 } else {469 output.error('Explicit failure');470 }471 };472 Object.keys(arg).forEach(function (key) {473 const value = arg[key];474 if (key === 'diff') {475 if (typeof value === 'function' && this.parent) {476 error.createDiff = (output, diff, inspect, equal) => {477 const childOutput = this.createOutput(output.format);478 childOutput.inline = output.inline;479 childOutput.output = output.output;480 return value(481 childOutput,482 (actual, expected) => {483 return this.diff(actual, expected, childOutput.clone());484 },485 (v, depth) =>486 childOutput487 .clone()488 .appendInspected(v, (depth || defaultDepth) - 1),489 (actual, expected) => this.equal(actual, expected)490 );491 };492 } else {493 error.createDiff = value;494 }495 } else if (key !== 'message') {496 error[key] = value;497 }498 }, this);499 } else {500 let placeholderArgs;501 if (arguments.length > 0) {502 placeholderArgs = new Array(arguments.length - 1);503 for (let i = 1; i < arguments.length; i += 1) {504 placeholderArgs[i - 1] = arguments[i];505 }506 }507 error.errorMode = 'bubble';508 error.output = (output) => {509 const message = arg ? String(arg) : 'Explicit failure';510 const tokens = message.split(placeholderSplitRegexp);511 tokens.forEach((token) => {512 const match = placeholderRegexp.exec(token);513 if (match) {514 const index = match[1];515 if (index in placeholderArgs) {516 const placeholderArg = placeholderArgs[index];517 if (placeholderArg && placeholderArg.isMagicPen) {518 output.append(placeholderArg);519 } else {520 output.appendInspected(placeholderArg);521 }522 } else {523 output.text(match[0]);524 }525 } else {526 output.error(token);527 }528 });529 };530 }531 throw error;532};533function compareSpecificities(a, b) {534 for (let i = 0; i < Math.min(a.length, b.length); i += 1) {535 const c = b[i] - a[i];536 if (c !== 0) {537 return c;538 }539 }540 return b.length - a.length;541}542function calculateAssertionSpecificity({ subject, args }) {543 return [subject.type.level].concat(544 args.map(({ minimum, maximum, type }) => {545 const bonus = minimum === 1 && maximum === 1 ? 0.5 : 0;546 return bonus + type.level;547 })548 );549}550function calculateLimits(items) {551 let minimum = 0;552 let maximum = 0;553 items.forEach((item) => {554 minimum += item.minimum;555 maximum += item.maximum;556 });557 return {558 minimum,559 maximum,560 };561}562expectPrototype.addAssertion = function (563 patternOrPatterns,564 handler,565 childExpect566) {567 if (this._frozen) {568 throw new Error(569 'Cannot add an assertion to a frozen instance, please run .clone() first'570 );571 }572 let maxArguments;573 if (typeof childExpect === 'function') {574 maxArguments = 3;575 } else {576 maxArguments = 2;577 }578 if (579 arguments.length > maxArguments ||580 typeof handler !== 'function' ||581 (typeof patternOrPatterns !== 'string' && !Array.isArray(patternOrPatterns))582 ) {583 let errorMessage =584 'Syntax: expect.addAssertion(<string|array[string]>, function (expect, subject, ...) { ... });';585 if (586 (typeof handler === 'string' || Array.isArray(handler)) &&587 typeof arguments[2] === 'function'588 ) {589 errorMessage +=590 '\nAs of Unexpected 10, the syntax for adding assertions that apply only to specific\n' +591 'types has changed. See http://unexpected.js.org/api/addAssertion/';592 }593 throw new Error(errorMessage);594 }595 const patterns = Array.isArray(patternOrPatterns)596 ? patternOrPatterns597 : [patternOrPatterns];598 patterns.forEach((pattern) => {599 if (typeof pattern !== 'string' || pattern === '') {600 throw new Error('Assertion patterns must be a non-empty string');601 } else {602 if (pattern !== pattern.trim()) {603 throw new Error(604 `Assertion patterns can't start or end with whitespace:\n\n ${JSON.stringify(605 pattern606 )}`607 );608 }609 }610 });611 const assertions = this.assertions;612 const defaultValueByFlag = {};613 const assertionHandlers = [];614 let maxNumberOfArgs = 0;615 patterns.forEach((pattern) => {616 const assertionDeclarations = this.parseAssertion(pattern);617 assertionDeclarations.forEach(({ assertion, args, subject }) => {618 ensureValidUseOfParenthesesOrBrackets(assertion);619 const expandedAssertions = expandAssertion(assertion);620 expandedAssertions.forEach(({ flags, alternations, text }) => {621 Object.keys(flags).forEach((flag) => {622 defaultValueByFlag[flag] = false;623 });624 maxNumberOfArgs = Math.max(625 maxNumberOfArgs,626 args.reduce(627 (previous, { maximum }) =>628 previous + (maximum === null ? Infinity : maximum),629 0630 )631 );632 const limits = calculateLimits(args);633 assertionHandlers.push({634 handler,635 alternations,636 flags,637 subject,638 args,639 testDescriptionString: text,640 declaration: pattern,641 expect: childExpect,642 minimum: limits.minimum,643 maximum: limits.maximum,644 });645 });646 });647 });648 if (handler.length - 2 > maxNumberOfArgs) {649 throw new Error(650 `The provided assertion handler takes ${651 handler.length - 2652 } parameters, but the type signature specifies a maximum of ${maxNumberOfArgs}:\n\n ${JSON.stringify(653 patterns654 )}`655 );656 }657 assertionHandlers.forEach((handler) => {658 // Make sure that all flags are defined.659 handler.flags = extend({}, defaultValueByFlag, handler.flags);660 const assertionHandlers = assertions[handler.testDescriptionString];661 handler.specificity = calculateAssertionSpecificity(handler);662 if (!assertionHandlers) {663 assertions[handler.testDescriptionString] = [handler];664 } else {665 let i = 0;666 while (667 i < assertionHandlers.length &&668 compareSpecificities(669 handler.specificity,670 assertionHandlers[i].specificity671 ) > 0672 ) {673 i += 1;674 }675 assertionHandlers.splice(i, 0, handler);676 }677 });678 return this; // for chaining679};680expectPrototype.addType = function (type, childExpect) {681 if (this._frozen) {682 throw new Error(683 'Cannot add a type to a frozen instance, please run .clone() first'684 );685 }686 let baseType;687 if (688 typeof type.name !== 'string' ||689 !/^[a-z_](?:|[a-z0-9_.-]*[_a-z0-9])$/i.test(type.name)690 ) {691 throw new Error(692 'A type must be given a non-empty name and must match ^[a-z_](?:|[a-z0-9_.-]*[_a-z0-9])$'693 );694 }695 if (typeof type.identify !== 'function' && type.identify !== false) {696 throw new Error(697 `Type ${type.name} must specify an identify function or be declared abstract by setting identify to false`698 );699 }700 if (this.typeByName[type.name]) {701 throw new Error(`The type with the name ${type.name} already exists`);702 }703 if (type.base) {704 baseType = this.getType(type.base);705 if (!baseType) {706 throw new Error(`Unknown base type: ${type.base}`);707 }708 } else {709 baseType = anyType;710 }711 const extendedBaseType = Object.create(baseType);712 extendedBaseType.inspect = (value, depth, output) => {713 if (!output || !output.isMagicPen) {714 throw new Error(715 'You need to pass the output to baseType.inspect() as the third parameter'716 );717 }718 return baseType.inspect(value, depth, output, (value, depth) =>719 output.clone().appendInspected(value, depth)720 );721 };722 if (nodeJsCustomInspect !== 'inspect') {723 extendedBaseType[nodeJsCustomInspect] = extendedBaseType.inspect;724 }725 extendedBaseType.diff = (actual, expected, output) => {726 if (!output || !output.isMagicPen) {727 throw new Error(728 'You need to pass the output to baseType.diff() as the third parameter'729 );730 }731 return baseType.diff(732 actual,733 expected,734 output.clone(),735 (actual, expected) => this.diff(actual, expected, output.clone()),736 (value, depth) => output.clone().appendInspected(value, depth),737 this.equal.bind(this)738 );739 };740 extendedBaseType.equal = (actual, expected) =>741 baseType.equal(actual, expected, this.equal.bind(this));742 const extendedType = extend({}, baseType, type, {743 baseType: extendedBaseType,744 });745 const originalInspect = extendedType.inspect;746 // Prevent node.js' util.inspect from complaining about our inspect method:747 if (nodeJsCustomInspect !== 'inspect') {748 extendedType[nodeJsCustomInspect] = function () {749 return `type: ${type.name}`;750 };751 }752 extendedType.inspect = function (obj, depth, output, inspect) {753 if (arguments.length < 2 || !output || !output.isMagicPen) {754 return `type: ${type.name}`;755 } else if (childExpect) {756 const childOutput = childExpect.createOutput(output.format);757 return (758 originalInspect.call(this, obj, depth, childOutput, inspect) ||759 childOutput760 );761 } else {762 return originalInspect.call(this, obj, depth, output, inspect) || output;763 }764 };765 if (childExpect) {766 extendedType.childExpect = childExpect;767 const originalDiff = extendedType.diff;768 extendedType.diff = function (769 actual,770 expected,771 output,772 inspect,773 diff,774 equal775 ) {776 const childOutput = childExpect.createOutput(output.format);777 // Make sure that already buffered up output is preserved:778 childOutput.output = output.output;779 return (780 originalDiff.call(781 this,782 actual,783 expected,784 childOutput,785 inspect,786 diff,787 equal788 ) || output789 );790 };791 }792 if (extendedType.identify === false) {793 this.types.push(extendedType);794 } else {795 this.types.unshift(extendedType);796 }797 extendedType.level = baseType.level + 1;798 extendedType.typeEqualityCache = {};799 this.typeByName[extendedType.name] = extendedType;800 return this;801};802expectPrototype.getType = function (typeName) {803 return (804 this.typeByName[typeName] || (this.parent && this.parent.getType(typeName))805 );806};807expectPrototype.findTypeOf = function (obj) {808 return (809 utils.findFirst(810 this.types || [],811 (type) => type.identify && type.identify(obj)812 ) ||813 (this.parent && this.parent.findTypeOf(obj))814 );815};816expectPrototype.findTypeOfWithParentType = function (obj, requiredParentType) {817 return (818 utils.findFirst(819 this.types || [],820 (type) =>821 type.identify &&822 type.identify(obj) &&823 (!requiredParentType || type.is(requiredParentType))824 ) ||825 (this.parent &&826 this.parent.findTypeOfWithParentType(obj, requiredParentType))827 );828};829expectPrototype.findCommonType = function (a, b) {830 const aAncestorIndex = {};831 let current = this.findTypeOf(a);832 while (current) {833 aAncestorIndex[current.name] = current;834 current = current.baseType;835 }836 current = this.findTypeOf(b);837 while (current) {838 if (aAncestorIndex[current.name]) {839 return current;840 }841 current = current.baseType;842 }843};844expectPrototype.addStyle = function (...args) {845 if (this._frozen) {846 throw new Error(847 'Cannot add a style to a frozen instance, please run .clone() first'848 );849 }850 this.output.addStyle(...args);851 return this;852};853expectPrototype.installTheme = function (...args) {854 if (this._frozen) {855 throw new Error(856 'Cannot install a theme into a frozen instance, please run .clone() first'857 );858 }859 this.output.installTheme(...args);860 return this;861};862function getPluginName(plugin) {863 if (typeof plugin === 'function') {864 return utils.getFunctionName(plugin);865 } else {866 return plugin.name;867 }868}869expectPrototype.use = function (plugin) {870 this._assertTopLevelExpect();871 if (this._frozen) {872 throw new Error(873 'Cannot install a plugin into a frozen instance, please run .clone() first'874 );875 }876 if (877 (typeof plugin !== 'function' &&878 (typeof plugin !== 'object' ||879 typeof plugin.installInto !== 'function')) ||880 (typeof plugin.name !== 'undefined' && typeof plugin.name !== 'string')881 ) {882 throw new Error(883 'Plugins must be functions or adhere to the following interface\n' +884 '{\n' +885 ' name: <an optional plugin name>,\n' +886 ' version: <an optional semver version string>,\n' +887 ' installInto: <a function that will update the given expect instance>\n' +888 '}'889 );890 }891 const pluginName = getPluginName(plugin);892 const existingPlugin = utils.findFirst(893 this.installedPlugins,894 (installedPlugin) => {895 if (installedPlugin === plugin) {896 return true;897 } else {898 return pluginName && pluginName === getPluginName(installedPlugin);899 }900 }901 );902 if (existingPlugin) {903 if (904 existingPlugin === plugin ||905 (typeof plugin.version !== 'undefined' &&906 plugin.version === existingPlugin.version)907 ) {908 // No-op909 return this;910 } else {911 throw new Error(912 `Another instance of the plugin '${pluginName}' is already installed${913 typeof existingPlugin.version !== 'undefined'914 ? ` (version ${existingPlugin.version}${915 typeof plugin.version !== 'undefined'916 ? `, trying to install ${plugin.version}`917 : ''918 })`919 : ''920 }. Please check your node_modules folder for unmet peerDependencies.`921 );922 }923 }924 if (pluginName === 'unexpected-promise') {925 throw new Error(926 'The unexpected-promise plugin was pulled into Unexpected as of 8.5.0. This means that the plugin is no longer supported.'927 );928 }929 if (pluginName === 'unexpected-set') {930 throw new Error(931 'The unexpected-set plugin was pulled into Unexpected as of 13.0.0. This means that the plugin is no longer supported.'932 );933 }934 this.installedPlugins.push(plugin);935 if (typeof plugin === 'function') {936 plugin(this);937 } else {938 plugin.installInto(this);939 }940 return this; // for chaining941};942expectPrototype.withError = (body, handler) =>943 oathbreaker(944 makePromise(body).caught((e) => {945 throwIfNonUnexpectedError(e);946 return handler(e);947 })948 );949expectPrototype.installPlugin = expectPrototype.use; // Legacy alias950expectPrototype.throwAssertionNotFoundError = function (951 subject,952 testDescriptionString,953 args954) {955 let candidateHandlers = this.assertions[testDescriptionString];956 let instance = this;957 while (instance && !candidateHandlers) {958 candidateHandlers = instance.assertions[testDescriptionString];959 instance = instance.parent;960 }961 if (candidateHandlers) {962 this.fail({963 message: (output) => {964 const subjectOutput = (output) => {965 output.appendInspected(subject);966 };967 const argsOutput = (output) => {968 output.appendItems(args, ', ');969 };970 output971 .append(972 createStandardErrorMessage(973 output.clone(),974 subjectOutput,975 testDescriptionString,976 argsOutput977 )978 )979 .nl()980 .indentLines();981 output982 .i()983 .error('The assertion does not have a matching signature for:')984 .nl()985 .indentLines()986 .i()987 .text('<')988 .text(this.findTypeOf(subject).name)989 .text('>')990 .sp()991 .text(testDescriptionString);992 args.forEach((arg, i) => {993 output.sp().text('<').text(this.findTypeOf(arg).name).text('>');994 });995 output.outdentLines().nl().i().text('did you mean:').indentLines().nl();996 const assertionDeclarations = Object.keys(997 candidateHandlers.reduce((result, { declaration }) => {998 result[declaration] = true;999 return result;1000 }, {})1001 ).sort();1002 assertionDeclarations.forEach((declaration, i) => {1003 output1004 .nl(i > 0 ? 1 : 0)1005 .i()1006 .text(declaration);1007 });1008 output.outdentLines();1009 },1010 });1011 }1012 const assertionsWithScore = [];1013 const assertionStrings = [];1014 instance = this;1015 while (instance) {1016 assertionStrings.push(...Object.keys(instance.assertions));1017 instance = instance.parent;1018 }1019 const compareAssertions = (a, b) => {1020 const aAssertion = this.lookupAssertionRule(subject, a, args);1021 const bAssertion = this.lookupAssertionRule(subject, b, args);1022 if (!aAssertion && !bAssertion) {1023 return 0;1024 }1025 if (aAssertion && !bAssertion) {1026 return -1;1027 }1028 if (!aAssertion && bAssertion) {1029 return 1;1030 }1031 return compareSpecificities(aAssertion.specificity, bAssertion.specificity);1032 };1033 assertionStrings.forEach((assertionString) => {1034 const score = ukkonen(testDescriptionString, assertionString);1035 assertionsWithScore.push({1036 assertion: assertionString,1037 score,1038 });1039 });1040 const bestMatch = assertionsWithScore1041 .sort((a, b) => {1042 const c = a.score - b.score;1043 if (c !== 0) {1044 return c;1045 }1046 if (a.assertion < b.assertion) {1047 return -1;1048 } else {1049 return 1;1050 }1051 })1052 .slice(0, 10)1053 .filter(({ score }, i, arr) => Math.abs(score - arr[0].score) <= 2)1054 .sort((a, b) => {1055 const c = compareAssertions(a.assertion, b.assertion);1056 if (c !== 0) {1057 return c;1058 }1059 return a.score - b.score;1060 })[0];1061 this.fail({1062 errorMode: 'bubbleThrough',1063 message(output) {1064 output1065 .error("Unknown assertion '")1066 .jsString(testDescriptionString)1067 .error("', did you mean: '")1068 .jsString(bestMatch.assertion)1069 .error("'");1070 },1071 });1072};1073expectPrototype.lookupAssertionRule = function (1074 subject,1075 testDescriptionString,1076 args,1077 requireAssertionSuffix1078) {1079 if (typeof testDescriptionString !== 'string') {1080 throw new Error(1081 'The expect function requires the second parameter to be a string or an expect.it.'1082 );1083 }1084 let handlers;1085 let instance = this;1086 while (instance) {1087 const instanceHandlers = instance.assertions[testDescriptionString];1088 if (instanceHandlers) {1089 handlers = handlers1090 ? handlers.concat(instanceHandlers)1091 : instanceHandlers;1092 }1093 instance = instance.parent;1094 }1095 if (!handlers) {1096 return null;1097 }1098 const cachedTypes = {};1099 const findTypeOf = (value, key) => {1100 let type = cachedTypes[key];1101 if (!type) {1102 type = this.findTypeOf(value);1103 cachedTypes[key] = type;1104 }1105 return type;1106 };1107 const matches = (value, assertionType, key, relaxed) => {1108 if (assertionType.is('assertion') && typeof value === 'string') {1109 return true;1110 }1111 if (relaxed) {1112 if (assertionType.identify === false) {1113 return this.types.some(1114 (type) =>1115 type.identify && type.is(assertionType) && type.identify(value)1116 );1117 }1118 return assertionType.identify(value);1119 } else {1120 return findTypeOf(value, key).is(assertionType);1121 }1122 };1123 function matchesHandler(handler, relaxed) {1124 if (!matches(subject, handler.subject.type, 'subject', relaxed)) {1125 return false;1126 }1127 if (requireAssertionSuffix && !handler.args.some(isAssertionArg)) {1128 return false;1129 }1130 if (args.length < handler.minimum || handler.maximum < args.length) {1131 return false;1132 } else if (args.length === 0 && handler.maximum === 0) {1133 return true;1134 }1135 const lastRequirement = handler.args[handler.args.length - 1];1136 return args.every((arg, i) => {1137 if (i < handler.args.length - 1) {1138 return matches(arg, handler.args[i].type, i, relaxed);1139 } else {1140 return matches(arg, lastRequirement.type, i, relaxed);1141 }1142 });1143 }1144 let j, handler;1145 for (j = 0; j < handlers.length; j += 1) {1146 handler = handlers[j];1147 if (matchesHandler(handler)) {1148 return handler;1149 }1150 }1151 for (j = 0; j < handlers.length; j += 1) {1152 handler = handlers[j];1153 if (matchesHandler(handler, true)) {1154 return handler;1155 }1156 }1157 return null;1158};1159expectPrototype._assertTopLevelExpect = function () {1160 // Cannot use this !== this._topLevelExpect due to https://github.com/unexpectedjs/unexpected/issues/6311161 if (this.flags) {1162 throw new Error('This method only works on the top level expect function');1163 }1164};1165expectPrototype._assertWrappedExpect = function () {1166 // Cannot use this === this._topLevelExpect due to https://github.com/unexpectedjs/unexpected/issues/6311167 if (!this.flags) {1168 throw new Error(1169 'This method only works on the expect function handed to an assertion'1170 );1171 }1172};1173expectPrototype.setErrorMessage = function (err) {1174 err.serializeMessage(this.outputFormat());1175};1176expectPrototype._createWrappedExpect = function (1177 assertionRule,1178 subject,1179 args,1180 testDescriptionString,1181 context,1182 forwardedFlags1183) {1184 const flags = extend({}, forwardedFlags, assertionRule.flags);1185 const parentExpect = this;1186 function wrappedExpect(subject, testDescriptionString) {1187 if (arguments.length === 0) {1188 throw new Error('The expect function requires at least one parameter.');1189 } else if (arguments.length === 1) {1190 return addAdditionalPromiseMethods(1191 makePromise.resolve(subject),1192 wrappedExpect,1193 subject1194 );1195 } else if (typeof testDescriptionString === 'function') {1196 wrappedExpect.errorMode = 'nested';1197 return wrappedExpect.withError(1198 () => testDescriptionString(subject),1199 (err) => {1200 wrappedExpect.fail(err);1201 }1202 );1203 }1204 testDescriptionString = utils.forwardFlags(testDescriptionString, flags);1205 const args = new Array(arguments.length - 2);1206 for (let i = 2; i < arguments.length; i += 1) {1207 args[i - 2] = arguments[i];1208 }1209 return wrappedExpect._callInNestedContext(() =>1210 parentExpect._executeExpect(1211 context.child(),1212 subject,1213 testDescriptionString,1214 args,1215 wrappedExpect.flags1216 )1217 );1218 }1219 utils.setPrototypeOfOrExtend(wrappedExpect, this);1220 wrappedExpect.context = context;1221 wrappedExpect.execute = wrappedExpect;1222 wrappedExpect.alternations = assertionRule.alternations;1223 wrappedExpect.flags = flags;1224 wrappedExpect.subject = subject;1225 wrappedExpect.testDescription = testDescriptionString;1226 wrappedExpect.args = args;1227 wrappedExpect.assertionRule = assertionRule;1228 wrappedExpect.subjectOutput = (output) => {1229 output.appendInspected(subject);1230 };1231 wrappedExpect.argsOutput = args.map((arg, i) => {1232 const argRule = wrappedExpect.assertionRule.args[i];1233 if (1234 typeof arg === 'string' &&1235 ((argRule && argRule.type.is('assertion')) ||1236 wrappedExpect._getAssertionIndices().indexOf(i) >= 0)1237 ) {1238 return new AssertionString(utils.forwardFlags(arg, flags));1239 }1240 return (output) => {1241 output.appendInspected(arg);1242 };1243 });1244 return wrappedExpect;1245};1246expectPrototype._executeExpect = function (1247 context,1248 subject,1249 testDescriptionString,1250 args,1251 forwardedFlags1252) {1253 if (forwardedFlags) {1254 testDescriptionString = utils.forwardFlags(1255 testDescriptionString,1256 forwardedFlags1257 );1258 }1259 let assertionRule = this.lookupAssertionRule(1260 subject,1261 testDescriptionString,1262 args1263 );1264 if (!assertionRule) {1265 const tokens = testDescriptionString.split(' ');1266 // eslint-disable-next-line no-labels1267 OUTER: for (let n = tokens.length - 1; n > 0; n -= 1) {1268 const prefix = tokens.slice(0, n).join(' ');1269 const remainingTokens = tokens.slice(n);1270 const argsWithAssertionPrepended = [remainingTokens.join(' ')].concat(1271 args1272 );1273 assertionRule = this.lookupAssertionRule(1274 subject,1275 prefix,1276 argsWithAssertionPrepended,1277 true1278 );1279 if (assertionRule) {1280 // Found the longest prefix of the string that yielded a suitable assertion for the given subject and args1281 // To avoid bogus error messages when shifting later (#394) we require some prefix of the remaining tokens1282 // to be a valid assertion name:1283 for (let i = 1; i < remainingTokens.length; i += 1) {1284 if (1285 Object.prototype.hasOwnProperty.call(1286 this.assertions,1287 remainingTokens.slice(0, i + 1).join(' ')1288 )1289 ) {1290 testDescriptionString = prefix;1291 args = argsWithAssertionPrepended;1292 // eslint-disable-next-line no-labels1293 break OUTER;1294 }1295 }1296 }1297 }1298 if (!assertionRule) {1299 this.throwAssertionNotFoundError(subject, testDescriptionString, args);1300 }1301 }1302 if (assertionRule.expect && assertionRule.expect !== this._topLevelExpect) {1303 return assertionRule.expect._expect(context, [1304 subject,1305 testDescriptionString,1306 ...args,1307 ]);1308 }1309 const wrappedExpect = this._createWrappedExpect(1310 assertionRule,1311 subject,1312 args,1313 testDescriptionString,1314 context,1315 forwardedFlags1316 );1317 return oathbreaker(assertionRule.handler(wrappedExpect, subject, ...args));1318};1319expectPrototype._expect = function (context, args, forwardedFlags) {1320 const subject = args[0];1321 const testDescriptionString = args[1];1322 if (args.length < 2) {1323 throw new Error('The expect function requires at least two parameters.');1324 } else if (typeof testDescriptionString === 'function') {1325 return this.withError(1326 () => testDescriptionString(subject),1327 (err) => {1328 this.fail(err);1329 }1330 );1331 }1332 try {1333 let result = this._executeExpect(1334 context,1335 subject,1336 testDescriptionString,1337 Array.prototype.slice.call(args, 2),1338 forwardedFlags1339 );1340 if (utils.isPromise(result)) {1341 result = wrapPromiseIfNecessary(result);1342 if (result.isPending()) {1343 result = result.then(undefined, (e) => {1344 if (e && e._isUnexpected && context.level === 0) {1345 this.setErrorMessage(e);1346 }1347 throw e;1348 });1349 this.notifyPendingPromise(result);1350 }1351 } else {1352 result = makePromise.resolve(result);1353 }1354 return addAdditionalPromiseMethods(result, this, subject);1355 } catch (e) {1356 if (e && e._isUnexpected) {1357 let newError = e;1358 if (typeof mochaPhantomJS !== 'undefined') {1359 newError = e.clone();1360 }1361 if (context.level === 0) {1362 this.setErrorMessage(newError);1363 }1364 throw newError;1365 }1366 throw e;1367 }1368};1369expectPrototype.diff = function (1370 a,1371 b,1372 output = this.createOutput(),1373 recursions,1374 seen1375) {1376 const maxRecursions = 100;1377 recursions = typeof recursions === 'number' ? recursions : maxRecursions;1378 if (recursions <= 0) {1379 // detect recursive loops in the structure1380 seen = seen || [];1381 if (seen.indexOf(a) !== -1) {1382 throw new Error('Cannot compare circular structures');1383 }1384 seen.push(a);1385 }1386 return this.findCommonType(a, b).diff(1387 a,1388 b,1389 output,1390 (actual, expected) =>1391 this.diff(actual, expected, output.clone(), recursions - 1, seen),1392 (v, depth) => output.clone().appendInspected(v, depth),1393 (actual, expected) => this.equal(actual, expected)1394 );1395};1396expectPrototype.toString = function () {1397 const assertions = this.assertions;1398 const seen = {};1399 const declarations = [];1400 const pen = magicpen();1401 Object.keys(assertions)1402 .sort()1403 .forEach((key) => {1404 assertions[key].forEach(({ declaration }) => {1405 if (!seen[declaration]) {1406 declarations.push(declaration);1407 seen[declaration] = true;1408 }1409 });1410 });1411 declarations.forEach((declaration) => {1412 pen.text(declaration).nl();1413 });1414 return pen.toString();1415};1416expectPrototype.clone = function () {1417 this._assertTopLevelExpect();1418 const clonedAssertions = {};1419 Object.keys(this.assertions).forEach(function (assertion) {1420 clonedAssertions[assertion] = [].concat(this.assertions[assertion]);1421 }, this);1422 const expect = createTopLevelExpect({1423 assertions: clonedAssertions,1424 types: [].concat(this.types),1425 typeByName: extend({}, this.typeByName),1426 output: this.output.clone(),1427 format: this.outputFormat(),1428 installedPlugins: [].concat(this.installedPlugins),1429 });1430 // Install the hooks:1431 this.installedHooks.forEach((hook) => {1432 expect.hook(hook);1433 });1434 // expect._expect = this._expect;1435 // Make sure that changes to the parent's preferredWidth doesn't propagate:1436 expect.output.preferredWidth = this.output.preferredWidth;1437 return expect;1438};1439expectPrototype.child = function () {1440 this._assertTopLevelExpect();1441 const childExpect = createTopLevelExpect(1442 {1443 assertions: {},1444 types: [],1445 typeByName: {},1446 output: this.output.clone(),1447 format: this.outputFormat(),1448 installedPlugins: [],1449 },1450 this1451 );1452 childExpect.exportAssertion = function (testDescription, handler) {1453 childExpect.parent.addAssertion(testDescription, handler, childExpect);1454 return this;1455 };1456 childExpect.exportType = function (type) {1457 if (childExpect.getType(type.name) !== type) {1458 childExpect.addType(type);1459 }1460 childExpect.parent.addType(type, childExpect);1461 return this;1462 };1463 childExpect.exportStyle = function (name, handler, allowRedefinition) {1464 childExpect.parent.addStyle(1465 name,1466 function (...args) {1467 const childOutput = childExpect.createOutput(this.format);1468 this.append(handler.call(childOutput, ...args) || childOutput);1469 },1470 allowRedefinition1471 );1472 return this;1473 };1474 return childExpect;1475};1476expectPrototype.freeze = function () {1477 this._assertTopLevelExpect();1478 this._frozen = true;1479 return this;1480};1481expectPrototype.outputFormat = function (format) {1482 if (typeof format === 'undefined') {1483 return this._outputFormat;1484 } else {1485 this._assertTopLevelExpect();1486 this._outputFormat = format;1487 return this;1488 }1489};1490expectPrototype.createOutput = function (format) {1491 const that = this;1492 const output = this.output.clone(format || 'text');1493 output.addStyle('appendInspected', function (value, depth) {1494 this.append(that.inspect(value, depth, this.clone()));1495 });1496 return output;1497};1498expectPrototype.hook = function (fn) {1499 this._assertTopLevelExpect();1500 if (this._frozen) {1501 throw new Error(1502 'Cannot install a hook into a frozen instance, please run .clone() first'1503 );1504 }1505 this.installedHooks.push(fn);1506 this._expect = fn(this._expect.bind(this));1507};1508// This is not super elegant, but wrappedExpect.fail was different:1509expectPrototype.fail = function (...args) {1510 // Cannot use this !== this._topLevelExpect due to https://github.com/unexpectedjs/unexpected/issues/6311511 if (this.flags) {1512 this._callInNestedContext(() => {1513 this._topLevelExpect._fail(...args);1514 });1515 } else {1516 try {1517 this._fail(...args);1518 } catch (e) {1519 if (e && e._isUnexpected) {1520 this.setErrorMessage(e);1521 }1522 throw e;1523 }1524 }1525};1526function lookupAssertionsInParentChain(assertionString, expect) {1527 const assertions = [];1528 for (let instance = expect; instance; instance = instance.parent) {1529 if (instance.assertions[assertionString]) {1530 assertions.push(...instance.assertions[assertionString]);1531 }1532 }1533 return assertions;1534}1535function findSuffixAssertions(assertionString, expect) {1536 if (typeof assertionString !== 'string') {1537 return null;1538 }1539 const straightforwardAssertions = lookupAssertionsInParentChain(1540 assertionString,1541 expect1542 );1543 if (straightforwardAssertions.length > 0) {1544 return straightforwardAssertions;1545 }1546 const tokens = assertionString.split(' ');1547 for (let n = tokens.length - 1; n > 0; n -= 1) {1548 const suffix = tokens.slice(n).join(' ');1549 const suffixAssertions = lookupAssertionsInParentChain(suffix, expect);1550 if (1551 findSuffixAssertions(tokens.slice(0, n).join(' '), expect) &&1552 suffixAssertions.length > 01553 ) {1554 return suffixAssertions;1555 }1556 }1557 return null;1558}1559expectPrototype.standardErrorMessage = function (output, options) {1560 this._assertWrappedExpect();1561 options = typeof options === 'object' ? options : {};1562 if ('omitSubject' in output) {1563 options.subject = this.subject;1564 }1565 if (options && options.compact) {1566 options.compactSubject = (output) => {1567 output.jsFunctionName(this.subjectType.name);1568 };1569 }1570 return createStandardErrorMessage(1571 output,1572 this.subjectOutput,1573 this.testDescription,1574 this.argsOutput,1575 options1576 );1577};1578expectPrototype._callInNestedContext = function (callback) {1579 this._assertWrappedExpect();1580 try {1581 let result = oathbreaker(callback());1582 if (utils.isPromise(result)) {1583 result = wrapPromiseIfNecessary(result);1584 if (result.isPending()) {1585 result = result.then(undefined, (e) => {1586 if (e && e._isUnexpected) {1587 const wrappedError = new UnexpectedError(this, e);1588 wrappedError.originalError = e.originalError;1589 throw wrappedError;1590 }1591 throw e;1592 });1593 }1594 } else {1595 result = makePromise.resolve(result);1596 }1597 return addAdditionalPromiseMethods(result, this.execute, this.subject);1598 } catch (e) {1599 if (e && e._isUnexpected) {1600 const wrappedError = new UnexpectedError(this, e);1601 wrappedError.originalError = e.originalError;1602 throw wrappedError;1603 }1604 throw e;1605 }1606};1607expectPrototype.shift = function (subject, assertionIndex) {1608 this._assertWrappedExpect();1609 if (arguments.length <= 1) {1610 if (arguments.length === 0) {1611 subject = this.subject;1612 }1613 assertionIndex = -1;1614 for (let i = 0; i < this.assertionRule.args.length; i += 1) {1615 const type = this.assertionRule.args[i].type;1616 if (type.is('assertion') || type.is('expect.it')) {1617 assertionIndex = i;1618 break;1619 }1620 }1621 } else if (arguments.length === 3) {1622 // The 3-argument syntax for wrappedExpect.shift is deprecated, please omit the first (expect) arg1623 subject = arguments[1];1624 assertionIndex = arguments[2];1625 }1626 if (assertionIndex !== -1) {1627 const args = this.args.slice(0, assertionIndex);1628 const rest = this.args.slice(assertionIndex);1629 const nextArgumentType = this.findTypeOf(rest[0]);1630 if (arguments.length > 1) {1631 // Legacy1632 this.argsOutput = (output) => {1633 args.forEach((arg, index) => {1634 if (index > 0) {1635 output.text(', ');1636 }1637 output.appendInspected(arg);1638 });1639 if (args.length > 0) {1640 output.sp();1641 }1642 if (nextArgumentType.is('string')) {1643 output.error(rest[0]);1644 } else if (rest.length > 0) {1645 output.appendInspected(rest[0]);1646 }1647 if (rest.length > 1) {1648 output.sp();1649 }1650 rest.slice(1).forEach((arg, index) => {1651 if (index > 0) {1652 output.text(', ');1653 }1654 output.appendInspected(arg);1655 });1656 };1657 }1658 if (nextArgumentType.is('expect.it')) {1659 return this.withError(1660 () => rest[0](subject),1661 (err) => {1662 this.fail(err);1663 }1664 );1665 } else if (nextArgumentType.is('string')) {1666 return this.execute(subject, ...rest);1667 } else {1668 return subject;1669 }1670 } else {1671 // No assertion to delegate to. Provide the new subject as the fulfillment value:1672 return subject;1673 }1674};1675expectPrototype._getSubjectType = function () {1676 this._assertWrappedExpect();1677 return this.findTypeOfWithParentType(1678 this.subject,1679 this.assertionRule.subject.type1680 );1681};1682expectPrototype._getArgTypes = function (index) {1683 this._assertWrappedExpect();1684 const lastIndex = this.assertionRule.args.length - 1;1685 return this.args.map((arg, index) => {1686 return this.findTypeOfWithParentType(1687 arg,1688 this.assertionRule.args[Math.min(index, lastIndex)].type1689 );1690 });1691};1692expectPrototype._getAssertionIndices = function () {1693 this._assertWrappedExpect();1694 if (!this._assertionIndices) {1695 const assertionIndices = [];1696 const args = this.args;1697 let currentAssertionRule = this.assertionRule;1698 let offset = 0;1699 // eslint-disable-next-line no-labels1700 OUTER: while (true) {1701 if (1702 currentAssertionRule.args.length > 1 &&1703 isAssertionArg(1704 currentAssertionRule.args[currentAssertionRule.args.length - 2]1705 )1706 ) {1707 assertionIndices.push(offset + currentAssertionRule.args.length - 2);1708 const suffixAssertions = findSuffixAssertions(1709 args[offset + currentAssertionRule.args.length - 2],1710 this1711 );1712 if (suffixAssertions) {1713 for (let i = 0; i < suffixAssertions.length; i += 1) {1714 if (suffixAssertions[i].args.some(isAssertionArg)) {1715 offset += currentAssertionRule.args.length - 1;1716 currentAssertionRule = suffixAssertions[i];1717 // eslint-disable-next-line no-labels...
Using AI Code Generation
1var unexpected = require('unexpected'),2 unexpectedHtmlLike = require('unexpected-htmllike-assertions'),3 unexpectedReact = require('unexpected-react'),4 React = require('react'),5 TestUtils = require('react-addons-test-utils'),6 unexpectedReact = require('unexpected-react'),7 MyComponent = require('../src/myComponent.js');8var expect = unexpected.clone()9 .use(unexpectedHtmlLike)10 .use(unexpectedReact);11describe('MyComponent', function () {12 it('should render a div', function () {13 var renderer = TestUtils.createRenderer();14 renderer.render(React.createElement(MyComponent));15 var output = renderer.getRenderOutput();16 expect(output, 'to have rendered', <div>some text</div>);17 });18});19var React = require('react');20var MyComponent = React.createClass({21 render: function () {22 return (23 );24 }25});26module.exports = MyComponent;
Using AI Code Generation
1var expect = require('unexpected').clone();2var unexpected = require('unexpected');3var unexpectedSinon = require('unexpected-sinon');4var sinon = require('sinon');5expect.use(unexpectedSinon);6var spy = sinon.spy();7var stub = sinon.stub().returns(42);8expect(spy, 'was not called');9expect(stub, 'was called once');10expect(stub, 'was called with', 123);11expect(stub, 'was called with', 123, 456);12expect(stub, 'was called with', 123, 456, 789);13expect(stub, 'was called with', 123, 456, 789, 101112);14expect(stub, 'was called with', 123, 456, 789, 101112, 131415);15expect(stub, 'was called with', 123, 456, 789, 101112, 131415, 161718);16expect(stub, 'was called with', 123, 456, 789, 101112, 131415, 161718, 192021);17expect(stub, 'was called with', 123, 456, 789, 101112, 131415, 161718, 192021, 222324);18expect(stub, 'was called with', 123, 456, 789, 101112, 131415, 161718, 192021, 222324, 252627);19expect(stub, 'was called with', 123, 456, 789, 101112, 131415, 161718, 192021, 222324, 252627, 282930);20expect(stub, 'was called with', 123, 456, 789, 101112, 131415, 161718, 192021, 222324, 252627, 282930, 313233);21expect(stub, 'was called with', 123, 456, 789, 101112, 131415, 161718, 192021, 222324, 252627, 282930, 313233, 343536);22expect(stub, 'was called with', 123, 456, 789, 101112, 131415, 161718, 192021
Using AI Code Generation
1const expect = require('unexpected')2 .clone()3 .use(require('unexpected-messy'));4const messy = require('messy');5expect(messy.isAssertionArg, 'to be a function');6const isAssertionArg = require('unexpected-messy').isAssertionArg;7const isExpectedArg = require('unexpected-messy').isExpectedArg;8const isUnexpectedArg = require('unexpected-messy').isUnexpectedArg;9const isMessageArg = require('unexpected-messy').isMessageArg;10const isDiffArg = require('unexpected-messy').isDiffArg;11const isDiffOptionsArg = require('unexpected-messy').isDiffOptionsArg;12const isDiffActualArg = require('unexpected-messy
Using AI Code Generation
1var expect = require('unexpected').clone();2var isAssertionArg = expect.isAssertionArg;3console.log(isAssertionArg('to be a string'));4console.log(isAssertionArg('to be a string', 'to be a number'));5console.log(isAssertionArg('to be a string', 'to be a number', 'to be a boolean'));6console.log(isAssertionArg('to be a string', 'to be a number', 'to be a boolean', 'to be a function'));7console.log(isAssertionArg('to be a string', 'to be a number', 'to be a boolean', 'to be a function', 'to be a regexp'));8console.log(isAssertionArg('to be a string', 'to be a number', 'to be a boolean', 'to be a function', 'to be a regexp', 'to be a date'));9console.log(isAssertionArg('to be a string', 'to be a number', 'to be a boolean', 'to be a function', 'to be a regexp', 'to be a date', 'to be a map'));10console.log(isAssertionArg('to be a string', 'to be a number', 'to be a boolean', 'to be a function', 'to be a regexp', 'to be a date', 'to be a map', 'to be a set'));11console.log(isAssertionArg('to be a string', 'to be a number', 'to be a boolean', 'to be a function', 'to be a regexp', 'to be a date', 'to be a map', 'to be a set', 'to be a promise'));12console.log(isAssertionArg('to be a string', 'to be a number', 'to be a boolean', 'to be a function', 'to be a regexp', 'to be a date', 'to be a map', 'to be a set', 'to be a promise', 'to be an error'));13console.log(isAssertionArg('to be a string', 'to be a number', 'to be a boolean', 'to be a function', 'to be a regexp', 'to be a date', 'to be a map', 'to be a set', 'to be a promise', 'to be an error', 'to be a buffer'));14console.log(isAssertionArg('to be a string', 'to be a number', 'to be a boolean', 'to be a
Using AI Code Generation
1var expect = require('unexpected').clone();2expect.use(require('unexpected-sinon'));3var sinon = require('sinon');4var myCode = require('./myCode.js');5var myCodeSpy = sinon.spy(myCode);6var myCodeStub = sinon.stub(myCode);7var myCodeMock = sinon.mock(myCode);8var myCodeFake = sinon.fake(myCode);9describe('myCode', function() {10 it('should call the callback', function() {11 var callback = sinon.spy();12 myCode(callback);13 expect(callback, 'was called');14 });15});16module.exports = function(callback) {17 callback();18};19var callback = sinon.spy();20myCode(callback);21expect(callback.function, 'was called');22You can also use the .call() method on the spy object:23var callback = sinon.spy();24myCode(callback);25expect(callback.call, 'was called');26var callback = sinon.spy();27myCode(callback);28expect(callback, 'was called');29var callback = sinon.spy();30myCode(callback);31expect(callback.called, 'to be true');32var callback = sinon.spy();33myCode(callback);34expect(callback.calledOnce, 'to be true');35var callback = sinon.spy();36myCode(callback);37expect(callback.callCount, 'to be', 1);
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!