UNPKG

expression-language

Version:

Javascript implementation of symfony/expression-language

210 lines (208 loc) 9.07 kB
"use strict"; var _ArrayAdapter = _interopRequireWildcard(require("../ArrayAdapter")); function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } test('getItem returns a miss for an unknown key', () => { let adapter = new _ArrayAdapter.default(); let item = adapter.getItem('foo'); expect(item.isHit).toBe(false); expect(item.get()).toBeNull(); }); test('save then getItem returns a hit with the saved value', () => { let adapter = new _ArrayAdapter.default(); let item = adapter.getItem('foo'); item.set('bar'); expect(adapter.save(item)).toBe(true); let hit = adapter.getItem('foo'); expect(hit.isHit).toBe(true); expect(hit.get()).toBe('bar'); }); test('save returns false for a non-CacheItem argument', () => { let adapter = new _ArrayAdapter.default(); expect(adapter.save({ key: 'foo', value: 'bar' })).toBe(false); expect(adapter.getItem('foo').isHit).toBe(false); }); test('save of an already-expired item deletes it and reports success', () => { let adapter = new _ArrayAdapter.default(); let item = adapter.getItem('foo'); item.set('bar'); item.expiresAt(new Date(0)); expect(adapter.save(item)).toBe(true); expect(adapter.getItem('foo').isHit).toBe(false); }); test('save applies defaultLifetime when the item has no explicit expiry', () => { let adapter = new _ArrayAdapter.default(3600); let item = adapter.getItem('foo'); item.set('bar'); adapter.save(item); expect(adapter.hasItem('foo')).toBe(true); expect(adapter.getValues().foo).toBe('bar'); }); test('saveDeferred behaves like save', () => { let adapter = new _ArrayAdapter.default(); let item = adapter.getItem('foo'); item.set('bar'); expect(adapter.saveDeferred(item)).toBe(true); expect(adapter.getItem('foo').get()).toBe('bar'); }); test('commit always returns true', () => { let adapter = new _ArrayAdapter.default(); expect(adapter.commit()).toBe(true); }); test('get computes and caches the value via the callback on a miss', () => { let adapter = new _ArrayAdapter.default(); let calls = 0; let compute = (item, save) => { calls++; return 'computed'; }; expect(adapter.get('foo', compute)).toBe('computed'); expect(calls).toBe(1); // Second call should be a hit and must not invoke the callback again. expect(adapter.get('foo', compute)).toBe('computed'); expect(calls).toBe(1); }); test('delete removes a stored item', () => { let adapter = new _ArrayAdapter.default(); let item = adapter.getItem('foo'); item.set('bar'); adapter.save(item); expect(adapter.delete('foo')).toBe(true); expect(adapter.getItem('foo').isHit).toBe(false); }); test('deleteItems removes multiple keys', () => { let adapter = new _ArrayAdapter.default(); for (let key of ['a', 'b', 'c']) { let item = adapter.getItem(key); item.set(key.toUpperCase()); adapter.save(item); } expect(adapter.deleteItems(['a', 'b'])).toBe(true); expect(adapter.hasItem('a')).toBe(false); expect(adapter.hasItem('b')).toBe(false); expect(adapter.hasItem('c')).toBe(true); }); test('getItems returns a CacheItem per key, hit or miss', () => { let adapter = new _ArrayAdapter.default(); let known = adapter.getItem('known'); known.set('value'); adapter.save(known); let items = adapter.getItems(['known', 'unknown']); expect(items.known.isHit).toBe(true); expect(items.known.get()).toBe('value'); expect(items.unknown.isHit).toBe(false); }); test('getItems validates non-string keys that have not been seen before', () => { let adapter = new _ArrayAdapter.default(); expect(() => adapter.getItems([42])).toThrow('Cache key must be string'); }); test('getValues returns the internal values map', () => { let adapter = new _ArrayAdapter.default(); let item = adapter.getItem('foo'); item.set('bar'); adapter.save(item); expect(adapter.getValues()).toEqual({ foo: 'bar' }); }); test('hasItem is false before saving and true after', () => { let adapter = new _ArrayAdapter.default(); expect(adapter.hasItem('foo')).toBe(false); let item = adapter.getItem('foo'); item.set('bar'); adapter.save(item); expect(adapter.hasItem('foo')).toBe(true); }); test('clear empties all values and expiries', () => { let adapter = new _ArrayAdapter.default(); let item = adapter.getItem('foo'); item.set('bar'); adapter.save(item); expect(adapter.clear()).toBe(true); expect(adapter.getValues()).toEqual({}); expect(adapter.hasItem('foo')).toBe(false); }); test('reset clears the adapter', () => { let adapter = new _ArrayAdapter.default(); let item = adapter.getItem('foo'); item.set('bar'); adapter.save(item); adapter.reset(); expect(adapter.hasItem('foo')).toBe(false); }); test('deleteItem/hasItem validate the key and reject invalid keys', () => { let adapter = new _ArrayAdapter.default(); expect(() => adapter.hasItem(42)).toThrow('Cache key must be string'); expect(() => adapter.hasItem('')).toThrow('Cache key length must be greater than zero'); expect(() => adapter.hasItem('foo{bar}')).toThrow('contains reserved character'); expect(() => adapter.deleteItem(42)).toThrow('Cache key must be string'); }); test('CacheItem getKey/get/set', () => { let item = new _ArrayAdapter.CacheItem(); item.key = 'foo'; item.set('bar'); expect(item.getKey()).toBe('foo'); expect(item.get()).toBe('bar'); }); test('CacheItem.set returns the item for chaining', () => { let item = new _ArrayAdapter.CacheItem(); expect(item.set('value')).toBe(item); }); test('CacheItem.expiresAt accepts null, a Date, or throws otherwise', () => { let item = new _ArrayAdapter.CacheItem(); item.defaultLifetime = 100; expect(item.expiresAt(null)).toBe(item); expect(item.expiry).toBeGreaterThan(Date.now() / 1000); let withoutDefaultLifetime = new _ArrayAdapter.CacheItem(); withoutDefaultLifetime.expiresAt(null); expect(withoutDefaultLifetime.expiry).toBeNull(); let atDate = new _ArrayAdapter.CacheItem(); let when = new Date('2020-01-01T00:00:00Z'); atDate.expiresAt(when); expect(atDate.expiry).toBe(when.getTime() / 1000); let invalid = new _ArrayAdapter.CacheItem(); expect(() => invalid.expiresAt('not-a-date')).toThrow('Expiration date must be instance of Date'); }); test('CacheItem.expiresAfter accepts null, an integer, or throws otherwise', () => { let item = new _ArrayAdapter.CacheItem(); item.defaultLifetime = 100; expect(item.expiresAfter(null)).toBe(item); expect(item.expiry).toBeGreaterThan(Date.now() / 1000); let withoutDefaultLifetime = new _ArrayAdapter.CacheItem(); withoutDefaultLifetime.expiresAfter(null); expect(withoutDefaultLifetime.expiry).toBeNull(); let afterSeconds = new _ArrayAdapter.CacheItem(); let before = Date.now() / 1000; afterSeconds.expiresAfter(60); expect(afterSeconds.expiry).toBeGreaterThanOrEqual(before + 60); let invalid = new _ArrayAdapter.CacheItem(); expect(() => invalid.expiresAfter('soon')).toThrow('Expiration date must be an integer'); }); test('CacheItem.tag throws on a non-tag-aware (non-taggable) pool item', () => { let item = new _ArrayAdapter.CacheItem(); expect(item.isTaggable).toBe(false); expect(() => item.tag('some-tag')).toThrow('comes from a non tag-aware pool'); }); test('CacheItem.tag is broken for taggable items: newMetadata.tags is never initialized', () => { // Nothing in this codebase ever sets isTaggable = true, so this path is currently unreachable // through the public API. Forcing it here documents a real latent bug (this.newMetadata.tags // is never initialized to an object in the constructor), so tagging a taggable item throws // instead of recording the tag. let item = new _ArrayAdapter.CacheItem(); item.isTaggable = true; expect(() => item.tag('some-tag')).toThrow(TypeError); }); test('CacheItem.getMetadata returns the metadata object', () => { let item = new _ArrayAdapter.CacheItem(); expect(item.getMetadata()).toEqual({}); }); test('CacheItem.validateKey rejects non-strings, empty strings, and reserved characters', () => { expect(() => _ArrayAdapter.CacheItem.validateKey(42)).toThrow('Cache key must be string'); expect(() => _ArrayAdapter.CacheItem.validateKey('')).toThrow('Cache key length must be greater than zero'); for (let reserved of ["{", "}", "(", ")", "/", "\\", "@", ":"]) { expect(() => _ArrayAdapter.CacheItem.validateKey(`foo${reserved}bar`)).toThrow('contains reserved character'); } expect(_ArrayAdapter.CacheItem.validateKey('valid-key')).toBe('valid-key'); });