Skip to content

Commit

Permalink
Replace print with serialize in AsymmetricMatcher plugin (#4173)
Browse files Browse the repository at this point in the history
  • Loading branch information
pedrottimark authored and cpojer committed Aug 1, 2017
1 parent 9665de2 commit ca366b5
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 26 deletions.
138 changes: 137 additions & 1 deletion packages/pretty-format/src/__tests__/asymmetric_matcher.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,17 @@ test(`stringMatching(regexp)`, () => {
expect(result).toEqual('StringMatching /(jest|niema).*/');
});

test(`stringMatching(regexp) {escapeRegex: false}`, () => {
const result = prettyFormat(expect.stringMatching(/regexp\d/gi), options);
expect(result).toEqual('StringMatching /regexp\\d/gi');
});

test(`stringMatching(regexp) {escapeRegex: true}`, () => {
options.escapeRegex = true;
const result = prettyFormat(expect.stringMatching(/regexp\d/gi), options);
expect(result).toEqual('StringMatching /regexp\\\\d/gi');
});

test(`supports multiple nested asymmetric matchers`, () => {
const result = prettyFormat(
{
Expand Down Expand Up @@ -129,7 +140,132 @@ test(`supports multiple nested asymmetric matchers`, () => {
}`);
});

test(`supports minified output`, () => {
describe(`indent option`, () => {
const val = {
nested: expect.objectContaining({
a: expect.arrayContaining([1]),
b: expect.anything(),
c: expect.any(String),
d: expect.stringContaining('jest'),
e: expect.stringMatching('jest'),
f: expect.objectContaining({
composite: ['exact', 'match'],
primitive: 'string',
}),
}),
};
const result = `Object {
"nested": ObjectContaining {
"a": ArrayContaining [
1,
],
"b": Anything,
"c": Any<String>,
"d": StringContaining "jest",
"e": StringMatching /jest/,
"f": ObjectContaining {
"composite": Array [
"exact",
"match",
],
"primitive": "string",
},
},
}`;

test(`default implicit: 2 spaces`, () => {
expect(prettyFormat(val, options)).toEqual(result);
});
test(`default explicit: 2 spaces`, () => {
options.indent = 2;
expect(prettyFormat(val, options)).toEqual(result);
});

// Tests assume that no strings in val contain multiple adjacent spaces!
test(`non-default: 0 spaces`, () => {
options.indent = 0;
expect(prettyFormat(val, options)).toEqual(result.replace(/ {2}/g, ''));
});
test('non-default: 4 spaces', () => {
options.indent = 4;
expect(prettyFormat(val, options)).toEqual(
result.replace(/ {2}/g, ' '.repeat(4)),
);
});
});

describe(`maxDepth option`, () => {
test(`matchers as leaf nodes`, () => {
options.maxDepth = 3;
const val = {
// ++depth === 1
nested: [
// ++depth === 2
expect.arrayContaining(
// ++depth === 3
[1],
),
expect.objectContaining({
// ++depth === 3
composite: ['exact', 'match'],
primitive: 'string',
}),
expect.stringContaining('jest'),
expect.stringMatching('jest'),
expect.any(String),
expect.anything(),
],
};
const result = prettyFormat(val, options);
expect(result).toEqual(`Object {
"nested": Array [
[ArrayContaining],
[ObjectContaining],
StringContaining "jest",
StringMatching /jest/,
Any<String>,
Anything,
],
}`);
});
test(`matchers as internal nodes`, () => {
options.maxDepth = 3;
const val = [
// ++depth === 1
expect.arrayContaining([
// ++depth === 2
'printed',
{
// ++depth === 3
properties: 'not printed',
},
]),
expect.objectContaining({
// ++depth === 2
array: [
// ++depth === 3
'items',
'not',
'printed',
],
primitive: 'printed',
}),
];
const result = prettyFormat(val, options);
expect(result).toEqual(`Array [
ArrayContaining [
"printed",
[Object],
],
ObjectContaining {
"array": [Array],
"primitive": "printed",
},
]`);
});
});

test(`min option`, () => {
options.min = true;
const result = prettyFormat(
{
Expand Down
7 changes: 6 additions & 1 deletion packages/pretty-format/src/__tests__/pretty_format.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,12 @@ describe('prettyFormat()', () => {
expect(prettyFormat(val)).toEqual('/regexp/gi');
});

it('escapes regular expressions', () => {
it('prints regular expressions {escapeRegex: false}', () => {
const val = /regexp\d/gi;
expect(prettyFormat(val)).toEqual('/regexp\\d/gi');
});

it('prints regular expressions {escapeRegex: true}', () => {
const val = /regexp\d/gi;
expect(prettyFormat(val, {escapeRegex: true})).toEqual('/regexp\\\\d/gi');
});
Expand Down
50 changes: 26 additions & 24 deletions packages/pretty-format/src/plugins/asymmetric_matcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,55 +8,57 @@
* @flow
*/

import type {
Colors,
Indent,
PluginOptions,
Print,
Plugin,
} from 'types/PrettyFormat';
import type {Config, NewPlugin, Printer, Refs} from 'types/PrettyFormat';

const asymmetricMatcher = Symbol.for('jest.asymmetricMatcher');
const SPACE = ' ';

class ArrayContaining extends Array {}
class ObjectContaining extends Object {}

export const print = (
export const serialize = (
val: any,
print: Print,
indent: Indent,
opts: PluginOptions,
colors: Colors,
) => {
config: Config,
print: Printer,
indentation: string,
depth: number,
refs: Refs,
): string => {
const stringedValue = val.toString();

if (stringedValue === 'ArrayContaining') {
if (++depth > config.maxDepth) {
return '[' + stringedValue + ']';
}
const array = ArrayContaining.from(val.sample);
return opts.spacing === SPACE
? stringedValue + SPACE + print(array)
: print(array);
return (
(config.min ? stringedValue + SPACE : '') +
print(array, indentation, depth, refs)
);
}

if (stringedValue === 'ObjectContaining') {
if (++depth > config.maxDepth) {
return '[' + stringedValue + ']';
}
const object = Object.assign(new ObjectContaining(), val.sample);
return opts.spacing === SPACE
? stringedValue + SPACE + print(object)
: print(object);
return (
(config.min ? stringedValue + SPACE : '') +
print(object, indentation, depth, refs)
);
}

if (stringedValue === 'StringMatching') {
return stringedValue + SPACE + print(val.sample);
return stringedValue + SPACE + print(val.sample, indentation, depth, refs);
}

if (stringedValue === 'StringContaining') {
return stringedValue + SPACE + print(val.sample);
return stringedValue + SPACE + print(val.sample, indentation, depth, refs);
}

return val.toAsymmetricMatcher();
};

export const test = (object: any) =>
object && object.$$typeof === asymmetricMatcher;
export const test = (val: any) => val && val.$$typeof === asymmetricMatcher;

export default ({print, test}: Plugin);
export default ({serialize, test}: NewPlugin);

0 comments on commit ca366b5

Please sign in to comment.