Repository: skovhus/jest-codemods
Pull request #144 (2018-12-13 07:41:13)

Chai assert matchers
This pull request adds matchers (and tests) for the following Chai `assert` matchers:
- `deepProperty`
- `notDeepProperty`
- `deepPropertyVal`
- `notDeepPropertyVal`
- `deepPropertyNotVal`
- `notPropertyVal`

I made a tiny repl to ensure the Jest conversions were valid: https://repl.it/repls/TurboRunnyApplicationsuite.

~I also noticed that `propertyNotVal` is actually shown as `notPropertyVal` in the Chai documentation: https://www.chaijs.com/api/assert/#method_notpropertyval. I changed the method name to match the Chai docs but I am happy to revert that commit if `propertyNotVal` was actually the correct method name.~ (Reverted and added as a new method)

codecov-io: # [Codecov](https://codecov.io/gh/skovhus/jest-codemods/pull/144?src=pr&el=h1) Report
> Merging [#144](https://codecov.io/gh/skovhus/jest-codemods/pull/144?src=pr&el=desc) into [master](https://codecov.io/gh/skovhus/jest-codemods/commit/17230a298797cc1286a5c2416fd92382e7c6013d?src=pr&el=desc) will **increase** coverage by `0.04%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/skovhus/jest-codemods/pull/144/graphs/tree.svg?width=650&token=rt2Tk3o31c&height=150&src=pr)](https://codecov.io/gh/skovhus/jest-codemods/pull/144?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #144      +/-   ##
==========================================
+ Coverage   94.89%   94.93%   +0.04%     
==========================================
  Files          24       24              
  Lines        1233     1245      +12     
==========================================
+ Hits         1170     1182      +12     
  Misses         63       63
```


| [Impacted Files](https://codecov.io/gh/skovhus/jest-codemods/pull/144?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [src/transformers/chai-assert.js](https://codecov.io/gh/skovhus/jest-codemods/pull/144/diff?src=pr&el=tree#diff-c3JjL3RyYW5zZm9ybWVycy9jaGFpLWFzc2VydC5qcw==) | `100% <100%> (ø)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/skovhus/jest-codemods/pull/144?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/skovhus/jest-codemods/pull/144?src=pr&el=footer). Last update [17230a2...d814a62](https://codecov.io/gh/skovhus/jest-codemods/pull/144?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

skovhus: Thanks. About the last commit:

According to chai changelog `propertyNotVal and assert. deepPropertyNotVal assertions were renamed to assert.notPropertyVal and assert.`

So we shouldn’t remove that property, but also support the new name. 
bcmarinacci: @skovhus Ah, nice find! Sorry about that. I reverted the last commit and added conversions/tests for `notPropertyVal` and `deepPropertyNotVal`.

Patch:
diff --git a/src/transformers/chai-assert.js b/src/transformers/chai-assert.js
index 4a0ee2f..7763276 100644
--- a/src/transformers/chai-assert.js
+++ b/src/transformers/chai-assert.js
@@ -157,10 +157,6 @@ const getArguments = (path, ignoreExpectedValue, expectedOverride) => {
 };
 
 const unsupportedAssertions = [
-    'deepProperty',
-    'notDeepProperty',
-    'deepPropertyVal',
-    'deepPropertyNotVal',
     'operator',
     'includeMembers',
     'includeDeepMembers',
@@ -335,6 +331,72 @@ export default function transformer(fileInfo, api, options) {
             return makeNegativeExpectation('toBe', j.memberExpression(obj, prop), value);
         });
 
+    // assert.notPropertyVal -> expect(*.[prop]).not.toBe()
+    ast
+        .find(
+            j.CallExpression,
+            getAssertionExpression(chaiAssertExpression, 'notPropertyVal')
+        )
+        .replaceWith(path => {
+            const [obj, prop, value] = path.value.arguments;
+            return makeNegativeExpectation('toBe', j.memberExpression(obj, prop), value);
+        });
+
+    // assert.deepPropertyVal -> expect(*).toHaveProperty(keyPath, ?value)
+    ast
+        .find(
+            j.CallExpression,
+            getAssertionExpression(chaiAssertExpression, 'deepPropertyVal')
+        )
+        .replaceWith(path => {
+            const [obj, prop, value] = path.value.arguments;
+            return makeExpectation('toHaveProperty', obj, [prop, value]);
+        });
+
+    // assert.deepPropertyNotVal -> expect(*).not.toHaveProperty(keyPath, ?value)
+    ast
+        .find(
+            j.CallExpression,
+            getAssertionExpression(chaiAssertExpression, 'deepPropertyNotVal')
+        )
+        .replaceWith(path => {
+            const [obj, prop, value] = path.value.arguments;
+            return makeNegativeExpectation('toHaveProperty', obj, [prop, value]);
+        });
+
+    // assert.notDeepPropertyVal -> expect(*).not.toHaveProperty(keyPath, ?value)
+    ast
+        .find(
+            j.CallExpression,
+            getAssertionExpression(chaiAssertExpression, 'notDeepPropertyVal')
+        )
+        .replaceWith(path => {
+            const [obj, prop, value] = path.value.arguments;
+            return makeNegativeExpectation('toHaveProperty', obj, [prop, value]);
+        });
+
+    // assert.deepProperty -> expect(*).toHaveProperty(keyPath)
+    ast
+        .find(
+            j.CallExpression,
+            getAssertionExpression(chaiAssertExpression, 'deepProperty')
+        )
+        .replaceWith(path => {
+            const [obj, prop] = path.value.arguments;
+            return makeExpectation('toHaveProperty', obj, prop);
+        });
+
+    // assert.notDeepProperty -> expect(*).not.toHaveProperty(keyPath)
+    ast
+        .find(
+            j.CallExpression,
+            getAssertionExpression(chaiAssertExpression, 'notDeepProperty')
+        )
+        .replaceWith(path => {
+            const [obj, prop] = path.value.arguments;
+            return makeNegativeExpectation('toHaveProperty', obj, prop);
+        });
+
     // assert.property -> expect(prop in obj).toBeTruthy()
     ast
         .find(j.CallExpression, getAssertionExpression(chaiAssertExpression, 'property'))


Test patch:
diff --git a/src/transformers/chai-assert.test.js b/src/transformers/chai-assert.test.js
index 832c0db..b85b67d 100644
--- a/src/transformers/chai-assert.test.js
+++ b/src/transformers/chai-assert.test.js
@@ -106,8 +106,37 @@ const mappings = [
     ['assert.notMatch(foo, bar, baz);', 'expect(foo).not.toMatch(bar);'],
     ['assert.property(foo, bar, baz);', 'expect(bar in foo).toBeTruthy();'],
     ['assert.notProperty(foo, bar, baz);', 'expect(bar in foo).toBeFalsy();'],
+    [
+        "assert.deepProperty({ tea: { green: 'matcha' }}, 'tea.green');",
+        "expect({ tea: { green: 'matcha' }}).toHaveProperty('tea.green');",
+    ],
+    [
+        "assert.notDeepProperty({ tea: { green: 'matcha' }}, 'tea.oolong');",
+        "expect({ tea: { green: 'matcha' }}).not.toHaveProperty('tea.oolong');",
+    ],
     ['assert.propertyVal(foo, bar, baz);', 'expect(foo.bar).toBe(baz);'],
     ['assert.propertyNotVal(foo, bar, baz);', 'expect(foo.bar).not.toBe(baz);'],
+    ['assert.notPropertyVal(foo, bar, baz);', 'expect(foo.bar).not.toBe(baz);'],
+    [
+        "assert.deepPropertyVal({ tea: { green: 'matcha' } }, 'tea', { green: 'matcha' });",
+        "expect({ tea: { green: 'matcha' } }).toHaveProperty('tea', { green: 'matcha' });",
+    ],
+    [
+        "assert.notDeepPropertyVal({ tea: { green: 'matcha' } }, 'tea', { black: 'matcha' });",
+        "expect({ tea: { green: 'matcha' } }).not.toHaveProperty('tea', { black: 'matcha' });",
+    ],
+    [
+        "assert.deepPropertyNotVal({ tea: { green: 'matcha' } }, 'tea', { green: 'oolong' });",
+        "expect({ tea: { green: 'matcha' } }).not.toHaveProperty('tea', { green: 'oolong' });",
+    ],
+    [
+        "assert.notDeepPropertyVal({ tea: { green: 'matcha' } }, 'tea', { green: 'oolong' });",
+        "expect({ tea: { green: 'matcha' } }).not.toHaveProperty('tea', { green: 'oolong' });",
+    ],
+    [
+        "assert.notDeepPropertyVal({ tea: { green: 'matcha' } }, 'coffee', { green: 'matcha' });",
+        "expect({ tea: { green: 'matcha' } }).not.toHaveProperty('coffee', { green: 'matcha' });",
+    ],
     ['assert.lengthOf(foo, bar, baz);', 'expect(foo.length).toBe(bar);'],
     ['assert.throws(foo, bar, baz);', 'expect(foo).toThrow();'],
     ['assert.doesNotThrow(foo, bar, baz);', 'expect(foo).not.toThrow();'],
@@ -160,10 +189,6 @@ testChanged(
 
 test('not supported assertions', () => {
     const unsupportedAssertions = [
-        'deepProperty',
-        'notDeepProperty',
-        'deepPropertyVal',
-        'deepPropertyNotVal',
         'operator',
         'includeMembers',
         'includeDeepMembers',
@@ -186,20 +211,16 @@ assert.${assertion}(foo, bar, baz);`,
     wrappedPlugin(fileInput);
 
     expect(consoleWarnings).toEqual([
-        'jest-codemods warning: (test.js line 2) Unsupported Chai Assertion "deepProperty".',
-        'jest-codemods warning: (test.js line 3) Unsupported Chai Assertion "notDeepProperty".',
-        'jest-codemods warning: (test.js line 4) Unsupported Chai Assertion "deepPropertyVal".',
-        'jest-codemods warning: (test.js line 5) Unsupported Chai Assertion "deepPropertyNotVal".',
-        'jest-codemods warning: (test.js line 6) Unsupported Chai Assertion "operator".',
-        'jest-codemods warning: (test.js line 7) Unsupported Chai Assertion "includeMembers".',
-        'jest-codemods warning: (test.js line 8) Unsupported Chai Assertion "includeDeepMembers".',
-        'jest-codemods warning: (test.js line 9) Unsupported Chai Assertion "changes".',
-        'jest-codemods warning: (test.js line 10) Unsupported Chai Assertion "doesNotChange".',
-        'jest-codemods warning: (test.js line 11) Unsupported Chai Assertion "increases".',
-        'jest-codemods warning: (test.js line 12) Unsupported Chai Assertion "doesNotIncrease".',
-        'jest-codemods warning: (test.js line 13) Unsupported Chai Assertion "decreases".',
-        'jest-codemods warning: (test.js line 14) Unsupported Chai Assertion "doesNotDecrease".',
-        'jest-codemods warning: (test.js line 15) Unsupported Chai Assertion "ifError".',
+        'jest-codemods warning: (test.js line 2) Unsupported Chai Assertion "operator".',
+        'jest-codemods warning: (test.js line 3) Unsupported Chai Assertion "includeMembers".',
+        'jest-codemods warning: (test.js line 4) Unsupported Chai Assertion "includeDeepMembers".',
+        'jest-codemods warning: (test.js line 5) Unsupported Chai Assertion "changes".',
+        'jest-codemods warning: (test.js line 6) Unsupported Chai Assertion "doesNotChange".',
+        'jest-codemods warning: (test.js line 7) Unsupported Chai Assertion "increases".',
+        'jest-codemods warning: (test.js line 8) Unsupported Chai Assertion "doesNotIncrease".',
+        'jest-codemods warning: (test.js line 9) Unsupported Chai Assertion "decreases".',
+        'jest-codemods warning: (test.js line 10) Unsupported Chai Assertion "doesNotDecrease".',
+        'jest-codemods warning: (test.js line 11) Unsupported Chai Assertion "ifError".',
     ]);
 });