diff options
-rw-r--r-- | src/data/composite/data/withPropertyFromObject.js | 28 | ||||
-rw-r--r-- | test/unit/data/composite/data/withPropertyFromObject.js | 84 |
2 files changed, 108 insertions, 4 deletions
diff --git a/src/data/composite/data/withPropertyFromObject.js b/src/data/composite/data/withPropertyFromObject.js index b31bab15..4f240506 100644 --- a/src/data/composite/data/withPropertyFromObject.js +++ b/src/data/composite/data/withPropertyFromObject.js @@ -2,11 +2,15 @@ // If the object itself is null, or the object doesn't have the listed property, // the provided dependency will also be null. // +// If the `internal` input is true, this reads the CacheableObject update value +// of the object rather than its exposed value. +// // See also: // - withPropertiesFromObject // - withPropertyFromList // +import CacheableObject from '#cacheable-object'; import {input, templateCompositeFrom} from '#composite'; export default templateCompositeFrom({ @@ -15,6 +19,7 @@ export default templateCompositeFrom({ inputs: { object: input({type: 'object', acceptsNull: true}), property: input({type: 'string'}), + internal: input({type: 'boolean', defaultValue: false}), }, outputs: ({ @@ -49,20 +54,35 @@ export default templateCompositeFrom({ { dependencies: [ - '#output', input('object'), input('property'), + input('internal'), ], compute: (continuation, { - ['#output']: output, [input('object')]: object, [input('property')]: property, + [input('internal')]: internal, }) => continuation({ - [output]: + '#value': (object === null ? null - : object[property] ?? null), + : internal + ? CacheableObject.getUpdateValue(object, property) + ?? null + : object[property] + ?? null), + }), + }, + + { + dependencies: ['#output', '#value'], + + compute: (continuation, { + ['#output']: output, + ['#value']: value, + }) => continuation({ + [output]: value, }), }, ], diff --git a/test/unit/data/composite/data/withPropertyFromObject.js b/test/unit/data/composite/data/withPropertyFromObject.js index 50ee835c..912c924c 100644 --- a/test/unit/data/composite/data/withPropertyFromObject.js +++ b/test/unit/data/composite/data/withPropertyFromObject.js @@ -1,6 +1,7 @@ import t from 'tap'; import {quickCheckCompositeOutputs} from '#test-lib'; +import CacheableObject from '#cacheable-object'; import {compositeFrom, input} from '#composite'; import {exposeDependency} from '#composite/control-flow'; import {withPropertyFromObject} from '#composite/data'; @@ -43,6 +44,89 @@ t.test(`withPropertyFromObject: basic behavior`, t => { }), null); }); +t.test(`withPropertyFromObject: "internal" input`, t => { + t.plan(7); + + const composite = compositeFrom({ + compose: false, + + steps: [ + withPropertyFromObject({ + object: 'object', + property: 'property', + internal: 'internal', + }), + + exposeDependency({dependency: '#value'}), + ], + }); + + const thing = new (class extends CacheableObject { + static [CacheableObject.propertyDescriptors] = { + foo: { + flags: {update: true, expose: false}, + }, + + bar: { + flags: {update: true, expose: true}, + }, + + baz: { + flags: {update: true, expose: true}, + expose: { + transform: baz => baz * 2, + }, + }, + }; + }); + + thing.foo = 100; + thing.bar = 200; + thing.baz = 300; + + t.match(composite, { + expose: { + dependencies: ['object', 'property', 'internal'], + }, + }); + + t.equal(composite.expose.compute({ + object: thing, + property: 'foo', + internal: true, + }), 100); + + t.equal(composite.expose.compute({ + object: thing, + property: 'bar', + internal: true, + }), 200); + + t.equal(composite.expose.compute({ + object: thing, + property: 'baz', + internal: true, + }), 300); + + t.equal(composite.expose.compute({ + object: thing, + property: 'baz', + internal: false, + }), 600); + + t.equal(composite.expose.compute({ + object: thing, + property: 'bimbam', + internal: false, + }), null); + + t.equal(composite.expose.compute({ + object: null, + property: 'bambim', + internal: false, + }), null); +}); + t.test(`withPropertyFromObject: output shapes & values`, t => { t.plan(2 * 3 ** 2); |