object-boolean-combinations3.0.0

Consumes a defaults object with booleans, generates all possible variations of it

§ Quick Take

import { strict as assert } from "assert";
import combinations from "object-boolean-combinations";

assert.deepEqual(
  combinations({
    a: true,
    b: false,
    c: true,
  }),
  [
    { a: false, b: false, c: false },
    { a: true, b: false, c: false },
    { a: false, b: true, c: false },
    { a: true, b: true, c: false },
    { a: false, b: false, c: true },
    { a: true, b: false, c: true },
    { a: false, b: true, c: true },
    { a: true, b: true, c: true },
  ]
);
// you get 2^n plain objects in an array

§ Purpose

It's used to generate an array of all possible variations, 2^n, of n boolean options object keys.

Input (key values don't matter as long as key are booleans):

{
"oodles": true,
"crambles": false
}

Output:

[
{
"oodles": true,
"crambles": true
},
{
"oodles": true,
"crambles": false
},
{
"oodles": false,
"crambles": true
},
{
"oodles": false,
"crambles": false
}
]

detergent has 12 boolean toggles — that's 2^12 = 4096 variations to test for each input.

string-collapse-white-space has 6 boolean toggles — that's 2^6 = 64 variations to test.

And so on.

Our packages don't use this library directly, there is a higher-level package test-mixer which takes into account non-boolean keys and uses this package to generate variations of boolean keys only, then restores the other keys.

§ API - Input

combinations(
  inputObject,
  [overrideObject]
)

In other words, it's a function which takes two input arguments, second one being optional (marked by square brackets).

Input argumentTypeObligatory?Description
inputObjectPlain objectyesPlain object from which we should reference the keys.
overrideObjectPlain objectnoKeys in this object will be used as-is and will not be used for generating combinations. See overriding section below.

§ API - Output

Program returns an array of plain objects.

§ Overriding

Sometimes you want to override the object keys, for example, in the a settings object, we want to override all a and b keys to be only true (1). This reduces the object combinations from 2^3 = 8 to: 2^(3-2) = 2^1 = 2:

const combinations = require("object-boolean-combinations");
const test = combinations(
{ a: false, b: false, c: false },
{ a: true, b: true } // <----- Override. These values will be on all combinations.
);
console.log(`test = ${JSON.stringify(test, null, 4)}`);
// => [
// {a: true, b: true, c: false},
// {a: true, b: true, c: true}
// ]

In example above, a and b are "pinned" to 1, thus reducing the amount of combinations by power of two, essentially halving resulting objects count twice. Notice how only c is having variations.

§ Overriding the combinations — in practice

In practice, we use this overriding to perform the specific tests on Detergent.js. For example, let's say, we are testing: does Detergent encode entities correctly. In that case we need two arrays filled with objects:

  • first array — encodeEntities = true and all possible combinations of the other 9 settings (2^(10-1)=512 objects in array)
  • second array — encodeEntities = false and all possible combinations of the rest — again 512 objects in array.

Here's a unit test which uses objectBooleanCombinations() to create a combinations array of settings objects, then uses forEach() to iterate through them all, testing each:

test("encode entities - pound sign", (t) => {
combinations(sampleObj, {
convertEntities: true,
}).forEach(function (elem) {
t.equal(
detergent("\u00A3", elem),
"&pound;",
"pound char converted into entity"
);
});
});

§ Changelog

See it in the monorepo opens in a new tab, on Sourcehut.

§ Licence

MIT opens in a new tab

Copyright © 2010–2020 Roy Revelt and other contributors

Related packages:

📦 test-mixer 1.0.1
Test helper to generate function opts object variations
📦 ast-monkey 7.12.1
Traverse and edit AST
📦 ast-monkey-traverse 1.13.1
Utility library to traverse AST
📦 ast-monkey-util 1.2.0
Utility library of AST helper functions
📦 json-comb-core 6.7.1
The inner core of json-comb
📦 json-variables 9.0.3
Resolves custom-marked, cross-referenced paths in parsed JSON
📦 object-merge-advanced 10.12.1
Recursive, deep merge of anything (objects, arrays, strings or nested thereof), which weighs contents by type hierarchy to ensure the maximum content is retained