function()

in packages/expect/src/spyMatchers.ts [1007:1136]


  function (
    this: MatcherState,
    received: any,
    nth: number,
    expected: unknown,
  ): SyncExpectationResult {
    const expectedArgument = 'n';
    const options: MatcherHintOptions = {
      expectedColor: (arg: string) => arg,
      isNot: this.isNot,
      promise: this.promise,
      secondArgument: 'expected',
    };
    ensureMock(received, matcherName, expectedArgument, options);

    if (!Number.isSafeInteger(nth) || nth < 1) {
      throw new Error(
        matcherErrorMessage(
          matcherHint(matcherName, undefined, expectedArgument, options),
          `${expectedArgument} must be a positive integer`,
          printWithType(expectedArgument, nth, stringify),
        ),
      );
    }

    const receivedName = received.getMockName();
    const {calls, results} = received.mock;
    const length = results.length;
    const iNth = nth - 1;

    const pass = iNth < length && isEqualReturn(expected, results[iNth]);

    const message = pass
      ? () => {
          // Display preceding and following results,
          // in case assertions fails because index is off by one.
          const indexedResults: Array<IndexedResult> = [];
          if (iNth - 1 >= 0) {
            indexedResults.push([iNth - 1, results[iNth - 1]]);
          }
          indexedResults.push([iNth, results[iNth]]);
          if (iNth + 1 < length) {
            indexedResults.push([iNth + 1, results[iNth + 1]]);
          }

          return (
            // eslint-disable-next-line prefer-template
            matcherHint(matcherName, receivedName, expectedArgument, options) +
            '\n\n' +
            `n: ${nth}\n` +
            `Expected: not ${printExpected(expected)}\n` +
            (results.length === 1 &&
            results[0].type === 'return' &&
            stringify(results[0].value) === stringify(expected)
              ? ''
              : printReceivedResults(
                  'Received:     ',
                  expected,
                  indexedResults,
                  results.length === 1,
                  iNth,
                )) +
            printNumberOfReturns(countReturns(results), calls.length)
          );
        }
      : () => {
          // Display preceding and following results:
          // * nearest result that is equal to expected value
          // * otherwise, adjacent result
          // in case assertions fails because of index, especially off by one.
          const indexedResults: Array<IndexedResult> = [];
          if (iNth < length) {
            if (iNth - 1 >= 0) {
              let i = iNth - 1;
              // Is there a preceding result that is equal to expected value?
              while (i >= 0 && !isEqualReturn(expected, results[i])) {
                i -= 1;
              }
              if (i < 0) {
                i = iNth - 1; // otherwise, adjacent result
              }

              indexedResults.push([i, results[i]]);
            }
            indexedResults.push([iNth, results[iNth]]);
            if (iNth + 1 < length) {
              let i = iNth + 1;
              // Is there a following result that is equal to expected value?
              while (i < length && !isEqualReturn(expected, results[i])) {
                i += 1;
              }
              if (i >= length) {
                i = iNth + 1; // otherwise, adjacent result
              }

              indexedResults.push([i, results[i]]);
            }
          } else if (length > 0) {
            // The number of received calls is fewer than the expected number.
            let i = length - 1;
            // Is there a result that is equal to expected value?
            while (i >= 0 && !isEqualReturn(expected, results[i])) {
              i -= 1;
            }
            if (i < 0) {
              i = length - 1; // otherwise, last result
            }

            indexedResults.push([i, results[i]]);
          }

          return (
            // eslint-disable-next-line prefer-template
            matcherHint(matcherName, receivedName, expectedArgument, options) +
            '\n\n' +
            `n: ${nth}\n` +
            `Expected: ${printExpected(expected)}\n` +
            printReceivedResults(
              'Received: ',
              expected,
              indexedResults,
              results.length === 1,
              iNth,
            ) +
            printNumberOfReturns(countReturns(results), calls.length)
          );
        };

    return {message, pass};
  };