import memoize from '../memoize';

describe('Utils/Function/memoize', () => {
    test('throws error if the given argument is not a function', () => {
        expect(() => memoize(null)).toThrowError();
    });
    test('calls the memozied function with exactly the same arguments, returns the correct value', () => {
        const result = {};
        const spy = jest.fn(() => result);
        const fn = memoize(spy);
        const obj = {};
        const v1 = fn('foo', 2, obj);
        expect(spy).toBeCalledWith('foo', 2, obj);
        expect(v1).toBe(result);
    });
    test(
        'does not call the memoized function if it was called with the previous arguments,' +
            ' but it returns the previous result',
        () => {
            const spy = jest.fn(() => ({}));
            const fn = memoize(spy);
            const obj = {};
            const v1 = fn('foo', 2, obj);
            const v2 = fn('foo', 2, obj);
            // the function should have been called only once
            expect(spy).toBeCalledTimes(1);
            // the returned values should be exactly the same object reference
            expect(v2).toBe(v1);
        }
    );
    test('returns the correct values when called with different arguments', () => {
        const spy = jest.fn(() => ({}));
        const fn = memoize(spy);
        // using different object references
        const v1 = fn('foo', 2, {});
        const v2 = fn('foo', 2, {});
        // the function should have been called twice
        expect(spy).toBeCalledTimes(2);
        // the return values should be different references
        expect(v2).not.toBe(v1);
    });
});
