DevTools: Add Jest snapshot serializer for number formatting (#23139)

Numbers in JavaScript can have precision issues due to how they are encoded. This shows up in snapshot tests sometimes with values like 0.0009999999999999992, which makes the tests hard to read and visually diff.

This PR adds a new snapshot serializers which clamps numbers at 3 decimal points (e.g. the above number 0.0009999999999999992 is serialized as 0.001). This new serializer does not impact non-numeric values, integers, and special numbers like NaN and Infinity.
This commit is contained in:
Brian Vaughn 2022-01-20 15:52:17 -05:00 committed by GitHub
parent 505c15c9ef
commit a637084320
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 57 additions and 30 deletions

View File

@ -0,0 +1,24 @@
const MAX_DECIMAL_PLACES = 3;
// test() is part of Jest's serializer API
export function test(maybeNumber) {
return (
typeof maybeNumber === 'number' &&
Number.isFinite(maybeNumber) &&
!Number.isInteger(maybeNumber) &&
!Number.isNaN(maybeNumber)
);
}
// print() is part of Jest's serializer API
export function print(number, serialize, indent) {
const string = number.toString();
const pieces = string.split('.');
if (pieces.length === 2) {
if (pieces[1].length > MAX_DECIMAL_PLACES) {
return number.toFixed(MAX_DECIMAL_PLACES);
}
}
return string;
}

View File

@ -439,7 +439,7 @@ describe('Timeline profiler', () => {
Object {
"batchUID": 0,
"depth": 0,
"duration": 0.004999999999999999,
"duration": 0.005,
"lanes": Array [
9,
],
@ -459,7 +459,7 @@ describe('Timeline profiler', () => {
Object {
"batchUID": 0,
"depth": 0,
"duration": 0.002999999999999999,
"duration": 0.003,
"lanes": Array [
9,
],
@ -469,7 +469,7 @@ describe('Timeline profiler', () => {
Object {
"batchUID": 0,
"depth": 1,
"duration": 0.0010000000000000009,
"duration": 0.001,
"lanes": Array [
9,
],
@ -529,7 +529,7 @@ describe('Timeline profiler', () => {
Object {
"batchUID": 0,
"depth": 0,
"duration": 0.004999999999999999,
"duration": 0.005,
"lanes": Array [
9,
],
@ -549,7 +549,7 @@ describe('Timeline profiler', () => {
Object {
"batchUID": 0,
"depth": 0,
"duration": 0.002999999999999999,
"duration": 0.003,
"lanes": Array [
9,
],
@ -559,7 +559,7 @@ describe('Timeline profiler', () => {
Object {
"batchUID": 0,
"depth": 1,
"duration": 0.0010000000000000009,
"duration": 0.001,
"lanes": Array [
9,
],
@ -656,7 +656,7 @@ describe('Timeline profiler', () => {
Object {
"batchUID": 0,
"depth": 1,
"duration": 0.0009999999999999992,
"duration": 0.001,
"lanes": Array [
0,
],
@ -748,7 +748,7 @@ describe('Timeline profiler', () => {
Object {
"batchUID": 0,
"depth": 1,
"duration": 0.0009999999999999992,
"duration": 0.001,
"lanes": Array [
0,
],
@ -865,7 +865,7 @@ describe('Timeline profiler', () => {
Object {
"batchUID": 0,
"depth": 1,
"duration": 0.0009999999999999992,
"duration": 0.001,
"lanes": Array [
4,
],
@ -887,7 +887,7 @@ describe('Timeline profiler', () => {
Object {
"batchUID": 1,
"depth": 0,
"duration": 0.012000000000000004,
"duration": 0.012,
"lanes": Array [
4,
],
@ -897,7 +897,7 @@ describe('Timeline profiler', () => {
Object {
"batchUID": 1,
"depth": 0,
"duration": 0.0030000000000000027,
"duration": 0.003,
"lanes": Array [
4,
],
@ -907,7 +907,7 @@ describe('Timeline profiler', () => {
Object {
"batchUID": 1,
"depth": 0,
"duration": 0.008000000000000004,
"duration": 0.008,
"lanes": Array [
4,
],
@ -917,7 +917,7 @@ describe('Timeline profiler', () => {
Object {
"batchUID": 1,
"depth": 1,
"duration": 0.0010000000000000009,
"duration": 0.001,
"lanes": Array [
4,
],
@ -927,7 +927,7 @@ describe('Timeline profiler', () => {
Object {
"batchUID": 1,
"depth": 0,
"duration": 0.0029999999999999957,
"duration": 0.003,
"lanes": Array [
4,
],
@ -946,21 +946,21 @@ describe('Timeline profiler', () => {
},
Object {
"componentName": "App",
"duration": 0.0020000000000000018,
"duration": 0.002,
"timestamp": 0.018,
"type": "passive-effect-mount",
"warning": null,
},
Object {
"componentName": "App",
"duration": 0.0010000000000000009,
"duration": 0.001,
"timestamp": 0.023,
"type": "render",
"warning": null,
},
Object {
"componentName": "App",
"duration": 0.0010000000000000009,
"duration": 0.001,
"timestamp": 0.036,
"type": "passive-effect-mount",
"warning": null,
@ -1052,7 +1052,7 @@ describe('Timeline profiler', () => {
Object {
"batchUID": 0,
"depth": 1,
"duration": 0.0009999999999999992,
"duration": 0.001,
"lanes": Array [
4,
],
@ -1072,7 +1072,7 @@ describe('Timeline profiler', () => {
Object {
"batchUID": 1,
"depth": 0,
"duration": 0.012000000000000004,
"duration": 0.012,
"lanes": Array [
4,
],
@ -1082,7 +1082,7 @@ describe('Timeline profiler', () => {
Object {
"batchUID": 1,
"depth": 0,
"duration": 0.0030000000000000027,
"duration": 0.003,
"lanes": Array [
4,
],
@ -1092,7 +1092,7 @@ describe('Timeline profiler', () => {
Object {
"batchUID": 1,
"depth": 0,
"duration": 0.008000000000000004,
"duration": 0.008,
"lanes": Array [
4,
],
@ -1102,7 +1102,7 @@ describe('Timeline profiler', () => {
Object {
"batchUID": 1,
"depth": 1,
"duration": 0.0010000000000000009,
"duration": 0.001,
"lanes": Array [
4,
],
@ -1112,7 +1112,7 @@ describe('Timeline profiler', () => {
Object {
"batchUID": 1,
"depth": 0,
"duration": 0.0029999999999999957,
"duration": 0.003,
"lanes": Array [
4,
],

View File

@ -28,7 +28,7 @@ describe('StoreStress (Legacy Mode)', () => {
act = utils.act;
legacyRender = utils.legacyRender;
print = require('./storeSerializer').print;
print = require('./__serializers__/storeSerializer').print;
});
// This is a stress test for the tree mount/update/unmount traversal.

View File

@ -28,7 +28,7 @@ describe('StoreStressConcurrent', () => {
// this helper with the real thing.
actAsync = require('./utils').actAsync;
print = require('./storeSerializer').print;
print = require('./__serializers__/storeSerializer').print;
});
// TODO: Remove this in favor of @gate pragma

View File

@ -62,19 +62,22 @@ module.exports = Object.assign({}, baseConfig, {
testRegex: 'packages/react-devtools-shared/.+/__tests__/[^]+.test.js$',
snapshotSerializers: [
require.resolve(
'../../packages/react-devtools-shared/src/__tests__/dehydratedValueSerializer.js'
'../../packages/react-devtools-shared/src/__tests__/__serializers__/dehydratedValueSerializer.js'
),
require.resolve(
'../../packages/react-devtools-shared/src/__tests__/hookSerializer.js'
'../../packages/react-devtools-shared/src/__tests__/__serializers__/hookSerializer.js'
),
require.resolve(
'../../packages/react-devtools-shared/src/__tests__/inspectedElementSerializer.js'
'../../packages/react-devtools-shared/src/__tests__/__serializers__/inspectedElementSerializer.js'
),
require.resolve(
'../../packages/react-devtools-shared/src/__tests__/storeSerializer.js'
'../../packages/react-devtools-shared/src/__tests__/__serializers__/storeSerializer.js'
),
require.resolve(
'../../packages/react-devtools-shared/src/__tests__/treeContextStateSerializer.js'
'../../packages/react-devtools-shared/src/__tests__/__serializers__/treeContextStateSerializer.js'
),
require.resolve(
'../../packages/react-devtools-shared/src/__tests__/__serializers__/numberToFixedSerializer.js'
),
],
setupFiles: [