mirror of
https://github.com/nodejs/node.git
synced 2025-04-28 13:40:37 +00:00

PR-URL: https://github.com/nodejs/node/pull/57881 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
1177 lines
37 KiB
JavaScript
1177 lines
37 KiB
JavaScript
// Flags: --js-float16array
|
|
// TODO(LiviaMedeiros): once `Float16Array` is unflagged in v8, remove the line above
|
|
'use strict';
|
|
|
|
const common = require('../common');
|
|
const vm = require('node:vm');
|
|
const assert = require('node:assert');
|
|
const { describe, it } = require('node:test');
|
|
|
|
// TODO(LiviaMedeiros): once linter recognizes `Float16Array`, remove next line
|
|
const { Float16Array } = globalThis;
|
|
|
|
const x = ['x'];
|
|
|
|
function createCircularObject() {
|
|
const obj = {};
|
|
obj.self = obj;
|
|
obj.set = new Set([x, ['y']]);
|
|
return obj;
|
|
}
|
|
|
|
function createDeepNestedObject() {
|
|
return { level1: { level2: { level3: 'deepValue' } } };
|
|
}
|
|
|
|
async function generateCryptoKey() {
|
|
const { KeyObject } = require('node:crypto');
|
|
const { subtle } = globalThis.crypto;
|
|
|
|
const cryptoKey = await subtle.generateKey(
|
|
{
|
|
name: 'HMAC',
|
|
hash: 'SHA-256',
|
|
length: 256,
|
|
},
|
|
true,
|
|
['sign', 'verify']
|
|
);
|
|
|
|
const keyObject = KeyObject.from(cryptoKey);
|
|
|
|
return { cryptoKey, keyObject };
|
|
}
|
|
|
|
describe('Object Comparison Tests', () => {
|
|
describe('partialDeepStrictEqual', () => {
|
|
describe('throws an error', () => {
|
|
const tests = [
|
|
{
|
|
description: 'throws when only actual is provided',
|
|
actual: { a: 1 },
|
|
expected: undefined,
|
|
},
|
|
{
|
|
description: 'throws when unequal zeros are compared',
|
|
actual: 0,
|
|
expected: -0,
|
|
},
|
|
{
|
|
description: 'throws when only expected is provided',
|
|
actual: undefined,
|
|
expected: { a: 1 },
|
|
},
|
|
{
|
|
description: 'throws when expected has more properties than actual',
|
|
actual: [1, 'two'],
|
|
expected: [1, 'two', true],
|
|
},
|
|
{
|
|
description: 'throws because expected has seven 2 while actual has six one',
|
|
actual: [1, 2, 2, 2, 2, 2, 2, 3],
|
|
expected: [1, 2, 2, 2, 2, 2, 2, 2],
|
|
},
|
|
{
|
|
description: 'throws when comparing two different sets with objects',
|
|
actual: new Set([{ a: 1 }]),
|
|
expected: new Set([{ a: 1 }, { b: 1 }]),
|
|
},
|
|
|
|
{
|
|
description: 'throws when comparing two WeakSet objects',
|
|
actual: new WeakSet(),
|
|
expected: new WeakSet(),
|
|
},
|
|
{
|
|
description: 'throws when comparing two WeakMap objects',
|
|
actual: new WeakMap(),
|
|
expected: new WeakMap(),
|
|
},
|
|
{
|
|
description: 'throws when comparing two different objects',
|
|
actual: { a: 1, b: 'string' },
|
|
expected: { a: 2, b: 'string' },
|
|
},
|
|
{
|
|
description:
|
|
'throws when comparing two objects with different nested objects',
|
|
actual: createDeepNestedObject(),
|
|
expected: { level1: { level2: { level3: 'differentValue' } } },
|
|
},
|
|
{
|
|
description:
|
|
'throws when comparing two objects with different RegExp properties',
|
|
actual: { pattern: /abc/ },
|
|
expected: { pattern: /def/ },
|
|
},
|
|
{
|
|
description:
|
|
'throws when comparing two arrays with different elements',
|
|
actual: [1, 'two', true],
|
|
expected: [1, 'two', false],
|
|
},
|
|
{
|
|
description: 'throws when comparing [0] with [-0]',
|
|
actual: [0],
|
|
expected: [-0],
|
|
},
|
|
{
|
|
description: 'throws when comparing [0, 0, 0] with [0, -0]',
|
|
actual: [0, 0, 0],
|
|
expected: [0, -0],
|
|
},
|
|
{
|
|
description: 'throws when comparing ["-0"] with [-0]',
|
|
actual: ['-0'],
|
|
expected: [-0],
|
|
},
|
|
{
|
|
description: 'throws when comparing [-0] with [0]',
|
|
actual: [-0],
|
|
expected: [0],
|
|
},
|
|
{
|
|
description: 'throws when comparing [-0] with ["-0"]',
|
|
actual: [-0],
|
|
expected: ['-0'],
|
|
},
|
|
{
|
|
description: 'throws when comparing ["0"] with [0]',
|
|
actual: ['0'],
|
|
expected: [0],
|
|
},
|
|
{
|
|
description: 'throws when comparing [0] with ["0"]',
|
|
actual: [0],
|
|
expected: ['0'],
|
|
},
|
|
{
|
|
description:
|
|
'throws when comparing two Date objects with different times',
|
|
actual: new Date(0),
|
|
expected: new Date(1),
|
|
},
|
|
{
|
|
description:
|
|
'throws when comparing two objects with different large number of properties',
|
|
actual: Object.fromEntries(
|
|
Array.from({ length: 100 }, (_, i) => [`key${i}`, i])
|
|
),
|
|
expected: Object.fromEntries(
|
|
Array.from({ length: 100 }, (_, i) => [`key${i}`, i + 1])
|
|
),
|
|
},
|
|
{
|
|
description:
|
|
'throws when comparing two objects with different Symbols',
|
|
actual: { [Symbol('test')]: 'symbol' },
|
|
expected: { [Symbol('test')]: 'symbol' },
|
|
},
|
|
{
|
|
description:
|
|
'throws when comparing two objects with different array properties',
|
|
actual: { a: [1, 2, 3] },
|
|
expected: { a: [1, 2, 4] },
|
|
},
|
|
{
|
|
description:
|
|
'throws when comparing two objects with different function properties',
|
|
actual: { fn: () => {} },
|
|
expected: { fn: () => {} },
|
|
},
|
|
{
|
|
description:
|
|
'throws when comparing two objects with different Error message',
|
|
actual: { error: new Error('Test error 1') },
|
|
expected: { error: new Error('Test error 2') },
|
|
},
|
|
{
|
|
description:
|
|
'throws when comparing two objects with missing cause on the actual Error',
|
|
actual: { error: new Error('Test error 1') },
|
|
expected: { error: new Error('Test error 1', { cause: 42 }) },
|
|
},
|
|
{
|
|
description:
|
|
'throws when comparing two objects with missing message on the actual Error',
|
|
actual: { error: new Error() },
|
|
expected: { error: new Error('Test error 1') },
|
|
},
|
|
{
|
|
description: 'throws when comparing two Errors with missing cause on the actual Error',
|
|
actual: { error: new Error('Test error 1') },
|
|
expected: { error: new Error('Test error 1', { cause: undefined }) },
|
|
},
|
|
{
|
|
description: 'throws when comparing two AggregateErrors with missing message on the actual Error',
|
|
actual: { error: new AggregateError([], 'Test error 1') },
|
|
expected: { error: new AggregateError([new Error()], 'Test error 1') },
|
|
},
|
|
{
|
|
description:
|
|
'throws when comparing two objects with different TypedArray instances and content',
|
|
actual: { typedArray: new Uint8Array([1, 2, 3]) },
|
|
expected: { typedArray: new Uint8Array([4, 5, 6]) },
|
|
},
|
|
{
|
|
description:
|
|
'throws when comparing two Map objects with different entries',
|
|
actual: new Map([
|
|
['key1', 'value1'],
|
|
['key2', 'value2'],
|
|
]),
|
|
expected: new Map([
|
|
['key1', 'value1'],
|
|
['key3', 'value3'],
|
|
]),
|
|
},
|
|
{
|
|
description:
|
|
'throws when comparing two Map objects with different keys',
|
|
actual: new Map([
|
|
['key1', 'value1'],
|
|
['key2', 'value2'],
|
|
]),
|
|
expected: new Map([
|
|
['key1', 'value1'],
|
|
['key3', 'value2'],
|
|
]),
|
|
},
|
|
{
|
|
description:
|
|
'throws when the expected Map has more entries than the actual Map',
|
|
actual: new Map([
|
|
['key1', 'value1'],
|
|
['key2', 'value2'],
|
|
]),
|
|
expected: new Map([
|
|
['key1', 'value1'],
|
|
['key2', 'value2'],
|
|
['key3', 'value3'],
|
|
]),
|
|
},
|
|
{
|
|
description: 'throws when the nested array in the Map is not a subset of the other nested array',
|
|
actual: new Map([
|
|
['key1', ['value1', 'value2']],
|
|
['key2', 'value2'],
|
|
]),
|
|
expected: new Map([
|
|
['key1', ['value3']],
|
|
]),
|
|
},
|
|
{
|
|
description: 'throws for maps with object keys and different values',
|
|
actual: new Map([
|
|
[{ a: 1 }, 'value1'],
|
|
[{ b: 2 }, 'value2'],
|
|
[{ b: 2 }, 'value4'],
|
|
]),
|
|
expected: new Map([
|
|
[{ a: 1 }, 'value1'],
|
|
[{ b: 2 }, 'value3'],
|
|
]),
|
|
},
|
|
{
|
|
description: 'throws for maps with multiple identical object keys, just not enough',
|
|
actual: new Map([
|
|
[{ a: 1 }, 'value1'],
|
|
[{ b: 1 }, 'value2'],
|
|
[{ a: 1 }, 'value1'],
|
|
]),
|
|
expected: new Map([
|
|
[{ a: 1 }, 'value1'],
|
|
[{ a: 1 }, 'value1'],
|
|
[{ a: 1 }, 'value1'],
|
|
]),
|
|
},
|
|
{
|
|
description: 'throws for Maps with mixed unequal entries',
|
|
actual: new Map([[{ a: 2 }, 1], [1, 1], [{ b: 1 }, 1], [[], 1], [2, 1], [{ a: 1 }, 1]]),
|
|
expected: new Map([[{ a: 1 }, 1], [[], 1], [2, 1], [{ a: 1 }, 1]]),
|
|
},
|
|
{
|
|
description: 'throws for sets with different object values',
|
|
actual: new Set([
|
|
{ a: 1 },
|
|
{ a: 2 },
|
|
{ a: 1 },
|
|
{ a: 2 },
|
|
]),
|
|
expected: new Set([
|
|
{ a: 1 },
|
|
{ a: 2 },
|
|
{ a: 1 },
|
|
{ a: 1 },
|
|
]),
|
|
},
|
|
{
|
|
description:
|
|
'throws when comparing two TypedArray instances with different content',
|
|
actual: new Uint8Array(10),
|
|
expected: () => {
|
|
const typedArray2 = new Int8Array(10);
|
|
Object.defineProperty(typedArray2, Symbol.toStringTag, {
|
|
value: 'Uint8Array'
|
|
});
|
|
Object.setPrototypeOf(typedArray2, Uint8Array.prototype);
|
|
|
|
return typedArray2;
|
|
},
|
|
},
|
|
{
|
|
description:
|
|
'throws when comparing two Set objects from different realms with different values',
|
|
actual: new vm.runInNewContext('new Set(["value1", "value2"])'),
|
|
expected: new Set(['value1', 'value3']),
|
|
},
|
|
{
|
|
description:
|
|
'throws when comparing two Set objects with different values',
|
|
actual: new Set(['value1', 'value2']),
|
|
expected: new Set(['value1', 'value3']),
|
|
},
|
|
{
|
|
description: 'throws when comparing one subset object with another',
|
|
actual: { a: 1, b: 2, c: 3 },
|
|
expected: { b: '2' },
|
|
},
|
|
{
|
|
description: 'throws when comparing one subset array with another',
|
|
actual: [1, 2, 3],
|
|
expected: ['2'],
|
|
},
|
|
{
|
|
description: 'throws when comparing an array with symbol properties not matching',
|
|
actual: (() => {
|
|
const array = [1, 2, 3];
|
|
array[Symbol.for('test')] = 'test';
|
|
return array;
|
|
})(),
|
|
expected: (() => {
|
|
const array = [1, 2, 3];
|
|
array[Symbol.for('test')] = 'different';
|
|
return array;
|
|
})(),
|
|
},
|
|
{
|
|
description: 'throws when comparing an array with extra properties not matching',
|
|
actual: (() => {
|
|
const array = [1, 2, 3];
|
|
array.extra = 'test';
|
|
return array;
|
|
})(),
|
|
expected: (() => {
|
|
const array = [1, 2, 3];
|
|
array.extra = 'different';
|
|
return array;
|
|
})(),
|
|
},
|
|
{
|
|
description: 'throws when comparing a non matching sparse array',
|
|
actual: (() => {
|
|
const array = new Array(1000);
|
|
array[90] = 1;
|
|
array[92] = 2;
|
|
array[95] = 1;
|
|
array[96] = 2;
|
|
array.foo = 'bar';
|
|
array.extra = 'test';
|
|
return array;
|
|
})(),
|
|
expected: (() => {
|
|
const array = new Array(1000);
|
|
array[90] = 1;
|
|
array[92] = 1;
|
|
array[95] = 1;
|
|
array.extra = 'test';
|
|
array.foo = 'bar';
|
|
return array;
|
|
})(),
|
|
},
|
|
{
|
|
description: 'throws when comparing a same length sparse array with actual less keys',
|
|
actual: (() => {
|
|
const array = new Array(1000);
|
|
array[90] = 1;
|
|
array[92] = 1;
|
|
return array;
|
|
})(),
|
|
expected: (() => {
|
|
const array = new Array(1000);
|
|
array[90] = 1;
|
|
array[92] = 1;
|
|
array[95] = 1;
|
|
return array;
|
|
})(),
|
|
},
|
|
{
|
|
description: 'throws when comparing an array with symbol properties matching but other enumerability',
|
|
actual: (() => {
|
|
const array = [1, 2, 3];
|
|
array[Symbol.for('abc')] = 'test';
|
|
Object.defineProperty(array, Symbol.for('test'), {
|
|
value: 'test',
|
|
enumerable: false,
|
|
});
|
|
array[Symbol.for('other')] = 'test';
|
|
return array;
|
|
})(),
|
|
expected: (() => {
|
|
const array = [1, 2, 3];
|
|
array[Symbol.for('test')] = 'test';
|
|
return array;
|
|
})(),
|
|
},
|
|
{
|
|
description: 'throws comparing an array with extra properties matching but other enumerability',
|
|
actual: (() => {
|
|
const array = [1, 2, 3];
|
|
array.alsoIgnored = [{ nested: { property: true } }];
|
|
Object.defineProperty(array, 'extra', {
|
|
value: 'test',
|
|
enumerable: false,
|
|
});
|
|
array.ignored = 'test';
|
|
return array;
|
|
})(),
|
|
expected: (() => {
|
|
const array = [1, 2, 3];
|
|
array.extra = 'test';
|
|
return array;
|
|
})(),
|
|
},
|
|
{
|
|
description: 'throws when comparing an ArrayBuffer with a Uint8Array',
|
|
actual: new ArrayBuffer(3),
|
|
expected: new Uint8Array(3),
|
|
},
|
|
{
|
|
description: 'throws when comparing an TypedArrays with symbol properties not matching',
|
|
actual: (() => {
|
|
const typed = new Uint8Array(3);
|
|
typed[Symbol.for('test')] = 'test';
|
|
return typed;
|
|
})(),
|
|
expected: (() => {
|
|
const typed = new Uint8Array(3);
|
|
typed[Symbol.for('test')] = 'different';
|
|
return typed;
|
|
})(),
|
|
},
|
|
{
|
|
description: 'throws when comparing a ArrayBuffer with a SharedArrayBuffer',
|
|
actual: new ArrayBuffer(3),
|
|
expected: new SharedArrayBuffer(3),
|
|
},
|
|
{
|
|
description: 'throws when comparing a SharedArrayBuffer with an ArrayBuffer',
|
|
actual: new SharedArrayBuffer(3),
|
|
expected: new ArrayBuffer(3),
|
|
},
|
|
{
|
|
description: 'throws when comparing an Int16Array with a Uint16Array',
|
|
actual: new Int16Array(3),
|
|
expected: new Uint16Array(3),
|
|
},
|
|
{
|
|
description: 'throws when comparing two dataviews with different buffers',
|
|
actual: { dataView: new DataView(new ArrayBuffer(3)) },
|
|
expected: { dataView: new DataView(new ArrayBuffer(4)) },
|
|
},
|
|
{
|
|
description: 'throws because expected Uint8Array(SharedArrayBuffer) is not a subset of actual',
|
|
actual: { typedArray: new Uint8Array(new SharedArrayBuffer(3)) },
|
|
expected: { typedArray: new Uint8Array(new SharedArrayBuffer(5)) },
|
|
},
|
|
{
|
|
description: 'throws because expected SharedArrayBuffer is not a subset of actual',
|
|
actual: { typedArray: new SharedArrayBuffer(3) },
|
|
expected: { typedArray: new SharedArrayBuffer(5) },
|
|
},
|
|
{
|
|
description: 'throws when comparing a DataView with a TypedArray',
|
|
actual: { dataView: new DataView(new ArrayBuffer(3)) },
|
|
expected: { dataView: new Uint8Array(3) },
|
|
},
|
|
{
|
|
description: 'throws when comparing a TypedArray with a DataView',
|
|
actual: { dataView: new Uint8Array(3) },
|
|
expected: { dataView: new DataView(new ArrayBuffer(3)) },
|
|
},
|
|
{
|
|
description: 'throws when comparing Float16Array([+0.0]) with Float16Array([-0.0])',
|
|
actual: new Float16Array([+0.0]),
|
|
expected: new Float16Array([-0.0]),
|
|
},
|
|
{
|
|
description: 'throws when comparing Float32Array([+0.0]) with Float32Array([-0.0])',
|
|
actual: new Float32Array([+0.0]),
|
|
expected: new Float32Array([-0.0]),
|
|
},
|
|
{
|
|
description: 'throws when comparing two Uint8Array objects with non-matching entries',
|
|
actual: { typedArray: new Uint8Array([1, 2, 3, 4, 5]) },
|
|
expected: { typedArray: new Uint8Array([1, 333, 2, 4]) },
|
|
},
|
|
{
|
|
description: 'throws when comparing two different urls',
|
|
actual: new URL('http://foo'),
|
|
expected: new URL('http://bar'),
|
|
},
|
|
{
|
|
description: 'throws when comparing SharedArrayBuffers when expected has different elements actual',
|
|
actual: (() => {
|
|
const sharedBuffer = new SharedArrayBuffer(4 * Int32Array.BYTES_PER_ELEMENT);
|
|
const sharedArray = new Int32Array(sharedBuffer);
|
|
|
|
sharedArray[0] = 1;
|
|
sharedArray[1] = 2;
|
|
sharedArray[2] = 3;
|
|
|
|
return sharedBuffer;
|
|
})(),
|
|
expected: (() => {
|
|
const sharedBuffer = new SharedArrayBuffer(4 * Int32Array.BYTES_PER_ELEMENT);
|
|
const sharedArray = new Int32Array(sharedBuffer);
|
|
|
|
sharedArray[0] = 1;
|
|
sharedArray[1] = 2;
|
|
sharedArray[2] = 6;
|
|
|
|
return sharedBuffer;
|
|
})(),
|
|
},
|
|
];
|
|
|
|
if (common.hasCrypto) {
|
|
tests.push({
|
|
description:
|
|
'throws when comparing two objects with different CryptoKey instances objects',
|
|
actual: async () => {
|
|
return generateCryptoKey();
|
|
},
|
|
expected: async () => {
|
|
return generateCryptoKey();
|
|
},
|
|
});
|
|
|
|
const { createSecretKey } = require('node:crypto');
|
|
|
|
tests.push({
|
|
description:
|
|
'throws when comparing two objects with different KeyObject instances objects',
|
|
actual: createSecretKey(Buffer.alloc(1, 0)),
|
|
expected: createSecretKey(Buffer.alloc(1, 1)),
|
|
});
|
|
}
|
|
|
|
tests.forEach(({ description, actual, expected }) => {
|
|
it(description, () => {
|
|
assert.throws(() => assert.partialDeepStrictEqual(actual, expected), Error);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('does not throw an error', () => {
|
|
const sym = Symbol('test');
|
|
const func = () => {};
|
|
|
|
[
|
|
{
|
|
description: 'compares two identical simple objects',
|
|
actual: { a: 1, b: 'string' },
|
|
expected: { a: 1, b: 'string' },
|
|
},
|
|
{
|
|
description: 'compares two objects with different property order',
|
|
actual: { a: 1, b: 'string' },
|
|
expected: { b: 'string', a: 1 },
|
|
},
|
|
{
|
|
description: 'compares two deeply nested objects with partial equality',
|
|
actual: { a: { nested: { property: true, some: 'other' } } },
|
|
expected: { a: { nested: { property: true } } },
|
|
},
|
|
{
|
|
description:
|
|
'compares plain objects from different realms',
|
|
actual: vm.runInNewContext(`({
|
|
a: 1,
|
|
b: 2n,
|
|
c: "3",
|
|
d: /4/,
|
|
e: new Set([5]),
|
|
f: [6],
|
|
g: new Uint8Array()
|
|
})`),
|
|
expected: { b: 2n, e: new Set([5]), f: [6], g: new Uint8Array() },
|
|
},
|
|
{
|
|
description: 'compares two integers',
|
|
actual: 1,
|
|
expected: 1,
|
|
},
|
|
{
|
|
description: 'compares two strings',
|
|
actual: '1',
|
|
expected: '1',
|
|
},
|
|
{
|
|
description: 'compares two objects with nested objects',
|
|
actual: createDeepNestedObject(),
|
|
expected: createDeepNestedObject(),
|
|
},
|
|
{
|
|
description: 'compares two objects with circular references',
|
|
actual: createCircularObject(),
|
|
expected: createCircularObject(),
|
|
},
|
|
{
|
|
description: 'compares two arrays with identical elements',
|
|
actual: [1, 'two', true],
|
|
expected: [1, 'two', true],
|
|
},
|
|
{
|
|
description: 'compares [0] with [0]',
|
|
actual: [0],
|
|
expected: [0],
|
|
},
|
|
{
|
|
description: 'compares [-0] with [-0]',
|
|
actual: [-0],
|
|
expected: [-0],
|
|
},
|
|
{
|
|
description: 'compares [0, -0, 0] with [0, 0]',
|
|
actual: [0, -0, 0],
|
|
expected: [0, 0],
|
|
},
|
|
{
|
|
description: 'comparing an array with symbol properties matching',
|
|
actual: (() => {
|
|
const array = [1, 2, 3];
|
|
array[Symbol.for('abc')] = 'test';
|
|
array[Symbol.for('test')] = 'test';
|
|
Object.defineProperty(array, Symbol.for('hidden'), {
|
|
value: 'hidden',
|
|
enumerable: false,
|
|
});
|
|
return array;
|
|
})(),
|
|
expected: (() => {
|
|
const array = [1, 2, 3];
|
|
array[Symbol.for('test')] = 'test';
|
|
return array;
|
|
})(),
|
|
},
|
|
{
|
|
description: 'comparing an array with extra properties matching',
|
|
actual: (() => {
|
|
const array = [1, 2, 3];
|
|
array.alsoIgnored = [{ nested: { property: true } }];
|
|
array.extra = 'test';
|
|
array.ignored = 'test';
|
|
return array;
|
|
})(),
|
|
expected: (() => {
|
|
const array = [1, 2, 3];
|
|
array.extra = 'test';
|
|
Object.defineProperty(array, 'ignored', { enumerable: false });
|
|
Object.defineProperty(array, Symbol.for('hidden'), {
|
|
value: 'hidden',
|
|
enumerable: false,
|
|
});
|
|
return array;
|
|
})(),
|
|
},
|
|
{
|
|
description: 'compares two Date objects with the same time',
|
|
actual: new Date(0),
|
|
expected: new Date(0),
|
|
},
|
|
{
|
|
description: 'compares two objects with large number of properties',
|
|
actual: Object.fromEntries(
|
|
Array.from({ length: 100 }, (_, i) => [`key${i}`, i])
|
|
),
|
|
expected: Object.fromEntries(
|
|
Array.from({ length: 100 }, (_, i) => [`key${i}`, i])
|
|
),
|
|
},
|
|
{
|
|
description: 'compares two objects with Symbol properties',
|
|
actual: { [sym]: 'symbol' },
|
|
expected: { [sym]: 'symbol' },
|
|
},
|
|
{
|
|
description: 'compares two objects with RegExp properties',
|
|
actual: { pattern: /abc/ },
|
|
expected: { pattern: /abc/ },
|
|
},
|
|
{
|
|
description: 'compares two objects with identical function properties',
|
|
actual: { fn: func },
|
|
expected: { fn: func },
|
|
},
|
|
{
|
|
description: 'compares two objects with mixed types of properties',
|
|
actual: { num: 1, str: 'test', bool: true, sym },
|
|
expected: { num: 1, str: 'test', bool: true, sym },
|
|
},
|
|
{
|
|
description: 'compares two objects with Buffers',
|
|
actual: { buf: Buffer.from('Node.js') },
|
|
expected: { buf: Buffer.from('Node.js') },
|
|
},
|
|
{
|
|
description: 'compares two objects with identical Error properties',
|
|
actual: { error: new Error('Test error') },
|
|
expected: { error: new Error('Test error') },
|
|
},
|
|
{
|
|
description: 'compares two Uint8Array objects',
|
|
actual: { typedArray: new Uint8Array([1, 2, 3, 4, 5]) },
|
|
expected: { typedArray: new Uint8Array([1, 2, 3, 5]) },
|
|
},
|
|
{
|
|
description: 'compares two Int16Array objects',
|
|
actual: { typedArray: new Int16Array([1, 2, 3, 4, 5]) },
|
|
expected: { typedArray: new Int16Array([1, 2, 3]) },
|
|
},
|
|
{
|
|
description: 'compares two DataView objects with the same buffer and different views',
|
|
actual: { dataView: new DataView(new ArrayBuffer(8), 0, 4) },
|
|
expected: { dataView: new DataView(new ArrayBuffer(8), 4, 4) },
|
|
},
|
|
{
|
|
description: 'compares two DataView objects with different buffers',
|
|
actual: { dataView: new DataView(new ArrayBuffer(8)) },
|
|
expected: { dataView: new DataView(new ArrayBuffer(8)) },
|
|
},
|
|
{
|
|
description: 'compares two DataView objects with the same buffer and same views',
|
|
actual: { dataView: new DataView(new ArrayBuffer(8), 0, 8) },
|
|
expected: { dataView: new DataView(new ArrayBuffer(8), 0, 8) },
|
|
},
|
|
{
|
|
description: 'compares two SharedArrayBuffers with the same length',
|
|
actual: new SharedArrayBuffer(3),
|
|
expected: new SharedArrayBuffer(3),
|
|
},
|
|
{
|
|
description: 'compares two Uint8Array objects from SharedArrayBuffer',
|
|
actual: { typedArray: new Uint8Array(new SharedArrayBuffer(5)) },
|
|
expected: { typedArray: new Uint8Array(new SharedArrayBuffer(3)) },
|
|
},
|
|
{
|
|
description: 'compares two Int16Array objects from SharedArrayBuffer',
|
|
actual: { typedArray: new Int16Array(new SharedArrayBuffer(10)) },
|
|
expected: { typedArray: new Int16Array(new SharedArrayBuffer(6)) },
|
|
},
|
|
{
|
|
description: 'compares two DataView objects with the same SharedArrayBuffer and different views',
|
|
actual: { dataView: new DataView(new SharedArrayBuffer(8), 0, 4) },
|
|
expected: { dataView: new DataView(new SharedArrayBuffer(8), 4, 4) },
|
|
},
|
|
{
|
|
description: 'compares two DataView objects with different SharedArrayBuffers',
|
|
actual: { dataView: new DataView(new SharedArrayBuffer(8)) },
|
|
expected: { dataView: new DataView(new SharedArrayBuffer(8)) },
|
|
},
|
|
{
|
|
description: 'compares two DataView objects with the same SharedArrayBuffer and same views',
|
|
actual: { dataView: new DataView(new SharedArrayBuffer(8), 0, 8) },
|
|
expected: { dataView: new DataView(new SharedArrayBuffer(8), 0, 8) },
|
|
},
|
|
{
|
|
description: 'compares two SharedArrayBuffers',
|
|
actual: { typedArray: new SharedArrayBuffer(5) },
|
|
expected: { typedArray: new SharedArrayBuffer(3) },
|
|
},
|
|
{
|
|
description: 'compares two SharedArrayBuffers with data inside',
|
|
actual: (() => {
|
|
const sharedBuffer = new SharedArrayBuffer(4 * Int32Array.BYTES_PER_ELEMENT);
|
|
const sharedArray = new Int32Array(sharedBuffer);
|
|
|
|
sharedArray[0] = 1;
|
|
sharedArray[1] = 2;
|
|
sharedArray[2] = 3;
|
|
sharedArray[3] = 4;
|
|
|
|
return sharedBuffer;
|
|
})(),
|
|
expected: (() => {
|
|
const sharedBuffer = new SharedArrayBuffer(3 * Int32Array.BYTES_PER_ELEMENT);
|
|
const sharedArray = new Int32Array(sharedBuffer);
|
|
|
|
sharedArray[0] = 1;
|
|
sharedArray[1] = 2;
|
|
sharedArray[2] = 3;
|
|
|
|
return sharedBuffer;
|
|
})(),
|
|
},
|
|
{
|
|
description: 'compares two Map objects with identical entries',
|
|
actual: new Map([
|
|
['key1', 'value1'],
|
|
['key2', 'value2'],
|
|
]),
|
|
expected: new Map([
|
|
['key1', 'value1'],
|
|
['key2', 'value2'],
|
|
]),
|
|
},
|
|
{
|
|
description: 'compares two Map where one is a subset of the other',
|
|
actual: new Map([
|
|
['key1', { nested: { property: true } }],
|
|
['key2', new Set([1, 2, 3])],
|
|
['key3', new Uint8Array([1, 2, 3])],
|
|
]),
|
|
expected: new Map([
|
|
['key1', { nested: { property: true } }],
|
|
['key2', new Set([1, 2, 3])],
|
|
['key3', new Uint8Array([1, 2, 3])],
|
|
])
|
|
},
|
|
{
|
|
description: 'compares maps with object keys',
|
|
actual: new Map([
|
|
[{ a: 1 }, 'value1'],
|
|
[{ a: 2 }, 'value2'],
|
|
[{ a: 2 }, 'value3'],
|
|
[{ a: 2 }, 'value3'],
|
|
[{ a: 2 }, 'value4'],
|
|
[{ a: 1 }, 'value2'],
|
|
]),
|
|
expected: new Map([
|
|
[{ a: 2 }, 'value3'],
|
|
[{ a: 1 }, 'value1'],
|
|
[{ a: 2 }, 'value3'],
|
|
[{ a: 1 }, 'value2'],
|
|
]),
|
|
},
|
|
{
|
|
describe: 'compares two simple sparse arrays',
|
|
actual: new Array(1_000),
|
|
expected: new Array(100),
|
|
},
|
|
{
|
|
describe: 'compares two identical sparse arrays',
|
|
actual: (() => {
|
|
const array = new Array(100);
|
|
array[1] = 2;
|
|
return array;
|
|
})(),
|
|
expected: (() => {
|
|
const array = new Array(100);
|
|
array[1] = 2;
|
|
return array;
|
|
})(),
|
|
},
|
|
{
|
|
describe: 'compares two big sparse arrays',
|
|
actual: (() => {
|
|
const array = new Array(150_000_000);
|
|
array[0] = 1;
|
|
array[1] = 2;
|
|
array[100] = 100n;
|
|
array[200_000] = 3;
|
|
array[1_200_000] = 4;
|
|
array[120_200_000] = [];
|
|
return array;
|
|
})(),
|
|
expected: (() => {
|
|
const array = new Array(100_000_000);
|
|
array[0] = 1;
|
|
array[1] = 2;
|
|
array[200_000] = 3;
|
|
array[1_200_000] = 4;
|
|
return array;
|
|
})(),
|
|
},
|
|
{
|
|
describe: 'compares two array of objects',
|
|
actual: [{ a: 5 }],
|
|
expected: [{ a: 5 }],
|
|
},
|
|
{
|
|
describe: 'compares two array of objects where expected is a subset of actual',
|
|
actual: [{ a: 5 }, { b: 5 }],
|
|
expected: [{ a: 5 }],
|
|
},
|
|
{
|
|
description: 'compares two Set objects with identical objects',
|
|
actual: new Set([{ a: 1 }]),
|
|
expected: new Set([{ a: 1 }]),
|
|
},
|
|
{
|
|
description: 'compares two Set objects where expected is a subset of actual',
|
|
actual: new Set([{ a: 1 }, { b: 1 }]),
|
|
expected: new Set([{ a: 1 }]),
|
|
},
|
|
{
|
|
description: 'compares two Sets with mixed entries',
|
|
actual: new Set([{ b: 1 }, [], 1, { a: 1 }, 2, []]),
|
|
expected: new Set([{ a: 1 }, 2, []]),
|
|
},
|
|
{
|
|
description: 'compares two Sets with mixed entries different order',
|
|
actual: new Set([{ a: 1 }, 1, { b: 1 }, [], 2, { a: 1 }]),
|
|
expected: new Set([{ a: 1 }, [], 2, { a: 1 }]),
|
|
},
|
|
{
|
|
description: 'compares two Sets with mixed entries different order 2',
|
|
actual: new Set([{ a: 1 }, { a: 1 }, 1, { b: 1 }, [], 2, { a: 1 }]),
|
|
expected: new Set([{ a: 1 }, [], 2, { a: 1 }]),
|
|
},
|
|
{
|
|
description: 'compares two Set objects with identical arrays',
|
|
actual: new Set(['value1', 'value2']),
|
|
expected: new Set(['value1', 'value2']),
|
|
},
|
|
{
|
|
description: 'compares two Set objects',
|
|
actual: new Set(['value1', 'value2', 'value3']),
|
|
expected: new Set(['value1', 'value2']),
|
|
},
|
|
{
|
|
description:
|
|
'compares two Map objects from different realms with identical entries',
|
|
actual: new vm.runInNewContext(
|
|
'new Map([["key1", "value1"], ["key2", "value2"]])'
|
|
),
|
|
expected: new Map([
|
|
['key1', 'value1'],
|
|
['key2', 'value2'],
|
|
]),
|
|
},
|
|
{
|
|
description:
|
|
'compares two Map objects where expected is a subset of actual',
|
|
actual: new Map([
|
|
['key1', 'value1'],
|
|
['key2', 'value2'],
|
|
]),
|
|
expected: new Map([['key1', 'value1']]),
|
|
},
|
|
{
|
|
description:
|
|
'compares two deeply nested Maps',
|
|
actual: {
|
|
a: {
|
|
b: {
|
|
c: new Map([
|
|
['key1', 'value1'],
|
|
['key2', 'value2'],
|
|
])
|
|
},
|
|
z: [1, 2, 3]
|
|
}
|
|
},
|
|
expected: {
|
|
a: {
|
|
z: [1, 2, 3],
|
|
b: {
|
|
c: new Map([['key1', 'value1']])
|
|
}
|
|
}
|
|
},
|
|
},
|
|
{
|
|
description: 'compares Maps nested into Maps',
|
|
actual: new Map([
|
|
['key1', new Map([
|
|
['nestedKey1', 'nestedValue1'],
|
|
['nestedKey2', 'nestedValue2'],
|
|
])],
|
|
['key2', 'value2'],
|
|
]),
|
|
expected: new Map([
|
|
['key1', new Map([
|
|
['nestedKey1', 'nestedValue1'],
|
|
])],
|
|
])
|
|
},
|
|
{
|
|
description: 'compares Maps with nested arrays inside',
|
|
actual: new Map([
|
|
['key1', ['value1', 'value2']],
|
|
['key2', 'value2'],
|
|
]),
|
|
expected: new Map([
|
|
['key1', ['value1', 'value2']],
|
|
]),
|
|
},
|
|
{
|
|
description:
|
|
'compares two objects with identical getter/setter properties',
|
|
actual: (() => {
|
|
let value = 'test';
|
|
return Object.defineProperty({}, 'prop', {
|
|
get: () => value,
|
|
set: (newValue) => {
|
|
value = newValue;
|
|
},
|
|
enumerable: true,
|
|
configurable: true,
|
|
});
|
|
})(),
|
|
expected: (() => {
|
|
let value = 'test';
|
|
return Object.defineProperty({}, 'prop', {
|
|
get: () => value,
|
|
set: (newValue) => {
|
|
value = newValue;
|
|
},
|
|
enumerable: true,
|
|
configurable: true,
|
|
});
|
|
})(),
|
|
},
|
|
{
|
|
description: 'compares two objects with no prototype',
|
|
actual: { __proto__: null, prop: 'value' },
|
|
expected: { __proto__: null, prop: 'value' },
|
|
},
|
|
{
|
|
description:
|
|
'compares two objects with identical non-enumerable properties',
|
|
actual: (() => {
|
|
const obj = {};
|
|
Object.defineProperty(obj, 'hidden', {
|
|
value: 'secret',
|
|
enumerable: false,
|
|
});
|
|
return obj;
|
|
})(),
|
|
expected: (() => {
|
|
const obj = {};
|
|
Object.defineProperty(obj, 'hidden', {
|
|
value: 'secret',
|
|
enumerable: false,
|
|
});
|
|
return obj;
|
|
})(),
|
|
},
|
|
{
|
|
description: 'compares two identical primitives, string',
|
|
actual: 'foo',
|
|
expected: 'foo',
|
|
},
|
|
{
|
|
description: 'compares two identical primitives, number',
|
|
actual: 1,
|
|
expected: 1,
|
|
},
|
|
{
|
|
description: 'compares two identical primitives, boolean',
|
|
actual: false,
|
|
expected: false,
|
|
},
|
|
{
|
|
description: 'compares two identical primitives, null',
|
|
actual: null,
|
|
expected: null,
|
|
},
|
|
{
|
|
description: 'compares two identical primitives, undefined',
|
|
actual: undefined,
|
|
expected: undefined,
|
|
},
|
|
{
|
|
description: 'compares two identical primitives, Symbol',
|
|
actual: sym,
|
|
expected: sym,
|
|
},
|
|
{
|
|
description:
|
|
'compares one subset object with another',
|
|
actual: { a: 1, b: 2, c: 3 },
|
|
expected: { b: 2 },
|
|
},
|
|
{
|
|
description:
|
|
'compares one subset array with another',
|
|
actual: [1, 2, 3, 4, 5, 6, 7, 8, 9],
|
|
expected: [2, 5, 6, 7, 8],
|
|
},
|
|
{
|
|
description: 'ensures that File extends Blob',
|
|
actual: Object.getPrototypeOf(File.prototype),
|
|
expected: Blob.prototype
|
|
},
|
|
{
|
|
description: 'compares NaN with NaN',
|
|
actual: NaN,
|
|
expected: NaN,
|
|
},
|
|
{
|
|
description: 'compares two identical urls',
|
|
actual: new URL('http://foo'),
|
|
expected: new URL('http://foo'),
|
|
},
|
|
{
|
|
description: 'compares a more complex object with additional parts on the actual',
|
|
actual: [{
|
|
foo: 'yarp',
|
|
nope: {
|
|
bar: '123',
|
|
a: [ 1, 2, 0 ],
|
|
c: {},
|
|
b: [
|
|
{
|
|
foo: 'yarp',
|
|
nope: { bar: '123', a: [ 1, 2, 0 ], c: {}, b: [] }
|
|
},
|
|
{
|
|
foo: 'yarp',
|
|
nope: { bar: '123', a: [ 1, 2, 1 ], c: {}, b: [] }
|
|
},
|
|
],
|
|
}
|
|
}],
|
|
expected: [{
|
|
foo: 'yarp',
|
|
nope: {
|
|
bar: '123',
|
|
c: {},
|
|
b: [
|
|
{ foo: 'yarp', nope: { bar: '123', c: {}, b: [] } },
|
|
{ foo: 'yarp', nope: { bar: '123', c: {}, b: [] } },
|
|
],
|
|
}
|
|
}]
|
|
},
|
|
{
|
|
description: 'comparing two Errors with missing cause on the expected Error',
|
|
actual: { error: new Error('Test error 1', { cause: 42 }) },
|
|
expected: { error: new Error('Test error 1') },
|
|
},
|
|
{
|
|
description: 'comparing two Errors with cause set to undefined on the actual Error',
|
|
actual: { error: new Error('Test error 1', { cause: undefined }) },
|
|
expected: { error: new Error('Test error 1') },
|
|
},
|
|
{
|
|
description: 'comparing two Errors with missing message on the expected Error',
|
|
actual: { error: new Error('Test error 1') },
|
|
expected: { error: new Error() },
|
|
},
|
|
{
|
|
description: 'comparing two AggregateErrors with no message or errors on the expected Error',
|
|
actual: { error: new AggregateError([new Error(), 123]) },
|
|
expected: { error: new AggregateError([]) },
|
|
},
|
|
].forEach(({ description, actual, expected }) => {
|
|
it(description, () => {
|
|
assert.partialDeepStrictEqual(actual, expected);
|
|
});
|
|
});
|
|
});
|
|
});
|