diff --git a/lib/utils/client.js b/lib/utils/client.js index 70bc4a1..14e022f 100644 --- a/lib/utils/client.js +++ b/lib/utils/client.js @@ -38,7 +38,13 @@ export const isEqual = (first, second) => { // Check for Set if (first instanceof Set && second instanceof Set) { - return first.size === second.size && first.isSubsetOf(second); + if (first.size !== second.size) return false; + + // Check if all elements in first are also in second + for (const item of first) { + if (!second.has(item)) return false; + } + return true; } if (typeof first === 'object') { @@ -52,7 +58,7 @@ export const isEqual = (first, second) => { const keys = Object.keys(first); if (keys.length !== Object.keys(second).length) return false; - return keys.every(key => isEqual(first[key], second[key])); + return keys.every((key) => isEqual(first[key], second[key])); } return false; diff --git a/tests.js b/tests.js index 5875aa3..b5a7b81 100644 --- a/tests.js +++ b/tests.js @@ -4,7 +4,7 @@ import { Mongo, MongoInternals } from 'meteor/mongo'; import { MongoID } from 'meteor/mongo-id'; import { DDP } from 'meteor/ddp-client'; import { Tracker } from 'meteor/tracker'; -import { merge, extractSubscribeArguments } from './lib/utils/client'; +import { merge, extractSubscribeArguments, isEqual } from './lib/utils/client'; import { convertFilter, removeValue, trim, matchesFilter, convertObjectId, createProjection } from './lib/utils/server'; import { createKey } from './lib/utils/shared'; import { subsCache } from './lib/subs-cache'; @@ -2069,6 +2069,126 @@ if (Meteor.isServer) { test.equal(_isEqual(lodashMerged, merged), true); }) + + // Tests for isEqual function with Set compatibility + Tinytest.add('isEqual - Set equality - identical sets', function (test) { + const set1 = new Set([1, 2, 3]); + const set2 = new Set([1, 2, 3]); + test.isTrue(isEqual(set1, set2), 'Identical sets should be equal'); + }); + + Tinytest.add('isEqual - Set equality - same elements different order', function (test) { + const set1 = new Set([1, 2, 3]); + const set2 = new Set([3, 1, 2]); + test.isTrue( + isEqual(set1, set2), + 'Sets with same elements in different order should be equal' + ); + } + ); + + Tinytest.add('isEqual - Set inequality - different sizes', function (test) { + const set1 = new Set([1, 2, 3]); + const set2 = new Set([1, 2]); + test.isFalse( + isEqual(set1, set2), + 'Sets with different sizes should not be equal' + ); + }); + + Tinytest.add('isEqual - Set inequality - different elements', function (test) { + const set1 = new Set([1, 2, 3]); + const set2 = new Set([1, 2, 4]); + test.isFalse( + isEqual(set1, set2), + 'Sets with different elements should not be equal' + ); + } + ); + + Tinytest.add('isEqual - Set equality - empty sets', function (test) { + const set1 = new Set(); + const set2 = new Set(); + test.isTrue(isEqual(set1, set2), 'Empty sets should be equal'); + }); + + Tinytest.add('isEqual - Set inequality - one empty', function (test) { + const set1 = new Set(); + const set2 = new Set([1, 2, 3]); + test.isFalse( + isEqual(set1, set2), + 'Empty set should not equal non-empty set' + ); + }); + + Tinytest.add('isEqual - Set equality - with strings', function (test) { + const set1 = new Set(['a', 'b', 'c']); + const set2 = new Set(['c', 'a', 'b']); + test.isTrue( + isEqual(set1, set2), + 'Sets with same string elements should be equal' + ); + }); + + Tinytest.add('isEqual - Set equality - with objects', function (test) { + const obj1 = { id: 1, name: 'test' }; + const obj2 = { id: 2, name: 'test2' }; + const set1 = new Set([obj1, obj2]); + const set2 = new Set([obj2, obj1]); + test.isTrue( + isEqual(set1, set2), + 'Sets with same object elements should be equal' + ); + }); + + Tinytest.add('isEqual - Set inequality - with objects', function (test) { + const obj1 = { id: 1, name: 'test' }; + const obj2 = { id: 2, name: 'test2' }; + const obj3 = { id: 3, name: 'test3' }; + const set1 = new Set([obj1, obj2]); + const set2 = new Set([obj1, obj3]); + test.isFalse( + isEqual(set1, set2), + 'Sets with different object elements should not be equal' + ); + }); + + Tinytest.add('isEqual - Set vs non-Set', function (test) { + const set1 = new Set([1, 2, 3]); + const array1 = [1, 2, 3]; + test.isFalse(isEqual(set1, array1), 'Set should not equal array'); + }); + + Tinytest.add('isEqual - non-Set vs Set', function (test) { + const array1 = [1, 2, 3]; + const set1 = new Set([1, 2, 3]); + test.isFalse(isEqual(array1, set1), 'Array should not equal Set'); + }); + + Tinytest.add('isEqual - Set with duplicate values', function (test) { + // Note: Sets don't have duplicates, but testing edge case + const set1 = new Set([1, 2, 3]); + const set2 = new Set([1, 2, 3, 3]); // This will be the same as [1, 2, 3] + test.isTrue( + isEqual(set1, set2), + 'Sets should handle duplicate values correctly' + ); + }); + + Tinytest.add('isEqual - Set with undefined and null', function (test) { + const set1 = new Set([undefined, null, 0]); + const set2 = new Set([null, undefined, 0]); + test.isTrue( + isEqual(set1, set2), + 'Sets with undefined and null should be equal' + ); + }); + + Tinytest.add('isEqual - Set with NaN', function (test) { + const set1 = new Set([NaN, 1, 2]); + const set2 = new Set([1, NaN, 2]); + test.isTrue(isEqual(set1, set2), 'Sets with NaN should be equal'); + }); } Tinytest.addAsync('subscribe - .once - current user is not removed', async (test) => {