From 4581f566236ed6178386c2909f1b6c74424506da Mon Sep 17 00:00:00 2001 From: eps1lon Date: Tue, 19 Jan 2021 11:29:07 +0100 Subject: [PATCH 1/5] Revert "You're killing me, Jest" This reverts commit 9fd67355f9e9ccfde628dbaf1195cc60ebeb1dca. --- .../__tests__/legacy/inspectElement-test.js | 240 +++++++++--------- 1 file changed, 113 insertions(+), 127 deletions(-) diff --git a/packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js b/packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js index b01d9c0fe9c5a..213188c011e79 100644 --- a/packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js +++ b/packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js @@ -207,133 +207,119 @@ describe('InspectedElementContext', () => { const id = ((store.getElementIDAtIndex(0): any): number); const inspectedElement = await read(id); - const { - anonymous_fn, - array_buffer, - array_of_arrays, - big_int, - bound_fn, - data_view, - date, - fn, - html_element, - immutable, - map, - map_of_maps, - object_of_objects, - react_element, - regexp, - set, - set_of_sets, - symbol, - typed_array, - } = inspectedElement.props; - - const {meta} = require('react-devtools-shared/src/hydration'); - - expect(anonymous_fn[meta.inspectable]).toBe(false); - expect(anonymous_fn[meta.name]).toBe('function'); - expect(anonymous_fn[meta.type]).toBe('function'); - expect(anonymous_fn[meta.preview_long]).toBe('ƒ () {}'); - expect(anonymous_fn[meta.preview_short]).toBe('ƒ () {}'); - - expect(array_buffer[meta.size]).toBe(3); - expect(array_buffer[meta.inspectable]).toBe(false); - expect(array_buffer[meta.name]).toBe('ArrayBuffer'); - expect(array_buffer[meta.type]).toBe('array_buffer'); - expect(array_buffer[meta.preview_short]).toBe('ArrayBuffer(3)'); - expect(array_buffer[meta.preview_long]).toBe('ArrayBuffer(3)'); - - expect(array_of_arrays[0][meta.size]).toBe(2); - expect(array_of_arrays[0][meta.inspectable]).toBe(true); - expect(array_of_arrays[0][meta.name]).toBe('Array'); - expect(array_of_arrays[0][meta.type]).toBe('array'); - expect(array_of_arrays[0][meta.preview_long]).toBe('[Array(3), Array(0)]'); - expect(array_of_arrays[0][meta.preview_short]).toBe('Array(2)'); - - expect(big_int[meta.inspectable]).toBe(false); - expect(big_int[meta.name]).toBe('123'); - expect(big_int[meta.type]).toBe('bigint'); - - expect(bound_fn[meta.inspectable]).toBe(false); - expect(bound_fn[meta.name]).toBe('bound exampleFunction'); - expect(bound_fn[meta.type]).toBe('function'); - expect(bound_fn[meta.preview_long]).toBe('ƒ bound exampleFunction() {}'); - expect(bound_fn[meta.preview_short]).toBe('ƒ bound exampleFunction() {}'); - - expect(data_view[meta.size]).toBe(3); - expect(data_view[meta.inspectable]).toBe(false); - expect(data_view[meta.name]).toBe('DataView'); - expect(data_view[meta.type]).toBe('data_view'); - - expect(date[meta.inspectable]).toBe(false); - expect(date[meta.type]).toBe('date'); - - expect(fn[meta.inspectable]).toBe(false); - expect(fn[meta.name]).toBe('exampleFunction'); - expect(fn[meta.type]).toBe('function'); - expect(fn[meta.preview_long]).toBe('ƒ exampleFunction() {}'); - expect(fn[meta.preview_short]).toBe('ƒ exampleFunction() {}'); - - expect(html_element[meta.inspectable]).toBe(false); - expect(html_element[meta.name]).toBe('DIV'); - expect(html_element[meta.type]).toBe('html_element'); - - expect(immutable[meta.inspectable]).toBeUndefined(); // Complex type - expect(immutable[meta.name]).toBe('Map'); - expect(immutable[meta.type]).toBe('iterator'); - - expect(map[meta.inspectable]).toBeUndefined(); // Complex type - expect(map[meta.name]).toBe('Map'); - expect(map[meta.type]).toBe('iterator'); - expect(map[0][meta.type]).toBe('array'); - - expect(map_of_maps[meta.inspectable]).toBeUndefined(); // Complex type - expect(map_of_maps[meta.name]).toBe('Map'); - expect(map_of_maps[meta.type]).toBe('iterator'); - expect(map_of_maps[0][meta.type]).toBe('array'); - - expect(object_of_objects.inner[meta.size]).toBe(3); - expect(object_of_objects.inner[meta.inspectable]).toBe(true); - expect(object_of_objects.inner[meta.name]).toBe(''); - expect(object_of_objects.inner[meta.type]).toBe('object'); - expect(object_of_objects.inner[meta.preview_long]).toBe( - '{boolean: true, number: 123, string: "abc"}', - ); - expect(object_of_objects.inner[meta.preview_short]).toBe('{…}'); - - expect(react_element[meta.inspectable]).toBe(false); - expect(react_element[meta.name]).toBe('span'); - expect(react_element[meta.type]).toBe('react_element'); - - expect(regexp[meta.inspectable]).toBe(false); - expect(regexp[meta.name]).toBe('/abc/giu'); - expect(regexp[meta.preview_long]).toBe('/abc/giu'); - expect(regexp[meta.preview_short]).toBe('/abc/giu'); - expect(regexp[meta.type]).toBe('regexp'); - - expect(set[meta.inspectable]).toBeUndefined(); // Complex type - expect(set[meta.name]).toBe('Set'); - expect(set[meta.type]).toBe('iterator'); - expect(set[0]).toBe('abc'); - expect(set[1]).toBe(123); - - expect(set_of_sets[meta.inspectable]).toBeUndefined(); // Complex type - expect(set_of_sets[meta.name]).toBe('Set'); - expect(set_of_sets[meta.type]).toBe('iterator'); - expect(set_of_sets['0'][meta.inspectable]).toBe(true); - - expect(symbol[meta.inspectable]).toBe(false); - expect(symbol[meta.name]).toBe('Symbol(symbol)'); - expect(symbol[meta.type]).toBe('symbol'); - - expect(typed_array[meta.inspectable]).toBeUndefined(); // Complex type - expect(typed_array[meta.size]).toBe(3); - expect(typed_array[meta.name]).toBe('Int8Array'); - expect(typed_array[meta.type]).toBe('typed_array'); - expect(typed_array[0]).toBe(100); - expect(typed_array[1]).toBe(-100); - expect(typed_array[2]).toBe(0); + expect(inspectedElement.props).toMatchInlineSnapshot(` + Object { + "anonymous_fn": Dehydrated { + "preview_short": ƒ () {}, + "preview_long": ƒ () {}, + }, + "array_buffer": Dehydrated { + "preview_short": ArrayBuffer(3), + "preview_long": ArrayBuffer(3), + }, + "array_of_arrays": Array [ + Dehydrated { + "preview_short": Array(2), + "preview_long": [Array(3), Array(0)], + }, + ], + "big_int": Dehydrated { + "preview_short": 123n, + "preview_long": 123n, + }, + "bound_fn": Dehydrated { + "preview_short": ƒ bound exampleFunction() {}, + "preview_long": ƒ bound exampleFunction() {}, + }, + "data_view": Dehydrated { + "preview_short": DataView(3), + "preview_long": DataView(3), + }, + "date": Dehydrated { + "preview_short": Wed Dec 31 1969 19:00:00 GMT-0500 (Eastern Standard Time), + "preview_long": Wed Dec 31 1969 19:00:00 GMT-0500 (Eastern Standard Time), + }, + "fn": Dehydrated { + "preview_short": ƒ exampleFunction() {}, + "preview_long": ƒ exampleFunction() {}, + }, + "html_element": Dehydrated { + "preview_short":
, + "preview_long":
, + }, + "immutable": Object { + "0": Dehydrated { + "preview_short": Array(2), + "preview_long": ["a", List(3)], + }, + "1": Dehydrated { + "preview_short": Array(2), + "preview_long": ["b", 123], + }, + "2": Dehydrated { + "preview_short": Array(2), + "preview_long": ["c", Map(2)], + }, + }, + "map": Object { + "0": Dehydrated { + "preview_short": Array(2), + "preview_long": ["name", "Brian"], + }, + "1": Dehydrated { + "preview_short": Array(2), + "preview_long": ["food", "sushi"], + }, + }, + "map_of_maps": Object { + "0": Dehydrated { + "preview_short": Array(2), + "preview_long": ["first", Map(2)], + }, + "1": Dehydrated { + "preview_short": Array(2), + "preview_long": ["second", Map(2)], + }, + }, + "object_of_objects": Object { + "inner": Dehydrated { + "preview_short": {…}, + "preview_long": {boolean: true, number: 123, string: "abc"}, + }, + }, + "react_element": Dehydrated { + "preview_short": , + "preview_long": , + }, + "regexp": Dehydrated { + "preview_short": /abc/giu, + "preview_long": /abc/giu, + }, + "set": Object { + "0": "abc", + "1": 123, + }, + "set_of_sets": Object { + "0": Dehydrated { + "preview_short": Set(3), + "preview_long": Set(3) {"a", "b", "c"}, + }, + "1": Dehydrated { + "preview_short": Set(3), + "preview_long": Set(3) {1, 2, 3}, + }, + }, + "symbol": Dehydrated { + "preview_short": Symbol(symbol), + "preview_long": Symbol(symbol), + }, + "typed_array": Object { + "0": 100, + "1": -100, + "2": 0, + }, + } + `); }); it('should support objects with no prototype', async () => { From a579f5d88f48c738263a6bcc9c73ffea0c8869bf Mon Sep 17 00:00:00 2001 From: eps1lon Date: Tue, 19 Jan 2021 12:06:28 +0100 Subject: [PATCH 2/5] Fix false-positive snapshot mismatch Same reason why jest can fail with "could not find all inline snapshots". Since we don't need "done()" on async tests we can safely remove it. --- .../__tests__/dehydratedValueSerializer.js | 6 +- .../src/__tests__/inspectedElement-test.js | 350 ++++++++---------- .../__tests__/inspectedElementSerializer.js | 20 +- .../__tests__/legacy/inspectElement-test.js | 4 +- .../__tests__/treeContextStateSerializer.js | 13 +- 5 files changed, 180 insertions(+), 213 deletions(-) diff --git a/packages/react-devtools-shared/src/__tests__/dehydratedValueSerializer.js b/packages/react-devtools-shared/src/__tests__/dehydratedValueSerializer.js index d8eac57df035c..23a9a1af02ef2 100644 --- a/packages/react-devtools-shared/src/__tests__/dehydratedValueSerializer.js +++ b/packages/react-devtools-shared/src/__tests__/dehydratedValueSerializer.js @@ -10,10 +10,14 @@ // test() is part of Jest's serializer API export function test(maybeDehydratedValue) { const {meta} = require('react-devtools-shared/src/hydration'); + + const hasOwnProperty = Object.prototype.hasOwnProperty.bind( + maybeDehydratedValue, + ); return ( maybeDehydratedValue !== null && typeof maybeDehydratedValue === 'object' && - maybeDehydratedValue.hasOwnProperty(meta.inspectable) && + hasOwnProperty(meta.inspectable) && maybeDehydratedValue[meta.inspected] !== true ); } diff --git a/packages/react-devtools-shared/src/__tests__/inspectedElement-test.js b/packages/react-devtools-shared/src/__tests__/inspectedElement-test.js index 60119df3a972b..5b08238498e68 100644 --- a/packages/react-devtools-shared/src/__tests__/inspectedElement-test.js +++ b/packages/react-devtools-shared/src/__tests__/inspectedElement-test.js @@ -20,7 +20,6 @@ describe('InspectedElement', () => { let TestRenderer: ReactTestRenderer; let bridge: FrontendBridge; let store: Store; - let meta; let utils; let BridgeContext; @@ -39,8 +38,6 @@ describe('InspectedElement', () => { utils = require('./utils'); utils.beforeEachProfiling(); - meta = require('react-devtools-shared/src/hydration').meta; - bridge = global.bridge; store = global.store; store.collapseNodesByDefault = false; @@ -442,18 +439,21 @@ describe('InspectedElement', () => { const inspectedElement = await inspectElementAtIndex(0); - const {props} = (inspectedElement: any); - expect(props.boolean_false).toBe(false); - expect(props.boolean_true).toBe(true); - expect(Number.isFinite(props.infinity)).toBe(false); - expect(props.integer_zero).toEqual(0); - expect(props.integer_one).toEqual(1); - expect(props.float).toEqual(1.23); - expect(props.string).toEqual('abc'); - expect(props.string_empty).toEqual(''); - expect(props.nan).toBeNaN(); - expect(props.value_null).toBeNull(); - expect(props.value_undefined).toBeUndefined(); + expect(inspectedElement.props).toMatchInlineSnapshot(` + Object { + "boolean_false": false, + "boolean_true": true, + "float": 1.23, + "infinity": Infinity, + "integer_one": 1, + "integer_zero": 0, + "nan": NaN, + "string": "abc", + "string_empty": "", + "value_null": null, + "value_undefined": undefined, + } + `); }); it('should support complex data types', async () => { @@ -539,175 +539,126 @@ describe('InspectedElement', () => { const inspectedElement = await inspectElementAtIndex(0); - const { - anonymous_fn, - array_buffer, - array_of_arrays, - big_int, - bound_fn, - data_view, - date, - fn, - html_element, - immutable, - map, - map_of_maps, - object_of_objects, - object_with_symbol, - proxy, - react_element, - regexp, - set, - set_of_sets, - symbol, - typed_array, - } = (inspectedElement: any).props; - - expect(anonymous_fn[meta.inspectable]).toBe(false); - expect(anonymous_fn[meta.name]).toBe('function'); - expect(anonymous_fn[meta.type]).toBe('function'); - expect(anonymous_fn[meta.preview_long]).toBe('ƒ () {}'); - expect(anonymous_fn[meta.preview_short]).toBe('ƒ () {}'); - - expect(array_buffer[meta.size]).toBe(3); - expect(array_buffer[meta.inspectable]).toBe(false); - expect(array_buffer[meta.name]).toBe('ArrayBuffer'); - expect(array_buffer[meta.type]).toBe('array_buffer'); - expect(array_buffer[meta.preview_short]).toBe('ArrayBuffer(3)'); - expect(array_buffer[meta.preview_long]).toBe('ArrayBuffer(3)'); - - expect(array_of_arrays[0][meta.size]).toBe(2); - expect(array_of_arrays[0][meta.inspectable]).toBe(true); - expect(array_of_arrays[0][meta.name]).toBe('Array'); - expect(array_of_arrays[0][meta.type]).toBe('array'); - expect(array_of_arrays[0][meta.preview_long]).toBe('[Array(3), Array(0)]'); - expect(array_of_arrays[0][meta.preview_short]).toBe('Array(2)'); - - expect(big_int[meta.inspectable]).toBe(false); - expect(big_int[meta.name]).toBe('123'); - expect(big_int[meta.type]).toBe('bigint'); - expect(big_int[meta.preview_long]).toBe('123n'); - expect(big_int[meta.preview_short]).toBe('123n'); - - expect(bound_fn[meta.inspectable]).toBe(false); - expect(bound_fn[meta.name]).toBe('bound exampleFunction'); - expect(bound_fn[meta.type]).toBe('function'); - expect(bound_fn[meta.preview_long]).toBe('ƒ bound exampleFunction() {}'); - expect(bound_fn[meta.preview_short]).toBe('ƒ bound exampleFunction() {}'); - - expect(data_view[meta.size]).toBe(3); - expect(data_view[meta.inspectable]).toBe(false); - expect(data_view[meta.name]).toBe('DataView'); - expect(data_view[meta.type]).toBe('data_view'); - expect(data_view[meta.preview_long]).toBe('DataView(3)'); - expect(data_view[meta.preview_short]).toBe('DataView(3)'); - - expect(date[meta.inspectable]).toBe(false); - expect(date[meta.type]).toBe('date'); - expect(new Date(date[meta.preview_long]).toISOString()).toBe( - exampleDateISO, - ); - expect(new Date(date[meta.preview_short]).toISOString()).toBe( - exampleDateISO, - ); - - expect(fn[meta.inspectable]).toBe(false); - expect(fn[meta.name]).toBe('exampleFunction'); - expect(fn[meta.type]).toBe('function'); - expect(fn[meta.preview_long]).toBe('ƒ exampleFunction() {}'); - expect(fn[meta.preview_short]).toBe('ƒ exampleFunction() {}'); - - expect(html_element[meta.inspectable]).toBe(false); - expect(html_element[meta.name]).toBe('DIV'); - expect(html_element[meta.type]).toBe('html_element'); - expect(html_element[meta.preview_long]).toBe('
'); - expect(html_element[meta.preview_short]).toBe('
'); - - expect(immutable[meta.inspectable]).toBeUndefined(); // Complex type - expect(immutable[meta.name]).toBe('Map'); - expect(immutable[meta.type]).toBe('iterator'); - expect(immutable[meta.preview_long]).toBe( - 'Map(3) {"a" => List(3), "b" => 123, "c" => Map(2)}', - ); - expect(immutable[meta.preview_short]).toBe('Map(3)'); - - expect(map[meta.inspectable]).toBeUndefined(); // Complex type - expect(map[meta.name]).toBe('Map'); - expect(map[meta.type]).toBe('iterator'); - expect(map[0][meta.type]).toBe('array'); - expect(map[meta.preview_long]).toBe( - 'Map(2) {"name" => "Brian", "food" => "sushi"}', - ); - expect(map[meta.preview_short]).toBe('Map(2)'); - - expect(map_of_maps[meta.inspectable]).toBeUndefined(); // Complex type - expect(map_of_maps[meta.name]).toBe('Map'); - expect(map_of_maps[meta.type]).toBe('iterator'); - expect(map_of_maps[0][meta.type]).toBe('array'); - expect(map_of_maps[meta.preview_long]).toBe( - 'Map(2) {"first" => Map(2), "second" => Map(2)}', - ); - expect(map_of_maps[meta.preview_short]).toBe('Map(2)'); - - expect(object_of_objects.inner[meta.size]).toBe(3); - expect(object_of_objects.inner[meta.inspectable]).toBe(true); - expect(object_of_objects.inner[meta.name]).toBe(''); - expect(object_of_objects.inner[meta.type]).toBe('object'); - expect(object_of_objects.inner[meta.preview_long]).toBe( - '{boolean: true, number: 123, string: "abc"}', - ); - expect(object_of_objects.inner[meta.preview_short]).toBe('{…}'); - - expect(object_with_symbol['Symbol(name)']).toBe('hello'); - - expect(proxy[meta.inspectable]).toBe(false); - expect(proxy[meta.name]).toBe('function'); - expect(proxy[meta.type]).toBe('function'); - expect(proxy[meta.preview_long]).toBe('ƒ () {}'); - expect(proxy[meta.preview_short]).toBe('ƒ () {}'); - - expect(react_element[meta.inspectable]).toBe(false); - expect(react_element[meta.name]).toBe('span'); - expect(react_element[meta.type]).toBe('react_element'); - expect(react_element[meta.preview_long]).toBe(''); - expect(react_element[meta.preview_short]).toBe(''); - - expect(regexp[meta.inspectable]).toBe(false); - expect(regexp[meta.name]).toBe('/abc/giu'); - expect(regexp[meta.preview_long]).toBe('/abc/giu'); - expect(regexp[meta.preview_short]).toBe('/abc/giu'); - expect(regexp[meta.type]).toBe('regexp'); - - expect(set[meta.inspectable]).toBeUndefined(); // Complex type - expect(set[meta.name]).toBe('Set'); - expect(set[meta.type]).toBe('iterator'); - expect(set[0]).toBe('abc'); - expect(set[1]).toBe(123); - expect(set[meta.preview_long]).toBe('Set(2) {"abc", 123}'); - expect(set[meta.preview_short]).toBe('Set(2)'); - - expect(set_of_sets[meta.inspectable]).toBeUndefined(); // Complex type - expect(set_of_sets[meta.name]).toBe('Set'); - expect(set_of_sets[meta.type]).toBe('iterator'); - expect(set_of_sets['0'][meta.inspectable]).toBe(true); - expect(set_of_sets[meta.preview_long]).toBe('Set(2) {Set(3), Set(3)}'); - expect(set_of_sets[meta.preview_short]).toBe('Set(2)'); - - expect(symbol[meta.inspectable]).toBe(false); - expect(symbol[meta.name]).toBe('Symbol(symbol)'); - expect(symbol[meta.type]).toBe('symbol'); - expect(symbol[meta.preview_long]).toBe('Symbol(symbol)'); - expect(symbol[meta.preview_short]).toBe('Symbol(symbol)'); - - expect(typed_array[meta.inspectable]).toBeUndefined(); // Complex type - expect(typed_array[meta.size]).toBe(3); - expect(typed_array[meta.name]).toBe('Int8Array'); - expect(typed_array[meta.type]).toBe('typed_array'); - expect(typed_array[0]).toBe(100); - expect(typed_array[1]).toBe(-100); - expect(typed_array[2]).toBe(0); - expect(typed_array[meta.preview_long]).toBe('Int8Array(3) [100, -100, 0]'); - expect(typed_array[meta.preview_short]).toBe('Int8Array(3)'); + expect(inspectedElement.props).toMatchInlineSnapshot(` + Object { + "anonymous_fn": Dehydrated { + "preview_short": ƒ () {}, + "preview_long": ƒ () {}, + }, + "array_buffer": Dehydrated { + "preview_short": ArrayBuffer(3), + "preview_long": ArrayBuffer(3), + }, + "array_of_arrays": Array [ + Dehydrated { + "preview_short": Array(2), + "preview_long": [Array(3), Array(0)], + }, + ], + "big_int": Dehydrated { + "preview_short": 123n, + "preview_long": 123n, + }, + "bound_fn": Dehydrated { + "preview_short": ƒ bound exampleFunction() {}, + "preview_long": ƒ bound exampleFunction() {}, + }, + "data_view": Dehydrated { + "preview_short": DataView(3), + "preview_long": DataView(3), + }, + "date": Dehydrated { + "preview_short": Wed Jan 01 2020 00:42:42 GMT+0100 (Central European Standard Time), + "preview_long": Wed Jan 01 2020 00:42:42 GMT+0100 (Central European Standard Time), + }, + "fn": Dehydrated { + "preview_short": ƒ exampleFunction() {}, + "preview_long": ƒ exampleFunction() {}, + }, + "html_element": Dehydrated { + "preview_short":
, + "preview_long":
, + }, + "immutable": Object { + "0": Dehydrated { + "preview_short": Array(2), + "preview_long": ["a", List(3)], + }, + "1": Dehydrated { + "preview_short": Array(2), + "preview_long": ["b", 123], + }, + "2": Dehydrated { + "preview_short": Array(2), + "preview_long": ["c", Map(2)], + }, + }, + "map": Object { + "0": Dehydrated { + "preview_short": Array(2), + "preview_long": ["name", "Brian"], + }, + "1": Dehydrated { + "preview_short": Array(2), + "preview_long": ["food", "sushi"], + }, + }, + "map_of_maps": Object { + "0": Dehydrated { + "preview_short": Array(2), + "preview_long": ["first", Map(2)], + }, + "1": Dehydrated { + "preview_short": Array(2), + "preview_long": ["second", Map(2)], + }, + }, + "object_of_objects": Object { + "inner": Dehydrated { + "preview_short": {…}, + "preview_long": {boolean: true, number: 123, string: "abc"}, + }, + }, + "object_with_symbol": Object { + "Symbol(name)": "hello", + }, + "proxy": Dehydrated { + "preview_short": ƒ () {}, + "preview_long": ƒ () {}, + }, + "react_element": Dehydrated { + "preview_short": , + "preview_long": , + }, + "regexp": Dehydrated { + "preview_short": /abc/giu, + "preview_long": /abc/giu, + }, + "set": Object { + "0": "abc", + "1": 123, + }, + "set_of_sets": Object { + "0": Dehydrated { + "preview_short": Set(3), + "preview_long": Set(3) {"a", "b", "c"}, + }, + "1": Dehydrated { + "preview_short": Set(3), + "preview_long": Set(3) {1, 2, 3}, + }, + }, + "symbol": Dehydrated { + "preview_short": Symbol(symbol), + "preview_long": Symbol(symbol), + }, + "typed_array": Object { + "0": 100, + "1": -100, + "2": 0, + }, + } + `); }); it('should not consume iterables while inspecting', async () => { @@ -725,13 +676,14 @@ describe('InspectedElement', () => { ); const inspectedElement = await inspectElementAtIndex(0); - - const {prop} = (inspectedElement: any).props; - expect(prop[meta.inspectable]).toBe(false); - expect(prop[meta.name]).toBe('Generator'); - expect(prop[meta.type]).toBe('opaque_iterator'); - expect(prop[meta.preview_long]).toBe('Generator'); - expect(prop[meta.preview_short]).toBe('Generator'); + expect(inspectedElement.props).toMatchInlineSnapshot(` + Object { + "prop": Dehydrated { + "preview_short": Generator, + "preview_long": Generator, + }, + } + `); }); it('should support objects with no prototype', async () => { @@ -774,10 +726,14 @@ describe('InspectedElement', () => { const inspectedElement = await inspectElementAtIndex(0); - // TRICKY: Don't use toMatchInlineSnapshot() for this test! - // Our snapshot serializer relies on hasOwnProperty() for feature detection. - expect(inspectedElement.props.object.name).toBe('blah'); - expect(inspectedElement.props.object.hasOwnProperty).toBe(true); + expect(inspectedElement.props).toMatchInlineSnapshot(` + Object { + "object": Object { + "hasOwnProperty": true, + "name": "blah", + }, + } + `); }); it('should support custom objects with enumerable properties and getters', async () => { @@ -1834,8 +1790,8 @@ describe('InspectedElement', () => { ReactDOM.render(, container), ); - const inspectedElement = await inspectElementAtIndex(0); - expect(inspectedElement.hooks).toMatchInlineSnapshot(` + const {hooks} = await inspectElementAtIndex(0); + expect(hooks).toMatchInlineSnapshot(` Array [ Object { "id": null, diff --git a/packages/react-devtools-shared/src/__tests__/inspectedElementSerializer.js b/packages/react-devtools-shared/src/__tests__/inspectedElementSerializer.js index a615777421fe3..db75d9e150880 100644 --- a/packages/react-devtools-shared/src/__tests__/inspectedElementSerializer.js +++ b/packages/react-devtools-shared/src/__tests__/inspectedElementSerializer.js @@ -1,12 +1,20 @@ // test() is part of Jest's serializer API export function test(maybeInspectedElement) { + if ( + maybeInspectedElement === null || + typeof maybeInspectedElement !== 'object' + ) { + return false; + } + + const hasOwnProperty = Object.prototype.hasOwnProperty.bind( + maybeInspectedElement, + ); return ( - maybeInspectedElement !== null && - typeof maybeInspectedElement === 'object' && - maybeInspectedElement.hasOwnProperty('canEditFunctionProps') && - maybeInspectedElement.hasOwnProperty('canEditHooks') && - maybeInspectedElement.hasOwnProperty('canToggleSuspense') && - maybeInspectedElement.hasOwnProperty('canViewSource') + hasOwnProperty('canEditFunctionProps') && + hasOwnProperty('canEditHooks') && + hasOwnProperty('canToggleSuspense') && + hasOwnProperty('canViewSource') ); } diff --git a/packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js b/packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js index 213188c011e79..5790cd2fc0c99 100644 --- a/packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js +++ b/packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js @@ -236,8 +236,8 @@ describe('InspectedElementContext', () => { "preview_long": DataView(3), }, "date": Dehydrated { - "preview_short": Wed Dec 31 1969 19:00:00 GMT-0500 (Eastern Standard Time), - "preview_long": Wed Dec 31 1969 19:00:00 GMT-0500 (Eastern Standard Time), + "preview_short": Thu Jan 01 1970 01:00:00 GMT+0100 (Central European Standard Time), + "preview_long": Thu Jan 01 1970 01:00:00 GMT+0100 (Central European Standard Time), }, "fn": Dehydrated { "preview_short": ƒ exampleFunction() {}, diff --git a/packages/react-devtools-shared/src/__tests__/treeContextStateSerializer.js b/packages/react-devtools-shared/src/__tests__/treeContextStateSerializer.js index 866d4ed4c3662..06c593ed7a1ac 100644 --- a/packages/react-devtools-shared/src/__tests__/treeContextStateSerializer.js +++ b/packages/react-devtools-shared/src/__tests__/treeContextStateSerializer.js @@ -2,15 +2,14 @@ import {printStore} from 'react-devtools-shared/src/devtools/utils'; // test() is part of Jest's serializer API export function test(maybeState) { - if (maybeState === null || typeof maybeState !== 'object') { - return false; - } - + const hasOwnProperty = Object.prototype.hasOwnProperty.bind(maybeState); // Duck typing at its finest. return ( - maybeState.hasOwnProperty('inspectedElementID') && - maybeState.hasOwnProperty('ownerFlatTree') && - maybeState.hasOwnProperty('ownerSubtreeLeafElementID') + maybeState !== null && + typeof maybeState === 'object' && + hasOwnProperty('inspectedElementID') && + hasOwnProperty('ownerFlatTree') && + hasOwnProperty('ownerSubtreeLeafElementID') ); } From 9c0650ba38cee936207afa8087cdc74f4f0b9e62 Mon Sep 17 00:00:00 2001 From: eps1lon Date: Tue, 19 Jan 2021 12:21:45 +0100 Subject: [PATCH 3/5] Fix date mismatch --- .../src/__tests__/dehydratedValueSerializer.js | 16 ++++++++++++++-- .../src/__tests__/inspectedElement-test.js | 4 ++-- .../src/__tests__/legacy/inspectElement-test.js | 4 ++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/packages/react-devtools-shared/src/__tests__/dehydratedValueSerializer.js b/packages/react-devtools-shared/src/__tests__/dehydratedValueSerializer.js index 23a9a1af02ef2..c621d05705e99 100644 --- a/packages/react-devtools-shared/src/__tests__/dehydratedValueSerializer.js +++ b/packages/react-devtools-shared/src/__tests__/dehydratedValueSerializer.js @@ -22,6 +22,18 @@ export function test(maybeDehydratedValue) { ); } +function serializeDehydratedValuePreview(preview) { + const date = new Date(preview); + const isDatePreview = !Number.isNaN(date.valueOf()); + if (isDatePreview) { + // The preview is just `String(date)` which formats the date in the local timezone. + // This results in a snapshot mismatch between tests run in e.g. GMT and ET + // WARNING: This does not guard against dates created with the default timezone i.e. the local timezone e.g. new Date('05 October 2011 14:48'). + return date.toISOString(); + } + return preview; +} + // print() is part of Jest's serializer API export function print(dehydratedValue, serialize, indent) { const {meta} = require('react-devtools-shared/src/hydration'); @@ -31,11 +43,11 @@ export function print(dehydratedValue, serialize, indent) { 'Dehydrated {\n' + paddingLeft + ' "preview_short": ' + - dehydratedValue[meta.preview_short] + + serializeDehydratedValuePreview(dehydratedValue[meta.preview_short]) + ',\n' + paddingLeft + ' "preview_long": ' + - dehydratedValue[meta.preview_long] + + serializeDehydratedValuePreview(dehydratedValue[meta.preview_long]) + ',\n' + paddingLeft + '}' diff --git a/packages/react-devtools-shared/src/__tests__/inspectedElement-test.js b/packages/react-devtools-shared/src/__tests__/inspectedElement-test.js index 5b08238498e68..f3fc7c33b2212 100644 --- a/packages/react-devtools-shared/src/__tests__/inspectedElement-test.js +++ b/packages/react-devtools-shared/src/__tests__/inspectedElement-test.js @@ -568,8 +568,8 @@ describe('InspectedElement', () => { "preview_long": DataView(3), }, "date": Dehydrated { - "preview_short": Wed Jan 01 2020 00:42:42 GMT+0100 (Central European Standard Time), - "preview_long": Wed Jan 01 2020 00:42:42 GMT+0100 (Central European Standard Time), + "preview_short": 2019-12-31T23:42:42.000Z, + "preview_long": 2019-12-31T23:42:42.000Z, }, "fn": Dehydrated { "preview_short": ƒ exampleFunction() {}, diff --git a/packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js b/packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js index 5790cd2fc0c99..49acc9654f5ea 100644 --- a/packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js +++ b/packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js @@ -236,8 +236,8 @@ describe('InspectedElementContext', () => { "preview_long": DataView(3), }, "date": Dehydrated { - "preview_short": Thu Jan 01 1970 01:00:00 GMT+0100 (Central European Standard Time), - "preview_long": Thu Jan 01 1970 01:00:00 GMT+0100 (Central European Standard Time), + "preview_short": 1970-01-01T00:00:00.000Z, + "preview_long": 1970-01-01T00:00:00.000Z, }, "fn": Dehydrated { "preview_short": ƒ exampleFunction() {}, From ee699c04c09f674fab3d1f8dc46caa2245d40788 Mon Sep 17 00:00:00 2001 From: eps1lon Date: Thu, 8 Apr 2021 11:32:53 +0200 Subject: [PATCH 4/5] Try normalizing TZ across environments instead of changing the previewed string --- .../src/__tests__/dehydratedValueSerializer.js | 16 ++-------------- .../src/__tests__/inspectedElement-test.js | 4 ++-- .../src/__tests__/legacy/inspectElement-test.js | 4 ++-- scripts/jest/config.base.js | 1 + scripts/jest/setupGlobal.js | 7 +++++++ 5 files changed, 14 insertions(+), 18 deletions(-) create mode 100644 scripts/jest/setupGlobal.js diff --git a/packages/react-devtools-shared/src/__tests__/dehydratedValueSerializer.js b/packages/react-devtools-shared/src/__tests__/dehydratedValueSerializer.js index c621d05705e99..23a9a1af02ef2 100644 --- a/packages/react-devtools-shared/src/__tests__/dehydratedValueSerializer.js +++ b/packages/react-devtools-shared/src/__tests__/dehydratedValueSerializer.js @@ -22,18 +22,6 @@ export function test(maybeDehydratedValue) { ); } -function serializeDehydratedValuePreview(preview) { - const date = new Date(preview); - const isDatePreview = !Number.isNaN(date.valueOf()); - if (isDatePreview) { - // The preview is just `String(date)` which formats the date in the local timezone. - // This results in a snapshot mismatch between tests run in e.g. GMT and ET - // WARNING: This does not guard against dates created with the default timezone i.e. the local timezone e.g. new Date('05 October 2011 14:48'). - return date.toISOString(); - } - return preview; -} - // print() is part of Jest's serializer API export function print(dehydratedValue, serialize, indent) { const {meta} = require('react-devtools-shared/src/hydration'); @@ -43,11 +31,11 @@ export function print(dehydratedValue, serialize, indent) { 'Dehydrated {\n' + paddingLeft + ' "preview_short": ' + - serializeDehydratedValuePreview(dehydratedValue[meta.preview_short]) + + dehydratedValue[meta.preview_short] + ',\n' + paddingLeft + ' "preview_long": ' + - serializeDehydratedValuePreview(dehydratedValue[meta.preview_long]) + + dehydratedValue[meta.preview_long] + ',\n' + paddingLeft + '}' diff --git a/packages/react-devtools-shared/src/__tests__/inspectedElement-test.js b/packages/react-devtools-shared/src/__tests__/inspectedElement-test.js index f3fc7c33b2212..1acc8a67c5db0 100644 --- a/packages/react-devtools-shared/src/__tests__/inspectedElement-test.js +++ b/packages/react-devtools-shared/src/__tests__/inspectedElement-test.js @@ -568,8 +568,8 @@ describe('InspectedElement', () => { "preview_long": DataView(3), }, "date": Dehydrated { - "preview_short": 2019-12-31T23:42:42.000Z, - "preview_long": 2019-12-31T23:42:42.000Z, + "preview_short": Tue Dec 31 2019 23:42:42 GMT+0000 (Coordinated Universal Time), + "preview_long": Tue Dec 31 2019 23:42:42 GMT+0000 (Coordinated Universal Time), }, "fn": Dehydrated { "preview_short": ƒ exampleFunction() {}, diff --git a/packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js b/packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js index 49acc9654f5ea..3afab2f38feeb 100644 --- a/packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js +++ b/packages/react-devtools-shared/src/__tests__/legacy/inspectElement-test.js @@ -236,8 +236,8 @@ describe('InspectedElementContext', () => { "preview_long": DataView(3), }, "date": Dehydrated { - "preview_short": 1970-01-01T00:00:00.000Z, - "preview_long": 1970-01-01T00:00:00.000Z, + "preview_short": Thu Jan 01 1970 00:00:00 GMT+0000 (Coordinated Universal Time), + "preview_long": Thu Jan 01 1970 00:00:00 GMT+0000 (Coordinated Universal Time), }, "fn": Dehydrated { "preview_short": ƒ exampleFunction() {}, diff --git a/scripts/jest/config.base.js b/scripts/jest/config.base.js index 0e9508221a654..4252489020291 100644 --- a/scripts/jest/config.base.js +++ b/scripts/jest/config.base.js @@ -1,6 +1,7 @@ 'use strict'; module.exports = { + globalSetup: require.resolve('./setupGlobal.js'), haste: { hasteImplModulePath: require.resolve('./noHaste.js'), }, diff --git a/scripts/jest/setupGlobal.js b/scripts/jest/setupGlobal.js new file mode 100644 index 0000000000000..f820078fea88a --- /dev/null +++ b/scripts/jest/setupGlobal.js @@ -0,0 +1,7 @@ +/* eslint-disable */ + +module.exports = () => { + // can use beforeEach/afterEach or setupEnvironment.js in node >= 13: https://github.com/nodejs/node/pull/20026 + // jest's `setupFiles` is too late: https://stackoverflow.com/a/56482581/3406963 + process.env.TZ = 'UTC'; +}; From 56fcc69f66b86f12defc1e0b6578cd0895d66b14 Mon Sep 17 00:00:00 2001 From: eps1lon Date: Sun, 25 Apr 2021 20:16:18 +0200 Subject: [PATCH 5/5] Use same pattern in custom snapshot serializers --- .../src/__tests__/treeContextStateSerializer.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/react-devtools-shared/src/__tests__/treeContextStateSerializer.js b/packages/react-devtools-shared/src/__tests__/treeContextStateSerializer.js index 06c593ed7a1ac..f434cd66b5a4c 100644 --- a/packages/react-devtools-shared/src/__tests__/treeContextStateSerializer.js +++ b/packages/react-devtools-shared/src/__tests__/treeContextStateSerializer.js @@ -2,11 +2,13 @@ import {printStore} from 'react-devtools-shared/src/devtools/utils'; // test() is part of Jest's serializer API export function test(maybeState) { + if (maybeState === null || typeof maybeState !== 'object') { + return false; + } + const hasOwnProperty = Object.prototype.hasOwnProperty.bind(maybeState); // Duck typing at its finest. return ( - maybeState !== null && - typeof maybeState === 'object' && hasOwnProperty('inspectedElementID') && hasOwnProperty('ownerFlatTree') && hasOwnProperty('ownerSubtreeLeafElementID')