mirror of
				https://github.com/microsoft/playwright.git
				synced 2025-06-26 21:40:17 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			1500 lines
		
	
	
		
			43 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			1500 lines
		
	
	
		
			43 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
/**
 | 
						|
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 | 
						|
 *
 | 
						|
 * This source code is licensed under the MIT license found in the
 | 
						|
 * LICENSE file in the root directory of this source tree.
 | 
						|
 */
 | 
						|
 | 
						|
import { test, expect } from './fixtures';
 | 
						|
import { expect as expectUnderTest, mock } from '../../packages/playwright/bundles/expect/src/expectBundleImpl';
 | 
						|
import Immutable from 'immutable';
 | 
						|
 | 
						|
const expectUnderTestAsAny = expectUnderTest as any;
 | 
						|
 | 
						|
expectUnderTest.extend({
 | 
						|
  optionalFn(fn?: unknown) {
 | 
						|
    const pass = fn === undefined || typeof fn === 'function';
 | 
						|
    return { message: () => 'expect either a function or undefined', pass };
 | 
						|
  },
 | 
						|
});
 | 
						|
 | 
						|
 | 
						|
// Given a Jest mock function, return a minimal mock of a spy.
 | 
						|
const createSpy = (fn: mock.Mock) => {
 | 
						|
  const spy = function() { };
 | 
						|
 | 
						|
  spy.calls = {
 | 
						|
    all() {
 | 
						|
      return fn.mock.calls.map(args => ({ args }));
 | 
						|
    },
 | 
						|
    count() {
 | 
						|
      return fn.mock.calls.length;
 | 
						|
    },
 | 
						|
  };
 | 
						|
 | 
						|
  return spy;
 | 
						|
};
 | 
						|
 | 
						|
