From 1532c19a0c3102845f0c9728c73696da21e1befb Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Thu, 9 May 2024 20:25:43 +0900 Subject: [PATCH] fix(expect): fix immutable.js iterable equality (#5692) --- packages/expect/src/jest-utils.ts | 47 ++++++++++++++++++++++++++++--- pnpm-lock.yaml | 10 ++++++- test/core/package.json | 1 + test/core/test/immutable.test.ts | 9 ++++++ 4 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 test/core/test/immutable.test.ts diff --git a/packages/expect/src/jest-utils.ts b/packages/expect/src/jest-utils.ts index 20e57ad31556..cb5f90b6d08b 100644 --- a/packages/expect/src/jest-utils.ts +++ b/packages/expect/src/jest-utils.ts @@ -268,7 +268,9 @@ export function hasProperty(obj: object | null, property: string): boolean { // SENTINEL constants are from https://github.com/facebook/immutable-js const IS_KEYED_SENTINEL = '@@__IMMUTABLE_KEYED__@@' const IS_SET_SENTINEL = '@@__IMMUTABLE_SET__@@' +const IS_LIST_SENTINEL = '@@__IMMUTABLE_LIST__@@' const IS_ORDERED_SENTINEL = '@@__IMMUTABLE_ORDERED__@@' +const IS_RECORD_SYMBOL = '@@__IMMUTABLE_RECORD__@@' export function isImmutableUnorderedKeyed(maybeKeyed: any) { return !!( @@ -286,6 +288,36 @@ export function isImmutableUnorderedSet(maybeSet: any) { ) } +function isObjectLiteral(source: unknown): source is Record { + return source != null && typeof source === 'object' && !Array.isArray(source) +} + +function isImmutableList(source: unknown): boolean { + return Boolean(source && isObjectLiteral(source) && source[IS_LIST_SENTINEL]) +} + +function isImmutableOrderedKeyed(source: unknown): boolean { + return Boolean( + source + && isObjectLiteral(source) + && source[IS_KEYED_SENTINEL] + && source[IS_ORDERED_SENTINEL], + ) +} + +function isImmutableOrderedSet(source: unknown): boolean { + return Boolean( + source + && isObjectLiteral(source) + && source[IS_SET_SENTINEL] + && source[IS_ORDERED_SENTINEL], + ) +} + +function isImmutableRecord(source: unknown): boolean { + return Boolean(source && isObjectLiteral(source) && source[IS_RECORD_SYMBOL]) +} + /** * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. * @@ -411,10 +443,17 @@ export function iterableEquality(a: any, b: any, customTesters: Array = if (!bIterator.next().done) return false - const aEntries = Object.entries(a) - const bEntries = Object.entries(b) - if (!equals(aEntries, bEntries)) - return false + if ( + !isImmutableList(a) + && !isImmutableOrderedKeyed(a) + && !isImmutableOrderedSet(a) + && !isImmutableRecord(a) + ) { + const aEntries = Object.entries(a) + const bEntries = Object.entries(b) + if (!equals(aEntries, bEntries)) + return false + } // Remove the first value from the stack of traversed values. aStack.pop() diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 13bc6e06b69a..9be9f82a1b48 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1166,6 +1166,9 @@ importers: debug: specifier: ^4.3.4 version: 4.3.4(supports-color@8.1.1) + immutable: + specifier: 5.0.0-beta.5 + version: 5.0.0-beta.5 strip-ansi: specifier: ^7.1.0 version: 7.1.0 @@ -10996,6 +10999,10 @@ packages: engines: {node: '>= 4'} dev: true + /immutable@5.0.0-beta.5: + resolution: {integrity: sha512-1RO6wxfJdh/uyWb2MTn3RuCPXYmpRiAhoKm8vEnA50+2Gy0j++6GBtu5q6sq2d4tpcL+e1sCHzk8NkWnRhT2/Q==} + dev: true + /import-fresh@3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} @@ -16374,7 +16381,7 @@ packages: '@vue/composition-api': optional: true dependencies: - vue: 3.4.26(typescript@5.4.5) + vue: 3.4.26(typescript@5.2.2) dev: true /vue-eslint-parser@9.4.2(eslint@9.1.0): @@ -16911,6 +16918,7 @@ packages: /workbox-google-analytics@7.0.0: resolution: {integrity: sha512-MEYM1JTn/qiC3DbpvP2BVhyIH+dV/5BjHk756u9VbwuAhu0QHyKscTnisQuz21lfRpOwiS9z4XdqeVAKol0bzg==} + deprecated: It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained dependencies: workbox-background-sync: 7.0.0 workbox-core: 7.0.0 diff --git a/test/core/package.json b/test/core/package.json index 53e5fce5b0a5..b06f3139a57c 100644 --- a/test/core/package.json +++ b/test/core/package.json @@ -21,6 +21,7 @@ "@vueuse/integrations": "^10.9.0", "axios": "^0.26.1", "debug": "^4.3.4", + "immutable": "5.0.0-beta.5", "strip-ansi": "^7.1.0", "sweetalert2": "^11.6.16", "tinyspy": "^1.0.2", diff --git a/test/core/test/immutable.test.ts b/test/core/test/immutable.test.ts new file mode 100644 index 000000000000..b15c939a94d8 --- /dev/null +++ b/test/core/test/immutable.test.ts @@ -0,0 +1,9 @@ +import { expect, test } from 'vitest' +import im from 'immutable' + +test('basic', () => { + expect(im.List([{ x: 1 }])).toEqual(im.List([{ x: 1 }])) + expect(im.List([{ x: 1 }])).toEqual(im.List([1]).map(i => ({ x: i }))) + expect(im.List([{ x: 1 }])).not.toEqual(im.List([{ x: 2 }])) + expect(im.List([{ x: 1 }])).not.toEqual(im.List([])) +})