X-Git-Url: http://git.squeep.com/?p=squeep-lazy-property;a=blobdiff_plain;f=test%2Flazy.js;fp=test%2Flazy.js;h=85ef05b98ae2e3ac3de4e7c0fdd1c4fff292b838;hp=b95be17d00f6e31306228cc2459913a4dd2939bd;hb=7e55eb8f04aaa7d0d6a6c3de90313153a40800af;hpb=cde5aaf728595e10c50041e8b6deafe53f6b3eda diff --git a/test/lazy.js b/test/lazy.js index b95be17..85ef05b 100644 --- a/test/lazy.js +++ b/test/lazy.js @@ -1,4 +1,6 @@ /* eslint-env mocha */ +/* eslint-disable capitalized-comments */ +/* eslint-disable security/detect-object-injection */ 'use strict'; const assert = require('assert'); @@ -9,20 +11,20 @@ describe('lazy', function () { beforeEach(function () { o = {}; - called = false; + called = 0; initializer = () => { - called = true; + called += 1; return 'value'; }; }); it('does not initialize if not accessed', function () { lazy(o, 'p', initializer); - assert.strictEqual(called, false); + assert.strictEqual(called, 0); assert(Object.keys(o).includes('p')); }); - it('wants a callable initializer', function () { + it('requires a callable initializer', function () { try { lazy(o, 'p', undefined); assert.fail('should reject un-callable initializer'); @@ -31,18 +33,20 @@ describe('lazy', function () { } }); - it('initializes if accessed', function () { + it('initializes once when accessed', function () { lazy(o, 'p', initializer); const v = o.p; - assert.strictEqual(called, true); + const v2 = o.p; + assert.strictEqual(called, 1); assert.strictEqual(v, 'value'); + assert.strictEqual(v2, 'value'); }); it('handles symbolic properties', function () { const s = Symbol('s'); lazy(o, s, initializer); const v = o[s]; - assert.strictEqual(called, true); + assert.strictEqual(called, 1); assert.strictEqual(v, 'value'); }); @@ -52,7 +56,63 @@ describe('lazy', function () { o.p = expected; const v = o.p; assert.strictEqual(v, expected); - assert.strictEqual(called, false); + assert.strictEqual(called, 0); }); -}); // lazy + it('cannot be overwritten before being read if eventually not writable', function () { + lazy(o, 'p', initializer, { + writable: false, + }); + try { + o.p = 'nope'; + assert.fail('should disallow setting non-writable property'); + } catch (e) { + assert(e instanceof TypeError, `expected 'TypeError', got ${e.name}`); + } + }); + + it('async initializer awkwardly needs await on all gets but technically works', async function () { + lazy(o, 'p', async () => { + called += 1; + return 'value'; + }); + const v = await o.p; + assert.strictEqual(called, 1); + assert.strictEqual(v, 'value'); + }); + + it('prototypical lazy sets value on prototype by default', function () { + lazy(o, 'p', initializer); + o.id = 'proto'; + const o1 = Object.create(o); + o1.id = 'o1'; + const o2 = Object.create(o); + o2.id = 'o2'; + const v1 = o1.p; + const v2 = o2.p; + + assert.strictEqual(v1, 'value'); + assert.strictEqual(v2, 'value'); + assert.strictEqual(called, 1); + assert(!Object.hasOwnProperty.call(o1, 'p')); + assert(!Object.hasOwnProperty.call(o2, 'p')); + }); + + it('prototypical lazy sets value on inherited objects when requested', function () { + lazy(o, 'p', initializer, undefined, false); + o.id = 'proto'; + const o1 = Object.create(o); + o1.id = 'o1'; + const o2 = Object.create(o); + o2.id = 'o2'; + const v1 = o1.p; + const v2 = o2.p; + + assert.strictEqual(v1, 'value'); + assert.strictEqual(v2, 'value'); + assert.strictEqual(called, 2); + assert(Object.hasOwnProperty.call(o1, 'p')); + assert(Object.hasOwnProperty.call(o2, 'p')); + }); + +}); // lazy \ No newline at end of file