Skip to content

Commit 187566a

Browse files
authored
feat(pretty-format): allow to opt out from sorting object keys with compareKeys: null (#12443)
1 parent ae2bed7 commit 187566a

File tree

7 files changed

+52
-36
lines changed

7 files changed

+52
-36
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
- `[@jest/test-result, @jest/types]` [**BREAKING**] Replace `Bytes` and `Milliseconds` types with `number` ([#13155](https://github.com/facebook/jest/pull/13155))
1515
- `[jest-worker]` Adds `workerIdleMemoryLimit` option which is used as a check for worker memory leaks >= Node 16.11.0 and recycles child workers as required ([#13056](https://github.com/facebook/jest/pull/13056), [#13105](https://github.com/facebook/jest/pull/13105), [#13106](https://github.com/facebook/jest/pull/13106), [#13107](https://github.com/facebook/jest/pull/13107))
1616
- `[pretty-format]` [**BREAKING**] Remove `ConvertAnsi` plugin in favour of `jest-serializer-ansi-escapes` ([#13040](https://github.com/facebook/jest/pull/13040))
17+
- `[pretty-format]` Allow to opt out from sorting object keys with `compareKeys: null` ([#12443](https://github.com/facebook/jest/pull/12443))
1718

1819
### Fixes
1920

packages/jest-schemas/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {Static, Type} from '@sinclair/typebox';
1010
const RawSnapshotFormat = Type.Partial(
1111
Type.Object({
1212
callToJSON: Type.Readonly(Type.Boolean()),
13+
compareKeys: Type.Readonly(Type.Null()),
1314
escapeRegex: Type.Readonly(Type.Boolean()),
1415
escapeString: Type.Readonly(Type.Boolean()),
1516
highlight: Type.Readonly(Type.Boolean()),

packages/pretty-format/README.md

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -66,21 +66,21 @@ console.log(prettyFormat(onClick, options));
6666
```
6767

6868
<!-- prettier-ignore -->
69-
| key | type | default | description |
70-
| :-------------------- | :-------- | :--------- | :------------------------------------------------------ |
71-
| `callToJSON` | `boolean` | `true` | call `toJSON` method (if it exists) on objects |
72-
| `compareKeys` | `function`| `undefined`| compare function used when sorting object keys |
73-
| `escapeRegex` | `boolean` | `false` | escape special characters in regular expressions |
74-
| `escapeString` | `boolean` | `true` | escape special characters in strings |
75-
| `highlight` | `boolean` | `false` | highlight syntax with colors in terminal (some plugins) |
76-
| `indent` | `number` | `2` | spaces in each level of indentation |
77-
| `maxDepth` | `number` | `Infinity` | levels to print in arrays, objects, elements, and so on |
78-
| `maxWidth` | `number` | `Infinity` | number of elements to print in arrays, sets, and so on |
79-
| `min` | `boolean` | `false` | minimize added space: no indentation nor line breaks |
80-
| `plugins` | `array` | `[]` | plugins to serialize application-specific data types |
81-
| `printBasicPrototype` | `boolean` | `false` | print the prototype for plain objects and arrays |
82-
| `printFunctionName` | `boolean` | `true` | include or omit the name of a function |
83-
| `theme` | `object` | | colors to highlight syntax in terminal |
69+
| key | type | default | description |
70+
| :-------------------- | :--------------- | :---------- | :-------------------------------------------------------------------------------------- |
71+
| `callToJSON` | `boolean` | `true` | call `toJSON` method (if it exists) on objects |
72+
| `compareKeys` | `function\|null` | `undefined` | compare function used when sorting object keys, `null` can be used to skip over sorting |
73+
| `escapeRegex` | `boolean` | `false` | escape special characters in regular expressions |
74+
| `escapeString` | `boolean` | `true` | escape special characters in strings |
75+
| `highlight` | `boolean` | `false` | highlight syntax with colors in terminal (some plugins) |
76+
| `indent` | `number` | `2` | spaces in each level of indentation |
77+
| `maxDepth` | `number` | `Infinity` | levels to print in arrays, objects, elements, and so on |
78+
| `maxWidth` | `number` | `Infinity` | number of elements to print in arrays, sets, and so on |
79+
| `min` | `boolean` | `false` | minimize added space: no indentation nor line breaks |
80+
| `plugins` | `array` | `[]` | plugins to serialize application-specific data types |
81+
| `printBasicPrototype` | `boolean` | `false` | print the prototype for plain objects and arrays |
82+
| `printFunctionName` | `boolean` | `true` | include or omit the name of a function |
83+
| `theme` | `object` | | colors to highlight syntax in terminal |
8484

8585
Property values of `theme` are from [ansi-styles colors](https://github.com/chalk/ansi-styles#colors)
8686

@@ -206,20 +206,20 @@ Write `serialize` to return a string, given the arguments:
206206
### config
207207

208208
<!-- prettier-ignore -->
209-
| key | type | description |
210-
| :------------------ | :-------- | :------------------------------------------------------ |
211-
| `callToJSON` | `boolean` | call `toJSON` method (if it exists) on objects |
212-
| `compareKeys` | `function`| compare function used when sorting object keys |
213-
| `colors` | `Object` | escape codes for colors to highlight syntax |
214-
| `escapeRegex` | `boolean` | escape special characters in regular expressions |
215-
| `escapeString` | `boolean` | escape special characters in strings |
216-
| `indent` | `string` | spaces in each level of indentation |
217-
| `maxDepth` | `number` | levels to print in arrays, objects, elements, and so on |
218-
| `min` | `boolean` | minimize added space: no indentation nor line breaks |
219-
| `plugins` | `array` | plugins to serialize application-specific data types |
220-
| `printFunctionName` | `boolean` | include or omit the name of a function |
221-
| `spacingInner` | `string` | spacing to separate items in a list |
222-
| `spacingOuter` | `string` | spacing to enclose a list of items |
209+
| key | type | description |
210+
| :------------------ | :--------------- | :-------------------------------------------------------------------------------------- |
211+
| `callToJSON` | `boolean` | call `toJSON` method (if it exists) on objects |
212+
| `compareKeys` | `function\|null` | compare function used when sorting object keys, `null` can be used to skip over sorting |
213+
| `colors` | `Object` | escape codes for colors to highlight syntax |
214+
| `escapeRegex` | `boolean` | escape special characters in regular expressions |
215+
| `escapeString` | `boolean` | escape special characters in strings |
216+
| `indent` | `string` | spaces in each level of indentation |
217+
| `maxDepth` | `number` | levels to print in arrays, objects, elements, and so on |
218+
| `min` | `boolean` | minimize added space: no indentation nor line breaks |
219+
| `plugins` | `array` | plugins to serialize application-specific data types |
220+
| `printFunctionName` | `boolean` | include or omit the name of a function |
221+
| `spacingInner` | `string` | spacing to separate items in a list |
222+
| `spacingOuter` | `string` | spacing to enclose a list of items |
223223

224224
Each property of `colors` in `config` corresponds to a property of `theme` in `options`:
225225

packages/pretty-format/src/__tests__/prettyFormat.test.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ describe('prettyFormat()', () => {
334334
expect(prettyFormat(val)).toEqual('Object {\n "a": 2,\n "b": 1,\n}');
335335
});
336336

337-
it('prints an object with keys in their original order', () => {
337+
it('prints an object with keys in their original order with the appropriate comparing function', () => {
338338
// eslint-disable-next-line sort-keys
339339
const val = {b: 1, a: 2};
340340
const compareKeys = () => 0;
@@ -343,6 +343,14 @@ describe('prettyFormat()', () => {
343343
);
344344
});
345345

346+
it('prints an object with keys in their original order with compareKeys set to null', () => {
347+
// eslint-disable-next-line sort-keys
348+
const val = {b: 1, a: 2};
349+
expect(prettyFormat(val, {compareKeys: null})).toEqual(
350+
'Object {\n "b": 1,\n "a": 2,\n}',
351+
);
352+
});
353+
346354
it('prints an object with keys sorted in reverse order', () => {
347355
const val = {a: 1, b: 2};
348356
const compareKeys = (a: string, b: string) => (a > b ? -1 : 1);

packages/pretty-format/src/collections.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ const getKeysOfEnumerableProperties = (
1212
object: Record<string, unknown>,
1313
compareKeys: CompareKeys,
1414
) => {
15-
const keys: Array<string | symbol> = Object.keys(object).sort(compareKeys);
15+
const rawKeys = Object.keys(object);
16+
const keys: Array<string | symbol> =
17+
compareKeys !== null ? rawKeys.sort(compareKeys) : rawKeys;
1618

1719
if (Object.getOwnPropertySymbols) {
1820
Object.getOwnPropertySymbols(object).forEach(symbol => {

packages/pretty-format/src/index.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,10 @@ const DEFAULT_THEME_KEYS = Object.keys(DEFAULT_THEME) as Array<
400400
keyof typeof DEFAULT_THEME
401401
>;
402402

403-
export const DEFAULT_OPTIONS: Options = {
403+
// could be replaced by `satisfies` operator in the future: https://github.com/microsoft/TypeScript/issues/47920
404+
const toOptionsSubtype = <T extends Options>(options: T) => options;
405+
406+
export const DEFAULT_OPTIONS = toOptionsSubtype({
404407
callToJSON: true,
405408
compareKeys: undefined,
406409
escapeRegex: false,
@@ -414,7 +417,7 @@ export const DEFAULT_OPTIONS: Options = {
414417
printBasicPrototype: true,
415418
printFunctionName: true,
416419
theme: DEFAULT_THEME,
417-
};
420+
});
418421

419422
function validateOptions(options: OptionsReceived) {
420423
Object.keys(options).forEach(key => {
@@ -482,7 +485,7 @@ const getConfig = (options?: OptionsReceived): Config => ({
482485
callToJSON: options?.callToJSON ?? DEFAULT_OPTIONS.callToJSON,
483486
colors: options?.highlight ? getColorsHighlight(options) : getColorsEmpty(),
484487
compareKeys:
485-
typeof options?.compareKeys === 'function'
488+
typeof options?.compareKeys === 'function' || options?.compareKeys === null
486489
? options.compareKeys
487490
: DEFAULT_OPTIONS.compareKeys,
488491
escapeRegex: getEscapeRegex(options),

packages/pretty-format/src/types.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ type Print = (arg0: unknown) => string;
2020

2121
export type Theme = Options['theme'];
2222

23-
export type CompareKeys = ((a: string, b: string) => number) | undefined;
23+
export type CompareKeys = ((a: string, b: string) => number) | null | undefined;
2424

2525
type RequiredOptions = Required<PrettyFormatOptions>;
2626

@@ -30,7 +30,8 @@ export interface Options
3030
theme: Required<RequiredOptions['theme']>;
3131
}
3232

33-
export interface PrettyFormatOptions extends SnapshotFormat {
33+
export interface PrettyFormatOptions
34+
extends Omit<SnapshotFormat, 'compareKeys'> {
3435
compareKeys?: CompareKeys;
3536
plugins?: Plugins;
3637
}

0 commit comments

Comments
 (0)