diff --git a/CHANGELOG.md b/CHANGELOG.md index 28caf2af8add..f0f80b743520 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -67,6 +67,7 @@ - `[jest-jasmine2]` Pending calls inside async tests are reported as pending not failed ([#6782](https://github.com/facebook/jest/pull/6782)) - `[jest-circus]` Better error message when a describe block is empty ([#6372](https://github.com/facebook/jest/pull/6372)) - `[jest-jasmine2]` Add missing testLocationResults for `xit` and `fit`([#6482](https://github.com/facebook/jest/pull/6482)) +- `[expect]` Return false from asymmetric matchers if received value isn’t string ([#7107](https://github.com/facebook/jest/pull/7107)) - `[jest-cli]` Fix unhandled error when a bad revision is provided to `changedSince` ([#7115](https://github.com/facebook/jest/pull/7115)) - `[jest-config]` Moved dynamically assigned `cwd` from `jest-cli` to default configuration in `jest-config` ([#7146](https://github.com/facebook/jest/pull/7146)) - `[jest-config]` Fix `getMaxWorkers` on termux ([#7154](https://github.com/facebook/jest/pull/7154)) diff --git a/docs/ExpectAPI.md b/docs/ExpectAPI.md index 73cd9a0594c1..c362734a8f8f 100644 --- a/docs/ExpectAPI.md +++ b/docs/ExpectAPI.md @@ -351,7 +351,7 @@ describe('not.objectContaining', () => { ### `expect.not.stringContaining(string)` -`expect.not.stringContaining(string)` matches the received string that does not contain the exact expected string. +`expect.not.stringContaining(string)` matches the received value if it is not a string or if it is a string that does not contain the exact expected string. It is the inverse of `expect.stringContaining`. @@ -359,7 +359,7 @@ It is the inverse of `expect.stringContaining`. describe('not.stringContaining', () => { const expected = 'Hello world!'; - it('matches if the actual string does not contain the expected substring', () => { + it('matches if the received value does not contain the expected substring', () => { expect('How are you?').toEqual(expect.not.stringContaining(expected)); }); }); @@ -367,7 +367,7 @@ describe('not.stringContaining', () => { ### `expect.not.stringMatching(string | regexp)` -`expect.not.stringMatching(string | regexp)` matches the received string that does not match the expected regexp. +`expect.not.stringMatching(string | regexp)` matches the received value if it is not a string or if it is a string that does not match the expected string or regular expression. It is the inverse of `expect.stringMatching`. @@ -375,7 +375,7 @@ It is the inverse of `expect.stringMatching`. describe('not.stringMatching', () => { const expected = /Hello world!/; - it('matches if the actual string does not match the expected regex', () => { + it('matches if the received value does not match the expected regex', () => { expect('How are you?').toEqual(expect.not.stringMatching(expected)); }); }); @@ -404,11 +404,11 @@ test('onPress gets called with the right thing', () => { ### `expect.stringContaining(string)` -`expect.stringContaining(string)` matches the received string that contains the exact expected string. +`expect.stringContaining(string)` matches the received value if it is a string that contains the exact expected string. ### `expect.stringMatching(string | regexp)` -`expect.stringMatching(string | regexp)` matches the received string that matches the expected regexp. +`expect.stringMatching(string | regexp)` matches the received value if it is a string that matches the expected string or regular expression. You can use it instead of a literal value: diff --git a/packages/expect/src/__tests__/asymmetricMatchers.test.js b/packages/expect/src/__tests__/asymmetricMatchers.test.js index 08b0907d09ee..a48d6eb23161 100644 --- a/packages/expect/src/__tests__/asymmetricMatchers.test.js +++ b/packages/expect/src/__tests__/asymmetricMatchers.test.js @@ -199,14 +199,14 @@ test('StringContaining matches string against string', () => { jestExpect(stringContaining('en').asymmetricMatch('queue')).toBe(false); }); -test('StringContaining throws for non-strings', () => { +test('StringContaining throws if expected value is not string', () => { jestExpect(() => { stringContaining([1]).asymmetricMatch('queen'); }).toThrow(); +}); - jestExpect(() => { - stringContaining('en*').asymmetricMatch(1); - }).toThrow(); +test('StringContaining returns false if received value is not string', () => { + jestExpect(stringContaining('en*').asymmetricMatch(1)).toBe(false); }); test('StringNotContaining matches string against string', () => { @@ -214,14 +214,14 @@ test('StringNotContaining matches string against string', () => { jestExpect(stringNotContaining('en').asymmetricMatch('queue')).toBe(true); }); -test('StringNotContaining throws for non-strings', () => { +test('StringNotContaining throws if expected value is not string', () => { jestExpect(() => { stringNotContaining([1]).asymmetricMatch('queen'); }).toThrow(); +}); - jestExpect(() => { - stringNotContaining('en*').asymmetricMatch(1); - }).toThrow(); +test('StringNotContaining returns true if received value is not string', () => { + jestExpect(stringNotContaining('en*').asymmetricMatch(1)).toBe(true); }); test('StringMatching matches string against regexp', () => { @@ -234,16 +234,18 @@ test('StringMatching matches string against string', () => { jestExpect(stringMatching('en').asymmetricMatch('queue')).toBe(false); }); -test('StringMatching throws for non-strings and non-regexps', () => { +test('StringMatching throws if expected value is neither string nor regexp', () => { jestExpect(() => { stringMatching([1]).asymmetricMatch('queen'); }).toThrow(); }); -test('StringMatching throws for non-string actual values', () => { - jestExpect(() => { - stringMatching('en').asymmetricMatch(1); - }).toThrow(); +test('StringMatching returns false if received value is not string', () => { + jestExpect(stringMatching('en').asymmetricMatch(1)).toBe(false); +}); + +test('StringMatching returns false even if coerced non-string received value matches pattern', () => { + jestExpect(stringMatching('null').asymmetricMatch(null)).toBe(false); }); test('StringNotMatching matches string against regexp', () => { @@ -256,14 +258,12 @@ test('StringNotMatching matches string against string', () => { jestExpect(stringNotMatching('en').asymmetricMatch('queue')).toBe(true); }); -test('StringNotMatching throws for non-strings and non-regexps', () => { +test('StringNotMatching throws if expected value is neither string nor regexp', () => { jestExpect(() => { stringNotMatching([1]).asymmetricMatch('queen'); }).toThrow(); }); -test('StringNotMatching throws for non-string actual values', () => { - jestExpect(() => { - stringNotMatching('en').asymmetricMatch(1); - }).toThrow(); +test('StringNotMatching returns true if received value is not string', () => { + jestExpect(stringNotMatching('en').asymmetricMatch(1)).toBe(true); }); diff --git a/packages/expect/src/asymmetricMatchers.js b/packages/expect/src/asymmetricMatchers.js index 01cc89af8550..5ed36416dc50 100644 --- a/packages/expect/src/asymmetricMatchers.js +++ b/packages/expect/src/asymmetricMatchers.js @@ -210,12 +210,8 @@ class StringContaining extends AsymmetricMatcher { this.inverse = inverse; } - asymmetricMatch(other: string) { - if (!isA('String', other)) { - throw new Error('Actual is not a string'); - } - - const result = other.includes(this.sample); + asymmetricMatch(other: any) { + const result = isA('String', other) && other.includes(this.sample); return this.inverse ? !result : result; } @@ -242,12 +238,8 @@ class StringMatching extends AsymmetricMatcher { this.inverse = inverse; } - asymmetricMatch(other: string) { - if (!isA('String', other)) { - throw new Error('Actual is not a string'); - } - - const result = this.sample.test(other); + asymmetricMatch(other: any) { + const result = isA('String', other) && this.sample.test(other); return this.inverse ? !result : result; }