From ac37f9db30d997d64de069a7b3b53c3474bdc413 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Thu, 28 Sep 2023 18:29:33 -0300 Subject: test: reorganize data tests a lil --- .../composite/common-utilities/exposeConstant.js | 52 ++++ .../composite/common-utilities/exposeDependency.js | 74 +++++ .../withResultOfAvailabilityCheck.js | 226 ++++++++++++++ test/unit/data/composite/compositeFrom.js | 345 --------------------- test/unit/data/composite/exposeConstant.js | 52 ---- test/unit/data/composite/exposeDependency.js | 74 ----- test/unit/data/composite/templateCompositeFrom.js | 218 ------------- .../composite/withResultOfAvailabilityCheck.js | 226 -------------- 8 files changed, 352 insertions(+), 915 deletions(-) create mode 100644 test/unit/data/composite/common-utilities/exposeConstant.js create mode 100644 test/unit/data/composite/common-utilities/exposeDependency.js create mode 100644 test/unit/data/composite/common-utilities/withResultOfAvailabilityCheck.js delete mode 100644 test/unit/data/composite/compositeFrom.js delete mode 100644 test/unit/data/composite/exposeConstant.js delete mode 100644 test/unit/data/composite/exposeDependency.js delete mode 100644 test/unit/data/composite/templateCompositeFrom.js delete mode 100644 test/unit/data/composite/withResultOfAvailabilityCheck.js (limited to 'test/unit/data/composite') diff --git a/test/unit/data/composite/common-utilities/exposeConstant.js b/test/unit/data/composite/common-utilities/exposeConstant.js new file mode 100644 index 00000000..829dc706 --- /dev/null +++ b/test/unit/data/composite/common-utilities/exposeConstant.js @@ -0,0 +1,52 @@ +import t from 'tap'; + +import { + compositeFrom, + continuationSymbol, + exposeConstant, + input, +} from '#composite'; + +t.test(`exposeConstant: basic behavior`, t => { + t.plan(2); + + const composite1 = compositeFrom({ + compose: false, + + steps: [ + exposeConstant({ + value: input.value('foo'), + }), + ], + }); + + t.match(composite1, { + expose: { + dependencies: [], + }, + }); + + t.equal(composite1.expose.compute(), 'foo'); +}); + +t.test(`exposeConstant: validate inputs`, t => { + t.plan(2); + + t.throws( + () => exposeConstant({}), + { + message: `Errors in input options passed to exposeConstant`, + errors: [ + {message: `Required these inputs: value`}, + ], + }); + + t.throws( + () => exposeConstant({value: 'some dependency'}), + { + message: `Errors in input options passed to exposeConstant`, + errors: [ + {message: `value: Expected input.value() call, got dependency name`}, + ], + }); +}); diff --git a/test/unit/data/composite/common-utilities/exposeDependency.js b/test/unit/data/composite/common-utilities/exposeDependency.js new file mode 100644 index 00000000..78801343 --- /dev/null +++ b/test/unit/data/composite/common-utilities/exposeDependency.js @@ -0,0 +1,74 @@ +import t from 'tap'; + +import { + compositeFrom, + continuationSymbol, + exposeDependency, + input, +} from '#composite'; + +t.test(`exposeDependency: basic behavior`, t => { + t.plan(4); + + const composite1 = compositeFrom({ + compose: false, + + steps: [ + exposeDependency({dependency: 'foo'}), + ], + }); + + t.match(composite1, { + expose: { + dependencies: ['foo'], + }, + }); + + t.equal(composite1.expose.compute({foo: 'bar'}), 'bar'); + + const composite2 = compositeFrom({ + compose: false, + + steps: [ + { + dependencies: ['foo'], + compute: (continuation, {foo}) => + continuation({'#bar': foo.toUpperCase()}), + }, + + exposeDependency({dependency: '#bar'}), + ], + }); + + t.match(composite2, { + expose: { + dependencies: ['foo'], + }, + }); + + t.equal(composite2.expose.compute({foo: 'bar'}), 'BAR'); +}); + +t.test(`exposeDependency: validate inputs`, t => { + t.plan(2); + + t.throws( + () => exposeDependency({}), + { + message: `Errors in input options passed to exposeDependency`, + errors: [ + {message: `Required these inputs: dependency`}, + ], + }); + + t.throws( + () => exposeDependency({ + dependency: input.value('some static value'), + }), + { + message: `Errors in input options passed to exposeDependency`, + errors: [ + {message: `dependency: Expected dependency name, got input.value() call`}, + ], + }); +}); diff --git a/test/unit/data/composite/common-utilities/withResultOfAvailabilityCheck.js b/test/unit/data/composite/common-utilities/withResultOfAvailabilityCheck.js new file mode 100644 index 00000000..01220a3a --- /dev/null +++ b/test/unit/data/composite/common-utilities/withResultOfAvailabilityCheck.js @@ -0,0 +1,226 @@ +import t from 'tap'; + +import { + compositeFrom, + continuationSymbol, + withResultOfAvailabilityCheck, + input, +} from '#composite'; + +const composite = compositeFrom({ + compose: false, + + steps: [ + withResultOfAvailabilityCheck({ + from: 'from', + mode: 'mode', + }).outputs({ + ['#availability']: '#result', + }), + + { + dependencies: ['#result'], + compute: ({'#result': result}) => result, + }, + ], +}); + +t.test(`withResultOfAvailabilityCheck: basic behavior`, t => { + t.plan(1); + + t.match(composite, { + expose: { + dependencies: ['from', 'mode'], + }, + }); +}); + +const quickCompare = (t, expect, {from, mode}) => + t.equal(composite.expose.compute({from, mode}), expect); + +const quickThrows = (t, {from, mode}) => + t.throws(() => composite.expose.compute({from, mode})); + +t.test(`withResultOfAvailabilityCheck: mode = null`, t => { + t.plan(10); + + quickCompare(t, true, {mode: 'null', from: 'truthy string'}); + quickCompare(t, true, {mode: 'null', from: 123}); + quickCompare(t, true, {mode: 'null', from: true}); + + quickCompare(t, true, {mode: 'null', from: ''}); + quickCompare(t, true, {mode: 'null', from: 0}); + quickCompare(t, true, {mode: 'null', from: false}); + + quickCompare(t, true, {mode: 'null', from: [1, 2, 3]}); + quickCompare(t, true, {mode: 'null', from: []}); + + quickCompare(t, false, {mode: 'null', from: null}); + quickCompare(t, false, {mode: 'null', from: undefined}); +}); + +t.test(`withResultOfAvailabilityCheck: mode = empty`, t => { + t.plan(10); + + quickThrows(t, {mode: 'empty', from: 'truthy string'}); + quickThrows(t, {mode: 'empty', from: 123}); + quickThrows(t, {mode: 'empty', from: true}); + + quickThrows(t, {mode: 'empty', from: ''}); + quickThrows(t, {mode: 'empty', from: 0}); + quickThrows(t, {mode: 'empty', from: false}); + + quickCompare(t, true, {mode: 'empty', from: [1, 2, 3]}); + quickCompare(t, false, {mode: 'empty', from: []}); + + quickCompare(t, false, {mode: 'empty', from: null}); + quickCompare(t, false, {mode: 'empty', from: undefined}); +}); + +t.test(`withResultOfAvailabilityCheck: mode = falsy`, t => { + t.plan(10); + + quickCompare(t, true, {mode: 'falsy', from: 'truthy string'}); + quickCompare(t, true, {mode: 'falsy', from: 123}); + quickCompare(t, true, {mode: 'falsy', from: true}); + + quickCompare(t, false, {mode: 'falsy', from: ''}); + quickCompare(t, false, {mode: 'falsy', from: 0}); + quickCompare(t, false, {mode: 'falsy', from: false}); + + quickCompare(t, true, {mode: 'falsy', from: [1, 2, 3]}); + quickCompare(t, false, {mode: 'falsy', from: []}); + + quickCompare(t, false, {mode: 'falsy', from: null}); + quickCompare(t, false, {mode: 'falsy', from: undefined}); +}); + +t.test(`withResultOfAvailabilityCheck: default mode`, t => { + t.plan(1); + + const template = withResultOfAvailabilityCheck({ + from: 'foo', + }); + + t.match(template.toDescription(), { + inputMapping: { + from: input.dependency('foo'), + mode: input.value('null'), + }, + }); +}); + +t.test(`withResultOfAvailabilityCheck: validate static inputs`, t => { + t.plan(5); + + let caughtError; + + try { + caughtError = null; + withResultOfAvailabilityCheck({}); + } catch (error) { + caughtError = error; + } + + t.match(caughtError, { + errors: [/Required these inputs: from/], + }); + + t.doesNotThrow(() => + withResultOfAvailabilityCheck({ + from: 'dependency1', + mode: 'dependency2', + })); + + t.doesNotThrow(() => + withResultOfAvailabilityCheck({ + from: input.value('some static value'), + mode: input.value('null'), + })); + + try { + caughtError = null; + withResultOfAvailabilityCheck({ + from: 'foo', + mode: input.value('invalid'), + }); + } catch (error) { + caughtError = error; + } + + t.match(caughtError, { + message: /Errors in input options passed to withResultOfAvailabilityCheck/, + errors: [ + /mode: Expected one of null empty falsy, got invalid/, + ], + }); + + try { + caughtError = null; + withResultOfAvailabilityCheck({ + from: input.value(null), + mode: input.value(null), + }); + } catch (error) { + caughtError = error; + } + + t.match(caughtError, { + message: /Errors in input options passed to withResultOfAvailabilityCheck/, + errors: [ + /mode: Expected value, got null/, + ], + }); +}); + +t.test(`withResultOfAvailabilityCheck: validate dynamic inputs`, t => { + t.plan(2); + + let caughtError; + + try { + caughtError = null; + composite.expose.compute({ + from: 'apple', + mode: 'banana', + }); + } catch (error) { + caughtError = error; + } + + t.match(caughtError, { + message: /Error computing composition/, + cause: { + message: /Error computing composition withResultOfAvailabilityCheck/, + cause: { + message: /Errors in input values provided to withResultOfAvailabilityCheck/, + errors: [ + /mode: Expected one of null empty falsy, got banana/, + ], + }, + }, + }); + + try { + caughtError = null; + composite.expose.compute({ + from: null, + mode: null, + }); + } catch (error) { + caughtError = error; + } + + t.match(caughtError, { + message: /Error computing composition/, + cause: { + message: /Error computing composition withResultOfAvailabilityCheck/, + cause: { + message: /Errors in input values provided to withResultOfAvailabilityCheck/, + errors: [ + /mode: Expected value, got null/, + ], + }, + }, + }); +}); diff --git a/test/unit/data/composite/compositeFrom.js b/test/unit/data/composite/compositeFrom.js deleted file mode 100644 index 00296675..00000000 --- a/test/unit/data/composite/compositeFrom.js +++ /dev/null @@ -1,345 +0,0 @@ -import t from 'tap'; - -import {compositeFrom, continuationSymbol, input} from '#composite'; -import {isString} from '#validators'; - -t.test(`compositeFrom: basic behavior`, t => { - t.plan(2); - - const composite = compositeFrom({ - annotation: `myComposite`, - compose: false, - - steps: [ - { - dependencies: ['foo'], - compute: (continuation, {foo}) => - continuation({'#bar': foo * 2}), - }, - - { - dependencies: ['#bar', 'baz', 'suffix'], - compute: ({'#bar': bar, baz, suffix}) => - baz.repeat(bar) + suffix, - }, - ], - }); - - t.match(composite, { - annotation: `myComposite`, - - flags: {expose: true, compose: false, update: false}, - - expose: { - dependencies: ['foo', 'baz', 'suffix'], - compute: Function, - transform: null, - }, - - update: null, - }); - - t.equal( - composite.expose.compute({ - foo: 3, - baz: 'ba', - suffix: 'BOOM', - }), - 'babababababaBOOM'); -}); - -t.test(`compositeFrom: input-shaped step dependencies`, t => { - t.plan(2); - - const composite = compositeFrom({ - compose: false, - steps: [ - { - dependencies: [ - input.myself(), - input.updateValue(), - ], - - transform: (updateValue1, { - [input.myself()]: me, - [input.updateValue()]: updateValue2, - }) => ({me, updateValue1, updateValue2}), - }, - ], - }); - - t.match(composite, { - expose: { - dependencies: ['this'], - transform: Function, - compute: null, - }, - }); - - const myself = {foo: 'bar'}; - - t.same( - composite.expose.transform('banana', { - this: myself, - pomelo: 'delicious', - }), - { - me: myself, - updateValue1: 'banana', - updateValue2: 'banana', - }); -}); - -t.test(`compositeFrom: dependencies from inputs`, t => { - t.plan(3); - - const composite = compositeFrom({ - annotation: `myComposite`, - - compose: true, - - inputMapping: { - foo: input('bar'), - pomelo: input.value('delicious'), - humorous: input.dependency('#mammal'), - data: input.dependency('albumData'), - ref: input.updateValue(), - }, - - inputDescriptions: { - foo: input(), - pomelo: input(), - humorous: input(), - data: input(), - ref: input(), - }, - - steps: [ - { - dependencies: [ - input('foo'), - input('pomelo'), - input('humorous'), - input('data'), - input('ref'), - ], - - compute: (continuation, { - [input('foo')]: foo, - [input('pomelo')]: pomelo, - [input('humorous')]: humorous, - [input('data')]: data, - [input('ref')]: ref, - }) => continuation.exit({foo, pomelo, humorous, data, ref}), - }, - ], - }); - - t.match(composite, { - expose: { - dependencies: [ - input('bar'), - '#mammal', - 'albumData', - ], - - transform: Function, - compute: null, - }, - }); - - const exitData = {}; - const continuation = { - exit(value) { - Object.assign(exitData, value); - return continuationSymbol; - }, - }; - - t.equal( - composite.expose.transform('album:bepis', continuation, { - [input('bar')]: 'squid time', - '#mammal': 'fox', - 'albumData': ['album1', 'album2'], - }), - continuationSymbol); - - t.same(exitData, { - foo: 'squid time', - pomelo: 'delicious', - humorous: 'fox', - data: ['album1', 'album2'], - ref: 'album:bepis', - }); -}); - -t.test(`compositeFrom: update from various sources`, t => { - t.plan(3); - - const match = { - flags: {update: true, expose: true, compose: false}, - - update: { - validate: isString, - default: 'foo', - }, - - expose: { - transform: Function, - compute: null, - }, - }; - - t.test(`compositeFrom: update from composition description`, t => { - t.plan(2); - - const composite = compositeFrom({ - compose: false, - - update: { - validate: isString, - default: 'foo', - }, - - steps: [ - {transform: (value, continuation) => continuation(value.repeat(2))}, - {transform: (value) => `Xx_${value}_xX`}, - ], - }); - - t.match(composite, match); - t.equal(composite.expose.transform('foo'), `Xx_foofoo_xX`); - }); - - t.test(`compositeFrom: update from step dependencies`, t => { - t.plan(2); - - const composite = compositeFrom({ - compose: false, - - steps: [ - { - dependencies: [ - input.updateValue({ - validate: isString, - default: 'foo', - }), - ], - - compute: ({ - [input.updateValue()]: value, - }) => `Xx_${value.repeat(2)}_xX`, - }, - ], - }); - - t.match(composite, match); - t.equal(composite.expose.transform('foo'), 'Xx_foofoo_xX'); - }); - - t.test(`compositeFrom: update from inputs`, t => { - t.plan(3); - - const composite = compositeFrom({ - inputMapping: { - myInput: input.updateValue({ - validate: isString, - default: 'foo', - }), - }, - - inputDescriptions: { - myInput: input(), - }, - - steps: [ - { - dependencies: [input('myInput')], - compute: (continuation, { - [input('myInput')]: value, - }) => continuation({ - '#value': `Xx_${value.repeat(2)}_xX`, - }), - }, - - { - dependencies: ['#value'], - transform: (_value, continuation, {'#value': value}) => - continuation(value), - }, - ], - }); - - let continuationValue = null; - const continuation = value => { - continuationValue = value; - return continuationSymbol; - }; - - t.match(composite, { - ...match, - - flags: {update: true, expose: true, compose: true}, - }); - - t.equal( - composite.expose.transform('foo', continuation), - continuationSymbol); - - t.equal(continuationValue, 'Xx_foofoo_xX'); - }); -}); - -t.test(`compositeFrom: dynamic input validation from type`, t => { - t.plan(2); - - const composite = compositeFrom({ - inputMapping: { - string: input('string'), - number: input('number'), - boolean: input('boolean'), - function: input('function'), - object: input('object'), - array: input('array'), - }, - - inputDescriptions: { - string: input({null: true, type: 'string'}), - number: input({null: true, type: 'number'}), - boolean: input({null: true, type: 'boolean'}), - function: input({null: true, type: 'function'}), - object: input({null: true, type: 'object'}), - array: input({null: true, type: 'array'}), - }, - - outputs: {'#result': '#result'}, - - steps: [ - {compute: continuation => continuation({'#result': 'OK'})}, - ], - }); - - const notCalledSymbol = Symbol('continuation not called'); - - let continuationValue; - const continuation = value => { - continuationValue = value; - return continuationSymbol; - }; - - let thrownError; - - try { - continuationValue = notCalledSymbol; - thrownError = null; - composite.expose.compute(continuation, { - [input('string')]: 123, - }); - } catch (error) { - thrownError = error; - } - - t.equal(continuationValue, notCalledSymbol); - t.match(thrownError, { - }); -}); diff --git a/test/unit/data/composite/exposeConstant.js b/test/unit/data/composite/exposeConstant.js deleted file mode 100644 index 829dc706..00000000 --- a/test/unit/data/composite/exposeConstant.js +++ /dev/null @@ -1,52 +0,0 @@ -import t from 'tap'; - -import { - compositeFrom, - continuationSymbol, - exposeConstant, - input, -} from '#composite'; - -t.test(`exposeConstant: basic behavior`, t => { - t.plan(2); - - const composite1 = compositeFrom({ - compose: false, - - steps: [ - exposeConstant({ - value: input.value('foo'), - }), - ], - }); - - t.match(composite1, { - expose: { - dependencies: [], - }, - }); - - t.equal(composite1.expose.compute(), 'foo'); -}); - -t.test(`exposeConstant: validate inputs`, t => { - t.plan(2); - - t.throws( - () => exposeConstant({}), - { - message: `Errors in input options passed to exposeConstant`, - errors: [ - {message: `Required these inputs: value`}, - ], - }); - - t.throws( - () => exposeConstant({value: 'some dependency'}), - { - message: `Errors in input options passed to exposeConstant`, - errors: [ - {message: `value: Expected input.value() call, got dependency name`}, - ], - }); -}); diff --git a/test/unit/data/composite/exposeDependency.js b/test/unit/data/composite/exposeDependency.js deleted file mode 100644 index 78801343..00000000 --- a/test/unit/data/composite/exposeDependency.js +++ /dev/null @@ -1,74 +0,0 @@ -import t from 'tap'; - -import { - compositeFrom, - continuationSymbol, - exposeDependency, - input, -} from '#composite'; - -t.test(`exposeDependency: basic behavior`, t => { - t.plan(4); - - const composite1 = compositeFrom({ - compose: false, - - steps: [ - exposeDependency({dependency: 'foo'}), - ], - }); - - t.match(composite1, { - expose: { - dependencies: ['foo'], - }, - }); - - t.equal(composite1.expose.compute({foo: 'bar'}), 'bar'); - - const composite2 = compositeFrom({ - compose: false, - - steps: [ - { - dependencies: ['foo'], - compute: (continuation, {foo}) => - continuation({'#bar': foo.toUpperCase()}), - }, - - exposeDependency({dependency: '#bar'}), - ], - }); - - t.match(composite2, { - expose: { - dependencies: ['foo'], - }, - }); - - t.equal(composite2.expose.compute({foo: 'bar'}), 'BAR'); -}); - -t.test(`exposeDependency: validate inputs`, t => { - t.plan(2); - - t.throws( - () => exposeDependency({}), - { - message: `Errors in input options passed to exposeDependency`, - errors: [ - {message: `Required these inputs: dependency`}, - ], - }); - - t.throws( - () => exposeDependency({ - dependency: input.value('some static value'), - }), - { - message: `Errors in input options passed to exposeDependency`, - errors: [ - {message: `dependency: Expected dependency name, got input.value() call`}, - ], - }); -}); diff --git a/test/unit/data/composite/templateCompositeFrom.js b/test/unit/data/composite/templateCompositeFrom.js deleted file mode 100644 index e96b782e..00000000 --- a/test/unit/data/composite/templateCompositeFrom.js +++ /dev/null @@ -1,218 +0,0 @@ -import t from 'tap'; - -import {isString} from '#validators'; - -import { - compositeFrom, - continuationSymbol, - input, - templateCompositeFrom, -} from '#composite'; - -t.test(`templateCompositeFrom: basic behavior`, t => { - t.plan(1); - - const myCoolUtility = templateCompositeFrom({ - annotation: `myCoolUtility`, - - inputs: { - foo: input(), - }, - - outputs: ['#bar'], - - steps: () => [ - { - dependencies: [input('foo')], - compute: (continuation, { - [input('foo')]: foo, - }) => continuation({ - ['#bar']: (typeof foo).toUpperCase() - }), - }, - ], - }); - - const instantiatedTemplate = myCoolUtility({ - foo: 'color', - }); - - t.match(instantiatedTemplate.toDescription(), { - annotation: `myCoolUtility`, - - inputMapping: { - foo: input.dependency('color'), - }, - - inputDescriptions: { - foo: input(), - }, - - outputs: { - '#bar': '#bar', - }, - - steps: Function, - }); -}); - -t.test(`templateCompositeFrom: validate static input values`, t => { - t.plan(3); - - const stub = { - annotation: 'stubComposite', - outputs: ['#result'], - steps: () => [{compute: continuation => continuation({'#result': 'OK'})}], - }; - - const quickThrows = (t, composite, inputOptions, ...errorMessages) => - t.throws( - () => composite(inputOptions), - { - message: `Errors in input options passed to stubComposite`, - errors: errorMessages.map(message => ({message})), - }); - - t.test(`templateCompositeFrom: validate input token shapes`, t => { - t.plan(15); - - const template1 = templateCompositeFrom({ - ...stub, inputs: { - foo: input(), - }, - }); - - t.doesNotThrow( - () => template1({foo: 'dependency'})); - - t.doesNotThrow( - () => template1({foo: input.dependency('dependency')})); - - t.doesNotThrow( - () => template1({foo: input.value('static value')})); - - t.doesNotThrow( - () => template1({foo: input('outerInput')})); - - t.doesNotThrow( - () => template1({foo: input.updateValue()})); - - t.doesNotThrow( - () => template1({foo: input.myself()})); - - quickThrows(t, template1, - {foo: input.staticValue()}, - `foo: Expected dependency name or value-providing input() call, got input.staticValue`); - - quickThrows(t, template1, - {foo: input.staticDependency()}, - `foo: Expected dependency name or value-providing input() call, got input.staticDependency`); - - const template2 = templateCompositeFrom({ - ...stub, inputs: { - bar: input.staticDependency(), - }, - }); - - t.doesNotThrow( - () => template2({bar: 'dependency'})); - - t.doesNotThrow( - () => template2({bar: input.dependency('dependency')})); - - quickThrows(t, template2, - {bar: input.value(123)}, - `bar: Expected dependency name, got input.value`); - - quickThrows(t, template2, - {bar: input('outOfPlace')}, - `bar: Expected dependency name, got input`); - - const template3 = templateCompositeFrom({ - ...stub, inputs: { - baz: input.staticValue(), - }, - }); - - t.doesNotThrow( - () => template3({baz: input.value(1025)})); - - quickThrows(t, template3, - {baz: 'dependency'}, - `baz: Expected input.value() call, got dependency name`); - - quickThrows(t, template3, - {baz: input('outOfPlace')}, - `baz: Expected input.value() call, got input() call`); - }); - - t.test(`templateCompositeFrom: validate missing / misplaced inputs`, t => { - t.plan(1); - - const template = templateCompositeFrom({ - ...stub, inputs: { - foo: input(), - bar: input(), - }, - }); - - t.throws( - () => template({ - baz: 'aeiou', - raz: input.value(123), - }), - { - message: `Errors in input options passed to stubComposite`, - errors: [ - {message: `Unexpected input names: baz, raz`}, - {message: `Required these inputs: foo, bar`}, - ], - }); - }); - - t.test(`templateCompositeFrom: validate acceptsNull / defaultValue: null`, t => { - t.plan(3); - - const template1 = templateCompositeFrom({ - ...stub, inputs: { - foo: input(), - }, - }); - - t.throws( - () => template1({}), - { - message: `Errors in input options passed to stubComposite`, - errors: [ - {message: `Required these inputs: foo`}, - ], - }, - `throws if input missing and not marked specially`); - - const template2 = templateCompositeFrom({ - ...stub, inputs: { - bar: input({acceptsNull: true}), - }, - }); - - t.throws( - () => template2({}), - { - message: `Errors in input options passed to stubComposite`, - errors: [ - {message: `Required these inputs: bar`}, - ], - }, - `throws if input missing even if marked {acceptsNull}`); - - const template3 = templateCompositeFrom({ - ...stub, inputs: { - baz: input({defaultValue: null}), - }, - }); - - t.doesNotThrow( - () => template3({}), - `does not throw if input missing if marked {defaultValue: null}`); - }); -}); diff --git a/test/unit/data/composite/withResultOfAvailabilityCheck.js b/test/unit/data/composite/withResultOfAvailabilityCheck.js deleted file mode 100644 index 01220a3a..00000000 --- a/test/unit/data/composite/withResultOfAvailabilityCheck.js +++ /dev/null @@ -1,226 +0,0 @@ -import t from 'tap'; - -import { - compositeFrom, - continuationSymbol, - withResultOfAvailabilityCheck, - input, -} from '#composite'; - -const composite = compositeFrom({ - compose: false, - - steps: [ - withResultOfAvailabilityCheck({ - from: 'from', - mode: 'mode', - }).outputs({ - ['#availability']: '#result', - }), - - { - dependencies: ['#result'], - compute: ({'#result': result}) => result, - }, - ], -}); - -t.test(`withResultOfAvailabilityCheck: basic behavior`, t => { - t.plan(1); - - t.match(composite, { - expose: { - dependencies: ['from', 'mode'], - }, - }); -}); - -const quickCompare = (t, expect, {from, mode}) => - t.equal(composite.expose.compute({from, mode}), expect); - -const quickThrows = (t, {from, mode}) => - t.throws(() => composite.expose.compute({from, mode})); - -t.test(`withResultOfAvailabilityCheck: mode = null`, t => { - t.plan(10); - - quickCompare(t, true, {mode: 'null', from: 'truthy string'}); - quickCompare(t, true, {mode: 'null', from: 123}); - quickCompare(t, true, {mode: 'null', from: true}); - - quickCompare(t, true, {mode: 'null', from: ''}); - quickCompare(t, true, {mode: 'null', from: 0}); - quickCompare(t, true, {mode: 'null', from: false}); - - quickCompare(t, true, {mode: 'null', from: [1, 2, 3]}); - quickCompare(t, true, {mode: 'null', from: []}); - - quickCompare(t, false, {mode: 'null', from: null}); - quickCompare(t, false, {mode: 'null', from: undefined}); -}); - -t.test(`withResultOfAvailabilityCheck: mode = empty`, t => { - t.plan(10); - - quickThrows(t, {mode: 'empty', from: 'truthy string'}); - quickThrows(t, {mode: 'empty', from: 123}); - quickThrows(t, {mode: 'empty', from: true}); - - quickThrows(t, {mode: 'empty', from: ''}); - quickThrows(t, {mode: 'empty', from: 0}); - quickThrows(t, {mode: 'empty', from: false}); - - quickCompare(t, true, {mode: 'empty', from: [1, 2, 3]}); - quickCompare(t, false, {mode: 'empty', from: []}); - - quickCompare(t, false, {mode: 'empty', from: null}); - quickCompare(t, false, {mode: 'empty', from: undefined}); -}); - -t.test(`withResultOfAvailabilityCheck: mode = falsy`, t => { - t.plan(10); - - quickCompare(t, true, {mode: 'falsy', from: 'truthy string'}); - quickCompare(t, true, {mode: 'falsy', from: 123}); - quickCompare(t, true, {mode: 'falsy', from: true}); - - quickCompare(t, false, {mode: 'falsy', from: ''}); - quickCompare(t, false, {mode: 'falsy', from: 0}); - quickCompare(t, false, {mode: 'falsy', from: false}); - - quickCompare(t, true, {mode: 'falsy', from: [1, 2, 3]}); - quickCompare(t, false, {mode: 'falsy', from: []}); - - quickCompare(t, false, {mode: 'falsy', from: null}); - quickCompare(t, false, {mode: 'falsy', from: undefined}); -}); - -t.test(`withResultOfAvailabilityCheck: default mode`, t => { - t.plan(1); - - const template = withResultOfAvailabilityCheck({ - from: 'foo', - }); - - t.match(template.toDescription(), { - inputMapping: { - from: input.dependency('foo'), - mode: input.value('null'), - }, - }); -}); - -t.test(`withResultOfAvailabilityCheck: validate static inputs`, t => { - t.plan(5); - - let caughtError; - - try { - caughtError = null; - withResultOfAvailabilityCheck({}); - } catch (error) { - caughtError = error; - } - - t.match(caughtError, { - errors: [/Required these inputs: from/], - }); - - t.doesNotThrow(() => - withResultOfAvailabilityCheck({ - from: 'dependency1', - mode: 'dependency2', - })); - - t.doesNotThrow(() => - withResultOfAvailabilityCheck({ - from: input.value('some static value'), - mode: input.value('null'), - })); - - try { - caughtError = null; - withResultOfAvailabilityCheck({ - from: 'foo', - mode: input.value('invalid'), - }); - } catch (error) { - caughtError = error; - } - - t.match(caughtError, { - message: /Errors in input options passed to withResultOfAvailabilityCheck/, - errors: [ - /mode: Expected one of null empty falsy, got invalid/, - ], - }); - - try { - caughtError = null; - withResultOfAvailabilityCheck({ - from: input.value(null), - mode: input.value(null), - }); - } catch (error) { - caughtError = error; - } - - t.match(caughtError, { - message: /Errors in input options passed to withResultOfAvailabilityCheck/, - errors: [ - /mode: Expected value, got null/, - ], - }); -}); - -t.test(`withResultOfAvailabilityCheck: validate dynamic inputs`, t => { - t.plan(2); - - let caughtError; - - try { - caughtError = null; - composite.expose.compute({ - from: 'apple', - mode: 'banana', - }); - } catch (error) { - caughtError = error; - } - - t.match(caughtError, { - message: /Error computing composition/, - cause: { - message: /Error computing composition withResultOfAvailabilityCheck/, - cause: { - message: /Errors in input values provided to withResultOfAvailabilityCheck/, - errors: [ - /mode: Expected one of null empty falsy, got banana/, - ], - }, - }, - }); - - try { - caughtError = null; - composite.expose.compute({ - from: null, - mode: null, - }); - } catch (error) { - caughtError = error; - } - - t.match(caughtError, { - message: /Error computing composition/, - cause: { - message: /Error computing composition withResultOfAvailabilityCheck/, - cause: { - message: /Errors in input values provided to withResultOfAvailabilityCheck/, - errors: [ - /mode: Expected value, got null/, - ], - }, - }, - }); -}); -- cgit 1.3.0-6-gf8a5