Merge branch 'develop' into travis/error-states
This commit is contained in:
commit
82119ad595
36 changed files with 1724 additions and 191 deletions
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {Singleflight} from "../src/utils/Singleflight";
|
||||
import {Singleflight} from "../../src/utils/Singleflight";
|
||||
|
||||
describe('Singleflight', () => {
|
||||
afterEach(() => {
|
294
test/utils/arrays-test.ts
Normal file
294
test/utils/arrays-test.ts
Normal file
|
@ -0,0 +1,294 @@
|
|||
/*
|
||||
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
arrayDiff,
|
||||
arrayFastClone,
|
||||
arrayFastResample,
|
||||
arrayHasDiff,
|
||||
arrayHasOrderChange,
|
||||
arrayMerge,
|
||||
arraySeed,
|
||||
arrayUnion,
|
||||
ArrayUtil,
|
||||
GroupedArray,
|
||||
} from "../../src/utils/arrays";
|
||||
import {objectFromEntries} from "../../src/utils/objects";
|
||||
|
||||
function expectSample(i: number, input: number[], expected: number[]) {
|
||||
console.log(`Resample case index: ${i}`); // for debugging test failures
|
||||
const result = arrayFastResample(input, expected.length);
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toHaveLength(expected.length);
|
||||
expect(result).toEqual(expected);
|
||||
}
|
||||
|
||||
describe('arrays', () => {
|
||||
describe('arrayFastResample', () => {
|
||||
it('should downsample', () => {
|
||||
[
|
||||
{input: [1, 2, 3, 4, 5], output: [1, 4]}, // Odd -> Even
|
||||
{input: [1, 2, 3, 4, 5], output: [1, 3, 5]}, // Odd -> Odd
|
||||
{input: [1, 2, 3, 4], output: [1, 2, 3]}, // Even -> Odd
|
||||
{input: [1, 2, 3, 4], output: [1, 3]}, // Even -> Even
|
||||
].forEach((c, i) => expectSample(i, c.input, c.output));
|
||||
});
|
||||
|
||||
it('should upsample', () => {
|
||||
[
|
||||
{input: [1, 2, 3], output: [1, 1, 2, 2, 3, 3]}, // Odd -> Even
|
||||
{input: [1, 2, 3], output: [1, 1, 2, 2, 3]}, // Odd -> Odd
|
||||
{input: [1, 2], output: [1, 1, 1, 2, 2]}, // Even -> Odd
|
||||
{input: [1, 2], output: [1, 1, 1, 2, 2, 2]}, // Even -> Even
|
||||
].forEach((c, i) => expectSample(i, c.input, c.output));
|
||||
});
|
||||
|
||||
it('should maintain sample', () => {
|
||||
[
|
||||
{input: [1, 2, 3], output: [1, 2, 3]}, // Odd
|
||||
{input: [1, 2], output: [1, 2]}, // Even
|
||||
].forEach((c, i) => expectSample(i, c.input, c.output));
|
||||
});
|
||||
});
|
||||
|
||||
describe('arraySeed', () => {
|
||||
it('should create an array of given length', () => {
|
||||
const val = 1;
|
||||
const output = [val, val, val];
|
||||
const result = arraySeed(val, output.length);
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toHaveLength(output.length);
|
||||
expect(result).toEqual(output);
|
||||
});
|
||||
it('should maintain pointers', () => {
|
||||
const val = {}; // this works because `{} !== {}`, which is what toEqual checks
|
||||
const output = [val, val, val];
|
||||
const result = arraySeed(val, output.length);
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toHaveLength(output.length);
|
||||
expect(result).toEqual(output);
|
||||
});
|
||||
});
|
||||
|
||||
describe('arrayFastClone', () => {
|
||||
it('should break pointer reference on source array', () => {
|
||||
const val = {}; // we'll test to make sure the values maintain pointers too
|
||||
const input = [val, val, val];
|
||||
const result = arrayFastClone(input);
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toHaveLength(input.length);
|
||||
expect(result).toEqual(input); // we want the array contents to match...
|
||||
expect(result).not.toBe(input); // ... but be a different reference
|
||||
});
|
||||
});
|
||||
|
||||
describe('arrayHasOrderChange', () => {
|
||||
it('should flag true on B ordering difference', () => {
|
||||
const a = [1, 2, 3];
|
||||
const b = [3, 2, 1];
|
||||
const result = arrayHasOrderChange(a, b);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should flag false on no ordering difference', () => {
|
||||
const a = [1, 2, 3];
|
||||
const b = [1, 2, 3];
|
||||
const result = arrayHasOrderChange(a, b);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should flag true on A length > B length', () => {
|
||||
const a = [1, 2, 3, 4];
|
||||
const b = [1, 2, 3];
|
||||
const result = arrayHasOrderChange(a, b);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should flag true on A length < B length', () => {
|
||||
const a = [1, 2, 3];
|
||||
const b = [1, 2, 3, 4];
|
||||
const result = arrayHasOrderChange(a, b);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('arrayHasDiff', () => {
|
||||
it('should flag true on A length > B length', () => {
|
||||
const a = [1, 2, 3, 4];
|
||||
const b = [1, 2, 3];
|
||||
const result = arrayHasDiff(a, b);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should flag true on A length < B length', () => {
|
||||
const a = [1, 2, 3];
|
||||
const b = [1, 2, 3, 4];
|
||||
const result = arrayHasDiff(a, b);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should flag true on element differences', () => {
|
||||
const a = [1, 2, 3];
|
||||
const b = [4, 5, 6];
|
||||
const result = arrayHasDiff(a, b);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should flag false if same but order different', () => {
|
||||
const a = [1, 2, 3];
|
||||
const b = [3, 1, 2];
|
||||
const result = arrayHasDiff(a, b);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should flag false if same', () => {
|
||||
const a = [1, 2, 3];
|
||||
const b = [1, 2, 3];
|
||||
const result = arrayHasDiff(a, b);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('arrayDiff', () => {
|
||||
it('should see added from A->B', () => {
|
||||
const a = [1, 2, 3];
|
||||
const b = [1, 2, 3, 4];
|
||||
const result = arrayDiff(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result.added).toBeDefined();
|
||||
expect(result.removed).toBeDefined();
|
||||
expect(result.added).toHaveLength(1);
|
||||
expect(result.removed).toHaveLength(0);
|
||||
expect(result.added).toEqual([4]);
|
||||
});
|
||||
|
||||
it('should see removed from A->B', () => {
|
||||
const a = [1, 2, 3];
|
||||
const b = [1, 2];
|
||||
const result = arrayDiff(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result.added).toBeDefined();
|
||||
expect(result.removed).toBeDefined();
|
||||
expect(result.added).toHaveLength(0);
|
||||
expect(result.removed).toHaveLength(1);
|
||||
expect(result.removed).toEqual([3]);
|
||||
});
|
||||
|
||||
it('should see added and removed in the same set', () => {
|
||||
const a = [1, 2, 3];
|
||||
const b = [1, 2, 4]; // note diff
|
||||
const result = arrayDiff(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result.added).toBeDefined();
|
||||
expect(result.removed).toBeDefined();
|
||||
expect(result.added).toHaveLength(1);
|
||||
expect(result.removed).toHaveLength(1);
|
||||
expect(result.added).toEqual([4]);
|
||||
expect(result.removed).toEqual([3]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('arrayUnion', () => {
|
||||
it('should return a union', () => {
|
||||
const a = [1, 2, 3];
|
||||
const b = [1, 2, 4]; // note diff
|
||||
const result = arrayUnion(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toHaveLength(2);
|
||||
expect(result).toEqual([1, 2]);
|
||||
});
|
||||
|
||||
it('should return an empty array on no matches', () => {
|
||||
const a = [1, 2, 3];
|
||||
const b = [4, 5, 6];
|
||||
const result = arrayUnion(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('arrayMerge', () => {
|
||||
it('should merge 3 arrays with deduplication', () => {
|
||||
const a = [1, 2, 3];
|
||||
const b = [1, 2, 4, 5]; // note missing 3
|
||||
const c = [6, 7, 8, 9];
|
||||
const result = arrayMerge(a, b, c);
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toHaveLength(9);
|
||||
expect(result).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
||||
});
|
||||
|
||||
it('should deduplicate a single array', () => {
|
||||
// dev note: this is technically an edge case, but it is described behaviour if the
|
||||
// function is only provided one function (it'll merge the array against itself)
|
||||
const a = [1, 1, 2, 2, 3, 3];
|
||||
const result = arrayMerge(a);
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toHaveLength(3);
|
||||
expect(result).toEqual([1, 2, 3]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ArrayUtil', () => {
|
||||
it('should maintain the pointer to the given array', () => {
|
||||
const input = [1, 2, 3];
|
||||
const result = new ArrayUtil(input);
|
||||
expect(result.value).toBe(input);
|
||||
});
|
||||
|
||||
it('should group appropriately', () => {
|
||||
const input = [['a', 1], ['b', 2], ['c', 3], ['a', 4], ['a', 5], ['b', 6]];
|
||||
const output = {
|
||||
'a': [['a', 1], ['a', 4], ['a', 5]],
|
||||
'b': [['b', 2], ['b', 6]],
|
||||
'c': [['c', 3]],
|
||||
};
|
||||
const result = new ArrayUtil(input).groupBy(p => p[0]);
|
||||
expect(result).toBeDefined();
|
||||
expect(result.value).toBeDefined();
|
||||
|
||||
const asObject = objectFromEntries(result.value.entries());
|
||||
expect(asObject).toMatchObject(output);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GroupedArray', () => {
|
||||
it('should maintain the pointer to the given map', () => {
|
||||
const input = new Map([
|
||||
['a', [1, 2, 3]],
|
||||
['b', [7, 8, 9]],
|
||||
['c', [4, 5, 6]],
|
||||
]);
|
||||
const result = new GroupedArray(input);
|
||||
expect(result.value).toBe(input);
|
||||
});
|
||||
|
||||
it('should ordering by the provided key order', () => {
|
||||
const input = new Map([
|
||||
['a', [1, 2, 3]],
|
||||
['b', [7, 8, 9]], // note counting diff
|
||||
['c', [4, 5, 6]],
|
||||
]);
|
||||
const output = [4, 5, 6, 1, 2, 3, 7, 8, 9];
|
||||
const keyOrder = ['c', 'a', 'b']; // note weird order to cause the `output` to be strange
|
||||
const result = new GroupedArray(input).orderBy(keyOrder);
|
||||
expect(result).toBeDefined();
|
||||
expect(result.value).toBeDefined();
|
||||
expect(result.value).toEqual(output);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
67
test/utils/enums-test.ts
Normal file
67
test/utils/enums-test.ts
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {getEnumValues, isEnumValue} from "../../src/utils/enums";
|
||||
|
||||
enum TestStringEnum {
|
||||
First = "__first__",
|
||||
Second = "__second__",
|
||||
}
|
||||
|
||||
enum TestNumberEnum {
|
||||
FirstKey = 10,
|
||||
SecondKey = 20,
|
||||
}
|
||||
|
||||
describe('enums', () => {
|
||||
describe('getEnumValues', () => {
|
||||
it('should work on string enums', () => {
|
||||
const result = getEnumValues(TestStringEnum);
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toHaveLength(2);
|
||||
expect(result).toEqual(['__first__', '__second__']);
|
||||
});
|
||||
|
||||
it('should work on number enums', () => {
|
||||
const result = getEnumValues(TestNumberEnum);
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toHaveLength(2);
|
||||
expect(result).toEqual([10, 20]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isEnumValue', () => {
|
||||
it('should return true on values in a string enum', () => {
|
||||
const result = isEnumValue(TestStringEnum, '__first__');
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false on values not in a string enum', () => {
|
||||
const result = isEnumValue(TestStringEnum, 'not a value');
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true on values in a number enum', () => {
|
||||
const result = isEnumValue(TestNumberEnum, 10);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false on values not in a number enum', () => {
|
||||
const result = isEnumValue(TestStringEnum, 99);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
77
test/utils/iterables-test.ts
Normal file
77
test/utils/iterables-test.ts
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {iterableDiff, iterableUnion} from "../../src/utils/iterables";
|
||||
|
||||
describe('iterables', () => {
|
||||
describe('iterableUnion', () => {
|
||||
it('should return a union', () => {
|
||||
const a = [1, 2, 3];
|
||||
const b = [1, 2, 4]; // note diff
|
||||
const result = iterableUnion(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toHaveLength(2);
|
||||
expect(result).toEqual([1, 2]);
|
||||
});
|
||||
|
||||
it('should return an empty array on no matches', () => {
|
||||
const a = [1, 2, 3];
|
||||
const b = [4, 5, 6];
|
||||
const result = iterableUnion(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('iterableDiff', () => {
|
||||
it('should see added from A->B', () => {
|
||||
const a = [1, 2, 3];
|
||||
const b = [1, 2, 3, 4];
|
||||
const result = iterableDiff(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result.added).toBeDefined();
|
||||
expect(result.removed).toBeDefined();
|
||||
expect(result.added).toHaveLength(1);
|
||||
expect(result.removed).toHaveLength(0);
|
||||
expect(result.added).toEqual([4]);
|
||||
});
|
||||
|
||||
it('should see removed from A->B', () => {
|
||||
const a = [1, 2, 3];
|
||||
const b = [1, 2];
|
||||
const result = iterableDiff(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result.added).toBeDefined();
|
||||
expect(result.removed).toBeDefined();
|
||||
expect(result.added).toHaveLength(0);
|
||||
expect(result.removed).toHaveLength(1);
|
||||
expect(result.removed).toEqual([3]);
|
||||
});
|
||||
|
||||
it('should see added and removed in the same set', () => {
|
||||
const a = [1, 2, 3];
|
||||
const b = [1, 2, 4]; // note diff
|
||||
const result = iterableDiff(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result.added).toBeDefined();
|
||||
expect(result.removed).toBeDefined();
|
||||
expect(result.added).toHaveLength(1);
|
||||
expect(result.removed).toHaveLength(1);
|
||||
expect(result.added).toEqual([4]);
|
||||
expect(result.removed).toEqual([3]);
|
||||
});
|
||||
});
|
||||
});
|
245
test/utils/maps-test.ts
Normal file
245
test/utils/maps-test.ts
Normal file
|
@ -0,0 +1,245 @@
|
|||
/*
|
||||
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {EnhancedMap, mapDiff, mapKeyChanges} from "../../src/utils/maps";
|
||||
|
||||
describe('maps', () => {
|
||||
describe('mapDiff', () => {
|
||||
it('should indicate no differences when the pointers are the same', () => {
|
||||
const a = new Map([[1, 1], [2, 2], [3, 3]]);
|
||||
const result = mapDiff(a, a);
|
||||
expect(result).toBeDefined();
|
||||
expect(result.added).toBeDefined();
|
||||
expect(result.removed).toBeDefined();
|
||||
expect(result.changed).toBeDefined();
|
||||
expect(result.added).toHaveLength(0);
|
||||
expect(result.removed).toHaveLength(0);
|
||||
expect(result.changed).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should indicate no differences when there are none', () => {
|
||||
const a = new Map([[1, 1], [2, 2], [3, 3]]);
|
||||
const b = new Map([[1, 1], [2, 2], [3, 3]]);
|
||||
const result = mapDiff(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result.added).toBeDefined();
|
||||
expect(result.removed).toBeDefined();
|
||||
expect(result.changed).toBeDefined();
|
||||
expect(result.added).toHaveLength(0);
|
||||
expect(result.removed).toHaveLength(0);
|
||||
expect(result.changed).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should indicate added properties', () => {
|
||||
const a = new Map([[1, 1], [2, 2], [3, 3]]);
|
||||
const b = new Map([[1, 1], [2, 2], [3, 3], [4, 4]]);
|
||||
const result = mapDiff(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result.added).toBeDefined();
|
||||
expect(result.removed).toBeDefined();
|
||||
expect(result.changed).toBeDefined();
|
||||
expect(result.added).toHaveLength(1);
|
||||
expect(result.removed).toHaveLength(0);
|
||||
expect(result.changed).toHaveLength(0);
|
||||
expect(result.added).toEqual([4]);
|
||||
});
|
||||
|
||||
it('should indicate removed properties', () => {
|
||||
const a = new Map([[1, 1], [2, 2], [3, 3]]);
|
||||
const b = new Map([[1, 1], [2, 2]]);
|
||||
const result = mapDiff(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result.added).toBeDefined();
|
||||
expect(result.removed).toBeDefined();
|
||||
expect(result.changed).toBeDefined();
|
||||
expect(result.added).toHaveLength(0);
|
||||
expect(result.removed).toHaveLength(1);
|
||||
expect(result.changed).toHaveLength(0);
|
||||
expect(result.removed).toEqual([3]);
|
||||
});
|
||||
|
||||
it('should indicate changed properties', () => {
|
||||
const a = new Map([[1, 1], [2, 2], [3, 3]]);
|
||||
const b = new Map([[1, 1], [2, 2], [3, 4]]); // note change
|
||||
const result = mapDiff(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result.added).toBeDefined();
|
||||
expect(result.removed).toBeDefined();
|
||||
expect(result.changed).toBeDefined();
|
||||
expect(result.added).toHaveLength(0);
|
||||
expect(result.removed).toHaveLength(0);
|
||||
expect(result.changed).toHaveLength(1);
|
||||
expect(result.changed).toEqual([3]);
|
||||
});
|
||||
|
||||
it('should indicate changed, added, and removed properties', () => {
|
||||
const a = new Map([[1, 1], [2, 2], [3, 3]]);
|
||||
const b = new Map([[1, 1], [2, 8], [4, 4]]); // note change
|
||||
const result = mapDiff(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result.added).toBeDefined();
|
||||
expect(result.removed).toBeDefined();
|
||||
expect(result.changed).toBeDefined();
|
||||
expect(result.added).toHaveLength(1);
|
||||
expect(result.removed).toHaveLength(1);
|
||||
expect(result.changed).toHaveLength(1);
|
||||
expect(result.added).toEqual([4]);
|
||||
expect(result.removed).toEqual([3]);
|
||||
expect(result.changed).toEqual([2]);
|
||||
});
|
||||
|
||||
it('should indicate changes for difference in pointers', () => {
|
||||
const a = new Map([[1, {}]]); // {} always creates a new object
|
||||
const b = new Map([[1, {}]]);
|
||||
const result = mapDiff(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result.added).toBeDefined();
|
||||
expect(result.removed).toBeDefined();
|
||||
expect(result.changed).toBeDefined();
|
||||
expect(result.added).toHaveLength(0);
|
||||
expect(result.removed).toHaveLength(0);
|
||||
expect(result.changed).toHaveLength(1);
|
||||
expect(result.changed).toEqual([1]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('mapKeyChanges', () => {
|
||||
it('should indicate no changes for unchanged pointers', () => {
|
||||
const a = new Map([[1, 1], [2, 2], [3, 3]]);
|
||||
const result = mapKeyChanges(a, a);
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should indicate no changes for unchanged maps with different pointers', () => {
|
||||
const a = new Map([[1, 1], [2, 2], [3, 3]]);
|
||||
const b = new Map([[1, 1], [2, 2], [3, 3]]);
|
||||
const result = mapKeyChanges(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should indicate changes for added properties', () => {
|
||||
const a = new Map([[1, 1], [2, 2], [3, 3]]);
|
||||
const b = new Map([[1, 1], [2, 2], [3, 3], [4, 4]]);
|
||||
const result = mapKeyChanges(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result).toEqual([4]);
|
||||
});
|
||||
|
||||
it('should indicate changes for removed properties', () => {
|
||||
const a = new Map([[1, 1], [2, 2], [3, 3], [4, 4]]);
|
||||
const b = new Map([[1, 1], [2, 2], [3, 3]]);
|
||||
const result = mapKeyChanges(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result).toEqual([4]);
|
||||
});
|
||||
|
||||
it('should indicate changes for changed properties', () => {
|
||||
const a = new Map([[1, 1], [2, 2], [3, 3], [4, 4]]);
|
||||
const b = new Map([[1, 1], [2, 2], [3, 3], [4, 55]]);
|
||||
const result = mapKeyChanges(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result).toEqual([4]);
|
||||
});
|
||||
|
||||
it('should indicate changes for properties with different pointers', () => {
|
||||
const a = new Map([[1, {}]]); // {} always creates a new object
|
||||
const b = new Map([[1, {}]]);
|
||||
const result = mapKeyChanges(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result).toEqual([1]);
|
||||
});
|
||||
|
||||
it('should indicate changes for changed, added, and removed properties', () => {
|
||||
const a = new Map([[1, 1], [2, 2], [3, 3]]);
|
||||
const b = new Map([[1, 1], [2, 8], [4, 4]]); // note change
|
||||
const result = mapKeyChanges(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toHaveLength(3);
|
||||
expect(result).toEqual([3, 4, 2]); // order irrelevant, but the test cares
|
||||
});
|
||||
});
|
||||
|
||||
describe('EnhancedMap', () => {
|
||||
// Most of these tests will make sure it implements the Map<K, V> class
|
||||
|
||||
it('should be empty by default', () => {
|
||||
const result = new EnhancedMap();
|
||||
expect(result.size).toBe(0);
|
||||
});
|
||||
|
||||
it('should use the provided entries', () => {
|
||||
const obj = {a: 1, b: 2};
|
||||
const result = new EnhancedMap(Object.entries(obj));
|
||||
expect(result.size).toBe(2);
|
||||
expect(result.get('a')).toBe(1);
|
||||
expect(result.get('b')).toBe(2);
|
||||
});
|
||||
|
||||
it('should create keys if they do not exist', () => {
|
||||
const key = 'a';
|
||||
const val = {}; // we'll check pointers
|
||||
|
||||
const result = new EnhancedMap<string, any>();
|
||||
expect(result.size).toBe(0);
|
||||
|
||||
let get = result.getOrCreate(key, val);
|
||||
expect(get).toBeDefined();
|
||||
expect(get).toBe(val);
|
||||
expect(result.size).toBe(1);
|
||||
|
||||
get = result.getOrCreate(key, 44); // specifically change `val`
|
||||
expect(get).toBeDefined();
|
||||
expect(get).toBe(val);
|
||||
expect(result.size).toBe(1);
|
||||
|
||||
get = result.get(key); // use the base class function
|
||||
expect(get).toBeDefined();
|
||||
expect(get).toBe(val);
|
||||
expect(result.size).toBe(1);
|
||||
});
|
||||
|
||||
it('should proxy remove to delete and return it', () => {
|
||||
const val = {};
|
||||
const result = new EnhancedMap<string, any>();
|
||||
result.set('a', val);
|
||||
|
||||
expect(result.size).toBe(1);
|
||||
|
||||
const removed = result.remove('a');
|
||||
expect(result.size).toBe(0);
|
||||
expect(removed).toBeDefined();
|
||||
expect(removed).toBe(val);
|
||||
});
|
||||
|
||||
it('should support removing unknown keys', () => {
|
||||
const val = {};
|
||||
const result = new EnhancedMap<string, any>();
|
||||
result.set('a', val);
|
||||
|
||||
expect(result.size).toBe(1);
|
||||
|
||||
const removed = result.remove('not-a');
|
||||
expect(result.size).toBe(1);
|
||||
expect(removed).not.toBeDefined();
|
||||
});
|
||||
});
|
||||
});
|
163
test/utils/numbers-test.ts
Normal file
163
test/utils/numbers-test.ts
Normal file
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {clamp, defaultNumber, percentageOf, percentageWithin, sum} from "../../src/utils/numbers";
|
||||
|
||||
describe('numbers', () => {
|
||||
describe('defaultNumber', () => {
|
||||
it('should use the default when the input is not a number', () => {
|
||||
const def = 42;
|
||||
|
||||
let result = defaultNumber(null, def);
|
||||
expect(result).toBe(def);
|
||||
|
||||
result = defaultNumber(undefined, def);
|
||||
expect(result).toBe(def);
|
||||
|
||||
result = defaultNumber(Number.NaN, def);
|
||||
expect(result).toBe(def);
|
||||
});
|
||||
|
||||
it('should use the number when it is a number', () => {
|
||||
const input = 24;
|
||||
const def = 42;
|
||||
const result = defaultNumber(input, def);
|
||||
expect(result).toBe(input);
|
||||
});
|
||||
});
|
||||
|
||||
describe('clamp', () => {
|
||||
it('should clamp high numbers', () => {
|
||||
const input = 101;
|
||||
const min = 0;
|
||||
const max = 100;
|
||||
const result = clamp(input, min, max);
|
||||
expect(result).toBe(max);
|
||||
});
|
||||
|
||||
it('should clamp low numbers', () => {
|
||||
const input = -1;
|
||||
const min = 0;
|
||||
const max = 100;
|
||||
const result = clamp(input, min, max);
|
||||
expect(result).toBe(min);
|
||||
});
|
||||
|
||||
it('should not clamp numbers in range', () => {
|
||||
const input = 50;
|
||||
const min = 0;
|
||||
const max = 100;
|
||||
const result = clamp(input, min, max);
|
||||
expect(result).toBe(input);
|
||||
});
|
||||
|
||||
it('should clamp floats', () => {
|
||||
const min = -0.10;
|
||||
const max = +0.10;
|
||||
|
||||
let result = clamp(-1.2, min, max);
|
||||
expect(result).toBe(min);
|
||||
|
||||
result = clamp(1.2, min, max);
|
||||
expect(result).toBe(max);
|
||||
|
||||
result = clamp(0.02, min, max);
|
||||
expect(result).toBe(0.02);
|
||||
});
|
||||
});
|
||||
|
||||
describe('sum', () => {
|
||||
it('should sum', () => { // duh
|
||||
const result = sum(1, 2, 1, 4);
|
||||
expect(result).toBe(8);
|
||||
});
|
||||
});
|
||||
|
||||
describe('percentageWithin', () => {
|
||||
it('should work within 0-100', () => {
|
||||
const result = percentageWithin(0.4, 0, 100);
|
||||
expect(result).toBe(40);
|
||||
});
|
||||
|
||||
it('should work within 0-100 when pct > 1', () => {
|
||||
const result = percentageWithin(1.4, 0, 100);
|
||||
expect(result).toBe(140);
|
||||
});
|
||||
|
||||
it('should work within 0-100 when pct < 0', () => {
|
||||
const result = percentageWithin(-1.4, 0, 100);
|
||||
expect(result).toBe(-140);
|
||||
});
|
||||
|
||||
it('should work with ranges other than 0-100', () => {
|
||||
const result = percentageWithin(0.4, 10, 20);
|
||||
expect(result).toBe(14);
|
||||
});
|
||||
|
||||
it('should work with ranges other than 0-100 when pct > 1', () => {
|
||||
const result = percentageWithin(1.4, 10, 20);
|
||||
expect(result).toBe(24);
|
||||
});
|
||||
|
||||
it('should work with ranges other than 0-100 when pct < 0', () => {
|
||||
const result = percentageWithin(-1.4, 10, 20);
|
||||
expect(result).toBe(-4);
|
||||
});
|
||||
|
||||
it('should work with floats', () => {
|
||||
const result = percentageWithin(0.4, 10.2, 20.4);
|
||||
expect(result).toBe(14.28);
|
||||
});
|
||||
});
|
||||
|
||||
// These are the inverse of percentageWithin
|
||||
describe('percentageOf', () => {
|
||||
it('should work within 0-100', () => {
|
||||
const result = percentageOf(40, 0, 100);
|
||||
expect(result).toBe(0.4);
|
||||
});
|
||||
|
||||
it('should work within 0-100 when val > 100', () => {
|
||||
const result = percentageOf(140, 0, 100);
|
||||
expect(result).toBe(1.40);
|
||||
});
|
||||
|
||||
it('should work within 0-100 when val < 0', () => {
|
||||
const result = percentageOf(-140, 0, 100);
|
||||
expect(result).toBe(-1.40);
|
||||
});
|
||||
|
||||
it('should work with ranges other than 0-100', () => {
|
||||
const result = percentageOf(14, 10, 20);
|
||||
expect(result).toBe(0.4);
|
||||
});
|
||||
|
||||
it('should work with ranges other than 0-100 when val > 100', () => {
|
||||
const result = percentageOf(24, 10, 20);
|
||||
expect(result).toBe(1.4);
|
||||
});
|
||||
|
||||
it('should work with ranges other than 0-100 when val < 0', () => {
|
||||
const result = percentageOf(-4, 10, 20);
|
||||
expect(result).toBe(-1.4);
|
||||
});
|
||||
|
||||
it('should work with floats', () => {
|
||||
const result = percentageOf(14.28, 10.2, 20.4);
|
||||
expect(result).toBe(0.4);
|
||||
});
|
||||
});
|
||||
});
|
262
test/utils/objects-test.ts
Normal file
262
test/utils/objects-test.ts
Normal file
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
objectClone,
|
||||
objectDiff,
|
||||
objectExcluding,
|
||||
objectFromEntries,
|
||||
objectHasDiff,
|
||||
objectKeyChanges,
|
||||
objectShallowClone,
|
||||
objectWithOnly,
|
||||
} from "../../src/utils/objects";
|
||||
|
||||
describe('objects', () => {
|
||||
describe('objectExcluding', () => {
|
||||
it('should exclude the given properties', () => {
|
||||
const input = {hello: "world", test: true};
|
||||
const output = {hello: "world"};
|
||||
const props = ["test", "doesnotexist"]; // we also make sure it doesn't explode on missing props
|
||||
const result = objectExcluding(input, <any>props); // any is to test the missing prop
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toMatchObject(output);
|
||||
});
|
||||
});
|
||||
|
||||
describe('objectWithOnly', () => {
|
||||
it('should exclusively use the given properties', () => {
|
||||
const input = {hello: "world", test: true};
|
||||
const output = {hello: "world"};
|
||||
const props = ["hello", "doesnotexist"]; // we also make sure it doesn't explode on missing props
|
||||
const result = objectWithOnly(input, <any>props); // any is to test the missing prop
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toMatchObject(output);
|
||||
});
|
||||
});
|
||||
|
||||
describe('objectShallowClone', () => {
|
||||
it('should create a new object', () => {
|
||||
const input = {test: 1};
|
||||
const result = objectShallowClone(input);
|
||||
expect(result).toBeDefined();
|
||||
expect(result).not.toBe(input);
|
||||
expect(result).toMatchObject(input);
|
||||
});
|
||||
|
||||
it('should only clone the top level properties', () => {
|
||||
const input = {a: 1, b: {c: 2}};
|
||||
const result = objectShallowClone(input);
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toMatchObject(input);
|
||||
expect(result.b).toBe(input.b);
|
||||
});
|
||||
|
||||
it('should support custom clone functions', () => {
|
||||
const input = {a: 1, b: 2};
|
||||
const output = {a: 4, b: 8};
|
||||
const result = objectShallowClone(input, (k, v) => {
|
||||
// XXX: inverted expectation for ease of assertion
|
||||
expect(Object.keys(input)).toContain(k);
|
||||
|
||||
return v * 4;
|
||||
});
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toMatchObject(output);
|
||||
});
|
||||
});
|
||||
|
||||
describe('objectHasDiff', () => {
|
||||
it('should return false for the same pointer', () => {
|
||||
const a = {};
|
||||
const result = objectHasDiff(a, a);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true if keys for A > keys for B', () => {
|
||||
const a = {a: 1, b: 2};
|
||||
const b = {a: 1};
|
||||
const result = objectHasDiff(a, b);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true if keys for A < keys for B', () => {
|
||||
const a = {a: 1};
|
||||
const b = {a: 1, b: 2};
|
||||
const result = objectHasDiff(a, b);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if the objects are the same but different pointers', () => {
|
||||
const a = {a: 1, b: 2};
|
||||
const b = {a: 1, b: 2};
|
||||
const result = objectHasDiff(a, b);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should consider pointers when testing values', () => {
|
||||
const a = {a: {}, b: 2}; // `{}` is shorthand for `new Object()`
|
||||
const b = {a: {}, b: 2};
|
||||
const result = objectHasDiff(a, b);
|
||||
expect(result).toBe(true); // even though the keys are the same, the value pointers vary
|
||||
});
|
||||
});
|
||||
|
||||
describe('objectDiff', () => {
|
||||
it('should return empty sets for the same object', () => {
|
||||
const a = {a: 1, b: 2};
|
||||
const b = {a: 1, b: 2};
|
||||
const result = objectDiff(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result.changed).toBeDefined();
|
||||
expect(result.added).toBeDefined();
|
||||
expect(result.removed).toBeDefined();
|
||||
expect(result.changed).toHaveLength(0);
|
||||
expect(result.added).toHaveLength(0);
|
||||
expect(result.removed).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should return empty sets for the same object pointer', () => {
|
||||
const a = {a: 1, b: 2};
|
||||
const result = objectDiff(a, a);
|
||||
expect(result).toBeDefined();
|
||||
expect(result.changed).toBeDefined();
|
||||
expect(result.added).toBeDefined();
|
||||
expect(result.removed).toBeDefined();
|
||||
expect(result.changed).toHaveLength(0);
|
||||
expect(result.added).toHaveLength(0);
|
||||
expect(result.removed).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should indicate when property changes are made', () => {
|
||||
const a = {a: 1, b: 2};
|
||||
const b = {a: 11, b: 2};
|
||||
const result = objectDiff(a, b);
|
||||
expect(result.changed).toBeDefined();
|
||||
expect(result.added).toBeDefined();
|
||||
expect(result.removed).toBeDefined();
|
||||
expect(result.changed).toHaveLength(1);
|
||||
expect(result.added).toHaveLength(0);
|
||||
expect(result.removed).toHaveLength(0);
|
||||
expect(result.changed).toEqual(['a']);
|
||||
});
|
||||
|
||||
it('should indicate when properties are added', () => {
|
||||
const a = {a: 1, b: 2};
|
||||
const b = {a: 1, b: 2, c: 3};
|
||||
const result = objectDiff(a, b);
|
||||
expect(result.changed).toBeDefined();
|
||||
expect(result.added).toBeDefined();
|
||||
expect(result.removed).toBeDefined();
|
||||
expect(result.changed).toHaveLength(0);
|
||||
expect(result.added).toHaveLength(1);
|
||||
expect(result.removed).toHaveLength(0);
|
||||
expect(result.added).toEqual(['c']);
|
||||
});
|
||||
|
||||
it('should indicate when properties are removed', () => {
|
||||
const a = {a: 1, b: 2};
|
||||
const b = {a: 1};
|
||||
const result = objectDiff(a, b);
|
||||
expect(result.changed).toBeDefined();
|
||||
expect(result.added).toBeDefined();
|
||||
expect(result.removed).toBeDefined();
|
||||
expect(result.changed).toHaveLength(0);
|
||||
expect(result.added).toHaveLength(0);
|
||||
expect(result.removed).toHaveLength(1);
|
||||
expect(result.removed).toEqual(['b']);
|
||||
});
|
||||
|
||||
it('should indicate when multiple aspects change', () => {
|
||||
const a = {a: 1, b: 2, c: 3};
|
||||
const b: (typeof a | {d: number}) = {a: 1, b: 22, d: 4};
|
||||
const result = objectDiff(a, b);
|
||||
expect(result.changed).toBeDefined();
|
||||
expect(result.added).toBeDefined();
|
||||
expect(result.removed).toBeDefined();
|
||||
expect(result.changed).toHaveLength(1);
|
||||
expect(result.added).toHaveLength(1);
|
||||
expect(result.removed).toHaveLength(1);
|
||||
expect(result.changed).toEqual(['b']);
|
||||
expect(result.removed).toEqual(['c']);
|
||||
expect(result.added).toEqual(['d']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('objectKeyChanges', () => {
|
||||
it('should return an empty set if no properties changed', () => {
|
||||
const a = {a: 1, b: 2};
|
||||
const b = {a: 1, b: 2};
|
||||
const result = objectKeyChanges(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should return an empty set if no properties changed for the same pointer', () => {
|
||||
const a = {a: 1, b: 2};
|
||||
const result = objectKeyChanges(a, a);
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should return properties which were changed, added, or removed', () => {
|
||||
const a = {a: 1, b: 2, c: 3};
|
||||
const b: (typeof a | {d: number}) = {a: 1, b: 22, d: 4};
|
||||
const result = objectKeyChanges(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toHaveLength(3);
|
||||
expect(result).toEqual(['c', 'd', 'b']); // order isn't important, but the test cares
|
||||
});
|
||||
});
|
||||
|
||||
describe('objectClone', () => {
|
||||
it('should deep clone an object', () => {
|
||||
const a = {
|
||||
hello: "world",
|
||||
test: {
|
||||
another: "property",
|
||||
test: 42,
|
||||
third: {
|
||||
prop: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
const result = objectClone(a);
|
||||
expect(result).toBeDefined();
|
||||
expect(result).not.toBe(a);
|
||||
expect(result).toMatchObject(a);
|
||||
expect(result.test).not.toBe(a.test);
|
||||
expect(result.test.third).not.toBe(a.test.third);
|
||||
});
|
||||
});
|
||||
|
||||
describe('objectFromEntries', () => {
|
||||
it('should create an object from an array of entries', () => {
|
||||
const output = {a: 1, b: 2, c: 3};
|
||||
const result = objectFromEntries(Object.entries(output));
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toMatchObject(output);
|
||||
});
|
||||
|
||||
it('should maintain pointers in values', () => {
|
||||
const output = {a: {}, b: 2, c: 3};
|
||||
const result = objectFromEntries(Object.entries(output));
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toMatchObject(output);
|
||||
expect(result['a']).toBe(output.a);
|
||||
});
|
||||
});
|
||||
});
|
56
test/utils/sets-test.ts
Normal file
56
test/utils/sets-test.ts
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {setHasDiff} from "../../src/utils/sets";
|
||||
|
||||
describe('sets', () => {
|
||||
describe('setHasDiff', () => {
|
||||
it('should flag true on A length > B length', () => {
|
||||
const a = new Set([1, 2, 3, 4]);
|
||||
const b = new Set([1, 2, 3]);
|
||||
const result = setHasDiff(a, b);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should flag true on A length < B length', () => {
|
||||
const a = new Set([1, 2, 3]);
|
||||
const b = new Set([1, 2, 3, 4]);
|
||||
const result = setHasDiff(a, b);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should flag true on element differences', () => {
|
||||
const a = new Set([1, 2, 3]);
|
||||
const b = new Set([4, 5, 6]);
|
||||
const result = setHasDiff(a, b);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should flag false if same but order different', () => {
|
||||
const a = new Set([1, 2, 3]);
|
||||
const b = new Set([3, 1, 2]);
|
||||
const result = setHasDiff(a, b);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should flag false if same', () => {
|
||||
const a = new Set([1, 2, 3]);
|
||||
const b = new Set([1, 2, 3]);
|
||||
const result = setHasDiff(a, b);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue