Skip to content

Commit

Permalink
added tests for strict equal
Browse files Browse the repository at this point in the history
basic format

add support for strings

copied test cases from matchers.tests

added perf benchmarks

refactored objects

refactored formatter

changed the directory structure

added asymmetric matcher

added printer
  • Loading branch information
grosto committed Mar 18, 2020
1 parent f8c7279 commit d181360
Show file tree
Hide file tree
Showing 34 changed files with 17,745 additions and 67 deletions.
54 changes: 0 additions & 54 deletions packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2887,41 +2887,6 @@ Expected: not <g>true</>

`;

exports[`.toEqual() failure message matches the expected snapshot 3`] = `
"<dim>expect(</><red>received</><dim>).toEqual(</><green>expected</><dim>)</>

Difference:

<green>- Expected</>
<red>+ Received</>

<dim> Object {</>
<green>- \\"a\\": \\"x\\",</>
<green>- \\"b\\": Any<String>,</>
<red>+ \\"a\\": \\"a\\",</>
<red>+ \\"b\\": \\"b\\",</>
<dim> }</>"
`;

exports[`.toEqual() failure message matches the expected snapshot 4`] = `
"<dim>expect(</><red>received</><dim>).toEqual(</><green>expected</><dim>)</>

Difference:

<green>- Expected</>
<red>+ Received</>

<green>- ObjectContaining {</>
<green>- \\"a\\": \\"x\\",</>
<green>- \\"b\\": Any<String>,</>
<red>+ Object {</>
<red>+ \\"a\\": \\"a\\",</>
<red>+ \\"b\\": \\"b\\",</>
<red>+ \\"c\\": \\"c\\",</>
<red>+ \\"d\\": \\"d\\",</>
<dim> }</>"
`;

exports[`.toHaveLength {pass: false} expect("").toHaveLength(1) 1`] = `
<d>expect(</><r>received</><d>).</>toHaveLength<d>(</><g>expected</><d>)</>

Expand Down Expand Up @@ -4406,25 +4371,6 @@ exports[`toMatchObject() does not match properties up in the prototype chain 1`]
<d> }</>
`;

exports[`toMatchObject() failure message matches the expected snapshot 1`] = `
"<dim>expect(</><red>received</><dim>).toMatchObject(</><green>expected</><dim>)</>

Expected value to match object:
<green>{\\"a\\": \\"x\\", \\"b\\": Any<String>}</>
Received:
<red>{\\"a\\": \\"a\\", \\"b\\": \\"b\\", \\"c\\": \\"c\\"}</>
Difference:
<green>- Expected</>
<red>+ Received</>

<dim> Object {</>
<green>- \\"a\\": \\"x\\",</>
<green>- \\"b\\": Any<String>,</>
<red>+ \\"a\\": \\"a\\",</>
<red>+ \\"b\\": \\"b\\",</>
<dim> }</>"
`;

exports[`toMatchObject() throws expect("44").toMatchObject({}) 1`] = `
<d>expect(</><r>received</><d>).</>toMatchObject<d>(</><g>expected</><d>)</>

Expand Down
13 changes: 0 additions & 13 deletions packages/expect/src/__tests__/matchers.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2105,7 +2105,6 @@ describe('toMatchObject()', () => {
});
});