for (const called of ['toBeCalled', 'toHaveBeenCalled']) {
 | 
						|
  test.describe(called, () => {
 | 
						|
    test('works only on spies or mock.fn', () => {
 | 
						|
      const fn = function fn() { };
 | 
						|
 | 
						|
      expect(() => expectUnderTest(fn)[called]()).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
 | 
						|
    test('passes when called', () => {
 | 
						|
      const fn = mock.fn();
 | 
						|
      fn('arg0', 'arg1', 'arg2');
 | 
						|
      expectUnderTest(createSpy(fn))[called]();
 | 
						|
      expectUnderTest(fn)[called]();
 | 
						|
      expect(() => expectUnderTest(fn).not[called]()).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
 | 
						|
    test('.not passes when called', () => {
 | 
						|
      const fn = mock.fn();
 | 
						|
      const spy = createSpy(fn);
 | 
						|
 | 
						|
      expectUnderTest(spy).not[called]();
 | 
						|
      expectUnderTest(fn).not[called]();
 | 
						|
      expect(() => expectUnderTest(spy)[called]()).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
 | 
						|
    test('fails with any argument passed', () => {
 | 
						|
      const fn = mock.fn();
 | 
						|
 | 
						|
      fn();
 | 
						|
      expect(() => expectUnderTest(fn)[called](555)).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
 | 
						|
    test('.not fails with any argument passed', () => {
 | 
						|
      const fn = mock.fn();
 | 
						|
 | 
						|
      expect(() =>
 | 
						|
        expectUnderTest(fn).not[called](555),
 | 
						|
      ).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
 | 
						|
    test('includes the custom mock name in the error message', () => {
 | 
						|
      const fn = mock.fn().mockName('named-mock');
 | 
						|
 | 
						|
      fn();
 | 
						|
      expectUnderTest(fn)[called]();
 | 
						|
      expect(() => expectUnderTest(fn).not[called]()).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
for (const calledTimes of ['toBeCalledTimes', 'toHaveBeenCalledTimes']) {
 | 
						|
  test.describe(calledTimes, () => {
 | 
						|
    test('.not works only on spies or mock.fn', () => {
 | 
						|
      const fn = function fn() { };
 | 
						|
 | 
						|
      expect(() =>
 | 
						|
        expectUnderTest(fn).not[calledTimes](2),
 | 
						|
      ).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
 | 
						|
    test('only accepts a number argument', () => {
 | 
						|
      const fn = mock.fn();
 | 
						|
      fn();
 | 
						|
      expectUnderTest(fn)[calledTimes](1);
 | 
						|
 | 
						|
      [{}, [], true, 'a', new Map(), () => { }].forEach(value => {
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[calledTimes](value),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      });
 | 
						|
    });
 | 
						|
 | 
						|
    test('.not only accepts a number argument', () => {
 | 
						|
      const fn = mock.fn();
 | 
						|
      expectUnderTest(fn).not[calledTimes](1);
 | 
						|
 | 
						|
      [{}, [], true, 'a', new Map(), () => { }].forEach(value => {
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[calledTimes](value),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      });
 | 
						|
    });
 | 
						|
 | 
						|
    test('passes if function called equal to expected times', () => {
 | 
						|
      const fn = mock.fn();
 | 
						|
      fn();
 | 
						|
      fn();
 | 
						|
 | 
						|
      const spy = createSpy(fn);
 | 
						|
      expectUnderTest(spy)[calledTimes](2);
 | 
						|
      expectUnderTest(fn)[calledTimes](2);
 | 
						|
 | 
						|
      expect(() =>
 | 
						|
        expectUnderTest(spy).not[calledTimes](2),
 | 
						|
      ).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
 | 
						|
    test('.not passes if function called more than expected times', () => {
 | 
						|
      const fn = mock.fn();
 | 
						|
      fn();
 | 
						|
      fn();
 | 
						|
      fn();
 | 
						|
 | 
						|
      const spy = createSpy(fn);
 | 
						|
      expectUnderTest(spy)[calledTimes](3);
 | 
						|
      expectUnderTest(spy).not[calledTimes](2);
 | 
						|
 | 
						|
      expectUnderTest(fn)[calledTimes](3);
 | 
						|
      expectUnderTest(fn).not[calledTimes](2);
 | 
						|
 | 
						|
      expect(() =>
 | 
						|
        expectUnderTest(fn)[calledTimes](2),
 | 
						|
      ).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
 | 
						|
    test('.not passes if function called less than expected times', () => {
 | 
						|
      const fn = mock.fn();
 | 
						|
      fn();
 | 
						|
 | 
						|
      const spy = createSpy(fn);
 | 
						|
      expectUnderTest(spy)[calledTimes](1);
 | 
						|
      expectUnderTest(spy).not[calledTimes](2);
 | 
						|
 | 
						|
      expectUnderTest(fn)[calledTimes](1);
 | 
						|
      expectUnderTest(fn).not[calledTimes](2);
 | 
						|
 | 
						|
      expect(() =>
 | 
						|
        expectUnderTest(fn)[calledTimes](2),
 | 
						|
      ).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
 | 
						|
    test('includes the custom mock name in the error message', () => {
 | 
						|
      const fn = mock.fn().mockName('named-mock');
 | 
						|
      fn();
 | 
						|
 | 
						|
      expect(() =>
 | 
						|
        expectUnderTest(fn)[calledTimes](2),
 | 
						|
      ).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
for (const calledWith of [
 | 
						|
  'lastCalledWith',
 | 
						|
  'toHaveBeenLastCalledWith',
 | 
						|
  'nthCalledWith',
 | 
						|
  'toHaveBeenNthCalledWith',
 | 
						|
  'toBeCalledWith',
 | 
						|
  'toHaveBeenCalledWith',
 | 
						|
]) {
 | 
						|
  test.describe(calledWith, () => {
 | 
						|
    function isToHaveNth(
 | 
						|
      calledWith: string,
 | 
						|
    ): calledWith is 'nthCalledWith' | 'toHaveBeenNthCalledWith' {
 | 
						|
      return (
 | 
						|
        calledWith === 'nthCalledWith' || calledWith === 'toHaveBeenNthCalledWith'
 | 
						|
      );
 | 
						|
    }
 | 
						|
 | 
						|
    test('works only on spies or mock.fn', () => {
 | 
						|
      const fn = function fn() { };
 | 
						|
 | 
						|
      if (isToHaveNth(calledWith)) {
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[calledWith](3),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      } else {
 | 
						|
        expect(() => expectUnderTest(fn)[calledWith]()).toThrowErrorMatchingSnapshot();
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    test('works when not called', () => {
 | 
						|
      const fn = mock.fn();
 | 
						|
 | 
						|
      if (isToHaveNth(calledWith)) {
 | 
						|
        expectUnderTest(createSpy(fn)).not[calledWith](1, 'foo', 'bar');
 | 
						|
        expectUnderTest(fn).not[calledWith](1, 'foo', 'bar');
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[calledWith](1, 'foo', 'bar'),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      } else {
 | 
						|
        expectUnderTest(createSpy(fn)).not[calledWith]('foo', 'bar');
 | 
						|
        expectUnderTest(fn).not[calledWith]('foo', 'bar');
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[calledWith]('foo', 'bar'),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    test('works with no arguments', () => {
 | 
						|
      const fn = mock.fn();
 | 
						|
      fn();
 | 
						|
 | 
						|
      if (isToHaveNth(calledWith)) {
 | 
						|
        expectUnderTest(createSpy(fn))[calledWith](1);
 | 
						|
        expectUnderTest(fn)[calledWith](1);
 | 
						|
      } else {
 | 
						|
        expectUnderTest(createSpy(fn))[calledWith]();
 | 
						|
        expectUnderTest(fn)[calledWith]();
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    test("works with arguments that don't match", () => {
 | 
						|
      const fn = mock.fn();
 | 
						|
      fn('foo', 'bar1');
 | 
						|
 | 
						|
      if (isToHaveNth(calledWith)) {
 | 
						|
        expectUnderTest(createSpy(fn)).not[calledWith](1, 'foo', 'bar');
 | 
						|
        expectUnderTest(fn).not[calledWith](1, 'foo', 'bar');
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[calledWith](1, 'foo', 'bar'),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      } else {
 | 
						|
        expectUnderTest(createSpy(fn)).not[calledWith]('foo', 'bar');
 | 
						|
        expectUnderTest(fn).not[calledWith]('foo', 'bar');
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[calledWith]('foo', 'bar'),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    test("works with arguments that don't match in number of arguments", () => {
 | 
						|
      const fn = mock.fn();
 | 
						|
      fn('foo', 'bar', 'plop');
 | 
						|
 | 
						|
      if (isToHaveNth(calledWith)) {
 | 
						|
        expectUnderTest(createSpy(fn)).not[calledWith](1, 'foo', 'bar');
 | 
						|
        expectUnderTest(fn).not[calledWith](1, 'foo', 'bar');
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[calledWith](1, 'foo', 'bar'),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      } else {
 | 
						|
        expectUnderTest(createSpy(fn)).not[calledWith]('foo', 'bar');
 | 
						|
        expectUnderTest(fn).not[calledWith]('foo', 'bar');
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[calledWith]('foo', 'bar'),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    test("works with arguments that don't match with matchers", () => {
 | 
						|
      const fn = mock.fn();
 | 
						|
      fn('foo', 'bar');
 | 
						|
 | 
						|
      if (isToHaveNth(calledWith)) {
 | 
						|
        expectUnderTest(createSpy(fn)).not[calledWith](
 | 
						|
            1,
 | 
						|
            expectUnderTest.any(String),
 | 
						|
            expectUnderTest.any(Number),
 | 
						|
        );
 | 
						|
        expectUnderTest(fn).not[calledWith](
 | 
						|
            1,
 | 
						|
            expectUnderTest.any(String),
 | 
						|
            expectUnderTest.any(Number),
 | 
						|
        );
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[calledWith](
 | 
						|
              1,
 | 
						|
              expectUnderTest.any(String),
 | 
						|
              expectUnderTest.any(Number),
 | 
						|
          ),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      } else {
 | 
						|
        expectUnderTest(createSpy(fn)).not[calledWith](
 | 
						|
            expectUnderTest.any(String),
 | 
						|
            expectUnderTest.any(Number),
 | 
						|
        );
 | 
						|
        expectUnderTest(fn).not[calledWith](
 | 
						|
            expectUnderTest.any(String),
 | 
						|
            expectUnderTest.any(Number),
 | 
						|
        );
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[calledWith](
 | 
						|
              expectUnderTest.any(String),
 | 
						|
              expectUnderTest.any(Number),
 | 
						|
          ),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    test("works with arguments that don't match with matchers even when argument is undefined", () => {
 | 
						|
      const fn = mock.fn();
 | 
						|
      fn('foo', undefined);
 | 
						|
 | 
						|
      if (isToHaveNth(calledWith)) {
 | 
						|
        expectUnderTest(createSpy(fn)).not[calledWith](
 | 
						|
            1,
 | 
						|
            'foo',
 | 
						|
            expectUnderTest.any(String),
 | 
						|
        );
 | 
						|
        expectUnderTest(fn).not[calledWith](1, 'foo', expectUnderTest.any(String));
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[calledWith](1, 'foo', expectUnderTest.any(String)),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      } else {
 | 
						|
        expectUnderTest(createSpy(fn)).not[calledWith]('foo', expectUnderTest.any(String));
 | 
						|
        expectUnderTest(fn).not[calledWith]('foo', expectUnderTest.any(String));
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[calledWith]('foo', expectUnderTest.any(String)),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    test("works with arguments that don't match in size even if one is an optional matcher", () => {
 | 
						|
      // issue 12463
 | 
						|
      const fn = mock.fn();
 | 
						|
      fn('foo');
 | 
						|
 | 
						|
      if (isToHaveNth(calledWith)) {
 | 
						|
        expectUnderTest(fn).not[calledWith](1, 'foo', expectUnderTestAsAny.optionalFn());
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[calledWith](1, 'foo', expectUnderTestAsAny.optionalFn()),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      } else {
 | 
						|
        expectUnderTest(fn).not[calledWith]('foo', expectUnderTestAsAny.optionalFn());
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[calledWith]('foo', expectUnderTestAsAny.optionalFn()),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    test('works with arguments that match', () => {
 | 
						|
      const fn = mock.fn();
 | 
						|
      fn('foo', 'bar');
 | 
						|
 | 
						|
      if (isToHaveNth(calledWith)) {
 | 
						|
        expectUnderTest(createSpy(fn))[calledWith](1, 'foo', 'bar');
 | 
						|
        expectUnderTest(fn)[calledWith](1, 'foo', 'bar');
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[calledWith](1, 'foo', 'bar'),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      } else {
 | 
						|
        expectUnderTest(createSpy(fn))[calledWith]('foo', 'bar');
 | 
						|
        expectUnderTest(fn)[calledWith]('foo', 'bar');
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[calledWith]('foo', 'bar'),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    test('works with arguments that match with matchers', () => {
 | 
						|
      const fn = mock.fn();
 | 
						|
      fn('foo', 'bar');
 | 
						|
 | 
						|
      if (isToHaveNth(calledWith)) {
 | 
						|
        expectUnderTest(createSpy(fn))[calledWith](
 | 
						|
            1,
 | 
						|
            expectUnderTest.any(String),
 | 
						|
            expectUnderTest.any(String),
 | 
						|
        );
 | 
						|
        expectUnderTest(fn)[calledWith](
 | 
						|
            1,
 | 
						|
            expectUnderTest.any(String),
 | 
						|
            expectUnderTest.any(String),
 | 
						|
        );
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[calledWith](
 | 
						|
              1,
 | 
						|
              expectUnderTest.any(String),
 | 
						|
              expectUnderTest.any(String),
 | 
						|
          ),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      } else {
 | 
						|
        expectUnderTest(createSpy(fn))[calledWith](
 | 
						|
            expectUnderTest.any(String),
 | 
						|
            expectUnderTest.any(String),
 | 
						|
        );
 | 
						|
        expectUnderTest(fn)[calledWith](
 | 
						|
            expectUnderTest.any(String),
 | 
						|
            expectUnderTest.any(String),
 | 
						|
        );
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[calledWith](
 | 
						|
              expectUnderTest.any(String),
 | 
						|
              expectUnderTest.any(String),
 | 
						|
          ),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    test('works with trailing undefined arguments', () => {
 | 
						|
      const fn = mock.fn();
 | 
						|
      fn('foo', undefined);
 | 
						|
 | 
						|
      if (isToHaveNth(calledWith)) {
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[calledWith](1, 'foo'),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      } else {
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[calledWith]('foo'),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    test('works with trailing undefined arguments if requested by the match query', () => {
 | 
						|
      const fn = mock.fn();
 | 
						|
      fn('foo', undefined);
 | 
						|
 | 
						|
      if (isToHaveNth(calledWith)) {
 | 
						|
        expectUnderTest(fn)[calledWith](1, 'foo', undefined);
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[calledWith](1, 'foo', undefined),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      } else {
 | 
						|
        expectUnderTest(fn)[calledWith]('foo', undefined);
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[calledWith]('foo', undefined),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    test('works with trailing undefined arguments when explicitly requested as optional by matcher', () => {
 | 
						|
      // issue 12463
 | 
						|
      const fn = mock.fn();
 | 
						|
      fn('foo', undefined);
 | 
						|
 | 
						|
      if (isToHaveNth(calledWith)) {
 | 
						|
        expectUnderTest(fn)[calledWith](1, 'foo', expectUnderTestAsAny.optionalFn());
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[calledWith](1, 'foo', expectUnderTestAsAny.optionalFn()),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      } else {
 | 
						|
        expectUnderTest(fn)[calledWith]('foo', expectUnderTestAsAny.optionalFn());
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[calledWith]('foo', expectUnderTestAsAny.optionalFn()),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    test('works with Map', () => {
 | 
						|
      const fn = mock.fn();
 | 
						|
 | 
						|
      const m1 = new Map([
 | 
						|
        [1, 2],
 | 
						|
        [2, 1],
 | 
						|
      ]);
 | 
						|
      const m2 = new Map([
 | 
						|
        [1, 2],
 | 
						|
        [2, 1],
 | 
						|
      ]);
 | 
						|
      const m3 = new Map([
 | 
						|
        ['a', 'b'],
 | 
						|
        ['b', 'a'],
 | 
						|
      ]);
 | 
						|
 | 
						|
      fn(m1);
 | 
						|
 | 
						|
      if (isToHaveNth(calledWith)) {
 | 
						|
        expectUnderTest(fn)[calledWith](1, m2);
 | 
						|
        expectUnderTest(fn).not[calledWith](1, m3);
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[calledWith](1, m2),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[calledWith](1, m3),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      } else {
 | 
						|
        expectUnderTest(fn)[calledWith](m2);
 | 
						|
        expectUnderTest(fn).not[calledWith](m3);
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[calledWith](m2),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[calledWith](m3),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    test('works with Set', () => {
 | 
						|
      const fn = mock.fn();
 | 
						|
 | 
						|
      const s1 = new Set([1, 2]);
 | 
						|
      const s2 = new Set([1, 2]);
 | 
						|
      const s3 = new Set([3, 4]);
 | 
						|
 | 
						|
      fn(s1);
 | 
						|
 | 
						|
      if (isToHaveNth(calledWith)) {
 | 
						|
        expectUnderTest(fn)[calledWith](1, s2);
 | 
						|
        expectUnderTest(fn).not[calledWith](1, s3);
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[calledWith](1, s2),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[calledWith](1, s3),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      } else {
 | 
						|
        expectUnderTest(fn)[calledWith](s2);
 | 
						|
        expectUnderTest(fn).not[calledWith](s3);
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[calledWith](s2),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[calledWith](s3),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    test('works with Immutable.js objects', () => {
 | 
						|
      const fn = mock.fn();
 | 
						|
      const directlyCreated = Immutable.Map([['a', { b: 'c' }]]);
 | 
						|
      const indirectlyCreated = Immutable.Map().set('a', { b: 'c' });
 | 
						|
      fn(directlyCreated, indirectlyCreated);
 | 
						|
 | 
						|
      if (isToHaveNth(calledWith)) {
 | 
						|
        expectUnderTest(fn)[calledWith](1, indirectlyCreated, directlyCreated);
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[calledWith](1, indirectlyCreated, directlyCreated),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      } else {
 | 
						|
        expectUnderTest(fn)[calledWith](indirectlyCreated, directlyCreated);
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[calledWith](indirectlyCreated, directlyCreated),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    if (!isToHaveNth(calledWith)) {
 | 
						|
      test('works with many arguments', () => {
 | 
						|
        const fn = mock.fn();
 | 
						|
        fn('foo1', 'bar');
 | 
						|
        fn('foo', 'bar1');
 | 
						|
        fn('foo', 'bar');
 | 
						|
 | 
						|
        expectUnderTest(fn)[calledWith]('foo', 'bar');
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[calledWith]('foo', 'bar'),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      });
 | 
						|
 | 
						|
      test("works with many arguments that don't match", () => {
 | 
						|
        const fn = mock.fn();
 | 
						|
        fn('foo', 'bar1');
 | 
						|
        fn('foo', 'bar2');
 | 
						|
        fn('foo', 'bar3');
 | 
						|
 | 
						|
        expectUnderTest(fn).not[calledWith]('foo', 'bar');
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[calledWith]('foo', 'bar'),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      });
 | 
						|
    }
 | 
						|
 | 
						|
    if (isToHaveNth(calledWith)) {
 | 
						|
      test('works with three calls', () => {
 | 
						|
        const fn = mock.fn();
 | 
						|
        fn('foo1', 'bar');
 | 
						|
        fn('foo', 'bar1');
 | 
						|
        fn('foo', 'bar');
 | 
						|
 | 
						|
        expectUnderTest(fn)[calledWith](1, 'foo1', 'bar');
 | 
						|
        expectUnderTest(fn)[calledWith](2, 'foo', 'bar1');
 | 
						|
        expectUnderTest(fn)[calledWith](3, 'foo', 'bar');
 | 
						|
 | 
						|
        expect(() => {
 | 
						|
          expectUnderTest(fn).not[calledWith](1, 'foo1', 'bar');
 | 
						|
        }).toThrowErrorMatchingSnapshot();
 | 
						|
      });
 | 
						|
 | 
						|
      test('positive throw matcher error for n that is not positive integer', async () => {
 | 
						|
        const fn = mock.fn();
 | 
						|
        fn('foo1', 'bar');
 | 
						|
 | 
						|
        expect(() => {
 | 
						|
          expectUnderTest(fn)[calledWith](0, 'foo1', 'bar');
 | 
						|
        }).toThrowErrorMatchingSnapshot();
 | 
						|
      });
 | 
						|
 | 
						|
      test('positive throw matcher error for n that is not integer', async () => {
 | 
						|
        const fn = mock.fn();
 | 
						|
        fn('foo1', 'bar');
 | 
						|
 | 
						|
        expect(() => {
 | 
						|
          expectUnderTest(fn)[calledWith](0.1, 'foo1', 'bar');
 | 
						|
        }).toThrowErrorMatchingSnapshot();
 | 
						|
      });
 | 
						|
 | 
						|
      test('negative throw matcher error for n that is not integer', async () => {
 | 
						|
        const fn = mock.fn();
 | 
						|
        fn('foo1', 'bar');
 | 
						|
 | 
						|
        expect(() => {
 | 
						|
          expectUnderTest(fn).not[calledWith](Infinity, 'foo1', 'bar');
 | 
						|
        }).toThrowErrorMatchingSnapshot();
 | 
						|
      });
 | 
						|
    }
 | 
						|
 | 
						|
    test('includes the custom mock name in the error message', () => {
 | 
						|
      const fn = mock.fn().mockName('named-mock');
 | 
						|
      fn('foo', 'bar');
 | 
						|
 | 
						|
      if (isToHaveNth(calledWith)) {
 | 
						|
        expectUnderTest(fn)[calledWith](1, 'foo', 'bar');
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[calledWith](1, 'foo', 'bar'),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      } else {
 | 
						|
        expectUnderTest(fn)[calledWith]('foo', 'bar');
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[calledWith]('foo', 'bar'),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      }
 | 
						|
    });
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
for (const returned of ['toReturn', 'toHaveReturned']) {
 | 
						|
  test.describe(returned, () => {
 | 
						|
    test('.not works only on mock.fn', () => {
 | 
						|
      const fn = function fn() { };
 | 
						|
 | 
						|
      expect(() => expectUnderTest(fn).not[returned]()).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
 | 
						|
    test('throw matcher error if received is spy', () => {
 | 
						|
      const spy = createSpy(mock.fn());
 | 
						|
 | 
						|
      expect(() => expectUnderTest(spy)[returned]()).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
 | 
						|
    test('passes when returned', () => {
 | 
						|
      const fn = mock.fn(() => 42);
 | 
						|
      fn();
 | 
						|
      expectUnderTest(fn)[returned]();
 | 
						|
      expect(() => expectUnderTest(fn).not[returned]()).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
 | 
						|
    test('passes when undefined is returned', () => {
 | 
						|
      const fn = mock.fn(() => undefined);
 | 
						|
      fn();
 | 
						|
      expectUnderTest(fn)[returned]();
 | 
						|
      expect(() => expectUnderTest(fn).not[returned]()).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
 | 
						|
    test('passes when at least one call does not throw', () => {
 | 
						|
      const fn = mock.fn((causeError: boolean) => {
 | 
						|
        if (causeError)
 | 
						|
          throw new Error('Error!');
 | 
						|
 | 
						|
 | 
						|
        return 42;
 | 
						|
      });
 | 
						|
 | 
						|
      fn(false);
 | 
						|
 | 
						|
      try {
 | 
						|
        fn(true);
 | 
						|
      } catch {
 | 
						|
        // ignore error
 | 
						|
      }
 | 
						|
 | 
						|
      fn(false);
 | 
						|
 | 
						|
      expectUnderTest(fn)[returned]();
 | 
						|
      expect(() => expectUnderTest(fn).not[returned]()).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
 | 
						|
    test('.not passes when not returned', () => {
 | 
						|
      const fn = mock.fn();
 | 
						|
 | 
						|
      expectUnderTest(fn).not[returned]();
 | 
						|
      expect(() => expectUnderTest(fn)[returned]()).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
 | 
						|
    test('.not passes when all calls throw', () => {
 | 
						|
      const fn = mock.fn(() => {
 | 
						|
        throw new Error('Error!');
 | 
						|
      });
 | 
						|
 | 
						|
      try {
 | 
						|
        fn();
 | 
						|
      } catch {
 | 
						|
        // ignore error
 | 
						|
      }
 | 
						|
 | 
						|
      try {
 | 
						|
        fn();
 | 
						|
      } catch {
 | 
						|
        // ignore error
 | 
						|
      }
 | 
						|
 | 
						|
      expectUnderTest(fn).not[returned]();
 | 
						|
      expect(() => expectUnderTest(fn)[returned]()).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
 | 
						|
    test('.not passes when a call throws undefined', () => {
 | 
						|
      const fn = mock.fn(() => {
 | 
						|
 | 
						|
        throw undefined;
 | 
						|
      });
 | 
						|
 | 
						|
      try {
 | 
						|
        fn();
 | 
						|
      } catch {
 | 
						|
        // ignore error
 | 
						|
      }
 | 
						|
 | 
						|
      expectUnderTest(fn).not[returned]();
 | 
						|
      expect(() => expectUnderTest(fn)[returned]()).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
 | 
						|
    test('fails with any argument passed', () => {
 | 
						|
      const fn = mock.fn();
 | 
						|
 | 
						|
      fn();
 | 
						|
      expect(() => expectUnderTest(fn)[returned](555)).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
 | 
						|
    test('.not fails with any argument passed', () => {
 | 
						|
      const fn = mock.fn();
 | 
						|
 | 
						|
      expect(() =>
 | 
						|
        expectUnderTest(fn).not[returned](555),
 | 
						|
      ).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
 | 
						|
    test('includes the custom mock name in the error message', () => {
 | 
						|
      const fn = mock.fn(() => 42).mockName('named-mock');
 | 
						|
      fn();
 | 
						|
      expectUnderTest(fn)[returned]();
 | 
						|
      expect(() => expectUnderTest(fn).not[returned]()).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
 | 
						|
    test('incomplete recursive calls are handled properly', () => {
 | 
						|
      // sums up all integers from 0 -> value, using recursion
 | 
						|
      const fn: mock.Mock<(value: number) => number> = mock.fn(value => {
 | 
						|
        if (value === 0) {
 | 
						|
          // Before returning from the base case of recursion, none of the
 | 
						|
          // calls have returned yet.
 | 
						|
          expectUnderTest(fn).not[returned]();
 | 
						|
          expect(() => expectUnderTest(fn)[returned]()).toThrowErrorMatchingSnapshot();
 | 
						|
          return 0;
 | 
						|
        } else {
 | 
						|
          return value + fn(value - 1);
 | 
						|
        }
 | 
						|
      });
 | 
						|
 | 
						|
      fn(3);
 | 
						|
    });
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
for (const returnedTimes of ['toReturnTimes', 'toHaveReturnedTimes']) {
 | 
						|
  test.describe(returnedTimes, () => {
 | 
						|
    test('throw matcher error if received is spy', () => {
 | 
						|
      const spy = createSpy(mock.fn());
 | 
						|
 | 
						|
      expect(() =>
 | 
						|
        expectUnderTest(spy).not[returnedTimes](2),
 | 
						|
      ).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
 | 
						|
    test('only accepts a number argument', () => {
 | 
						|
      const fn = mock.fn(() => 42);
 | 
						|
      fn();
 | 
						|
      expectUnderTest(fn)[returnedTimes](1);
 | 
						|
 | 
						|
      [{}, [], true, 'a', new Map(), () => { }].forEach(value => {
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[returnedTimes](value),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      });
 | 
						|
    });
 | 
						|
 | 
						|
    test('.not only accepts a number argument', () => {
 | 
						|
      const fn = mock.fn(() => 42);
 | 
						|
      expectUnderTest(fn).not[returnedTimes](2);
 | 
						|
 | 
						|
      [{}, [], true, 'a', new Map(), () => { }].forEach(value => {
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[returnedTimes](value),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      });
 | 
						|
    });
 | 
						|
 | 
						|
    test('passes if function returned equal to expected times', () => {
 | 
						|
      const fn = mock.fn(() => 42);
 | 
						|
      fn();
 | 
						|
      fn();
 | 
						|
 | 
						|
      expectUnderTest(fn)[returnedTimes](2);
 | 
						|
 | 
						|
      expect(() =>
 | 
						|
        expectUnderTest(fn).not[returnedTimes](2),
 | 
						|
      ).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
 | 
						|
    test('calls that return undefined are counted as returns', () => {
 | 
						|
      const fn = mock.fn(() => undefined);
 | 
						|
      fn();
 | 
						|
      fn();
 | 
						|
 | 
						|
      expectUnderTest(fn)[returnedTimes](2);
 | 
						|
 | 
						|
      expect(() =>
 | 
						|
        expectUnderTest(fn).not[returnedTimes](2),
 | 
						|
      ).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
 | 
						|
    test('.not passes if function returned more than expected times', () => {
 | 
						|
      const fn = mock.fn(() => 42);
 | 
						|
      fn();
 | 
						|
      fn();
 | 
						|
      fn();
 | 
						|
 | 
						|
      expectUnderTest(fn)[returnedTimes](3);
 | 
						|
      expectUnderTest(fn).not[returnedTimes](2);
 | 
						|
 | 
						|
      expect(() =>
 | 
						|
        expectUnderTest(fn)[returnedTimes](2),
 | 
						|
      ).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
 | 
						|
    test('.not passes if function called less than expected times', () => {
 | 
						|
      const fn = mock.fn(() => 42);
 | 
						|
      fn();
 | 
						|
 | 
						|
      expectUnderTest(fn)[returnedTimes](1);
 | 
						|
      expectUnderTest(fn).not[returnedTimes](2);
 | 
						|
 | 
						|
      expect(() =>
 | 
						|
        expectUnderTest(fn)[returnedTimes](2),
 | 
						|
      ).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
 | 
						|
    test('calls that throw are not counted', () => {
 | 
						|
      const fn = mock.fn((causeError: boolean) => {
 | 
						|
        if (causeError)
 | 
						|
          throw new Error('Error!');
 | 
						|
 | 
						|
 | 
						|
        return 42;
 | 
						|
      });
 | 
						|
 | 
						|
      fn(false);
 | 
						|
 | 
						|
      try {
 | 
						|
        fn(true);
 | 
						|
      } catch {
 | 
						|
      // ignore error
 | 
						|
      }
 | 
						|
 | 
						|
      fn(false);
 | 
						|
 | 
						|
      expectUnderTest(fn).not[returnedTimes](3);
 | 
						|
 | 
						|
      expect(() =>
 | 
						|
        expectUnderTest(fn)[returnedTimes](3),
 | 
						|
      ).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
 | 
						|
    test('calls that throw undefined are not counted', () => {
 | 
						|
      const fn = mock.fn((causeError: boolean) => {
 | 
						|
        if (causeError)
 | 
						|
 | 
						|
          throw undefined;
 | 
						|
 | 
						|
 | 
						|
        return 42;
 | 
						|
      });
 | 
						|
 | 
						|
      fn(false);
 | 
						|
 | 
						|
      try {
 | 
						|
        fn(true);
 | 
						|
      } catch {
 | 
						|
      // ignore error
 | 
						|
      }
 | 
						|
 | 
						|
      fn(false);
 | 
						|
 | 
						|
      expectUnderTest(fn)[returnedTimes](2);
 | 
						|
 | 
						|
      expect(() =>
 | 
						|
        expectUnderTest(fn).not[returnedTimes](2),
 | 
						|
      ).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
 | 
						|
    test('includes the custom mock name in the error message', () => {
 | 
						|
      const fn = mock.fn(() => 42).mockName('named-mock');
 | 
						|
      fn();
 | 
						|
      fn();
 | 
						|
 | 
						|
      expectUnderTest(fn)[returnedTimes](2);
 | 
						|
 | 
						|
      expect(() =>
 | 
						|
        expectUnderTest(fn)[returnedTimes](1),
 | 
						|
      ).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
 | 
						|
    test('incomplete recursive calls are handled properly', () => {
 | 
						|
    // sums up all integers from 0 -> value, using recursion
 | 
						|
      const fn: mock.Mock<(value: number) => number> = mock.fn(value => {
 | 
						|
        if (value === 0) {
 | 
						|
          return 0;
 | 
						|
        } else {
 | 
						|
          const recursiveResult = fn(value - 1);
 | 
						|
 | 
						|
          if (value === 2) {
 | 
						|
          // Only 2 of the recursive calls have returned at this point
 | 
						|
            expectUnderTest(fn)[returnedTimes](2);
 | 
						|
            expect(() =>
 | 
						|
              expectUnderTest(fn).not[returnedTimes](2),
 | 
						|
            ).toThrowErrorMatchingSnapshot();
 | 
						|
          }
 | 
						|
 | 
						|
          return value + recursiveResult;
 | 
						|
        }
 | 
						|
      });
 | 
						|
 | 
						|
      fn(3);
 | 
						|
    });
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
for (const returnedWith of [
 | 
						|
  'lastReturnedWith',
 | 
						|
  'toHaveLastReturnedWith',
 | 
						|
  'nthReturnedWith',
 | 
						|
  'toHaveNthReturnedWith',
 | 
						|
  'toReturnWith',
 | 
						|
  'toHaveReturnedWith',
 | 
						|
]) {
 | 
						|
  test.describe(returnedWith, () => {
 | 
						|
    function isToHaveNth(
 | 
						|
      returnedWith: string,
 | 
						|
    ): returnedWith is 'nthReturnedWith' | 'toHaveNthReturnedWith' {
 | 
						|
      return (
 | 
						|
        returnedWith === 'nthReturnedWith' ||
 | 
						|
        returnedWith === 'toHaveNthReturnedWith'
 | 
						|
      );
 | 
						|
    }
 | 
						|
 | 
						|
    function isToHaveLast(
 | 
						|
      returnedWith: string,
 | 
						|
    ): returnedWith is 'lastReturnedWith' | 'toHaveLastReturnedWith' {
 | 
						|
      return (
 | 
						|
        returnedWith === 'lastReturnedWith' ||
 | 
						|
        returnedWith === 'toHaveLastReturnedWith'
 | 
						|
      );
 | 
						|
    }
 | 
						|
    test('works only on spies or mock.fn', () => {
 | 
						|
      const fn = function fn() { };
 | 
						|
 | 
						|
      expect(() => expectUnderTest(fn)[returnedWith]()).toThrowErrorMatchingSnapshot();
 | 
						|
    });
 | 
						|
 | 
						|
    test('works when not called', () => {
 | 
						|
      const fn = mock.fn();
 | 
						|
 | 
						|
      if (isToHaveNth(returnedWith)) {
 | 
						|
        expectUnderTest(fn).not[returnedWith](1, 'foo');
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[returnedWith](1, 'foo'),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      } else {
 | 
						|
        expectUnderTest(fn).not[returnedWith]('foo');
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[returnedWith]('foo'),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    test('works with no arguments', () => {
 | 
						|
      const fn = mock.fn();
 | 
						|
      fn();
 | 
						|
 | 
						|
      if (isToHaveNth(returnedWith))
 | 
						|
        expectUnderTest(fn)[returnedWith](1);
 | 
						|
      else
 | 
						|
        expectUnderTest(fn)[returnedWith]();
 | 
						|
 | 
						|
    });
 | 
						|
 | 
						|
    test('works with argument that does not match', () => {
 | 
						|
      const fn = mock.fn(() => 'foo');
 | 
						|
      fn();
 | 
						|
 | 
						|
      if (isToHaveNth(returnedWith)) {
 | 
						|
        expectUnderTest(fn).not[returnedWith](1, 'bar');
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[returnedWith](1, 'bar'),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      } else {
 | 
						|
        expectUnderTest(fn).not[returnedWith]('bar');
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[returnedWith]('bar'),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    test('works with argument that does match', () => {
 | 
						|
      const fn = mock.fn(() => 'foo');
 | 
						|
      fn();
 | 
						|
 | 
						|
      if (isToHaveNth(returnedWith)) {
 | 
						|
        expectUnderTest(fn)[returnedWith](1, 'foo');
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[returnedWith](1, 'foo'),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      } else {
 | 
						|
        expectUnderTest(fn)[returnedWith]('foo');
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[returnedWith]('foo'),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    test('works with undefined', () => {
 | 
						|
      const fn = mock.fn(() => undefined);
 | 
						|
      fn();
 | 
						|
 | 
						|
      if (isToHaveNth(returnedWith)) {
 | 
						|
        expectUnderTest(fn)[returnedWith](1, undefined);
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[returnedWith](1, undefined),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      } else {
 | 
						|
        expectUnderTest(fn)[returnedWith](undefined);
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[returnedWith](undefined),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    test('works with Map', () => {
 | 
						|
      const m1 = new Map([
 | 
						|
        [1, 2],
 | 
						|
        [2, 1],
 | 
						|
      ]);
 | 
						|
      const m2 = new Map([
 | 
						|
        [1, 2],
 | 
						|
        [2, 1],
 | 
						|
      ]);
 | 
						|
      const m3 = new Map([
 | 
						|
        ['a', 'b'],
 | 
						|
        ['b', 'a'],
 | 
						|
      ]);
 | 
						|
 | 
						|
      const fn = mock.fn(() => m1);
 | 
						|
      fn();
 | 
						|
 | 
						|
      if (isToHaveNth(returnedWith)) {
 | 
						|
        expectUnderTest(fn)[returnedWith](1, m2);
 | 
						|
        expectUnderTest(fn).not[returnedWith](1, m3);
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[returnedWith](1, m2),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[returnedWith](1, m3),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      } else {
 | 
						|
        expectUnderTest(fn)[returnedWith](m2);
 | 
						|
        expectUnderTest(fn).not[returnedWith](m3);
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[returnedWith](m2),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[returnedWith](m3),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    test('works with Set', () => {
 | 
						|
      const s1 = new Set([1, 2]);
 | 
						|
      const s2 = new Set([1, 2]);
 | 
						|
      const s3 = new Set([3, 4]);
 | 
						|
 | 
						|
      const fn = mock.fn(() => s1);
 | 
						|
      fn();
 | 
						|
 | 
						|
      if (isToHaveNth(returnedWith)) {
 | 
						|
        expectUnderTest(fn)[returnedWith](1, s2);
 | 
						|
        expectUnderTest(fn).not[returnedWith](1, s3);
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[returnedWith](1, s2),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[returnedWith](1, s3),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      } else {
 | 
						|
        expectUnderTest(fn)[returnedWith](s2);
 | 
						|
        expectUnderTest(fn).not[returnedWith](s3);
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[returnedWith](s2),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[returnedWith](s3),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    test('works with Immutable.js objects directly created', () => {
 | 
						|
      const directlyCreated = Immutable.Map([['a', { b: 'c' }]]);
 | 
						|
      const fn = mock.fn(() => directlyCreated);
 | 
						|
      fn();
 | 
						|
 | 
						|
      if (isToHaveNth(returnedWith)) {
 | 
						|
        expectUnderTest(fn)[returnedWith](1, directlyCreated);
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[returnedWith](1, directlyCreated),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      } else {
 | 
						|
        expectUnderTest(fn)[returnedWith](directlyCreated);
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[returnedWith](directlyCreated),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    test('works with Immutable.js objects indirectly created', () => {
 | 
						|
      const indirectlyCreated = Immutable.Map().set('a', { b: 'c' });
 | 
						|
      const fn = mock.fn(() => indirectlyCreated);
 | 
						|
      fn();
 | 
						|
 | 
						|
      if (isToHaveNth(returnedWith)) {
 | 
						|
        expectUnderTest(fn)[returnedWith](1, indirectlyCreated);
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[returnedWith](1, indirectlyCreated),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      } else {
 | 
						|
        expectUnderTest(fn)[returnedWith](indirectlyCreated);
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn).not[returnedWith](indirectlyCreated),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    test('a call that throws is not considered to have returned', () => {
 | 
						|
      const fn = mock.fn(() => {
 | 
						|
        throw new Error('Error!');
 | 
						|
      });
 | 
						|
 | 
						|
      try {
 | 
						|
        fn();
 | 
						|
      } catch {
 | 
						|
        // ignore error
 | 
						|
      }
 | 
						|
 | 
						|
      if (isToHaveNth(returnedWith)) {
 | 
						|
        // It doesn't matter what return value is tested if the call threw
 | 
						|
        expectUnderTest(fn).not[returnedWith](1, 'foo');
 | 
						|
        expectUnderTest(fn).not[returnedWith](1, null);
 | 
						|
        expectUnderTest(fn).not[returnedWith](1, undefined);
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[returnedWith](1, undefined),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      } else {
 | 
						|
        // It doesn't matter what return value is tested if the call threw
 | 
						|
        expectUnderTest(fn).not[returnedWith]('foo');
 | 
						|
        expectUnderTest(fn).not[returnedWith](null);
 | 
						|
        expectUnderTest(fn).not[returnedWith](undefined);
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[returnedWith](undefined),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    test('a call that throws undefined is not considered to have returned', () => {
 | 
						|
      const fn = mock.fn(() => {
 | 
						|
 | 
						|
        throw undefined;
 | 
						|
      });
 | 
						|
 | 
						|
      try {
 | 
						|
        fn();
 | 
						|
      } catch {
 | 
						|
        // ignore error
 | 
						|
      }
 | 
						|
 | 
						|
      if (isToHaveNth(returnedWith)) {
 | 
						|
        // It doesn't matter what return value is tested if the call threw
 | 
						|
        expectUnderTest(fn).not[returnedWith](1, 'foo');
 | 
						|
        expectUnderTest(fn).not[returnedWith](1, null);
 | 
						|
        expectUnderTest(fn).not[returnedWith](1, undefined);
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[returnedWith](1, undefined),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      } else {
 | 
						|
        // It doesn't matter what return value is tested if the call threw
 | 
						|
        expectUnderTest(fn).not[returnedWith]('foo');
 | 
						|
        expectUnderTest(fn).not[returnedWith](null);
 | 
						|
        expectUnderTest(fn).not[returnedWith](undefined);
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[returnedWith](undefined),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    if (!isToHaveNth(returnedWith)) {
 | 
						|
      test.describe('returnedWith', () => {
 | 
						|
        test('works with more calls than the limit', () => {
 | 
						|
          const fn = mock.fn<() => string>();
 | 
						|
          fn.mockReturnValueOnce('foo1');
 | 
						|
          fn.mockReturnValueOnce('foo2');
 | 
						|
          fn.mockReturnValueOnce('foo3');
 | 
						|
          fn.mockReturnValueOnce('foo4');
 | 
						|
          fn.mockReturnValueOnce('foo5');
 | 
						|
          fn.mockReturnValueOnce('foo6');
 | 
						|
 | 
						|
          fn();
 | 
						|
          fn();
 | 
						|
          fn();
 | 
						|
          fn();
 | 
						|
          fn();
 | 
						|
          fn();
 | 
						|
 | 
						|
          expectUnderTest(fn).not[returnedWith]('bar');
 | 
						|
 | 
						|
          expect(() => {
 | 
						|
            expectUnderTest(fn)[returnedWith]('bar');
 | 
						|
          }).toThrowErrorMatchingSnapshot();
 | 
						|
        });
 | 
						|
 | 
						|
        test('incomplete recursive calls are handled properly', () => {
 | 
						|
          // sums up all integers from 0 -> value, using recursion
 | 
						|
          const fn: mock.Mock<(value: number) => number> = mock.fn(value => {
 | 
						|
            if (value === 0) {
 | 
						|
              // Before returning from the base case of recursion, none of the
 | 
						|
              // calls have returned yet.
 | 
						|
              // This test ensures that the incomplete calls are not incorrectly
 | 
						|
              // interpreted as have returned undefined
 | 
						|
              expectUnderTest(fn).not[returnedWith](undefined);
 | 
						|
              expect(() =>
 | 
						|
                expectUnderTest(fn)[returnedWith](undefined),
 | 
						|
              ).toThrowErrorMatchingSnapshot();
 | 
						|
 | 
						|
              return 0;
 | 
						|
            } else {
 | 
						|
              return value + fn(value - 1);
 | 
						|
            }
 | 
						|
          });
 | 
						|
 | 
						|
          fn(3);
 | 
						|
        });
 | 
						|
      });
 | 
						|
    }
 | 
						|
 | 
						|
    if (isToHaveNth(returnedWith)) {
 | 
						|
      test.describe('nthReturnedWith', () => {
 | 
						|
        test('works with three calls', () => {
 | 
						|
          const fn = mock.fn<() => string>();
 | 
						|
          fn.mockReturnValueOnce('foo1');
 | 
						|
          fn.mockReturnValueOnce('foo2');
 | 
						|
          fn.mockReturnValueOnce('foo3');
 | 
						|
          fn();
 | 
						|
          fn();
 | 
						|
          fn();
 | 
						|
 | 
						|
          expectUnderTest(fn)[returnedWith](1, 'foo1');
 | 
						|
          expectUnderTest(fn)[returnedWith](2, 'foo2');
 | 
						|
          expectUnderTest(fn)[returnedWith](3, 'foo3');
 | 
						|
 | 
						|
          expect(() => {
 | 
						|
            expectUnderTest(fn).not[returnedWith](1, 'foo1');
 | 
						|
            expectUnderTest(fn).not[returnedWith](2, 'foo2');
 | 
						|
            expectUnderTest(fn).not[returnedWith](3, 'foo3');
 | 
						|
          }).toThrowErrorMatchingSnapshot();
 | 
						|
        });
 | 
						|
 | 
						|
        test('should replace 1st, 2nd, 3rd with first, second, third', async () => {
 | 
						|
          const fn = mock.fn<() => string>();
 | 
						|
          fn.mockReturnValueOnce('foo1');
 | 
						|
          fn.mockReturnValueOnce('foo2');
 | 
						|
          fn.mockReturnValueOnce('foo3');
 | 
						|
          fn();
 | 
						|
          fn();
 | 
						|
          fn();
 | 
						|
 | 
						|
          expect(() => {
 | 
						|
            expectUnderTest(fn)[returnedWith](1, 'bar1');
 | 
						|
            expectUnderTest(fn)[returnedWith](2, 'bar2');
 | 
						|
            expectUnderTest(fn)[returnedWith](3, 'bar3');
 | 
						|
          }).toThrowErrorMatchingSnapshot();
 | 
						|
 | 
						|
          expect(() => {
 | 
						|
            expectUnderTest(fn).not[returnedWith](1, 'foo1');
 | 
						|
            expectUnderTest(fn).not[returnedWith](2, 'foo2');
 | 
						|
            expectUnderTest(fn).not[returnedWith](3, 'foo3');
 | 
						|
          }).toThrowErrorMatchingSnapshot();
 | 
						|
        });
 | 
						|
 | 
						|
        test('positive throw matcher error for n that is not positive integer', async () => {
 | 
						|
          const fn = mock.fn(() => 'foo');
 | 
						|
          fn();
 | 
						|
 | 
						|
          expect(() => {
 | 
						|
            expectUnderTest(fn)[returnedWith](0, 'foo');
 | 
						|
          }).toThrowErrorMatchingSnapshot();
 | 
						|
        });
 | 
						|
 | 
						|
        test('should reject nth value greater than number of calls', async () => {
 | 
						|
          const fn = mock.fn(() => 'foo');
 | 
						|
          fn();
 | 
						|
          fn();
 | 
						|
          fn();
 | 
						|
 | 
						|
          expect(() => {
 | 
						|
            expectUnderTest(fn)[returnedWith](4, 'foo');
 | 
						|
          }).toThrowErrorMatchingSnapshot();
 | 
						|
        });
 | 
						|
 | 
						|
        test('positive throw matcher error for n that is not integer', async () => {
 | 
						|
          const fn = mock.fn<(a: string) => string>(() => 'foo');
 | 
						|
          fn('foo');
 | 
						|
 | 
						|
          expect(() => {
 | 
						|
            expectUnderTest(fn)[returnedWith](0.1, 'foo');
 | 
						|
          }).toThrowErrorMatchingSnapshot();
 | 
						|
        });
 | 
						|
 | 
						|
        test('negative throw matcher error for n that is not number', async () => {
 | 
						|
          const fn = mock.fn<(a: string) => string>(() => 'foo');
 | 
						|
          fn('foo');
 | 
						|
 | 
						|
          expect(() => {
 | 
						|
            // @ts-expect-error: Testing runtime error
 | 
						|
            expectUnderTest(fn).not[returnedWith]();
 | 
						|
          }).toThrowErrorMatchingSnapshot();
 | 
						|
        });
 | 
						|
 | 
						|
        test('incomplete recursive calls are handled properly', () => {
 | 
						|
          // sums up all integers from 0 -> value, using recursion
 | 
						|
          const fn: mock.Mock<(value: number) => number> = mock.fn(value => {
 | 
						|
            if (value === 0) {
 | 
						|
              return 0;
 | 
						|
            } else {
 | 
						|
              const recursiveResult = fn(value - 1);
 | 
						|
 | 
						|
              if (value === 2) {
 | 
						|
                // Only 2 of the recursive calls have returned at this point
 | 
						|
                expectUnderTest(fn).not[returnedWith](1, 6);
 | 
						|
                expectUnderTest(fn).not[returnedWith](2, 3);
 | 
						|
                expectUnderTest(fn)[returnedWith](3, 1);
 | 
						|
                expectUnderTest(fn)[returnedWith](4, 0);
 | 
						|
 | 
						|
                expect(() =>
 | 
						|
                  expectUnderTest(fn)[returnedWith](1, 6),
 | 
						|
                ).toThrowErrorMatchingSnapshot();
 | 
						|
                expect(() =>
 | 
						|
                  expectUnderTest(fn)[returnedWith](2, 3),
 | 
						|
                ).toThrowErrorMatchingSnapshot();
 | 
						|
                expect(() =>
 | 
						|
                  expectUnderTest(fn).not[returnedWith](3, 1),
 | 
						|
                ).toThrowErrorMatchingSnapshot();
 | 
						|
                expect(() =>
 | 
						|
                  expectUnderTest(fn).not[returnedWith](4, 0),
 | 
						|
                ).toThrowErrorMatchingSnapshot();
 | 
						|
              }
 | 
						|
 | 
						|
              return value + recursiveResult;
 | 
						|
            }
 | 
						|
          });
 | 
						|
 | 
						|
          fn(3);
 | 
						|
        });
 | 
						|
      });
 | 
						|
    }
 | 
						|
 | 
						|
    if (isToHaveLast(returnedWith)) {
 | 
						|
      test.describe('lastReturnedWith', () => {
 | 
						|
        test('works with three calls', () => {
 | 
						|
          const fn = mock.fn<() => string>();
 | 
						|
          fn.mockReturnValueOnce('foo1');
 | 
						|
          fn.mockReturnValueOnce('foo2');
 | 
						|
          fn.mockReturnValueOnce('foo3');
 | 
						|
          fn();
 | 
						|
          fn();
 | 
						|
          fn();
 | 
						|
 | 
						|
          expectUnderTest(fn)[returnedWith]('foo3');
 | 
						|
 | 
						|
          expect(() => {
 | 
						|
            expectUnderTest(fn).not[returnedWith]('foo3');
 | 
						|
          }).toThrowErrorMatchingSnapshot();
 | 
						|
        });
 | 
						|
 | 
						|
        test('incomplete recursive calls are handled properly', () => {
 | 
						|
          // sums up all integers from 0 -> value, using recursion
 | 
						|
          const fn: mock.Mock<(value: number) => number> = mock.fn(value => {
 | 
						|
            if (value === 0) {
 | 
						|
              // Before returning from the base case of recursion, none of the
 | 
						|
              // calls have returned yet.
 | 
						|
              expectUnderTest(fn).not[returnedWith](0);
 | 
						|
              expect(() =>
 | 
						|
                expectUnderTest(fn)[returnedWith](0),
 | 
						|
              ).toThrowErrorMatchingSnapshot();
 | 
						|
              return 0;
 | 
						|
            } else {
 | 
						|
              return value + fn(value - 1);
 | 
						|
            }
 | 
						|
          });
 | 
						|
 | 
						|
          fn(3);
 | 
						|
        });
 | 
						|
      });
 | 
						|
    }
 | 
						|
 | 
						|
    test('includes the custom mock name in the error message', () => {
 | 
						|
      const fn = mock.fn().mockName('named-mock');
 | 
						|
 | 
						|
      if (isToHaveNth(returnedWith)) {
 | 
						|
        expectUnderTest(fn).not[returnedWith](1, 'foo');
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[returnedWith](1, 'foo'),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      } else {
 | 
						|
        expectUnderTest(fn).not[returnedWith]('foo');
 | 
						|
 | 
						|
        expect(() =>
 | 
						|
          expectUnderTest(fn)[returnedWith]('foo'),
 | 
						|
        ).toThrowErrorMatchingSnapshot();
 | 
						|
      }
 | 
						|
    });
 | 
						|
  });
 | 
						|
}
 |