diff --git a/src/__tests__/createCachedSelector.spec.js b/src/__tests__/createCachedSelector.spec.js index 01468848..496eeef4 100644 --- a/src/__tests__/createCachedSelector.spec.js +++ b/src/__tests__/createCachedSelector.spec.js @@ -1,4 +1,3 @@ -/* eslint comma-dangle: 0 */ import * as reselect from 'reselect'; import createCachedSelector, {FlatObjectCache} from '../../src/index'; @@ -20,106 +19,8 @@ function selectorWithMockedResultFunc() { } describe('createCachedSelector', () => { - describe('"recomputations" property and cached selectors', () => { - describe('keySelector returns the same value', () => { - it('Should create and use the same cached selector', () => { - const cachedSelector = selectorWithMockedResultFunc(); - const firstCall = cachedSelector('foo', 'bar'); - const secondCallWithSamekeySelector = cachedSelector('foo', 'bar'); - - expect(createSelectorSpy).toHaveBeenCalledTimes(1); - expect(cachedSelector.recomputations()).toBe(1); - }); - }); - - describe('keySelector returns 2 different values', () => { - it('Should create 2 selectors only and produce 2 recomputations', () => { - const cachedSelector = selectorWithMockedResultFunc(); - const firstCallResult = cachedSelector('foo', 'bar'); - const secondCallResult = cachedSelector('foo', 'moo'); - const thirdCallResult = cachedSelector('foo', 'bar'); - const fourthCallResult = cachedSelector('foo', 'moo'); - - expect(createSelectorSpy).toHaveBeenCalledTimes(2); - expect(cachedSelector.recomputations()).toBe(2); - }); - }); - }); - - describe('cacheKey validity check', () => { - describe('cacheObject.isValidCacheKey not available', () => { - it('Should accept any value', () => { - const cacheObjectMock = { - get: jest.fn(() => () => 'foo'), - }; - const values = [{}, [], null, undefined, 12, 'bar']; - - const cachedSelector = createCachedSelector(resultFuncMock)( - arg1 => arg1, // cacheKey - { - cacheObject: cacheObjectMock, - } - ); - - values.forEach((value, index) => { - cachedSelector(value); - expect(cacheObjectMock.get).toHaveBeenCalledTimes(index + 1); - expect(cacheObjectMock.get).toHaveBeenLastCalledWith(value); - }); - }); - }); - - describe('cacheObject.isValidCacheKey returns "true"', () => { - it('Should call cache.get method', () => { - const cacheObjectMock = new FlatObjectCache(); - cacheObjectMock.isValidCacheKey = jest.fn(() => true); - cacheObjectMock.get = jest.fn(); - - const cachedSelector = createCachedSelector(resultFuncMock)( - arg1 => arg1, - { - cacheObject: cacheObjectMock, - } - ); - - cachedSelector('foo'); - - expect(cacheObjectMock.get).toHaveBeenCalledTimes(1); - // Receive cacheKey and reselect selector as arguments - expect(cacheObjectMock.get).toHaveBeenCalledWith('foo'); - }); - }); - - describe('cacheObject.isValidCacheKey returns "false"', () => { - it('Should return "undefined" and call "console.warn"', () => { - const cacheObjectMock = new FlatObjectCache(); - cacheObjectMock.isValidCacheKey = jest.fn(() => false); - cacheObjectMock.get = jest.fn(); - - const cachedSelector = createCachedSelector(resultFuncMock)( - arg1 => arg1, - { - cacheObject: cacheObjectMock, - } - ); - - const actual = cachedSelector('foo'); - - expect(actual).toBe(undefined); - expect(cacheObjectMock.get).not.toHaveBeenCalled(); - expect(consoleWarnSpy).toHaveBeenCalledTimes(1); - }); - }); - }); - - it('Should throw an error when a function is provided as 2° argument', () => { - expect(() => { - createCachedSelector(resultFuncMock)(() => {}, reselect.createSelector); - }).toThrow(/Second argument "options" must be an object/); - }); - describe('options', () => { - it('Should accept cacheObject and selectorCreator options', () => { + it('accepts cacheObject and selectorCreator options', () => { const cachedSelector = createCachedSelector(resultFuncMock)( (arg1, arg2) => arg2, { @@ -134,7 +35,7 @@ describe('createCachedSelector', () => { expect(cachedSelector.recomputations()).toBe(1); }); - it('Should accept selectorCreator option', () => { + it('accepts selectorCreator option', () => { const inputSelector = () => {}; const resultFunc = () => {}; const keySelector = () => {}; @@ -157,118 +58,227 @@ describe('createCachedSelector', () => { }); }); - describe('getMatchingSelector()', () => { - it('Should return underlying reselect selector for a given cache key', () => { - const cachedSelector = createCachedSelector(() => {})( - (arg1, arg2) => arg2 - ); + describe('created selector', () => { + describe('cache retention', () => { + describe('calls producing identical cacheKey', () => { + it('creates and use the same cached selector', () => { + const cachedSelector = selectorWithMockedResultFunc(); + cachedSelector('foo', 'bar'); + cachedSelector('foo', 'bar'); - // Retrieve result from re-reselect cached selector - const actualResult = cachedSelector('foo', 1); + expect(createSelectorSpy).toHaveBeenCalledTimes(1); + expect(cachedSelector.recomputations()).toBe(1); + }); + }); - // Retrieve result directly calling underlying reselect selector - const reselectSelector = cachedSelector.getMatchingSelector('foo', 1); - const expectedResultFromSelector = reselectSelector('foo', 1); + describe('calls producing 2 different cacheKey', () => { + it('creates 2 selectors only and produce 2 recomputations', () => { + const cachedSelector = selectorWithMockedResultFunc(); + cachedSelector('foo', 'bar'); + cachedSelector('foo', 'moo'); + cachedSelector('foo', 'bar'); + cachedSelector('foo', 'moo'); - expect(actualResult).toBe(expectedResultFromSelector); + expect(createSelectorSpy).toHaveBeenCalledTimes(2); + expect(cachedSelector.recomputations()).toBe(2); + }); + }); }); - it('Should return "undefined" when given cache key doesn\'t match any cache entry', () => { - const cachedSelector = selectorWithMockedResultFunc(); + describe('cacheKey validation', () => { + describe('cacheObject.isValidCacheKey', () => { + describe("doesn't exist", () => { + it('accepts any value', () => { + const cacheObjectMock = { + get: jest.fn(() => () => 'foo'), + }; + const values = [{}, [], null, undefined, 12, 'bar']; + + const cachedSelector = createCachedSelector(resultFuncMock)( + arg1 => arg1, + { + cacheObject: cacheObjectMock, + } + ); + + values.forEach((value, index) => { + cachedSelector(value); + expect(cacheObjectMock.get).toHaveBeenCalledTimes(index + 1); + expect(cacheObjectMock.get).toHaveBeenLastCalledWith(value); + }); + }); + }); + + describe('returns true', () => { + it('calls cache.get method', () => { + const cacheObjectMock = new FlatObjectCache(); + cacheObjectMock.isValidCacheKey = () => true; + cacheObjectMock.get = jest.fn(); + + const cachedSelector = createCachedSelector(resultFuncMock)( + arg1 => arg1, + { + cacheObject: cacheObjectMock, + } + ); - const actual = cachedSelector.getMatchingSelector('foo', 1); - const expected = undefined; + cachedSelector('foo'); - expect(actual).toEqual(expected); + expect(cacheObjectMock.get).toHaveBeenCalledTimes(1); + expect(cacheObjectMock.get).toHaveBeenCalledWith('foo'); + }); + }); + + describe('returns false', () => { + it('returns "undefined" and call "console.warn"', () => { + const cacheObjectMock = new FlatObjectCache(); + cacheObjectMock.isValidCacheKey = () => false; + cacheObjectMock.get = jest.fn(); + + const cachedSelector = createCachedSelector(resultFuncMock)( + arg1 => arg1, + { + cacheObject: cacheObjectMock, + } + ); + + const actual = cachedSelector('foo'); + + expect(actual).toBe(undefined); + expect(cacheObjectMock.get).not.toHaveBeenCalled(); + expect(consoleWarnSpy).toHaveBeenCalledTimes(1); + }); + }); + }); }); - }); - describe('removeMatchingSelector()', () => { - it('Should set the matching cache entry to "undefined"', () => { - const cachedSelector = selectorWithMockedResultFunc(); + describe('available methods', () => { + describe('getMatchingSelector()', () => { + it('returns underlying reselect selector for a given cache key', () => { + const cachedSelector = createCachedSelector(() => {})( + (arg1, arg2) => arg2 + ); - cachedSelector('foo', 1); // add to cache - cachedSelector('foo', 2); // add to cache - cachedSelector.removeMatchingSelector('foo', 1); // remove key from chache + // Retrieve result from re-reselect cached selector + const actualResult = cachedSelector('foo', 1); - const firstSelectorActual = cachedSelector.getMatchingSelector('foo', 1); - const secondSelectorActual = cachedSelector.getMatchingSelector('foo', 2); + // Retrieve result directly calling underlying reselect selector + const reselectSelector = cachedSelector.getMatchingSelector('foo', 1); + const expectedResultFromSelector = reselectSelector('foo', 1); - expect(firstSelectorActual).toBe(undefined); - expect(secondSelectorActual).not.toBe(undefined); - }); - }); + expect(actualResult).toBe(expectedResultFromSelector); + }); - describe('clearCache()', () => { - it('Should reset cache', () => { - const cachedSelector = selectorWithMockedResultFunc(); + it('returns "undefined" when given cache key doesn\'t match any cache entry', () => { + const cachedSelector = selectorWithMockedResultFunc(); - cachedSelector('foo', 1); // add to cache - cachedSelector.clearCache(); // clear cache - const actual = cachedSelector.getMatchingSelector('foo', 1); + const actual = cachedSelector.getMatchingSelector('foo', 1); + const expected = undefined; - expect(actual).toBe(undefined); - }); - }); + expect(actual).toEqual(expected); + }); + }); - describe('resetRecomputations()', () => { - it('Should reset recomputations', () => { - const cachedSelector = selectorWithMockedResultFunc(); - const firstCallResult = cachedSelector('foo', 'bar'); + describe('removeMatchingSelector()', () => { + it('sets the matching cache entry to "undefined"', () => { + const cachedSelector = selectorWithMockedResultFunc(); + + cachedSelector('foo', 1); // add to cache + cachedSelector('foo', 2); // add to cache + cachedSelector.removeMatchingSelector('foo', 1); + + const firstSelectorActual = cachedSelector.getMatchingSelector( + 'foo', + 1 + ); + const secondSelectorActual = cachedSelector.getMatchingSelector( + 'foo', + 2 + ); + + expect(firstSelectorActual).toBe(undefined); + expect(secondSelectorActual).not.toBe(undefined); + }); + }); - expect(cachedSelector.recomputations()).toBe(1); - cachedSelector.resetRecomputations(); - expect(cachedSelector.recomputations()).toBe(0); - }); - }); + describe('clearCache()', () => { + it('resets cache', () => { + const cachedSelector = selectorWithMockedResultFunc(); - describe('"dependencies" property', () => { - it('Should export an array containing provided inputSelectors', () => { - const dependency1 = state => state.a; - const dependency2 = state => state.a; + cachedSelector('foo', 1); // add to cache + cachedSelector.clearCache(); + const actual = cachedSelector.getMatchingSelector('foo', 1); - const cachedSelector = createCachedSelector( - dependency1, - dependency2, - () => {} - )(arg1 => arg1); + expect(actual).toBe(undefined); + }); + }); - const actual = cachedSelector.dependencies; - const expected = [dependency1, dependency2]; - expect(actual).toEqual(expected); - }); - }); + describe('resetRecomputations()', () => { + it('resets recomputations', () => { + const cachedSelector = selectorWithMockedResultFunc(); + cachedSelector('foo', 'bar'); - describe('"resultFunc" property', () => { - it('Should point to provided result function', () => { - const cachedSelector = createCachedSelector(() => {}, resultFuncMock)( - (arg1, arg2) => arg2 - ); - expect(cachedSelector.resultFunc).toBe(resultFuncMock); - }); - }); + expect(cachedSelector.recomputations()).toBe(1); + cachedSelector.resetRecomputations(); + expect(cachedSelector.recomputations()).toBe(0); + }); + }); - describe('"cache" property', () => { - it('Should point to currently used cacheObject', () => { - const currentCacheObject = new FlatObjectCache(); - const cachedSelector = createCachedSelector(resultFuncMock)( - arg1 => arg1, - { - cacheObject: currentCacheObject, - } - ); + describe('"dependencies" property', () => { + it('exports an array containing provided inputSelectors', () => { + const dependency1 = state => state.a; + const dependency2 = state => state.a; + + const cachedSelector = createCachedSelector( + dependency1, + dependency2, + () => {} + )(arg1 => arg1); + + const actual = cachedSelector.dependencies; + const expected = [dependency1, dependency2]; + expect(actual).toEqual(expected); + }); + }); + + describe('"resultFunc" property', () => { + it('points to provided result function', () => { + const cachedSelector = createCachedSelector(() => {}, resultFuncMock)( + (arg1, arg2) => arg2 + ); + expect(cachedSelector.resultFunc).toBe(resultFuncMock); + }); + }); - expect(cachedSelector.cache).toBe(currentCacheObject); + describe('"cache" property', () => { + it('points to currently used cacheObject', () => { + const currentCacheObject = new FlatObjectCache(); + const cachedSelector = createCachedSelector(resultFuncMock)( + arg1 => arg1, + { + cacheObject: currentCacheObject, + } + ); + + expect(cachedSelector.cache).toBe(currentCacheObject); + }); + }); + + describe('"keySelector" property', () => { + it('points to provided keySelector', () => { + const keySelector = (arg1, arg2) => arg2; + const cachedSelector = createCachedSelector(() => {}, resultFuncMock)( + keySelector + ); + expect(cachedSelector.keySelector).toBe(keySelector); + }); + }); }); }); - describe('"keySelector" property', () => { - it('Should point to provided keySelector', () => { - const keySelector = (arg1, arg2) => arg2; - const cachedSelector = createCachedSelector(() => {}, resultFuncMock)( - keySelector - ); - expect(cachedSelector.keySelector).toBe(keySelector); - }); + it('throws an error when a function is provided as 2° argument', () => { + expect(() => { + createCachedSelector(resultFuncMock)(() => {}, reselect.createSelector); + }).toThrow(/Second argument "options" must be an object/); }); }); diff --git a/src/cache/__tests__/deprecated/FifoCacheObject.js b/src/cache/__tests__/deprecated/FifoCacheObject.js index 8b76c572..095279f7 100644 --- a/src/cache/__tests__/deprecated/FifoCacheObject.js +++ b/src/cache/__tests__/deprecated/FifoCacheObject.js @@ -1,7 +1,7 @@ import {FifoCacheObject as CacheObject} from '../../../../src/index'; describe('FifoCacheObject (deprecated)', () => { - it('Should return "FifoObjectCache" class', () => { + it('returns "FifoObjectCache" class', () => { expect(CacheObject.name).toBe('FifoObjectCache'); }); }); diff --git a/src/cache/__tests__/deprecated/FlatCacheObject.js b/src/cache/__tests__/deprecated/FlatCacheObject.js index 7818eb80..46432581 100644 --- a/src/cache/__tests__/deprecated/FlatCacheObject.js +++ b/src/cache/__tests__/deprecated/FlatCacheObject.js @@ -1,7 +1,7 @@ import {FlatCacheObject as CacheObject} from '../../../../src/index'; describe('FlatCacheObject (deprecated)', () => { - it('Should return "FlatObjectCache" class', () => { + it('returns "FlatObjectCache" class', () => { expect(CacheObject.name).toBe('FlatObjectCache'); }); }); diff --git a/src/cache/__tests__/deprecated/LruCacheObject.js b/src/cache/__tests__/deprecated/LruCacheObject.js index a66582e4..ffe4b259 100644 --- a/src/cache/__tests__/deprecated/LruCacheObject.js +++ b/src/cache/__tests__/deprecated/LruCacheObject.js @@ -1,7 +1,7 @@ import {LruCacheObject as CacheObject} from '../../../../src/index'; describe('LruCacheObject (deprecated)', () => { - it('Should return "LruMapCache" class', () => { + it('returns "LruMapCache" class', () => { expect(CacheObject.name).toBe('LruMapCache'); }); }); diff --git a/src/cache/__util__/testBasicBehavior.js b/src/cache/__util__/testBasicBehavior.js index 27db5a38..34d1284f 100644 --- a/src/cache/__util__/testBasicBehavior.js +++ b/src/cache/__util__/testBasicBehavior.js @@ -2,7 +2,7 @@ import fillCacheWith from './fillCacheWith'; function testBasicBehavior(CacheObject, options) { describe('Cache basic behavior', () => { - it('Should return cached value', () => { + it('returns cached value', () => { const cache = new CacheObject(options); const actual = () => {}; @@ -12,7 +12,7 @@ function testBasicBehavior(CacheObject, options) { expect(actual).toBe(expected); }); - it('Should remove a single item', () => { + it('removes a single item', () => { const cache = new CacheObject(options); const entries = [1, 2, 3, 4, 5]; fillCacheWith(cache, entries); @@ -25,7 +25,7 @@ function testBasicBehavior(CacheObject, options) { }); }); - it('Should clear the cache', () => { + it('clears the cache', () => { const cache = new CacheObject(options); const entries = [1, 2, 3, 4, 5]; fillCacheWith(cache, entries); diff --git a/src/cache/__util__/testCacheSizeOptionValidation.js b/src/cache/__util__/testCacheSizeOptionValidation.js index c537fb80..d59d18c5 100644 --- a/src/cache/__util__/testCacheSizeOptionValidation.js +++ b/src/cache/__util__/testCacheSizeOptionValidation.js @@ -1,12 +1,12 @@ function testCacheSizeOptionValidation(CacheObject) { describe('cacheSize option validation', () => { - it('Should throw error if not defined', () => { + it('throws error if not defined', () => { expect(() => { const cache = new CacheObject(); }).toThrow(/Missing/); }); - it('Should throw error if not a positive integer', () => { + it('throws error if not a positive integer', () => { const wrongValues = [2.5, -12, 0]; wrongValues.forEach(value => { @@ -16,7 +16,7 @@ function testCacheSizeOptionValidation(CacheObject) { }); }); - it('Should not throw if a positive integer', () => { + it("doesn't throw if a positive integer", () => { expect(() => { const cache = new CacheObject({cacheSize: 22}); }).not.toThrow(); diff --git a/src/cache/__util__/testFifoBehavior.js b/src/cache/__util__/testFifoBehavior.js index 309f4815..95bdc0fc 100644 --- a/src/cache/__util__/testFifoBehavior.js +++ b/src/cache/__util__/testFifoBehavior.js @@ -2,7 +2,7 @@ import fillCacheWith from './fillCacheWith'; function testFifoBehavior(CacheObject) { describe('FIFO cache behavior', () => { - it('Should limit cache queue by removing the first added items', () => { + it('limits cache queue by removing the first added items', () => { const cache = new CacheObject({cacheSize: 5}); const entries = [1, 2, 3, 4]; const newEntries = [5, 6, 7]; @@ -17,7 +17,7 @@ function testFifoBehavior(CacheObject) { }); }); - it('Should mantain cache updated after removing extraneous entry', () => { + it('mantains cache updated after removing extraneous entry', () => { const cache = new CacheObject({cacheSize: 5}); const entries = [1, 2, 3, 4, 5]; fillCacheWith(cache, entries); diff --git a/src/cache/__util__/testLruBehavior.js b/src/cache/__util__/testLruBehavior.js index cb392a31..963466fe 100644 --- a/src/cache/__util__/testLruBehavior.js +++ b/src/cache/__util__/testLruBehavior.js @@ -2,7 +2,7 @@ import fillCacheWith from './fillCacheWith'; function testLruBehavior(CacheObject) { describe('LRU cache behavior', () => { - it('Should remove an item and update cache ordering when another is added', () => { + it('removes an item and update cache ordering when another is added', () => { const cache = new CacheObject({cacheSize: 5}); const entries = [1, 2, 3, 4, 5]; fillCacheWith(cache, entries); @@ -16,7 +16,7 @@ function testLruBehavior(CacheObject) { }); }); - it('Should limit cache queue by removing the least recently used item', () => { + it('limits cache queue by removing the least recently used item', () => { const cache = new CacheObject({cacheSize: 5}); const entries = [0, 1, 2]; diff --git a/src/cache/__util__/testMapCacheKeyBehavior.js b/src/cache/__util__/testMapCacheKeyBehavior.js index 61609d99..d07e3485 100644 --- a/src/cache/__util__/testMapCacheKeyBehavior.js +++ b/src/cache/__util__/testMapCacheKeyBehavior.js @@ -3,13 +3,13 @@ import fillCacheWith from './fillCacheWith'; function testMapCacheKeyBehavior(CacheObject, options) { describe('cacheKey', () => { describe('isValidCacheKey method', () => { - it('Should not exist', () => { + it("doesn't not exist", () => { const cache = new CacheObject(options); expect(cache.isValidCacheKey).toBe(undefined); }); }); - it('Any kind of value should work as cache key', () => { + it('any kind of value works as cache key', () => { const cache = new CacheObject(options); const entries = new Set([1, {}, 3, [], null]); diff --git a/src/cache/__util__/testObjectCacheKeyBehavior.js b/src/cache/__util__/testObjectCacheKeyBehavior.js index 92292c5f..0d8b9f63 100644 --- a/src/cache/__util__/testObjectCacheKeyBehavior.js +++ b/src/cache/__util__/testObjectCacheKeyBehavior.js @@ -1,6 +1,6 @@ function testObjectCacheKeyBehavior(CacheObject, options) { describe('isValidCacheKey method', () => { - it('Should accept only numbers and string', () => { + it('accepts only numbers and string', () => { const cache = new CacheObject(options); const validValues = [1, 1.2, -5, 'foo', '12']; const invalidValues = [{}, [], null, undefined, new Map()];