<<<<<<< HEAD
it('does not match properties up in the prototype chain', () => {
const a = {};
a.ref = a;
Expand All @@ -2119,18 +2118,6 @@ describe('toMatchObject()', () => {
jestExpect(b).not.toMatchObject(matcher);
expect(() =>
jestExpect(b).toMatchObject(matcher),
=======
test('failure message matches the expected snapshot', () => {
expect(() =>
jestExpect({
a: 'a',
b: 'b',
c: 'c',
}).toMatchObject({
a: 'x',
b: expect.any(String),
}),
>>>>>>> 4576618b6... added new snapshot tests for error messages
).toThrowErrorMatchingSnapshot();
});
});
5 changes: 5 additions & 0 deletions packages/jest-deep-diff/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
**/__mocks__/**
**/__tests__/**
src
tsconfig.json
tsconfig.tsbuildinfo
122 changes: 122 additions & 0 deletions packages/jest-deep-diff/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# Jest New Diff

I have not thought about the name at all. If there are good suggestions, you are more than welcome.

## Motivation

`jest-diff` package works by serializing the values and then diffing the serializations. This approach works for most of the scenarios but has a few edge cases. New Diff tries to address these limitations by first by diffing the values and then serializing the differences.

## Understanding design and codebase

Note: Consider this as my attempt to write something that works to improve my understanding of the problem space.

API is almost identical to `jest-diff`. There are two extra fields added to the options but the rest is the same. For now, not options are partially implemented.

There are two major components in the current implementation.

1. `diff` function which returns DiffObject(Representation of difference between two values as a JS object)
2. `format` function which returns a formatted string based on DiffObject

There is support for plugins. I have made ReactElement and AsymmetricMatcher Plugin, but they are not fully functional.

## `diff`

### supported types:

- [x] primitives (String is the only primitve with childDiffs)
- [x] Date
- [x] RegExp
- [x] Function
- [x] PrimitiveWrapper
- [x] Array
- [x] Object
- [x] Circular
- [ ] Map
- [ ] Set
- [ ] DOM Node

I am quite happy with this module. It's clear to me what it does. It recursively marks values as Inserted, Updated, Deleted, Equal or TypeUnequal and returns an object which represents the differences between 2 values.

## `format`

- [x] primitives
- [x] Function
- [x] Array
- [x] Object
- [x] Circular
- [ ] Date
- [ ] RegExp
- [ ] Map
- [ ] Set
- [ ] DOM Node

`format` has two parts, `diffFormat`(desperately needs a name) and `print`. The first one returns an array of `Line` objects and the second serializes this array based on options.

### `Line` type

`Line` is a representation of a terminal line that will be printed on the screen. It has `type` which can be Inserted, Common or Deleted. The type determines the color of the content and diff indicator('-', '+'). `val` is a value that will be serialized. `prefix` and `suffix` are added to the serialized value, as well as `indent`.

`Line` also has `skipSerialize` field which can be set to `true` if you want to the full control of `val` serialization.

Note: `Line` can be printed as multiple lines too, but that is up to print function.

Example:

```ts
const line: Line = {type: Inserted, prefix: '"a": ', sufix: ',', val: {b: 1}};
```

can be rendered as

```
....more diff
- "a": Object {
"b": 1,
},
...more diff
```

or

```
....more diff
- "a": Object {...},
...more diff
```

### `Print`

The second part of `format` is the print function. It serializes the `val` from the `Line` and builds a final diff string. `serialize` function currently is `pretty-format` with extra plugins;

## Problems of implementation:

`serialize` and `diffFormat` needs to be manually kept in sync.

```ts
const a = {
a: {
a: 1,
},
};
const b = {
a: 'a',
};

console.log(newDiff(a, b));
/**
* Object { <- Constructor name and properties are formated by diffFormat
* - "a": Object { <-- Constructor name and properties are formatted by serialize
* "a": 1,
* },
* + "a": 'a',
* }
*/
```

In `jest-diff` this is the output. If we are going to keep it, then maybe the current abstraction is not the best. I would expect that there is no need to fully print the inner object.

Maybe there should be a single format function that is used for diff formatting and serialization? That could easily get very complicated and put a lot of restrictions, so is it worth it?
27 changes: 27 additions & 0 deletions packages/jest-deep-diff/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "jest-deep-diff",
"version": "1.0.0",
"main": "index.js",
"repository": {
"type": "git",
"url": "https://github.com/facebook/jest",
"directory": "packages/jest-core"
},
"bugs": {
"url": "https://github.com/facebook/jest/issues"
},
"dependencies": {
"chalk": "^3.0.0",
"diff-sequences": "^25.1.0",
"jest-diff": "^25.1.0",
"pretty-format": "^25.1.0",
"react-is": "^16.13.0"
},
"devDependencies": {
"@types/react-is": "^16.7.1",
"fast-check": "^1.23.0",
"strip-ansi": "^6.0.0"
},
"homepage": "https://jestjs.io/",
"license": "MIT"
}
Loading

0 comments on commit d181360

Please sign in to comment.