Coveralls logob
Coveralls logo
  • Home
  • Features
  • Pricing
  • Docs
  • Sign In

unexpectedjs / unexpected / 2229357644

26 Apr 2022 - 21:05 coverage increased (+0.01%) to 97.515%
2229357644

Pull #820

github

GitHub
Merge 8583e0e0b into 8f03e9e19
Pull Request #820: Upgrade eslint-plugin-markdown to version 2.2.1

1963 of 2081 branches covered (94.33%)

3571 of 3662 relevant lines covered (97.52%)

1962.78 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.83
/lib/assertions.js
1
const utils = require('./utils');
16×
2
const arrayChanges = require('array-changes');
16×
3
const arrayChangesAsync = require('array-changes-async');
16×
4
const throwIfNonUnexpectedError = require('./throwIfNonUnexpectedError');
16×
5
const objectIs = utils.objectIs;
16×
6
const extend = utils.extend;
16×
7

8
module.exports = (expect) => {
16×
9
  expect.addAssertion('<any> [not] to be (ok|truthy)', (expect, subject) => {
17×
10
    const not = !!expect.flags.not;
2,802×
11
    const condition = !!subject;
2,802×
12
    if (condition === not) {
2,802×
13
      expect.fail();
676×
14
    }
15
  });
16

17
  expect.addAssertion(
17×
18
    '<any> [not] to be (ok|truthy) <string>',
19
    (expect, subject, message) => {
20
      const not = !!expect.flags.not;
1×
21
      const condition = !!subject;
1×
22
      if (condition === not) {
Branches [[1, 1]] missed. 1×
23
        expect.fail({
1×
24
          errorMode: 'bubble',
25
          message,
26
        });
27
      }
28
    }
29
  );
30

31
  expect.addAssertion('<any> [not] to be <any>', (expect, subject, value) => {
17×
32
    if (objectIs(subject, value) === expect.flags.not) {
332×
33
      expect.fail({
41×
34
        label: 'should be',
35
      });
36
    }
37
  });
38

39
  expect.addAssertion(
17×
40
    '<string> [not] to be <string>',
41
    (expect, subject, value) => {
42
      expect(subject, '[not] to equal', value);
7×
43
    }
44
  );
45

46
  expect.addAssertion('<boolean> [not] to be true', (expect, subject) => {
17×
47
    expect(subject, '[not] to be', true);
58×
48
  });
49

50
  expect.addAssertion('<boolean> [not] to be false', (expect, subject) => {
17×
51
    expect(subject, '[not] to be', false);
11×
52
  });
53

54
  expect.addAssertion('<any> [not] to be falsy', (expect, subject) => {
17×
55
    expect(subject, '[!not] to be truthy');
77×
56
  });
57

58
  expect.addAssertion(
17×
59
    '<any> [not] to be falsy <string>',
60
    (expect, subject, message) => {
61
      const not = !!expect.flags.not;
1×
62
      const condition = !!subject;
1×
63
      if (condition !== not) {
Branches [[3, 1]] missed. 1×
64
        expect.fail({
1×
65
          errorMode: 'bubble',
66
          message,
67
        });
68
      }
69
    }
70
  );
71

72
  expect.addAssertion('<any> [not] to be null', (expect, subject) => {
17×
73
    expect(subject, '[not] to be', null);
3×
74
  });
75

76
  expect.addAssertion('<any> [not] to be undefined', (expect, subject) => {
17×
77
    expect(typeof subject === 'undefined', '[not] to be truthy');
85×
78
  });
79

80
  expect.addAssertion('<any> [not] to be defined', (expect, subject) => {
17×
81
    expect(subject, '[!not] to be undefined');
22×
82
  });
83

84
  expect.addAssertion('<number|NaN> [not] to be NaN', (expect, subject) => {
17×
85
    expect(isNaN(subject), '[not] to be truthy');
4×
86
  });
87

88
  expect.addAssertion(
17×
89
    '<number> [not] to be close to <number> <number?>',
90
    (expect, subject, value, epsilon) => {
91
      expect.errorMode = 'bubble';
8×
92
      if (typeof epsilon !== 'number') {
8×
93
        epsilon = 1e-9;
5×
94
      }
95

96
      expect.withError(
8×
97
        () => {
98
          expect(
8×
99
            Math.abs(subject - value),
100
            '[not] to be less than or equal to',
101
            epsilon
102
          );
103
        },
104
        (e) => {
105
          expect.fail((output) => {
3×
106
            output
6×
107
              .error('expected ')
108
              .appendInspected(subject)
109
              .sp()
110
              .error(expect.testDescription)
111
              .sp()
112
              .appendInspected(value)
113
              .sp()
114
              .text('(epsilon: ')
115
              .jsNumber(epsilon.toExponential())
116
              .text(')');
117
          });
118
        }
119
      );
120
    }
121
  );
122

123
  expect.addAssertion(
17×
124
    '<any> [not] to be (a|an) <type>',
125
    (expect, subject, type) => {
126
      expect.argsOutput[0] = (output) => {
1×
127
        output.text(type.name);
!
128
      };
129
      expect(type.identify(subject), '[not] to be true');
1×
130
    }
131
  );
132

133
  expect.addAssertion(
17×
134
    '<any> [not] to be (a|an) <string>',
135
    (expect, subject, typeName) => {
136
      typeName = /^reg(?:exp?|ular expression)$/.test(typeName)
360×
137
        ? 'regexp'
138
        : typeName;
139
      expect.argsOutput[0] = (output) => {
360×
140
        output.jsString(typeName);
8×
141
      };
142
      if (!expect.getType(typeName)) {
360×
143
        expect.errorMode = 'nested';
2×
144
        expect.fail((output) => {
2×
145
          output.error('Unknown type:').sp().jsString(typeName);
4×
146
        });
147
      }
148
      expect(expect.subjectType.is(typeName), '[not] to be truthy');
358×
149
    }
150
  );
151

152
  expect.addAssertion(
17×
153
    '<any> [not] to be (a|an) <function>',
154
    (expect, subject, Constructor) => {
155
      const className = utils.getFunctionName(Constructor);
15×
156
      if (className) {
15×
157
        expect.argsOutput[0] = (output) => {
14×
158
          output.text(className);
10×
159
        };
160
      }
161
      expect(subject instanceof Constructor, '[not] to be truthy');
15×
162
    }
163
  );
164

165
  expect.addAssertion(
17×
166
    '<any> [not] to be one of <array>',
167
    (expect, subject, superset) => {
168
      let found = false;
7×
169

170
      for (let i = 0; i < superset.length; i += 1) {
7×
171
        found = found || objectIs(subject, superset[i]);
11×
172
      }
173

174
      if (found === expect.flags.not) {
7×
175
        expect.fail();
2×
176
      }
177
    }
178
  );
179

180
  // Alias for common '[not] to be (a|an)' assertions
181
  expect.addAssertion(
17×
182
    '<any> [not] to be an (object|array)',
183
    (expect, subject) => {
184
      expect(subject, '[not] to be an', expect.alternations[0]);
32×
185
    }
186
  );
187

188
  expect.addAssertion(
17×
189
    '<any> [not] to be a (boolean|number|string|function|regexp|regex|regular expression|date)',
190
    (expect, subject) => {
191
      expect(subject, '[not] to be a', expect.alternations[0]);
315×
192
    }
193
  );
194

195
  expect.addAssertion(
17×
196
    '<string> to be (the empty|an empty|a non-empty) string',
197
    (expect, subject) => {
198
      expect(
3×
199
        subject,
200
        expect.alternations[0] === 'a non-empty'
201
          ? 'not to be empty'
202
          : 'to be empty'
203
      );
204
    }
205
  );
206

207
  expect.addAssertion(
17×
208
    '<array-like> to be (the empty|an empty|a non-empty) array',
209
    (expect, subject) => {
210
      expect(
2×
211
        subject,
212
        expect.alternations[0] === 'a non-empty'
213
          ? 'not to be empty'
214
          : 'to be empty'
215
      );
216
    }
217
  );
218

219
  expect.addAssertion('<string> to match <regexp>', (expect, subject, regexp) =>
17×
220
    expect.withError(
72×
221
      () => {
222
        const captures = subject.match(regexp);
72×
223
        expect(captures, 'to be truthy');
72×
224
        return captures;
60×
225
      },
226
      (e) => {
227
        e.label = 'should match';
12×
228
        expect.fail(e);
12×
229
      }
230
    )
231
  );
232

233
  expect.addAssertion(
17×
234
    '<string> not to match <regexp>',
235
    (expect, subject, regexp) =>
236
      expect.withError(
6×
237
        () => {
238
          expect(regexp.test(subject), 'to be false');
6×
239
        },
240
        (e) => {
241
          expect.fail({
5×
242
            label: 'should not match',
243
            diff(output) {
244
              output.inline = false;
14×
245
              let lastIndex = 0;
14×
246
              function flushUntilIndex(i) {
247
                if (i > lastIndex) {
30×
248
                  output.text(subject.substring(lastIndex, i));
20×
249
                  lastIndex = i;
20×
250
                }
251
              }
252
              subject.replace(new RegExp(regexp.source, 'g'), ($0, index) => {
14×
253
                flushUntilIndex(index);
16×
254
                lastIndex += $0.length;
16×
255
                output.removedHighlight($0);
16×
256
              });
257
              flushUntilIndex(subject.length);
14×
258
              return output;
14×
259
            },
260
          });
261
        }
262
      )
263
  );
264

265
  expect.addAssertion(
17×
266
    '<object> [not] to have own property <string|Symbol>',
267
    (expect, subject, key) => {
268
      expect(
23×
269
        Object.prototype.hasOwnProperty.call(subject, key),
270
        '[not] to be truthy'
271
      );
272
      return subject[key];
16×
273
    }
274
  );
275

276
  expect.addAssertion(
17×
277
    '<object> to have (enumerable|unenumerable|configurable|unconfigurable|writable|unwritable|readonly) property <string|Symbol>',
278
    (expect, subject, key) => {
279
      let attribute = expect.alternations[0];
17×
280
      let negated = false;
17×
281
      if (attribute.indexOf('un') === 0) {
17×
282
        attribute = attribute.substr(2);
6×
283
        negated = true;
6×
284
      } else if (attribute === 'readonly') {
11×
285
        attribute = 'writable';
2×
286
        negated = true;
2×
287
      }
288
      const descriptor = Object.getOwnPropertyDescriptor(subject, key);
17×
289
      expect(descriptor, 'to be defined');
17×
290
      expect(descriptor[attribute] !== negated, 'to be true');
15×
291
      return subject[key];
8×
292
    }
293
  );
294

295
  expect.addAssertion(
17×
296
    '<object> [not] to have property <string|Symbol>',
297
    (expect, subject, key) => {
298
      const subjectType = expect.findTypeOf(subject);
51×
299
      const subjectKey = subjectType.is('function')
51×
300
        ? subject[key]
301
        : subjectType.valueForKey(subject, key);
302
      expect(subjectKey, '[!not] to be undefined');
51×
303
      return subjectKey;
42×
304
    }
305
  );
306

307
  expect.addAssertion(
17×
308
    '<object> to have [own] property <string|Symbol> <any>',
309
    (expect, subject, key, expectedPropertyValue) =>
310
      expect(subject, 'to have [own] property', key).then(
26×
311
        (actualPropertyValue) => {
312
          expect.argsOutput = function () {
22×
313
            this.appendInspected(key)
9×
314
              .sp()
315
              .error('with a value of')
316
              .sp()
317
              .appendInspected(expectedPropertyValue);
318
          };
319
          expect(actualPropertyValue, 'to equal', expectedPropertyValue);
22×
320
          return actualPropertyValue;
16×
321
        }
322
      )
323
  );
324

325
  expect.addAssertion(
17×
326
    '<object> [not] to [only] have [own] properties <array>',
327
    (expect, subject, propertyNames) => {
328
      const unsupportedPropertyNames = propertyNames.filter((propertyName) => {
30×
329
        const type = typeof propertyName;
48×
330
        return type !== 'string' && type !== 'number' && type !== 'symbol';
48×
331
      });
332
      if (unsupportedPropertyNames.length > 0) {
30×
333
        expect.errorMode = 'nested';
3×
334
        expect.fail(function () {
3×
335
          this.error(
6×
336
            'All expected properties must be passed as strings, symbols, or numbers, but these are not:'
337
          ).indentLines();
338
          unsupportedPropertyNames.forEach(function (propertyName) {
6×
339
            this.nl().i().appendInspected(propertyName);
8×
340
          }, this);
341
          this.outdentLines();
6×
342
        });
343
      }
344

345
      if (expect.flags.only) {
27×
346
        if (expect.flags.not) {
9×
347
          expect.errorMode = 'bubble';
1×
348
          expect.fail(
1×
349
            'The "not" flag cannot be used together with "to only have properties".'
350
          );
351
        }
352
        if (expect.flags.own) {
8×
353
          expect.errorMode = 'bubble';
1×
354
          expect.fail(
1×
355
            'The "own" flag cannot be used together with "to only have properties".'
356
          );
357
        }
358
        const subjectType = expect.subjectType;
7×
359
        const subjectKeys = subjectType.getKeys(subject).filter(
7×
360
          (key) =>
361
            // include only those keys whose value is not undefined
362
            typeof subjectType.valueForKey(subject, key) !== 'undefined'
13×
363
        );
364

365
        expect.withError(
7×
366
          () => {
367
            expect(subjectKeys.length === propertyNames.length, 'to be true');
7×
368
            // now catch differing property names
369
            const keyInValue = {};
4×
370
            propertyNames.forEach((key) => {
4×
371
              keyInValue[key] = true;
8×
372
            });
373
            subjectKeys.forEach((key) =>
4×
374
              expect(
8×
375
                Object.prototype.hasOwnProperty.call(keyInValue, key),
376
                'to be true'
377
              )
378
            );
379
          },
380
          () => {
381
            expect.fail({
4×
382
              diff: (output, diff, inspect, equal) => {
383
                output.inline = true;
7×
384

385
                const keyInValue = {};
7×
386
                propertyNames.forEach((key) => {
7×
387
                  keyInValue[key] = true;
7×
388
                });
389

390
                subjectType.prefix(output, subject);
7×
391
                output.nl().indentLines();
7×
392

393
                subjectKeys.forEach((key, index) => {
7×
394
                  const propertyOutput = subjectType.property(
10×
395
                    output.clone(),
396
                    key,
397
                    inspect(subjectType.valueForKey(subject, key))
398
                  );
399
                  const delimiterOutput = subjectType.delimiter(
10×
400
                    output.clone(),
401
                    index,
402
                    subjectKeys.length
403
                  );
404

405
                  output
10×
406
                    .i()
407
                    .block(function () {
408
                      this.append(propertyOutput).amend(delimiterOutput);
10×
409
                      if (
10×
410
                        !Object.prototype.hasOwnProperty.call(keyInValue, key)
411
                      ) {
412
                        this.sp().annotationBlock(function () {
6×
413
                          this.error('should be removed');
6×
414
                        });
415
                      } else {
416
                        delete keyInValue[key];
4×
417
                      }
418
                    })
419
                    .nl();
420
                });
421

422
                // list any remaining value properties as missing
423
                Object.keys(keyInValue).forEach((valueKey) => {
7×
424
                  output
3×
425
                    .i()
426
                    .annotationBlock(function () {
427
                      this.error('missing').sp().append(inspect(valueKey));
3×
428
                    })
429
                    .nl();
430
                });
431

432
                output.outdentLines();
7×
433
                subjectType.suffix(output, subject);
7×
434

435
                return output;
7×
436
              },
437
            });
438
          }
439
        );
440
      } else {
441
        propertyNames.forEach((propertyName) => {
18×
442
          expect(
27×
443
            subject,
444
            '[not] to have [own] property',
445
            typeof propertyName === 'number'
446
              ? String(propertyName)
447
              : propertyName
448
          );
449
        });
450
      }
451
    }
452
  );
453

454
  expect.addAssertion(
17×
455
    '<object> to have [own] properties <object>',
456
    (expect, subject, properties) => {
457
      expect.withError(
12×
458
        () => {
459
          Object.keys(properties).forEach((property) => {
12×
460
            const value = properties[property];
19×
461
            if (typeof value === 'undefined') {
19×
462
              expect(subject, 'not to have [own] property', property);
2×
463
            } else {
464
              expect(subject, 'to have [own] property', property, value);
17×
465
            }
466
          });
467
        },
468
        (e) => {
469
          expect.fail({
6×
470
            diff(output, diff) {
471
              output.inline = false;
12×
472
              const expected = extend({}, properties);
12×
473
              const actual = {};
12×
474
              const propertyNames = expect.findTypeOf(subject).getKeys(subject);
12×
475
              // Might put duplicates into propertyNames, but that does not matter:
476
              for (const propertyName in subject) {
12×
477
                if (
20×
478
                  !Object.prototype.hasOwnProperty.call(subject, propertyName)
479
                ) {
480
                  propertyNames.push(propertyName);
6×
481
                }
482
              }
483
              propertyNames.forEach((propertyName) => {
12×
484
                if (
20×
485
                  (!expect.flags.own ||
486
                    Object.prototype.hasOwnProperty.call(
487
                      subject,
488
                      propertyName
489
                    )) &&
490
                  !(propertyName in properties)
491
                ) {
492
                  expected[propertyName] = subject[propertyName];
8×
493
                }
494
                if (
20×
495
                  (!expect.flags.own ||
496
                    Object.prototype.hasOwnProperty.call(
497
                      subject,
498
                      propertyName
499
                    )) &&
500
                  !(propertyName in actual)
501
                ) {
502
                  actual[propertyName] = subject[propertyName];
16×
503
                }
504
              });
505
              return utils.wrapConstructorNameAroundOutput(
12×
506
                diff(actual, expected),
507
                subject
508
              );
509
            },
510
          });
511
        }
512
      );
513
    }
514
  );
515

516
  expect.addAssertion(
17×
517
    '<string|array-like> [not] to have length <number>',
518
    (expect, subject, length) => {
519
      if (!expect.flags.not) {
190×
520
        expect.errorMode = 'nested';
24×
521
      }
522
      expect(subject.length, '[not] to be', length);
190×
523
    }
524
  );
525

526
  expect.addAssertion(
17×
527
    '<string|array-like> [not] to be empty',
528
    (expect, subject) => {
529
      expect(subject, '[not] to have length', 0);
171×
530
    }
531
  );
532

533
  expect.addAssertion(
17×
534
    '<string|array-like|object> to be non-empty',
535
    (expect, subject) => {
536
      expect(subject, 'not to be empty');
2×
537
    }
538
  );
539

540
  expect.addAssertion(
17×
541
    '<object> to [not] [only] have keys <array>',
542
    (expect, subject, keys) => {
543
      const keysInSubject = {};
67×
544
      const subjectType = expect.findTypeOf(subject);
67×
545
      const subjectKeys = subjectType.getKeys(subject);
67×
546
      subjectKeys.forEach((key) => {
67×
547
        keysInSubject[key] = true;
788×
548
      });
549

550
      if (expect.flags.not && keys.length === 0) {
67×
551
        return;
46×
552
      }
553

554
      const hasKeys = keys.every((key) => keysInSubject[key]);
27×
555

556
      if (expect.flags.only) {
21×
557
        expect(hasKeys, 'to be truthy');
13×
558
        expect.withError(
12×
559
          () => {
560
            expect(subjectKeys.length === keys.length, '[not] to be truthy');
12×
561
          },
562
          () => {
563
            expect.fail({
6×
564
              diff:
565
                !expect.flags.not &&
566
                ((output, diff, inspect, equal) => {
567
                  output.inline = true;
8×
568
                  const keyInValue = {};
8×
569
                  keys.forEach((key) => {
8×
570
                    keyInValue[key] = true;
6×
571
                  });
572
                  const subjectIsArrayLike = subjectType.is('array-like');
8×
573

574
                  subjectType.prefix(output, subject);
8×
575
                  output.nl().indentLines();
8×
576

577
                  subjectKeys.forEach((key, index) => {
8×
578
                    const propertyOutput = subjectType.property(
14×
579
                      output.clone(),
580
                      key,
581
                      inspect(subjectType.valueForKey(subject, key)),
582
                      subjectIsArrayLike
583
                    );
584
                    const delimiterOutput = subjectType.delimiter(
14×
585
                      output.clone(),
586
                      index,
587
                      subjectKeys.length
588
                    );
589

590
                    output
14×
591
                      .i()
592
                      .block(function () {
593
                        this.append(propertyOutput).amend(delimiterOutput);
14×
594
                        if (!keyInValue[key]) {
14×
595
                          this.sp().annotationBlock(function () {
8×
596
                            this.error('should be removed');
8×
597
                          });
598
                        }
599
                      })
600
                      .nl();
601
                  });
602

603
                  output.outdentLines();
8×
604
                  subjectType.suffix(output, subject);
8×
605

606
                  return output;
8×
607
                }),
608
            });
609
          }
610
        );
611
      } else {
612
        expect(hasKeys, '[not] to be truthy');
8×
613
      }
614
    }
615
  );
616

617
  expect.addAssertion('<object> [not] to be empty', (expect, subject) => {
17×
618
    if (
51×
619
      expect.flags.not &&
620
      !expect.findTypeOf(subject).getKeys(subject).length
621
    ) {
622
      return expect.fail();
4×
623
    }
624
    expect(subject, 'to [not] only have keys', []);
47×
625
  });
626

627
  expect.addAssertion(
17×
628
    '<object> not to have keys <array>',
629
    (expect, subject, keys) => {
630
      expect(subject, 'to not have keys', keys);
1×
631
    }
632
  );
633

634
  expect.addAssertion(
17×
635
    '<object> not to have key <string>',
636
    (expect, subject, value) => {
637
      expect(subject, 'to not have keys', [value]);
3×
638
    }
639
  );
640

641
  expect.addAssertion(
17×
642
    '<object> not to have keys <string+>',
643
    function (expect, subject, value) {
644
      expect(
1×
645
        subject,
646
        'to not have keys',
647
        Array.prototype.slice.call(arguments, 2)
648
      );
649
    }
650
  );
651

652
  expect.addAssertion(
17×
653
    '<object> to [not] [only] have key <string>',
654
    (expect, subject, value) => {
655
      expect(subject, 'to [not] [only] have keys', [value]);
5×
656
    }
657
  );
658

659
  expect.addAssertion(
17×
660
    '<object> to [not] [only] have keys <string+>',
661
    function (expect, subject) {
662
      expect(
5×
663
        subject,
664
        'to [not] [only] have keys',
665
        Array.prototype.slice.call(arguments, 2)
666
      );
667
    }
668
  );
669

670
  expect.addAssertion(
17×
671
    '<string> [not] to contain <string+>',
672
    function (expect, subject) {
673
      const args = Array.prototype.slice.call(arguments, 2);
54×
674
      args.forEach((arg) => {
54×
675
        if (arg === '') {
59×
676
          throw new Error(
1×
677
            `The '${expect.testDescription}' assertion does not support the empty string`
678
          );
679
        }
680
      });
681
      expect.withError(
53×
682
        () => {
683
          args.forEach((arg) => {
53×
684
            expect(subject.indexOf(arg) !== -1, '[not] to be truthy');
55×
685
          });
686
        },
687
        (e) => {
688
          expect.fail({
8×
689
            diff(output) {
690
              output.inline = false;
17×
691
              let lastIndex = 0;
17×
692
              function flushUntilIndex(i) {
693
                if (i > lastIndex) {
43×
694
                  output.text(subject.substring(lastIndex, i));
22×
695
                  lastIndex = i;
22×
696
                }
697
              }
698
              if (expect.flags.not) {
17×
699
                subject.replace(
6×
700
                  new RegExp(
701
                    args
702
                      .map((arg) => utils.escapeRegExpMetaChars(arg))
8×
703
                      .join('|'),
704
                    'g'
705
                  ),
706
                  ($0, index) => {
707
                    flushUntilIndex(index);
8×
708
                    lastIndex += $0.length;
8×
709
                    output.removedHighlight($0);
8×
710
                  }
711
                );
712
                flushUntilIndex(subject.length);
6×
713
              } else {
714
                const ranges = [];
11×
715
                args.forEach((arg) => {
11×
716
                  let needle = arg;
18×
717
                  let partial = false;
18×
718
                  while (needle.length > 1) {
18×
719
                    let found = false;
38×
720
                    lastIndex = -1;
38×
721
                    let index;
722
                    do {
38×
723
                      index = subject.indexOf(needle, lastIndex + 1);
56×
724
                      if (index !== -1) {
56×
725
                        found = true;
18×
726
                        ranges.push({
18×
727
                          startIndex: index,
728
                          endIndex: index + needle.length,
729
                          partial,
730
                        });
731
                      }
732
                      lastIndex = index;
56×
733
                    } while (lastIndex !== -1);
734
                    if (found) {
38×
735
                      break;
14×
736
                    }
737
                    needle = arg.substr(0, needle.length - 1);
24×
738
                    partial = true;
24×
739
                  }
740
                });
741
                lastIndex = 0;
11×
742
                ranges
11×
743
                  .sort((a, b) => a.startIndex - b.startIndex)
15×
744
                  .forEach(({ startIndex, endIndex, partial }) => {
745
                    flushUntilIndex(startIndex);
18×
746
                    const firstUncoveredIndex = Math.max(startIndex, lastIndex);
18×
747
                    if (endIndex > firstUncoveredIndex) {
18×
748
                      if (partial) {
14×
749
                        output.partialMatch(
9×
750
                          subject.substring(firstUncoveredIndex, endIndex)
751
                        );
752
                      } else {
753
                        output.match(
5×
754
                          subject.substring(firstUncoveredIndex, endIndex)
755
                        );
756
                      }
757
                      lastIndex = endIndex;
14×
758
                    }
759
                  });
760
                flushUntilIndex(subject.length);
11×
761
              }
762
              return output;
17×
763
            },
764
          });
765
        }
766
      );
767
    }
768
  );
769

770
  expect.addAssertion(
17×
771
    [
772
      '<array-like> to [only] contain <any+>',
773
      '<array-like> [not] to contain <any+>',
774
    ],
775
    function (expect, subject) {
776
      const args = Array.prototype.slice.call(arguments, 2);
10×
777

778
      expect.withError(
10×
779
        () => {
780
          args.forEach((arg) => {
10×
781
            expect(
16×
782
              Array.prototype.some.call(subject, (item) =>
783
                expect.equal(item, arg)
23×
784
              ),
785
              '[not] to be truthy'
786
            );
787
          });
788
          if (expect.flags.only) {
6×
789
            expect(
3×
790
              Array.prototype.every.call(subject, (item) =>
791
                Array.prototype.some.call(args, (arg) =>
8×
792
                  expect.equal(item, arg)
13×
793
                )
794
              ),
795
              'to be truthy'
796
            );
797
          }
798
        },
799
        (e) => {
800
          expect.fail({
5×
801
            diff(output, diff, inspect, equal) {
802
              if (expect.flags.not) {
10×
803
                return diff(
2×
804
                  subject,
805
                  Array.prototype.filter.call(
806
                    subject,
807
                    (item) => !args.some((arg) => equal(item, arg))
6×
808
                  )
809
                );
810
              } else if (expect.flags.only) {
8×
811
                const excessItems = Array.prototype.filter.call(
4×
812
                  subject,
813
                  (item) => args.some((arg) => equal(item, arg))
14×
814
                );
815
                const missingItems = args.filter(
4×
816
                  (arg) =>
817
                    !Array.prototype.some.call(subject, (item) =>
8×
818
                      equal(arg, item)
10×
819
                    )
820
                );
821

822
                return diff(subject, [...excessItems, ...missingItems]);
4×
823
              }
824
            },
825
          });
826
        }
827
      );
828
    }
829
  );
830

831
  expect.addAssertion(
17×
832
    [
833
      '<string> [not] to begin with <string>',
834
      '<string> [not] to start with <string>',
835
    ],
836
    (expect, subject, value) => {
837
      if (value === '') {
20×
838
        throw new Error(
2×
839
          `The '${expect.testDescription}' assertion does not support a prefix of the empty string`
840
        );
841
      }
842
      let isTruncated = false;
18×
843
      let outputSubject = utils.truncateSubjectStringForBegin(subject, value);
18×
844
      if (outputSubject === null) {
18×
845
        outputSubject = subject;
15×
846
      } else {
847
        isTruncated = true;
3×
848
      }
849
      expect.subjectOutput = (output) => {
18×
850
        output = output.jsString(
22×
851
          "'" + outputSubject.replace(/\n/g, '\\n') + "'"
852
        );
853
        if (isTruncated) {
22×
854
          output.jsComment('...');
6×
855
        }
856
      };
857
      expect.withError(
18×
858
        () => {
859
          expect(subject.substr(0, value.length), '[not] to equal', value);
18×
860
        },
861
        () => {
862
          expect.fail({
12×
863
            diff(output) {
864
              output.inline = false;
24×
865
              if (expect.flags.not) {
24×
866
                output
5×
867
                  .removedHighlight(value)
868
                  .text(subject.substr(value.length));
869
              } else {
870
                let i = 0;
19×
871
                while (subject[i] === value[i]) {
19×
872
                  i += 1;
48×
873
                }
874
                if (i === 0) {
19×
875
                  // No common prefix, omit diff
876
                  return null;
8×
877
                } else {
878
                  output
11×
879
                    .partialMatch(subject.substr(0, i))
880
                    .text(outputSubject.substr(i))
881
                    .jsComment(isTruncated ? '...' : '');
882
                }
883
              }
884
              return output;
16×
885
            },
886
          });
887
        }
888
      );
889
    }
890
  );
891

892
  expect.addAssertion(
17×
893
    '<string> [not] to end with <string>',
894
    (expect, subject, value) => {
895
      if (value === '') {
14×
896
        throw new Error(
1×
897
          `The '${expect.testDescription}' assertion does not support a suffix of the empty string`
898
        );
899
      }
900
      let isTruncated = false;
13×
901
      let outputSubject = utils.truncateSubjectStringForEnd(subject, value);
13×
902
      if (outputSubject === null) {
13×
903
        outputSubject = subject;
10×
904
      } else {
905
        isTruncated = true;
3×
906
      }
907
      expect.subjectOutput = (output) => {
13×
908
        if (isTruncated) {
18×
909
          output = output.jsComment('...');
6×
910
        }
911
        output.jsString("'" + outputSubject.replace(/\n/g, '\\n') + "'");
18×
912
      };
913
      expect.withError(
13×
914
        () => {
915
          expect(subject.substr(-value.length), '[not] to equal', value);
13×
916
        },
917
        () => {
918
          expect.fail({
9×
919
            diff(output) {
920
              output.inline = false;
20×
921
              if (expect.flags.not) {
20×
922
                output
5×
923
                  .text(subject.substr(0, subject.length - value.length))
924
                  .removedHighlight(value);
925
              } else {
926
                let i = 0;
15×
927
                while (
15×
928
                  outputSubject[outputSubject.length - 1 - i] ===
929
                  value[value.length - 1 - i]
930
                ) {
931
                  i += 1;
46×
932
                }
933
                if (i === 0) {
15×
934
                  // No common suffix, omit diff
935
                  return null;
6×
936
                }
937
                output
9×
938
                  .jsComment(isTruncated ? '...' : '')
939
                  .text(outputSubject.substr(0, outputSubject.length - i))
940
                  .partialMatch(
941
                    outputSubject.substr(
942
                      outputSubject.length - i,
943
                      outputSubject.length
944
                    )
945
                  );
946
              }
947
              return output;
14×
948
            },
949
          });
950
        }
951
      );
952
    }
953
  );
954

955
  expect.addAssertion('<number> [not] to be finite', (expect, subject) => {
17×
956
    expect(isFinite(subject), '[not] to be truthy');
6×
957
  });
958

959
  expect.addAssertion('<number> [not] to be infinite', (expect, subject) => {
17×
960
    expect(!isNaN(subject) && !isFinite(subject), '[not] to be truthy');
5×
961
  });
962

963
  expect.addAssertion(
17×
964
    [
965
      '<number> [not] to be within <number> <number>',
966
      '<BigInt> [not] to be within <BigInt> <BigInt>',
967
      '<string> [not] to be within <string> <string>',
968
    ],
969
    (expect, subject, start, finish) => {
970
      expect.argsOutput = (output) => {
110×
971
        output.appendInspected(start).text('..').appendInspected(finish);
8×
972
      };
973
      expect(subject >= start && subject <= finish, '[not] to be truthy');
110×
974
    }
975
  );
976

977
  expect.addAssertion(
17×
978
    [
979
      '<number> [not] to be (less than|below) <number>',
980
      '<BigInt> [not] to be (less than|below) <BigInt>',
981
      '<string> [not] to be (less than|below) <string>',
982
    ],
983
    (expect, subject, value) => {
984
      expect(subject < value, '[not] to be truthy');
21×
985
    }
986
  );
987

988
  expect.addAssertion(
17×
989
    '<string> [not] to be (less than|below) <string>',
990
    (expect, subject, value) => {
991
      expect(subject < value, '[not] to be truthy');
11×
992
    }
993
  );
994

995
  expect.addAssertion(
17×
996
    [
997
      '<number> [not] to be less than or equal to <number>',
998
      '<BigInt> [not] to be less than or equal to <BigInt>',
999
      '<string> [not] to be less than or equal to <string>',
1000
    ],
1001
    (expect, subject, value) => {
1002
      expect(subject <= value, '[not] to be truthy');
16×
1003
    }
1004
  );
1005

1006
  expect.addAssertion(
17×
1007
    [
1008
      '<number> [not] to be (greater than|above) <number>',
1009
      '<BigInt> [not] to be (greater than|above) <BigInt>',
1010
      '<string> [not] to be (greater than|above) <string>',
1011
    ],
1012
    (expect, subject, value) => {
1013
      expect(subject > value, '[not] to be truthy');
26×
1014
    }
1015
  );
1016

1017
  expect.addAssertion(
17×
1018
    [
1019
      '<number> [not] to be greater than or equal to <number>',
1020
      '<BigInt> [not] to be greater than or equal to <BigInt>',
1021
      '<string> [not] to be greater than or equal to <string>',
1022
    ],
1023
    (expect, subject, value) => {
1024
      expect(subject >= value, '[not] to be truthy');
8×
1025
    }
1026
  );
1027

1028
  expect.addAssertion('<number> [not] to be positive', (expect, subject) => {
17×
1029
    expect(subject, '[not] to be greater than', 0);
2×
1030
  });
1031

1032
  expect.addAssertion('<BigInt> [not] to be positive', (expect, subject) => {
17×
1033
    expect(subject > 0, '[not] to be true');
2×
1034
  });
1035

1036
  expect.addAssertion('<number> [not] to be negative', (expect, subject) => {
17×
1037
    expect(subject, '[not] to be less than', 0);
4×
1038
  });
1039

1040
  expect.addAssertion('<BigInt> [not] to be negative', (expect, subject) => {
17×
1041
    expect(subject < 0, '[not] to be true');
2×
1042
  });
1043

1044
  expect.addAssertion('<any> to equal <any>', (expect, subject, value) => {
17×
1045
    expect.withError(
1,756×
1046
      () => {
1047
        expect(expect.equal(value, subject), 'to be truthy');
1,756×
1048
      },
1049
      (e) => {
1050
        expect.fail({
387×
1051
          label: 'should equal',
1052
          diff(output, diff) {
1053
            return diff(subject, value);
596×
1054
          },
1055
        });
1056
      }
1057
    );
1058
  });
1059

1060
  expect.addAssertion('<any> not to equal <any>', (expect, subject, value) => {
17×
1061
    expect(expect.equal(value, subject), 'to be falsy');
58×
1062
  });
1063

1064
  expect.addAssertion('<function> to error', (expect, subject) =>
17×
1065
    expect
75×
1066
      .promise(() => subject())
75×
1067
      .then(
1068
        () => {
1069
          expect.fail();
2×
1070
        },
1071
        (error) => error
73×
1072
      )
1073
  );
1074

1075
  expect.addAssertion(
17×
1076
    '<function> to error [with] <any>',
1077
    (expect, subject, arg) =>
1078
      expect(subject, 'to error').then((error) => {
70×
1079
        expect.errorMode = 'nested';
70×
1080
        return expect.withError(
70×
1081
          () => {
1082
            return expect(error, 'to satisfy', arg);
70×
1083
          },
1084
          (e) => {
1085
            e.originalError = error;
3×
1086
            throw e;
3×
1087
          }
1088
        );
1089
      })
1090
  );
1091

1092
  expect.addAssertion('<function> not to error', (expect, subject) => {
17×
1093
    let threw = false;
9×
1094
    return expect
9×
1095
      .promise(() => {
1096
        try {
9×
1097
          return subject();
9×
1098
        } catch (e) {
1099
          threw = true;
2×
1100
          throw e;
2×
1101
        }
1102
      })
1103
      .caught((error) => {
1104
        expect.errorMode = 'nested';
7×
1105
        expect.fail({
7×
1106
          output(output) {
1107
            output
10×
1108
              .error(threw ? 'threw' : 'returned promise rejected with')
1109
              .error(': ')
1110
              .appendErrorMessage(error);
1111
          },
1112
          originalError: error,
1113
        });
1114
      });
1115
  });
1116

1117
  expect.addAssertion('<function> not to throw', (expect, subject) => {
17×
1118
    let threw = false;
21×
1119
    let error;
1120

1121
    try {
21×
1122
      subject();
21×
1123
    } catch (e) {
1124
      error = e;
4×
1125
      threw = true;
4×
1126
    }
1127

1128
    if (threw) {
21×
1129
      expect.errorMode = 'nested';
4×
1130
      expect.fail({
4×
1131
        output(output) {
1132
          output.error('threw: ').appendErrorMessage(error);
7×
1133
        },
1134
        originalError: error,
1135
      });
1136
    }
1137
  });
1138

1139
  expect.addAssertion(
17×
1140
    '<function> to (throw|throw error|throw exception)',
1141
    (expect, subject) => {
1142
      try {
663×
1143
        subject();
663×
1144
      } catch (e) {
1145
        return e;
661×
1146
      }
1147
      expect.errorMode = 'nested';
2×
1148
      expect.fail('did not throw');
2×
1149
    }
1150
  );
1151

1152
  expect.addAssertion('<object> to satisfy <function>', (expect) =>
17×
1153
    expect.fail()
2×
1154
  );
1155

1156
  expect.addAssertion(
17×
1157
    '<function> to throw (a|an) <function>',
1158
    (expect, subject, value) => {
1159
      const constructorName = utils.getFunctionName(value);
6×
1160
      if (constructorName) {
Branches [[63, 1]] missed. 6×
1161
        expect.argsOutput[0] = (output) => {
6×
1162
          output.jsFunctionName(constructorName);
8×
1163
        };
1164
      }
1165
      expect.errorMode = 'nested';
6×
1166
      return expect(subject, 'to throw').tap((error) => {
6×
1167
        expect(error, 'to be a', value);
5×
1168
      });
1169
    }
1170
  );
1171

1172
  expect.addAssertion(
17×
1173
    '<function> to (throw|throw error|throw exception) <any>',
1174
    (expect, subject, arg) => {
1175
      expect.errorMode = 'nested';
646×
1176
      return expect(subject, 'to throw').then((error) => {
646×
1177
        // in the presence of a matcher an error must have been thrown.
1178

1179
        expect.errorMode = 'nested';
646×
1180
        return expect.withError(
646×
1181
          () => {
1182
            return expect(error, 'to satisfy', arg);
646×
1183
          },
1184
          (err) => {
1185
            err.originalError = error;
8×
1186
            throw err;
8×
1187
          }
1188
        );
1189
      });
1190
    }
1191
  );
1192

1193
  expect.addAssertion(
17×
1194
    '<function> to have arity <number>',
1195
    (expect, { length }, value) => {
1196
      expect(length, 'to equal', value);
4×
1197
    }
1198
  );
1199

1200
  expect.addAssertion(
17×
1201
    [
1202
      '<object> to have values [exhaustively] satisfying <any>',
1203
      '<object> to have values [exhaustively] satisfying <assertion>',
1204
      '<object> to be (a map|a hash|an object) whose values [exhaustively] satisfy <any>',
1205
      '<object> to be (a map|a hash|an object) whose values [exhaustively] satisfy <assertion>',
1206
    ],
1207
    (expect, subject, nextArg) => {
1208
      expect.errorMode = 'nested';
69×
1209
      expect(subject, 'not to be empty');
69×
1210
      expect.errorMode = 'bubble';
67×
1211

1212
      const keys = expect.subjectType.getKeys(subject);
67×
1213
      const expected = {};
67×
1214
      keys.forEach((key) => {
67×
1215
        if (typeof nextArg === 'string') {
167×
1216
          expected[key] = expect.it((s) => expect.shift(s));
74×
1217
        } else {
1218
          expected[key] = nextArg;
93×
1219
        }
1220
      });
1221
      return expect.withError(
67×
1222
        () => expect(subject, 'to [exhaustively] satisfy', expected),
67×
1223
        (err) => {
1224
          expect.fail({
27×
1225
            message(output) {
1226
              output.append(
12×
1227
                expect.standardErrorMessage(output.clone(), {
1228
                  compact: err && err._isUnexpected && err.hasDiff(),
1229
                })
1230
              );
1231
            },
1232
            diff(output) {
1233
              const diff = err.getDiff({ output });
58×
1234
              diff.inline = true;
58×
1235
              return diff;
58×
1236
            },
1237
          });
1238
        }
1239
      );
1240
    }
1241
  );
1242

1243
  expect.addAssertion(
17×
1244
    [
1245
      '<array-like> to have items [exhaustively] satisfying <any>',
1246
      '<array-like> to have items [exhaustively] satisfying <assertion>',
1247
      '<array-like> to be an array whose items [exhaustively] satisfy <any>',
1248
      '<array-like> to be an array whose items [exhaustively] satisfy <assertion>',
1249
    ],
1250
    (expect, subject, ...rest) => {
1251
      // ...
1252
      expect.errorMode = 'nested';
53×
1253
      expect(subject, 'not to be empty');
53×
1254
      expect.errorMode = 'bubble';
51×
1255

1256
      return expect.withError(
51×
1257
        () =>
1258
          expect(subject, 'to have values [exhaustively] satisfying', ...rest),
51×
1259
        (err) => {
1260
          expect.fail({
21×
1261
            message(output) {
1262
              output.append(
28×
1263
                expect.standardErrorMessage(output.clone(), {
1264
                  compact: err && err._isUnexpected && err.hasDiff(),
1265
                })
1266
              );
1267
            },
1268
            diff(output) {
1269
              const diff = err.getDiff({ output });
46×
1270
              diff.inline = true;
46×
1271
              return diff;
46×
1272
            },
1273
          });
1274
        }
1275
      );
1276
    }
1277
  );
1278

1279
  expect.addAssertion(
17×
1280
    [
1281
      '<object> to have keys satisfying <any>',
1282
      '<object> to have keys satisfying <assertion>',
1283
      '<object> to be (a map|a hash|an object) whose (keys|properties) satisfy <any>',
1284
      '<object> to be (a map|a hash|an object) whose (keys|properties) satisfy <assertion>',
1285
    ],
1286
    (expect, subject, ...rest) => {
1287
      expect.errorMode = 'nested';
15×
1288
      expect(subject, 'not to be empty');
15×
1289
      expect.errorMode = 'default';
13×
1290

1291
      const keys = expect.subjectType.getKeys(subject);
13×
1292
      return expect(keys, 'to have items satisfying', ...rest);
13×
1293
    }
1294
  );
1295

1296
  expect.addAssertion(
17×
1297
    [
1298
      '<object> [not] to have a value [exhaustively] satisfying <any>',
1299
      '<object> [not] to have a value [exhaustively] satisfying <assertion>',
1300
    ],
1301
    (expect, subject, nextArg) => {
1302
      expect.errorMode = 'nested';
42×
1303
      expect(subject, 'not to be empty');
42×
1304
      expect.errorMode = 'bubble';
40×
1305

1306
      const subjectType = expect.findTypeOf(subject);
40×
1307
      const keys = subjectType.getKeys(subject);
40×
1308
      const not = !!expect.flags.not;
40×
1309

1310
      const keyResults = new Array(keys.length);
40×
1311

1312
      expect.withError(
40×
1313
        () =>
1314
          expect.promise[not ? 'all' : 'any'](
40×
1315
            keys.map((key) => {
1316
              let expected;
1317
              if (typeof nextArg === 'string') {
72×
1318
                expected = expect.it((s) => expect.shift(s));
50×
1319
              } else {
1320
                expected = nextArg;
22×
1321
              }
1322

1323
              keyResults[key] = expect.promise(() =>
72×
1324
                expect(
72×
1325
                  subjectType.valueForKey(subject, key),
1326
                  '[not] to [exhaustively] satisfy',
1327
                  expected
1328
                )
1329
              );
1330
              return keyResults[key];
72×
1331
            })
1332
          ),
1333
        (err) => {
1334
          expect.fail({
12×
1335
            message(output) {
1336
              output.append(
8×
1337
                expect.standardErrorMessage(output.clone(), {
1338
                  compact: err && err._isUnexpected && err.hasDiff(),
1339
                })
1340
              );
1341
            },
1342
            diff:
1343
              expect.flags.not &&
1344
              ((output, diff, inspect, equal) => {
1345
                const expectedObject = subjectType.is('array-like') ? [] : {};
4×
1346
                keys.forEach((key) => {
4×
1347
                  if (keyResults[key].isFulfilled()) {
8×
1348
                    expectedObject[key] = subjectType.valueForKey(subject, key);
4×
1349
                  }
1350
                });
1351

1352
                return diff(subject, expectedObject);
4×
1353
              }),
1354
          });
1355
        }
1356
      );
1357
    }
1358
  );
1359

1360
  expect.addAssertion(
17×
1361
    [
1362
      '<array-like> [not] to have an item [exhaustively] satisfying <any>',
1363
      '<array-like> [not] to have an item [exhaustively] satisfying <assertion>',
1364
    ],
1365
    (expect, subject, ...rest) => {
1366
      expect.errorMode = 'nested';
19×
1367
      expect(subject, 'not to be empty');
19×
1368
      expect.errorMode = 'default';
18×
1369

1370
      return expect(
18×
1371
        subject,
1372
        '[not] to have a value [exhaustively] satisfying',
1373
        ...rest
1374
      );
1375
    }
1376
  );
1377

1378
  expect.addAssertion('<object> to be canonical', (expect, subject) => {
17×
1379
    const stack = [];
5×
1380

1381
    (function traverse(obj) {
5×
1382
      let i;
1383
      for (i = 0; i < stack.length; i += 1) {
20×
1384
        if (stack[i] === obj) {
23×
1385
          return;
1×
1386
        }
1387
      }
1388
      if (obj && typeof obj === 'object') {
19×
1389
        const keys = Object.keys(obj);
9×
1390
        for (i = 0; i < keys.length - 1; i += 1) {
9×
1391
          expect(keys[i], 'to be less than', keys[i + 1]);
10×
1392
        }
1393
        stack.push(obj);
7×
1394
        keys.forEach((key) => {
7×
1395
          traverse(obj[key]);
15×
1396
        });
1397
        stack.pop();
6×
1398
      }
1399
    })(subject);
1400
  });
1401

1402
  expect.addAssertion(
17×
1403
    '<Error> to have message <any>',
1404
    (expect, subject, value) => {
1405
      expect.errorMode = 'nested';
557×
1406
      return expect(
557×
1407
        subject.isUnexpected
1408
          ? subject.getErrorMessage('text').toString()
1409
          : subject.message,
1410
        'to satisfy',
1411
        value
1412
      );
1413
    }
1414
  );
1415

1416
  expect.addAssertion(
17×
1417
    '<Error> to [exhaustively] satisfy <Error>',
1418
    (expect, subject, value) => {
1419
      expect(subject.constructor, 'to be', value.constructor);
31×
1420

1421
      const unwrappedValue = expect.argTypes[0].unwrap(value);
30×
1422
      return expect.withError(
30×
1423
        () => expect(subject, 'to [exhaustively] satisfy', unwrappedValue),
30×
1424
        (e) => {
1425
          expect.fail({
13×
1426
            diff(output, diff) {
1427
              output.inline = false;
24×
1428
              const unwrappedSubject = expect.subjectType.unwrap(subject);
24×
1429
              return utils.wrapConstructorNameAroundOutput(
24×
1430
                diff(unwrappedSubject, unwrappedValue),
1431
                subject
1432
              );
1433
            },
1434
          });
1435
        }
1436
      );
1437
    }
1438
  );
1439

1440
  expect.addAssertion(
17×
1441
    '<Error> to [exhaustively] satisfy <object>',
1442
    (expect, subject, value) => {
1443
      const valueType = expect.argTypes[0];
65×
1444
      const subjectKeys = expect.subjectType.getKeys(subject);
65×
1445
      const valueKeys = valueType.getKeys(value);
65×
1446
      const convertedSubject = {};
65×
1447
      subjectKeys.concat(valueKeys).forEach((key) => {
65×
1448
        convertedSubject[key] = subject[key];
248×
1449
      });
1450
      return expect(convertedSubject, 'to [exhaustively] satisfy', value);
65×
1451
    }
1452
  );
1453

1454
  expect.addAssertion(
17×
1455
    '<Error> to [exhaustively] satisfy <regexp|string|any>',
1456
    (expect, { message }, value) =>
1457
      expect(message, 'to [exhaustively] satisfy', value)
111×
1458
  );
1459

1460
  expect.addAssertion(
17×
1461
    '<UnexpectedError> to [exhaustively] satisfy <regexp|string>',
1462
    (expect, error, value) => {
1463
      expect.errorMode = 'bubble';
601×
1464
      return expect(error, 'to have message', value);
601×
1465
    }
1466
  );
1467

1468
  expect.addAssertion(
17×
1469
    '<binaryArray> to [exhaustively] satisfy <expect.it>',
1470
    (expect, subject, value) =>
1471
      expect.withError(
5×
1472
        () => value(subject, expect.context),
5×
1473
        (e) => {
1474
          expect.fail({
2×
1475
            diff(output, diff, inspect, equal) {
1476
              output.inline = false;
4×
1477
              return output.appendErrorMessage(e);
4×
1478
            },
1479
          });
1480
        }
1481
      )
1482
  );
1483

1484
  expect.addAssertion(
17×
1485
    '<any|Error> to [exhaustively] satisfy <expect.it>',
1486
    (expect, subject, value) => expect.promise(() => value(subject))
58×
1487
  );
1488

1489
  if (typeof Buffer !== 'undefined') {
Branches [[77, 1]] missed. 17×
1490
    expect.addAssertion(
17×
1491
      '<Buffer> [when] decoded as <string> <assertion?>',
1492
      (expect, subject, value) => expect.shift(subject.toString(value))
2×
1493
    );
1494
  }
1495

1496
  expect.addAssertion(
17×
1497
    '<any> not to [exhaustively] satisfy [assertion] <any>',
1498
    (expect, subject, value) =>
1499
      expect.promise((resolve, reject) =>
35×
1500
        expect
35×
1501
          .promise(() =>
1502
            expect(subject, 'to [exhaustively] satisfy [assertion]', value)
35×
1503
          )
1504
          .then(() => {
1505
            try {
3×
1506
              expect.fail();
3×
1507
            } catch (e) {
1508
              reject(e);
3×
1509
            }
1510
          })
1511
          .caught((e) => {
1512
            if (!e || !e._isUnexpected) {
32×
1513
              reject(e);
1×
1514
            } else {
1515
              resolve();
31×
1516
            }
1517
          })
1518
      )
1519
  );
1520

1521
  expect.addAssertion(
17×
1522
    '<any> to [exhaustively] satisfy assertion <any>',
1523
    (expect, subject, value) => {
1524
      expect.errorMode = 'bubble'; // to satisfy assertion 'to be a number' => to be a number
!
1525
      return expect(subject, 'to [exhaustively] satisfy', value);
!
1526
    }
1527
  );
1528

1529
  expect.addAssertion(
17×
1530
    '<any> to [exhaustively] satisfy assertion <assertion>',
1531
    (expect, subject) => {
1532
      expect.errorMode = 'bubble'; // to satisfy assertion 'to be a number' => to be a number
10×
1533
      return expect.shift();
10×
1534
    }
1535
  );
1536

1537
  expect.addAssertion(
17×
1538
    '<any|object> to [exhaustively] satisfy [assertion] <expect.it>',
1539
    (expect, subject, value) =>
1540
      expect.withError(
122×
1541
        () => value(subject, expect.context),
122×
1542
        (e) => {
1543
          expect.fail({
75×
1544
            diff(output) {
1545
              output.inline = false;
26×
1546
              return output.appendErrorMessage(e);
26×
1547
            },
1548
          });
1549
        }
1550
      )
1551
  );
1552

1553
  expect.addAssertion(
17×
1554
    '<regexp> to [exhaustively] satisfy <regexp>',
1555
    (expect, subject, value) => {
1556
      expect(subject, 'to equal', value);
3×
1557
    }
1558
  );
1559

1560
  expect.addAssertion(
17×
1561
    '<string> to [exhaustively] satisfy <regexp>',
1562
    (expect, subject, value) => {
1563
      expect.errorMode = 'bubble';
27×
1564
      return expect(subject, 'to match', value);
27×
1565
    }
1566
  );
1567

1568
  expect.addAssertion(
17×
1569
    '<function> to [exhaustively] satisfy <function>',
1570
    (expect, subject, value) => {
1571
      expect.errorMode = 'bubble';
9×
1572
      expect(subject, 'to be', value);
9×
1573
    }
1574
  );
1575

1576
  expect.addAssertion(
17×
1577
    '<binaryArray> to [exhaustively] satisfy <binaryArray>',
1578
    (expect, subject, value) => {
1579
      expect.errorMode = 'bubble';
4×
1580
      expect(subject, 'to equal', value);
4×
1581
    }
1582
  );
1583

1584
  expect.addAssertion(
17×
1585
    '<any> to [exhaustively] satisfy <any>',
1586
    (expect, subject, value) => {
1587
      expect.errorMode = 'bubble';
1,139×
1588
      expect(subject, 'to equal', value);
1,139×
1589
    }
1590
  );
1591

1592
  expect.addAssertion(
17×
1593
    '<array-like> to [exhaustively] satisfy <array-like>',
1594
    (expect, subject, value) => {
1595
      expect.errorMode = 'bubble';
69×
1596
      const subjectType = expect.subjectType;
69×
1597
      const subjectKeys = subjectType.getKeys(subject);
69×
1598
      const valueType = expect.argTypes[0];
69×
1599
      const valueKeys = valueType.getKeys(value).filter(
69×
1600
        (key) =>
1601
          utils.numericalRegExp.test(key) ||
142×
1602
          typeof key === 'symbol' ||
1603
          // include keys whose value is not undefined on either LHS or RHS
1604
          typeof valueType.valueForKey(value, key) !== 'undefined' ||
1605
          typeof subjectType.valueForKey(subject, key) !== 'undefined'
1606
      );
1607
      const keyPromises = {};
69×
1608
      valueKeys.forEach(function (keyInValue) {
69×
1609
        keyPromises[keyInValue] = expect.promise(function () {
141×
1610
          const subjectKey = subjectType.valueForKey(subject, keyInValue);
141×
1611
          const valueKey = valueType.valueForKey(value, keyInValue);
141×
1612
          const valueKeyType = expect.findTypeOf(valueKey);
141×
1613

1614
          if (valueKeyType.is('expect.it')) {
141×
1615
            expect.context.thisObject = subject;
34×
1616
            return valueKey(subjectKey, expect.context);
34×
1617
          } else {
1618
            return expect(subjectKey, 'to [exhaustively] satisfy', valueKey);
107×
1619
          }
1620
        });
1621
      });
1622
      return expect.promise
69×
1623
        .all([
1624
          expect.promise(() => {
1625
            // create subject key presence object
1626
            const remainingKeysInSubject = {};
69×
1627
            subjectKeys.forEach((key) => {
69×
1628
              remainingKeysInSubject[key] = 1; // present in subject
139×
1629
            });
1630
            // discard or mark missing each previously seen value key
1631
            valueKeys.forEach((key) => {
69×
1632
              if (
141×
1633
                !remainingKeysInSubject[key] &&
1634
                (utils.numericalRegExp.test(key) || expect.flags.exhaustively)
1635
              ) {
1636
                remainingKeysInSubject[key] = 2; // present in value
14×
1637
              } else {
1638
                delete remainingKeysInSubject[key];
127×
1639
              }
1640
            });
1641
            // check whether there are any outstanding keys we cannot account for
1642
            const outstandingKeys = Object.keys(remainingKeysInSubject).filter(
69×
1643
              (key) =>
1644
                utils.numericalRegExp.test(key) ||
28×
1645
                typeof key === 'symbol' ||
1646
                (typeof subjectType.valueForKey(subject, key) !== 'undefined' &&
1647
                  // key was only in the value
1648
                  remainingKeysInSubject[key] === 2)
1649
            );
1650
            // key checking succeeds with no outstanding keys
1651
            expect(outstandingKeys.length === 0, 'to be truthy');
69×
1652
          }),
1653
          expect.promise.all(keyPromises),
1654
        ])
1655
        .caught(() => {
1656
          let i = 0;
33×
1657
          return expect.promise.settle(keyPromises).then(() => {
33×
1658
            const toSatisfyMatrix = new Array(subject.length);
33×
1659
            for (i = 0; i < subject.length; i += 1) {
33×
1660
              toSatisfyMatrix[i] = new Array(value.length);
76×
1661
              if (i < value.length) {
76×
1662
                toSatisfyMatrix[i][i] =
65×
1663
                  keyPromises[i].isFulfilled() || keyPromises[i].reason();
1664
              }
1665
            }
1666
            if (subject.length > 10 || value.length > 10) {
33×
1667
              const indexByIndexChanges = [];
2×
1668
              for (i = 0; i < subject.length; i += 1) {
2×
1669
                const promise = keyPromises[i];
19×
1670
                if (i < value.length) {
19×
1671
                  indexByIndexChanges.push({
17×
1672
                    type: promise.isFulfilled() ? 'equal' : 'similar',
1673
                    value: subject[i],
1674
                    expected: value[i],
1675
                    actualIndex: i,
1676
                    expectedIndex: i,
1677
                    last: i === Math.max(subject.length, value.length) - 1,
1678
                  });
1679
                } else {
1680
                  indexByIndexChanges.push({
2×
1681
                    type: 'remove',
1682
                    value: subject[i],
1683
                    actualIndex: i,
1684
                    last: i === subject.length - 1,
1685
                  });
1686
                }
1687
              }
1688
              for (i = subject.length; i < value.length; i += 1) {
2×
1689
                indexByIndexChanges.push({
3×
1690
                  type: 'insert',
1691
                  value: value[i],
1692
                  expectedIndex: i,
1693
                });
1694
              }
1695
              return failWithChanges(indexByIndexChanges);
2×
1696
            }
1697

1698
            let isAsync = false;
31×
1699
            const subjectElements = utils.duplicateArrayLikeUsingType(
31×
1700
              subject,
1701
              subjectType
1702
            );
1703
            const valueElements = utils.duplicateArrayLikeUsingType(
31×
1704
              value,
1705
              valueType
1706
            );
1707
            const nonNumericalKeysAndSymbols =
1708
              !subjectType.numericalPropertiesOnly &&
31×
1709
              utils.uniqueNonNumericalStringsAndSymbols(subjectKeys, valueKeys);
1710

1711
            const changes = arrayChanges(
31×
1712
              subjectElements,
1713
              valueElements,
1714
              function equal(a, b, aIndex, bIndex) {
1715
                toSatisfyMatrix[aIndex] = toSatisfyMatrix[aIndex] || [];
166×
1716
                const existingResult = toSatisfyMatrix[aIndex][bIndex];
166×
1717
                if (typeof existingResult !== 'undefined') {
166×
1718
                  return existingResult === true;
142×
1719
                }
1720
                let result;
1721
                try {
24×
1722
                  result = expect(a, 'to [exhaustively] satisfy', b);
24×
1723
                } catch (err) {
1724
                  throwIfNonUnexpectedError(err);
6×
1725
                  toSatisfyMatrix[aIndex][bIndex] = err;
6×
1726
                  return false;
6×
1727
                }
1728
                result.then(
18×
1729
                  () => {},
1730
                  () => {}
1731
                );
1732
                if (result.isPending()) {
18×
1733
                  isAsync = true;
13×
1734
                  return false;
13×
1735
                }
1736
                toSatisfyMatrix[aIndex][bIndex] = true;
5×
1737
                return true;
5×
1738
              },
1739
              (a, b) => subjectType.similar(a, b),
64×
1740
              {
1741
                includeNonNumericalProperties: nonNumericalKeysAndSymbols,
1742
              }
1743
            );
1744
            if (isAsync) {
31×
1745
              return expect
2×
1746
                .promise((resolve, reject) => {
1747
                  arrayChangesAsync(
2×
1748
                    subject,
1749
                    value,
1750
                    function equal(a, b, aIndex, bIndex, fn) {
1751
                      toSatisfyMatrix[aIndex] = toSatisfyMatrix[aIndex] || [];
Branches [[96, 1]] missed. 28×
1752
                      const existingResult = toSatisfyMatrix[aIndex][bIndex];
28×
1753
                      if (typeof existingResult !== 'undefined') {
28×
1754
                        return fn(existingResult === true);
15×
1755
                      }
1756
                      expect
13×
1757
                        .promise(() =>
1758
                          expect(a, 'to [exhaustively] satisfy', b)
13×
1759
                        )
1760
                        .then(
1761
                          () => {
1762
                            toSatisfyMatrix[aIndex][bIndex] = true;
1×
1763
                            fn(true);
1×
1764
                          },
1765
                          (err) => {
1766
                            toSatisfyMatrix[aIndex][bIndex] = err;
12×
1767
                            fn(false);
12×
1768
                          }
1769
                        );
1770
                    },
1771
                    (a, b, aIndex, bIndex, fn) => {
1772
                      fn(subjectType.similar(a, b));
26×
1773
                    },
1774
                    nonNumericalKeysAndSymbols,
1775
                    resolve
1776
                  );
1777
                })
1778
                .then(failWithChanges);
1779
            } else {
1780
              return failWithChanges(changes);
29×
1781
            }
1782

1783
            function failWithChanges(changes) {
1784
              expect.errorMode = 'default';
33×
1785
              expect.fail({
33×
1786
                diff(output, diff, inspect, equal) {
1787
                  output.inline = true;
62×
1788
                  const indexOfLastNonInsert = changes.reduce(
62×
1789
                    (previousValue, { type }, index) =>
1790
                      type === 'insert' ? previousValue : index,
192×
1791
                    -1
1792
                  );
1793
                  const prefixOutput = subjectType.prefix(
62×
1794
                    output.clone(),
1795
                    subject
1796
                  );
1797
                  output
62×
1798
                    .append(prefixOutput)
1799
                    .nl(prefixOutput.isEmpty() ? 0 : 1);
Branches [[99, 0]] missed.
1800

1801
                  if (subjectType.indent) {
Branches [[100, 1]] missed. 62×
1802
                    output.indentLines();
62×
1803
                  }
1804
                  const packing = utils.packArrows(changes); // NOTE: Will have side effects in changes if the packing results in too many arrow lanes
62×
1805
                  output.arrowsAlongsideChangeOutputs(
62×
1806
                    packing,
1807
                    changes.map((diffItem, index) => {
1808
                      const delimiterOutput = subjectType.delimiter(
192×
1809
                        output.clone(),
1810
                        index,
1811
                        indexOfLastNonInsert + 1
1812
                      );
1813
                      const type = diffItem.type;
192×
1814
                      if (type === 'moveTarget') {
192×
1815
                        return output.clone();
2×
1816
                      } else {
1817
                        return output.clone().block(function () {
190×
1818
                          if (type === 'moveSource') {
190×
1819
                            const propertyOutput = subjectType.property(
2×
1820
                              output.clone(),
1821
                              diffItem.actualIndex,
1822
                              inspect(diffItem.value),
1823
                              true
1824
                            );
1825

1826
                            this.append(propertyOutput)
2×
1827
                              .amend(delimiterOutput)
1828
                              .sp()
1829
                              .error('// should be moved');
1830
                          } else if (type === 'insert') {
188×
1831
                            this.annotationBlock(function () {
32×
1832
                              if (
32×
1833
                                expect
1834
                                  .findTypeOf(diffItem.value)
1835
                                  .is('expect.it')
1836
                              ) {
1837
                                this.error('missing: ').block(function () {
6×
1838
                                  this.omitSubject = undefined;
6×
1839
                                  const promise =
1840
                                    keyPromises[diffItem.expectedIndex];
6×
1841
                                  if (promise.isRejected()) {
6×
1842
                                    this.appendErrorMessage(promise.reason());
4×
1843
                                  } else {
1844
                                    this.appendInspected(diffItem.value);
2×
1845
                                  }
1846
                                });
1847
                              } else {
1848
                                const index =
1849
                                  typeof diffItem.actualIndex !== 'undefined'
Branches [[106, 0]] missed. 26×
1850
                                    ? diffItem.actualIndex
1851
                                    : diffItem.expectedIndex;
1852
                                const propertyOutput = subjectType.property(
26×
1853
                                  output.clone(),
1854
                                  index,
1855
                                  inspect(diffItem.value),
1856
                                  true
1857
                                );
1858
                                this.error('missing ').append(propertyOutput);
26×
1859
                              }
1860
                            });
1861
                          } else {
1862
                            const propertyOutput = subjectType.property(
156×
1863
                              output.clone(),
1864
                              diffItem.actualIndex,
1865
                              inspect(diffItem.value),
1866
                              true
1867
                            );
1868

1869
                            this.block(function () {
156×
1870
                              if (type === 'remove') {
156×
1871
                                this.append(propertyOutput)
26×
1872
                                  .amend(delimiterOutput)
1873
                                  .sp()
1874
                                  .error('// should be removed');
1875
                              } else if (type === 'equal') {
130×
1876
                                this.append(propertyOutput).amend(
76×
1877
                                  delimiterOutput
1878
                                );
1879
                              } else {
1880
                                const toSatisfyResult =
1881
                                  toSatisfyMatrix[diffItem.actualIndex][
54×
1882
                                    diffItem.expectedIndex
1883
                                  ];
1884
                                const valueDiff =
1885
                                  toSatisfyResult &&
54×
1886
                                  toSatisfyResult !== true &&
1887
                                  toSatisfyResult.getDiff({
1888
                                    output: output.clone(),
1889
                                  });
1890
                                if (valueDiff && valueDiff.inline) {
54×
1891
                                  this.append(valueDiff).amend(delimiterOutput);
4×
1892
                                } else {
1893
                                  this.append(propertyOutput)
50×
1894
                                    .amend(delimiterOutput)
1895
                                    .sp()
1896
                                    .annotationBlock(function () {
1897
                                      this.omitSubject = diffItem.value;
50×
1898
                                      const label = toSatisfyResult.getLabel();
50×
1899
                                      if (label) {
50×
1900
                                        this.error(label)
30×
1901
                                          .sp()
1902
                                          .block(inspect(diffItem.expected));
1903
                                        if (valueDiff) {
30×
1904
                                          this.nl(2).append(valueDiff);
2×
1905
                                        }
1906
                                      } else {
1907
                                        this.appendErrorMessage(
20×
1908
                                          toSatisfyResult
1909
                                        );
1910
                                      }
1911
                                    });
1912
                                }
1913
                              }
1914
                            });
1915
                          }
1916
                        });
1917
                      }
1918
                    })
1919
                  );
1920

1921
                  if (subjectType.indent) {
Branches [[114, 1]] missed. 62×
1922
                    output.outdentLines();
62×
1923
                  }
1924
                  const suffixOutput = subjectType.suffix(
62×
1925
                    output.clone(),
1926
                    subject
1927
                  );
1928
                  output
62×
1929
                    .nl(suffixOutput.isEmpty() ? 0 : 1)
Branches [[115, 0]] missed.
1930
                    .append(suffixOutput);
1931

1932
                  return output;
62×
1933
                },
1934
              });
1935
            }
1936
          });
1937
        });
1938
    }
1939
  );
1940

1941
  const disallowedConstructors = [];
17×
1942
  ['Set', 'WeakSet', 'Map', 'WeakMap'].forEach((constructorName) => {
17×
1943
    const Constructor = (typeof window !== 'undefined' ? window : global)[
Branches [[116, 0]] missed. 68×
1944
      constructorName
1945
    ];
1946
    if (typeof Constructor === 'function') {
Branches [[117, 1]] missed. 68×
1947
      disallowedConstructors.push(Constructor);
68×
1948
    }
1949
  });
1950

1951
  expect.addAssertion(
17×
1952
    '<object> to [exhaustively] satisfy <object>',
1953
    (expect, subject, value) => {
1954
      const valueType = expect.argTypes[0];
368×
1955
      const subjectType = expect.subjectType;
368×
1956
      const subjectIsArrayLike = subjectType.is('array-like');
368×
1957
      if (subject === value) {
368×
1958
        return;
1×
1959
      }
1960
      if (valueType.is('array-like') && !subjectIsArrayLike) {
367×
1961
        expect.fail();
2×
1962
      }
1963
      disallowedConstructors.forEach(function (Constructor) {
365×
1964
        if (subject instanceof Constructor) {
1,454×
1965
          expect.fail({
4×
1966
            message: `A ${Constructor.name} instance is not allowed as a subject of "to satisfy"`,
1967
            errorMode: 'bubbleThrough',
1968
          });
1969
        }
1970
      });
1971

1972
      if (Object.getPrototypeOf(value) !== Object.prototype) {
361×
1973
        expect.fail({
1×
1974
          message: 'Can only satisfy against a plain object',
1975
          errorMode: 'bubbleThrough',
1976
        });
1977
      }
1978

1979
      const subjectKeys = subjectType.getKeys(subject);
360×
1980
      const valueKeys = valueType.getKeys(value);
360×
1981
      // calculate the unique keys early given enumerability no
1982
      // longer affects what is included in the list of keys
1983
      const uniqueKeys = subjectType.uniqueKeys(subjectKeys, valueKeys);
360×
1984

1985
      const promiseByKey = {};
360×
1986
      let forceExhaustivelyComparison = false;
360×
1987
      uniqueKeys.forEach((key, index) => {
360×
1988
        const subjectHasKey = subjectType.hasKey(subject, key);
1,324×
1989
        const valueKey = valueType.hasKey(value, key, true)
1,324×
1990
          ? valueType.valueForKey(value, key)
1991
          : undefined;
1992
        const valueKeyType = expect.findTypeOf(valueKey);
1,324×
1993
        if (expect.flags.exhaustively) {
1,324×
1994
          if (valueKeyType.is('expect.it') && !subjectHasKey) {
82×
1995
            // ensure value only expect.it key is marked missing
1996
            forceExhaustivelyComparison = true;
1×
1997
          }
1998
        } else if (subjectHasKey && typeof valueKey === 'undefined') {
1,242×
1999
          // ignore subject only keys unless we are being exhaustive
2000
          return;
724×
2001
        }
2002
        const subjectKey = subjectHasKey
600×
2003
          ? subjectType.valueForKey(subject, key)
2004
          : undefined;
2005

2006
        promiseByKey[key] = expect.promise(() => {
600×
2007
          if (valueKeyType.is('expect.it')) {
600×
2008
            expect.context.thisObject = subject;
200×
2009
            return valueKey(subjectKey, expect.context);
200×
2010
          } else {
2011
            return expect(subjectKey, 'to [exhaustively] satisfy', valueKey);
400×
2012
          }
2013
        });
2014
      });
2015

2016
      return expect.promise
360×
2017
        .all([
2018
          expect.promise(() => {
2019
            if (forceExhaustivelyComparison) {
360×
2020
              throw new Error('exhaustive comparison failure');
1×
2021
            }
2022
          }),
2023
          expect.promise.all(promiseByKey),
2024
        ])
2025
        .caught(() =>
2026
          expect.promise.settle(promiseByKey).then(() => {
119×
2027
            expect.fail({
119×
2028
              diff(output, diff, inspect, equal) {
2029
                output.inline = true;
196×
2030
                const subjectIsArrayLike = subjectType.is('array-like');
196×
2031
                // Skip missing keys expected to be missing so they don't get rendered in the diff
2032
                const keys = uniqueKeys.filter((key) => {
196×
2033
                  return (
406×
2034
                    subjectType.hasKey(subject, key) ||
2035
                    typeof valueType.valueForKey(value, key) !== 'undefined'
2036
                  );
2037
                });
2038
                const prefixOutput = subjectType.prefix(
196×
2039
                  output.clone(),
2040
                  subject
2041
                );
2042
                output.append(prefixOutput).nl(prefixOutput.isEmpty() ? 0 : 1);
196×
2043

2044
                if (subjectType.indent) {
196×
2045
                  output.indentLines();
192×
2046
                }
2047
                keys.forEach((key, index) => {
196×
2048
                  const subjectKey = subjectType.valueForKey(subject, key);
403×
2049
                  const valueKey = valueType.valueForKey(value, key);
403×
2050
                  output
403×
2051
                    .nl(index > 0 ? 1 : 0)
2052
                    .i()
2053
                    .block(function () {
2054
                      let valueOutput;
2055
                      const annotation = output.clone();
403×
2056
                      let conflicting;
2057

2058
                      if (
403×
2059
                        Object.prototype.hasOwnProperty.call(
2060
                          promiseByKey,
2061
                          key
2062
                        ) &&
2063
                        promiseByKey[key].isRejected()
2064
                      ) {
2065
                        conflicting = promiseByKey[key].reason();
222×
2066
                      }
2067

2068
                      const missingArrayIndex =
2069
                        subjectType.is('array-like') &&
403×
2070
                        !subjectType.hasKey(subject, key);
2071

2072
                      let isInlineDiff = true;
403×
2073

2074
                      output.omitSubject = subjectKey;
403×
2075
                      if (!valueType.hasKey(value, key)) {
403×
2076
                        if (expect.flags.exhaustively) {
72×
2077
                          annotation.error('should be removed');
20×
2078
                        } else {
2079
                          conflicting = null;
52×
2080
                        }
2081
                      } else if (!subjectType.hasKey(subject, key)) {
331×
2082
                        if (expect.findTypeOf(valueKey).is('expect.it')) {
28×
2083
                          if (promiseByKey[key].isRejected()) {
14×
2084
                            output.error('// missing:').sp();
10×
2085
                            valueOutput = output
10×
2086
                              .clone()
2087
                              .appendErrorMessage(promiseByKey[key].reason());
2088
                          } else {
2089
                            output.error('// missing').sp();
4×
2090
                            valueOutput = output
4×
2091
                              .clone()
2092
                              .error('should satisfy')
2093
                              .sp()
2094
                              .block(inspect(value[key]));
2095
                          }
2096
                        } else {
2097
                          output.error('// missing').sp();
14×
2098
                          valueOutput = inspect(valueKey);
14×
2099
                        }
2100
                      } else if (conflicting || missingArrayIndex) {
303×
2101
                        const keyDiff =
2102
                          conflicting && conflicting.getDiff({ output });
178×
2103
                        isInlineDiff = !keyDiff || keyDiff.inline;
178×
2104
                        if (missingArrayIndex) {
Branches [[148, 0]] missed. 178×
UNCOV
2105
                          output.error('// missing').sp();
!
2106
                        }
2107
                        if (keyDiff && keyDiff.inline) {
178×
2108
                          valueOutput = keyDiff;
28×
2109
                        } else if (
150×
2110
                          expect.findTypeOf(valueKey).is('expect.it')
2111
                        ) {
2112
                          isInlineDiff = false;
70×
2113
                          annotation.appendErrorMessage(conflicting);
70×
2114
                        } else if (!keyDiff || (keyDiff && !keyDiff.inline)) {
Branches [[152, 1]] missed. 80×
2115
                          annotation
80×
2116
                            .error(
2117
                              (conflicting && conflicting.getLabel()) ||
2118
                                'should satisfy'
2119
                            )
2120
                            .sp()
2121
                            .block(inspect(valueKey));
2122

2123
                          if (keyDiff) {
80×
2124
                            annotation.nl(2).append(keyDiff);
38×
2125
                          }
2126
                        } else {
UNCOV
2127
                          valueOutput = keyDiff;
!
2128
                        }
2129
                      }
2130

2131
                      if (!valueOutput) {
403×
2132
                        if (
Branches [[157, 0]] missed. 347×
2133
                          missingArrayIndex ||
2134
                          !subjectType.hasKey(subject, key)
2135
                        ) {
UNCOV
2136
                          valueOutput = output.clone();
!
2137
                        } else {
2138
                          valueOutput = inspect(subjectKey);
347×
2139
                        }
2140
                      }
2141

2142
                      const omitDelimiter =
2143
                        missingArrayIndex || index >= subjectKeys.length - 1;
403×
2144

2145
                      if (!omitDelimiter) {
403×
2146
                        const delimiterOutput = subjectType.delimiter(
187×
2147
                          output.clone(),
2148
                          index,
2149
                          keys.length
2150
                        );
2151
                        valueOutput.amend(delimiterOutput);
187×
2152
                      }
2153

2154
                      const annotationOnNextLine =
2155
                        !isInlineDiff &&
403×
2156
                        output.preferredWidth <
2157
                          this.size().width +
2158
                            valueOutput.size().width +
2159
                            annotation.size().width;
2160

2161
                      if (!annotation.isEmpty()) {
403×
2162
                        if (!valueOutput.isEmpty()) {
Branches [[163, 1]] missed. 170×
2163
                          if (annotationOnNextLine) {
170×
2164
                            valueOutput.nl();
2×
2165
                          } else {
2166
                            valueOutput.sp();
168×
2167
                          }
2168
                        }
2169

2170
                        valueOutput.annotationBlock(function () {
170×
2171
                          this.append(annotation);
170×
2172
                        });
2173
                      }
2174

2175
                      if (!isInlineDiff) {
403×
2176
                        valueOutput = output.clone().block(valueOutput);
108×
2177
                      }
2178

2179
                      const propertyOutput = subjectType.property(
403×
2180
                        output.clone(),
2181
                        key,
2182
                        valueOutput,
2183
                        subjectIsArrayLike
2184
                      );
2185

2186
                      this.append(propertyOutput);
403×
2187
                    });
2188
                });
2189

2190
                if (subjectType.indent) {
196×
2191
                  output.outdentLines();
192×
2192
                }
2193
                const suffixOutput = subjectType.suffix(
196×
2194
                  output.clone(),
2195
                  subject
2196
                );
2197
                return output
196×
2198
                  .nl(suffixOutput.isEmpty() ? 0 : 1)
2199
                  .append(suffixOutput);
2200
              },
2201
            });
2202
          })
2203
        );
2204
    }
2205
  );
2206

2207
  function wrapDiffWithTypePrefixAndSuffix(e, type, subject) {
2208
    const createDiff = e.getDiffMethod();
5×
2209
    if (createDiff) {
Branches [[168, 1]] missed. 5×
2210
      return function (output, ...rest) {
5×
2211
        type.prefix(output, subject);
10×
2212
        const result = createDiff.call(this, output, ...rest);
10×
2213
        type.suffix(output, subject);
10×
2214
        return result;
10×
2215
      };
2216
    }
2217
  }
2218

2219
  expect.addAssertion(
17×
2220
    '<wrapperObject> to [exhaustively] satisfy <wrapperObject>',
2221
    (expect, subject, value) => {
2222
      const type = expect.findCommonType(subject, value);
4×
2223
      expect(type.is('wrapperObject'), 'to be truthy');
4×
2224
      return expect.withError(
4×
2225
        () =>
2226
          expect(
4×
2227
            type.unwrap(subject),
2228
            'to [exhaustively] satisfy',
2229
            type.unwrap(value)
2230
          ),
2231
        (e) => {
2232
          expect.fail({
2×
2233
            label: e.getLabel(),
2234
            diff: wrapDiffWithTypePrefixAndSuffix(e, type, subject),
2235
          });
2236
        }
2237
      );
2238
    }
2239
  );
2240

2241
  expect.addAssertion(
17×
2242
    '<wrapperObject> to [exhaustively] satisfy <any>',
2243
    (expect, subject, value) => {
2244
      const subjectType = expect.subjectType;
6×
2245

2246
      return expect.withError(
6×
2247
        () =>
2248
          expect(
6×
2249
            subjectType.unwrap(subject),
2250
            'to [exhaustively] satisfy',
2251
            value
2252
          ),
2253
        (e) => {
2254
          expect.fail({
3×
2255
            label: e.getLabel(),
2256
            diff: wrapDiffWithTypePrefixAndSuffix(e, subjectType, subject),
2257
          });
2258
        }
2259
      );
2260
    }
2261
  );
2262

2263
  expect.addAssertion(
17×
2264
    '<function> [when] called with <array-like> <assertion?>',
2265
    (expect, subject, args) => {
2266
      // ...
2267
      expect.errorMode = 'nested';
6×
2268
      expect.argsOutput[0] = (output) => {
6×
2269
        output.appendItems(args, ', ');
2×
2270
      };
2271

2272
      const thisObject = expect.context.thisObject || null;
6×
2273

2274
      return expect.shift(subject.apply(thisObject, args));
6×
2275
    }
2276
  );
2277

2278
  expect.addAssertion(
17×
2279
    '<function> [when] called <assertion?>',
2280
    (expect, subject) => {
2281
      expect.errorMode = 'nested';
7×
2282

2283
      const thisObject = expect.context.thisObject || null;
7×
2284

2285
      return expect.shift(subject.call(thisObject));
7×
2286
    }
2287
  );
2288

2289
  function instantiate(Constructor, args) {
2290
    function ProxyConstructor() {
2291
      return Constructor.apply(this, args);
1×
2292
    }
2293
    ProxyConstructor.prototype = Constructor.prototype;
1×
2294
    return new ProxyConstructor();
1×
2295
  }
2296

2297
  expect.addAssertion(
17×
2298
    [
2299
      '<array-like> [when] passed as parameters to [async] <function> <assertion?>',
2300
      '<array-like> [when] passed as parameters to [constructor] <function> <assertion?>',
2301
    ],
2302
    (expect, subject, fn) => {
2303
      // ...
2304
      expect.errorMode = 'nested';
10×
2305
      let args = subject;
10×
2306
      if (expect.flags.async) {
10×
2307
        return expect.promise((run) => {
3×
2308
          args = [
3×
2309
            ...args,
2310
            run((err, result) => {
2311
              expect(err, 'to be falsy');
3×
2312
              return expect.shift(result);
2×
2313
            }),
2314
          ];
2315
          fn(...args);
3×
2316
        });
2317
      } else {
2318
        return expect.shift(
7×
2319
          expect.flags.constructor ? instantiate(fn, args) : fn(...args)
2320
        );
2321
      }
2322
    }
2323
  );
2324

2325
  expect.addAssertion(
17×
2326
    [
2327
      '<any> [when] passed as parameter to [async] <function> <assertion?>',
2328
      '<any> [when] passed as parameter to [constructor] <function> <assertion?>',
2329
    ],
2330
    (expect, subject, fn) => {
2331
      // ...
2332
      expect.errorMode = 'nested';
6×
2333
      let args = [subject];
6×
2334
      if (expect.flags.async) {
Branches [[173, 0]] missed. 6×
UNCOV
2335
        return expect.promise((run) => {
!
UNCOV
2336
          args = [
!
2337
            ...args,
2338
            run((err, result) => {
UNCOV
2339
              expect(err, 'to be falsy');
!
UNCOV
2340
              return expect.shift(result);
!
2341
            }),
2342
          ];
UNCOV
2343
          fn(...args);
!
2344
        });
2345
      } else {
2346
        return expect.shift(
6×
2347
          expect.flags.constructor ? instantiate(fn, args) : fn(...args)
Branches [[174, 0]] missed.
2348
        );
2349
      }
2350
    }
2351
  );
2352

2353
  expect.addAssertion(
17×
2354
    [
2355
      '<array-like> [when] sorted [numerically] <assertion?>',
2356
      '<array-like> [when] sorted by <function> <assertion?>',
2357
    ],
2358
    (expect, subject, compareFunction) => {
2359
      if (expect.flags.numerically) {
8×
2360
        compareFunction = (a, b) => a - b;
7×
2361
      }
2362
      return expect.shift(
8×
2363
        Array.prototype.slice
2364
          .call(subject)
2365
          .sort(
2366
            typeof compareFunction === 'function' ? compareFunction : undefined
2367
          )
2368
      );
2369
    }
2370
  );
2371

2372
  expect.addAssertion('<Promise> to be rejected', (expect, subject) => {
17×
2373
    expect.errorMode = 'nested';
82×
2374
    return expect
82×
2375
      .promise(() => subject)
82×
2376
      .then(
2377
        (obj) => {
2378
          expect.fail((output) => {
4×
2379
            output.appendInspected(subject).sp().text('unexpectedly fulfilled');
8×
2380
            if (typeof obj !== 'undefined') {
8×
2381
              output.sp().text('with').sp().appendInspected(obj);
6×
2382
            }
2383
          });
2384
        },
2385
        (err) => err
78×
2386
      );
2387
  });
2388

2389
  expect.addAssertion('<function> to be rejected', (expect, subject) => {
17×
2390
    expect.errorMode = 'nested';
5×
2391
    return expect(
5×
2392
      expect.promise(() => subject()),
5×
2393
      'to be rejected'
2394
    );
2395
  });
2396

2397
  expect.addAssertion(
17×
2398
    [
2399
      '<Promise> to be rejected with <any>',
2400
      '<Promise> to be rejected with error [exhaustively] satisfying <any>',
2401
    ],
2402
    (expect, subject, value) => {
2403
      expect.errorMode = 'nested';
71×
2404
      return expect(subject, 'to be rejected').tap((err) =>
71×
2405
        expect.withError(
71×
2406
          () => expect(err, 'to [exhaustively] satisfy', value),
71×
2407
          (e) => {
2408
            e.originalError = err;
13×
2409
            throw e;
13×
2410
          }
2411
        )
2412
      );
2413
    }
2414
  );
2415

2416
  expect.addAssertion(
17×
2417
    [
2418
      '<function> to be rejected with <any>',
2419
      '<function> to be rejected with error [exhaustively] satisfying <any>',
2420
    ],
2421
    (expect, subject, value) => {
2422
      expect.errorMode = 'nested';
11×
2423
      return expect(
11×
2424
        expect.promise(() => subject()),
11×
2425
        'to be rejected with error [exhaustively] satisfying',
2426
        value
2427
      );
2428
    }
2429
  );
2430

2431
  expect.addAssertion('<Promise> to be fulfilled', (expect, subject) => {
17×
2432
    expect.errorMode = 'nested';
28×
2433
    return expect
28×
2434
      .promise(() => subject)
28×
2435
      .caught((err) => {
2436
        expect.fail({
6×
2437
          output(output) {
2438
            output.appendInspected(subject).sp().text('unexpectedly rejected');
10×
2439
            if (typeof err !== 'undefined') {
10×
2440
              output.sp().text('with').sp().appendInspected(err);
8×
2441
            }
2442
          },
2443
          originalError: err,
2444
        });
2445
      });
2446
  });
2447

2448
  expect.addAssertion('<function> to be fulfilled', (expect, subject) => {
17×
2449
    expect.errorMode = 'nested';
6×
2450
    return expect(
6×
2451
      expect.promise(() => subject()),
6×
2452
      'to be fulfilled'
2453
    );
2454
  });
2455

2456
  expect.addAssertion(
17×
2457
    [
2458
      '<Promise> to be fulfilled with <any>',
2459
      '<Promise> to be fulfilled with value [exhaustively] satisfying <any>',
2460
    ],
2461
    (expect, subject, value) => {
2462
      expect.errorMode = 'nested';
18×
2463
      return expect(subject, 'to be fulfilled').tap((fulfillmentValue) =>
18×
2464
        expect(fulfillmentValue, 'to [exhaustively] satisfy', value)
18×
2465
      );
2466
    }
2467
  );
2468

2469
  expect.addAssertion(
17×
2470
    [
2471
      '<function> to be fulfilled with <any>',
2472
      '<function> to be fulfilled with value [exhaustively] satisfying <any>',
2473
    ],
2474
    (expect, subject, value) => {
2475
      expect.errorMode = 'nested';
5×
2476
      return expect(
5×
2477
        expect.promise(() => subject()),
5×
2478
        'to be fulfilled with value [exhaustively] satisfying',
2479
        value
2480
      );
2481
    }
2482
  );
2483

2484
  expect.addAssertion(
17×
2485
    '<Promise> when rejected <assertion>',
2486
    (expect, subject, nextAssertion) => {
2487
      expect.errorMode = 'nested';
14×
2488
      return expect
14×
2489
        .promise(() => subject)
14×
2490
        .then(
2491
          (fulfillmentValue) => {
2492
            if (typeof nextAssertion === 'string') {
Branches [[179, 1]] missed. 3×
2493
              expect.argsOutput = (output) => {
3×
2494
                output.error(nextAssertion);
6×
2495
                const rest = expect.args.slice(1);
6×
2496
                if (rest.length > 0) {
6×
2497
                  output.sp().appendItems(rest, ', ');
4×
2498
                }
2499
              };
2500
            }
2501
            expect.fail((output) => {
3×
2502
              output
6×
2503
                .appendInspected(subject)
2504
                .sp()
2505
                .text('unexpectedly fulfilled');
2506
              if (typeof fulfillmentValue !== 'undefined') {
6×
2507
                output.sp().text('with').sp().appendInspected(fulfillmentValue);
4×
2508
              }
2509
            });
2510
          },
2511
          (err) => {
2512
            if (
11×
2513
              err.isOperational &&
2514
              !Object.prototype.propertyIsEnumerable.call(err, 'isOperational')
2515
            ) {
2516
              delete err.isOperational;
7×
2517
            }
2518

2519
            expect.withError(
11×
2520
              () => expect.shift(err),
11×
2521
              (e) => {
2522
                e.originalError = err;
5×
2523
                throw e;
5×
2524
              }
2525
            );
2526
          }
2527
        );
2528
    }
2529
  );
2530

2531
  expect.addAssertion(
17×
2532
    '<function> when rejected <assertion>',
2533
    (expect, subject, ...rest) => {
2534
      expect.errorMode = 'nested';
4×
2535
      return expect(
4×
2536
        expect.promise(() => subject()),
4×
2537
        'when rejected',
2538
        ...rest
2539
      );
2540
    }
2541
  );
2542

2543
  expect.addAssertion(
17×
2544
    '<Promise> when fulfilled <assertion>',
2545
    (expect, subject, nextAssertion) => {
2546
      expect.errorMode = 'nested';
10×
2547
      return expect
10×
2548
        .promise(() => subject)
10×
2549
        .then(
2550
          (fulfillmentValue) => expect.shift(fulfillmentValue),
5×
2551
          (err) => {
2552
            // typeof nextAssertion === 'string' because expect.it is handled by the above (and shift only supports those two):
2553
            expect.argsOutput = (output) => {
5×
2554
              output.error(nextAssertion);
9×
2555
              const rest = expect.args.slice(1);
9×
2556
              if (rest.length > 0) {
9×
2557
                output.sp().appendItems(rest, ', ');
5×
2558
              }
2559
            };
2560
            expect.fail({
5×
2561
              output(output) {
2562
                output
9×
2563
                  .appendInspected(subject)
2564
                  .sp()
2565
                  .text('unexpectedly rejected');
2566
                if (typeof err !== 'undefined') {
9×
2567
                  output.sp().text('with').sp().appendInspected(err);
7×
2568
                }
2569
              },
2570
              originalError: err,
2571
            });
2572
          }
2573
        );
2574
    }
2575
  );
2576

2577
  expect.addAssertion(
17×
2578
    '<function> when fulfilled <assertion>',
2579
    (expect, subject, ...rest) => {
2580
      expect.errorMode = 'nested';
4×
2581
      return expect(
4×
2582
        expect.promise(() => subject()),
4×
2583
        'when fulfilled',
2584
        ...rest
2585
      );
2586
    }
2587
  );
2588

2589
  expect.addAssertion('<function> to call the callback', (expect, subject) => {
17×
2590
    expect.errorMode = 'nested';
30×
2591
    return expect.promise((run) => {
30×
2592
      let async = false;
30×
2593
      let calledTwice = false;
30×
2594
      let callbackArgs;
2595
      function cb(...args) {
2596
        if (callbackArgs) {
25×
2597
          calledTwice = true;
2×
2598
        } else {
2599
          callbackArgs = Array.prototype.slice.call(args);
23×
2600
        }
2601
        if (async) {
25×
2602
          setTimeout(assert, 0);
19×
2603
        }
2604
      }
2605

2606
      const assert = run(() => {
30×
2607
        if (calledTwice) {
24×
2608
          expect.fail(function () {
3×
2609
            this.error('The callback was called twice');
4×
2610
          });
2611
        }
2612
        return callbackArgs;
21×
2613
      });
2614

2615
      subject(cb);
30×
2616
      async = true;
29×
2617
      if (callbackArgs) {
29×
2618
        return assert();
5×
2619
      }
2620
    });
2621
  });
2622

2623
  expect.addAssertion(
17×
2624
    '<function> to call the callback without error',
2625
    (expect, subject) =>
2626
      expect(subject, 'to call the callback').then((callbackArgs) => {
4×
2627
        const err = callbackArgs[0];
4×
2628
        if (err) {
4×
2629
          expect.errorMode = 'nested';
2×
2630
          expect.fail({
2×
2631
            message(output) {
2632
              output.error('called the callback with: ');
4×
2633
              if (err.getErrorMessage) {
4×
2634
                output.appendErrorMessage(err);
2×
2635
              } else {
2636
                output.appendInspected(err);
2×
2637
              }
2638
            },
2639
          });
2640
        } else {
2641
          return callbackArgs.slice(1);
2×
2642
        }
2643
      })
2644
  );
2645

2646
  expect.addAssertion(
17×
2647
    '<function> to call the callback with error',
2648
    (expect, subject) =>
2649
      expect(subject, 'to call the callback').spread((err) => {
12×
2650
        expect(err, 'to be truthy');
12×
2651
        return err;
10×
2652
      })
2653
  );
2654

2655
  expect.addAssertion(
17×
2656
    '<function> to call the callback with error <any>',
2657
    (expect, subject, value) =>
2658
      expect(subject, 'to call the callback with error').tap((err) => {
10×
2659
        expect.errorMode = 'nested';
9×
2660
        expect(err, 'to satisfy', value);
9×
2661
      })
2662
  );
2663

2664
  expect.addAssertion(
17×
2665
    '<Set> [not] to contain <any+>',
2666
    (expect, subject, ...values) => {
2667
      const subjectElements = [];
10×
2668
      subject.forEach((element) => {
10×
2669
        subjectElements.push(element);
26×
2670
      });
2671

2672
      expect.withError(
10×
2673
        () => {
2674
          values.forEach((value) => {
10×
2675
            expect(
14×
2676
              subject.has(value) ||
2677
                subjectElements.some((element) => expect.equal(element, value)),
18×
2678
              '[not] to be true'
2679
            );
2680
          });
2681
        },
2682
        () => {
2683
          expect.fail({
5×
2684
            diff(output, diff, inspect, equal) {
2685
              output.inline = true;
10×
2686
              expect.subjectType.prefix(output, subject);
10×
2687
              output.nl().indentLines();
10×
2688

2689
              subjectElements.forEach((subjectElement, subjectIndex) => {
10×
2690
                output
26×
2691
                  .i()
2692
                  .block(function () {
2693
                    this.appendInspected(subjectElement);
26×
2694
                    expect.subjectType.delimiter(
26×
2695
                      this,
2696
                      subjectIndex,
2697
                      subjectElements.length
2698
                    );
2699
                    if (
26×
2700
                      expect.flags.not &&
2701
                      values.some((value) => equal(subjectElement, value))
20×
2702
                    ) {
2703
                      this.sp().annotationBlock(function () {
6×
2704
                        this.error('should be removed');
6×
2705
                      });
2706
                    }
2707
                  })
2708
                  .nl();
2709
              });
2710
              if (!expect.flags.not) {
10×
2711
                values.forEach((value) => {
6×
2712
                  if (
10×
2713
                    !subject.has(value) &&
2714
                    !subjectElements.some((element) => equal(element, value))
16×
2715
                  ) {
2716
                    output
6×
2717
                      .i()
2718
                      .block(function () {
2719
                        this.annotationBlock(function () {
6×
2720
                          this.error('missing').sp().appendInspected(value);
6×
2721
                        });
2722
                      })
2723
                      .nl();
2724
                  }
2725
                });
2726
              }
2727

2728
              output.outdentLines();
10×
2729
              expect.subjectType.suffix(output, subject);
10×
2730

2731
              return output;
10×
2732
            },
2733
          });
2734
        }
2735
      );
2736
    }
2737
  );
2738

2739
  expect.addAssertion('<Set> [not] to be empty', (expect, subject) => {
17×
2740
    expect(subject.size, '[not] to equal', 0);
16×
2741
  });
2742

2743
  expect.addAssertion(
17×
2744
    [
2745
      '<Set> to have items [exhaustively] satisfying <any>',
2746
      '<Set> to have items [exhaustively] satisfying <assertion>',
2747
    ],
2748
    (expect, subject, nextArg) => {
2749
      expect.errorMode = 'nested';
5×
2750
      expect(subject, 'not to be empty');
5×
2751
      expect.errorMode = 'bubble';
4×
2752

2753
      const subjectElements = [];
4×
2754
      subject.forEach((element) => {
4×
2755
        subjectElements.push(element);
11×
2756
      });
2757

2758
      const expected = [];
4×
2759
      subjectElements.forEach((subjectElement) => {
4×
2760
        if (typeof nextArg === 'string') {
11×
2761
          expected.push(expect.it((s) => expect.shift(s, 0)));
6×
2762
        } else {
2763
          expected.push(nextArg);
5×
2764
        }
2765
      });
2766

2767
      return expect.withError(
4×
2768
        () => expect(subjectElements, 'to [exhaustively] satisfy', expected),
4×
2769
        (err) => {
2770
          expect.fail({
2×
2771
            message(output) {
2772
              output.append(
4×
2773
                expect.standardErrorMessage(output.clone(), { compact: true })
2774
              );
2775
            },
2776
            diff(output) {
2777
              output.inline = true;
4×
2778
              return output
4×
2779
                .jsKeyword('new')
2780
                .sp()
2781
                .jsKeyword('Set')
2782
                .text('(')
2783
                .append(err.getDiff({ output }))
2784
                .text(')');
2785
            },
2786
          });
2787
        }
2788
      );
2789
    }
2790
  );
2791

2792
  expect.addAssertion(
17×
2793
    [
2794
      '<Set> to have an item [exhaustively] satisfying <any>',
2795
      '<Set> to have an item [exhaustively] satisfying <assertion>',
2796
    ],
2797
    (expect, subject, nextArg) => {
2798
      expect.errorMode = 'nested';
7×
2799
      expect(subject, 'not to be empty');
7×
2800
      expect.errorMode = 'bubble';
6×
2801

2802
      const subjectElements = [];
6×
2803
      subject.forEach((element) => {
6×
2804
        subjectElements.push(element);
15×
2805
      });
2806

2807
      const expected =
2808
        typeof nextArg === 'string'
6×
2809
          ? expect.it((s) => expect.shift(s, 0))
3×
2810
          : nextArg;
2811
      const expectedType = expect.findTypeOf(expected);
6×
2812
      const results = new Array(subjectElements.length);
6×
2813
      subjectElements.forEach((subjectElement, subjectIndex) => {
6×
2814
        results[subjectIndex] = expect.promise(() => {
15×
2815
          if (expectedType.is('expect.it')) {
15×
2816
            expect.context.thisObject = subject;
7×
2817
            return expected(subjectElement, expect.context);
7×
2818
          } else {
2819
            return expect(subjectElement, 'to [exhaustively] satisfy', nextArg);
8×
2820
          }
2821
        });
2822
      });
2823

2824
      return expect.promise.settle(results).then(function () {
6×
2825
        if (results.every((result) => !result.isFulfilled())) {
13×
2826
          expect.fail({
2×
2827
            message(output) {
2828
              output.append(
4×
2829
                expect.standardErrorMessage(output.clone(), { compact: true })
2830
              );
2831
            },
2832
            diff(output, diff, inspect, equal) {
2833
              output.inline = true;
4×
2834
              const prefixOutput = expect.subjectType.prefix(
4×
2835
                output.clone(),
2836
                subject
2837
              );
2838
              const suffixOutput = expect.subjectType.suffix(
4×
2839
                output.clone(),
2840
                subject
2841
              );
2842

2843
              output.append(prefixOutput);
4×
2844
              if (!prefixOutput.isEmpty()) {
Branches [[202, 1]] missed. 4×
2845
                output.nl();
4×
2846
              }
2847
              if (expect.subjectType.indent) {
Branches [[203, 1]] missed. 4×
2848
                output.indentLines();
4×
2849
              }
2850

2851
              let index = 0;
4×
2852
              subjectElements.forEach((subjectElement, subjectIndex) => {
4×
2853
                output.omitSubject = subject;
6×
2854
                output
6×
2855
                  .nl(index > 0 ? 1 : 0)
2856
                  .i()
2857
                  .block(function () {
2858
                    const delimiterOutput = expect.subjectType.delimiter(
6×
2859
                      output.clone(),
2860
                      subjectIndex,
2861
                      subjectElements.length
2862
                    );
2863

2864
                    const err = results[subjectIndex].reason();
6×
2865
                    const diff = err.getDiff({ output: output.clone() });
6×
2866

2867
                    if (diff && diff.inline) {
6×
2868
                      this.append(diff).amend(delimiterOutput);
4×
2869
                    } else {
2870
                      this.appendInspected(subjectElement)
2×
2871
                        .amend(delimiterOutput)
2872
                        .sp()
2873
                        .annotationBlock(function () {
2874
                          this.omitSubject = subjectElement;
2×
2875
                          this.appendErrorMessage(err);
2×
2876
                        });
2877
                    }
2878
                  });
2879
                index += 1;
6×
2880
              });
2881

2882
              if (expect.subjectType.indent) {
Branches [[207, 1]] missed. 4×
2883
                output.outdentLines();
4×
2884
              }
2885
              if (!suffixOutput.isEmpty()) {
Branches [[208, 1]] missed. 4×
2886
                output.nl();
4×
2887
              }
2888
              output.append(suffixOutput);
4×
2889

2890
              return output;
4×
2891
            },
2892
          });
2893
        }
2894
      });
2895
    }
2896
  );
2897

2898
  expect.addAssertion(
17×
2899
    '<Set> to [exhaustively] satisfy <Set>',
2900
    (expect, subject, value) => {
2901
      const subjectElements = [];
8×
2902
      subject.forEach((element) => {
8×
2903
        subjectElements.push(element);
12×
2904
      });
2905
      const valueElements = [];
8×
2906
      value.forEach((element) => {
8×
2907
        valueElements.push(element);
11×
2908
      });
2909

2910
      const promiseBySubjectIndexAndValueIndex = subjectElements.map(
8×
2911
        () => new Array(valueElements.length)
12×
2912
      );
2913

2914
      const promiseByValueIndexAndSubjectIndex = valueElements.map(
8×
2915
        (valueElement, valueIndex) =>
2916
          subjectElements.map((subjectElement, subjectIndex) => {
11×
2917
            const promise = expect.promise(() => {
16×
2918
              const valueElementType = expect.findTypeOf(valueElement);
16×
2919
              if (valueElementType.is('function')) {
16×
2920
                return valueElement(subjectElement);
1×
2921
              } else {
2922
                return expect(
15×
2923
                  subjectElement,
2924
                  'to [exhaustively] satisfy',
2925
                  valueElement
2926
                );
2927
              }
2928
            });
2929
            promiseBySubjectIndexAndValueIndex[subjectIndex][valueIndex] =
16×
2930
              promise;
2931
            return promise;
16×
2932
          })
2933
      );
2934

2935
      return expect.promise
8×
2936
        .settle(promiseByValueIndexAndSubjectIndex)
2937
        .then(() => {
2938
          if (
8×
2939
            !promiseByValueIndexAndSubjectIndex.every((row) =>
2940
              row.some((promise) => promise.isFulfilled())
14×
2941
            ) ||
2942
            !subjectElements.every((subjectElement, i) =>
2943
              promiseByValueIndexAndSubjectIndex.some((row) =>
6×
2944
                row[i].isFulfilled()
7×
2945
              )
2946
            )
2947
          ) {
2948
            expect.fail({
5×
2949
              diff(output, diff, inspect, equal) {
2950
                output.inline = true;
10×
2951
                const prefixOutput = expect.subjectType.prefix(
10×
2952
                  output.clone(),
2953
                  subject
2954
                );
2955
                const suffixOutput = expect.subjectType.suffix(
10×
2956
                  output.clone(),
2957
                  subject
2958
                );
2959

2960
                output.append(prefixOutput);
10×
2961
                if (!prefixOutput.isEmpty()) {
10×
2962
                  output.nl();
8×
2963
                }
2964
                if (expect.subjectType.indent) {
10×
2965
                  output.indentLines();
8×
2966
                }
2967

2968
                let index = 0;
10×
2969
                subjectElements.forEach((subjectElement, subjectIndex) => {
10×
2970
                  output
16×
2971
                    .nl(index > 0 ? 1 : 0)
2972
                    .i()
2973
                    .block(function () {
2974
                      this.appendInspected(subjectElement);
16×
2975
                      expect.subjectType.delimiter(
16×
2976
                        this,
2977
                        subjectIndex,
2978
                        subjectElements.length
2979
                      );
2980
                      if (
16×
2981
                        !promiseBySubjectIndexAndValueIndex[subjectIndex].some(
2982
                          (promise, valueIndex) =>
2983
                            promiseBySubjectIndexAndValueIndex[subjectIndex][
16×
2984
                              valueIndex
2985
                            ].isFulfilled()
2986
                        )
2987
                      ) {
2988
                        this.sp().annotationBlock(function () {
10×
2989
                          this.error('should be removed');
10×
2990
                        });
2991
                      }
2992
                    });
2993
                  index += 1;
16×
2994
                });
2995
                valueElements.forEach((valueElement, valueIndex) => {
10×
2996
                  if (
14×
2997
                    promiseByValueIndexAndSubjectIndex[valueIndex].every(
2998
                      (promise) => promise.isRejected()
18×
2999
                    )
3000
                  ) {
3001
                    output
8×
3002
                      .nl(index > 0 ? 1 : 0)
Branches [[217, 1]] missed.
3003
                      .i()
3004
                      .annotationBlock(function () {
3005
                        if (expect.findTypeOf(valueElement).is('function')) {
8×
3006
                          this.omitSubject = subjectElements[0];
2×
3007
                          this.error('missing:')
2×
3008
                            .sp()
3009
                            .appendErrorMessage(
3010
                              promiseByValueIndexAndSubjectIndex[
3011
                                valueIndex
3012
                              ][0].reason()
3013
                            );
3014
                        } else {
3015
                          this.error('missing')
6×
3016
                            .sp()
3017
                            .appendInspected(valueElement);
3018
                        }
3019
                      });
3020
                    index += 1;
8×
3021
                  }
3022
                });
3023

3024
                if (expect.subjectType.indent) {
10×
3025
                  output.outdentLines();
8×
3026
                }
3027
                if (!suffixOutput.isEmpty()) {
10×
3028
                  output.nl();
8×
3029
                }
3030
                output.append(suffixOutput);
10×
3031

3032
                return output;
10×
3033
              },
3034
            });
3035
          }
3036
        });
3037
    }
3038
  );
3039

3040
  expect.addAssertion(
17×
3041
    '<Set> [not] to have size <number>',
3042
    (expect, subject, value) => {
3043
      expect(subject.size, '[not] to equal', value);
4×
3044
    }
3045
  );
3046
};
Troubleshooting · Open an Issue · Sales · Support · ENTERPRISE · CAREERS · STATUS
BLOG · TWITTER · Legal & Privacy · Supported CI Services · What's a CI service? · Automated Testing

© 2022 Coveralls, Inc