Skip to content

Commit 4585c73

Browse files
incleafcpojer
authored andcommitted
Make rejects and resolves synchronous (#5364)
* Make `makeRejectMatcher` synchronizable (#5361) * Reorganize code using promise instaed of async/await * Update changelog * Move rejectedHandler onto then * Make `makeResolveMatcher` synchronizable * Update a snapshot * Update CHANGELOG.md * Update CHANGELOG.md
1 parent 4080d98 commit 4585c73

File tree

5 files changed

+117
-29
lines changed

5 files changed

+117
-29
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
([#5367](https://github.com/facebook/jest/pull/5367))
1414
* `[jest-cli]` Fix npm update command for snapshot summary.
1515
([#5376](https://github.com/facebook/jest/pull/5376))
16+
* `[expect]` Make `rejects` and `resolves` synchronously validate its argument.
17+
([#5364](https://github.com/facebook/jest/pull/5364))
1618

1719
## jest 22.1.4
1820

integration-tests/__tests__/__snapshots__/failures.test.js.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ exports[`works with async failures 1`] = `
118118
+ \\"foo\\": \\"bar\\",
119119
}
120120
121-
at ../../packages/expect/build/index.js:156:54
121+
at ../../packages/expect/build/index.js:145:57
122122
123123
"
124124
`;

packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,14 @@ Received:
8484
string: <red>\\"a\\"</>"
8585
`;
8686

87+
exports[`.resolves fails non-promise value "a" synchronously 1`] = `
88+
"<dim>expect(</><red>received</><dim>).resolves.toBeDefined(</><dim>)</>
89+
90+
<red>received</> value must be a Promise.
91+
Received:
92+
string: <red>\\"a\\"</>"
93+
`;
94+
8795
exports[`.resolves fails non-promise value [1] 1`] = `
8896
"<dim>expect(</><red>received</><dim>).resolves.toBeDefined(</><dim>)</>
8997

@@ -92,6 +100,14 @@ Received:
92100
array: <red>[1]</>"
93101
`;
94102

103+
exports[`.resolves fails non-promise value [1] synchronously 1`] = `
104+
"<dim>expect(</><red>received</><dim>).resolves.toBeDefined(</><dim>)</>
105+
106+
<red>received</> value must be a Promise.
107+
Received:
108+
array: <red>[1]</>"
109+
`;
110+
95111
exports[`.resolves fails non-promise value [Function anonymous] 1`] = `
96112
"<dim>expect(</><red>received</><dim>).resolves.toBeDefined(</><dim>)</>
97113

@@ -100,6 +116,14 @@ Received:
100116
function: <red>[Function anonymous]</>"
101117
`;
102118

119+
exports[`.resolves fails non-promise value [Function anonymous] synchronously 1`] = `
120+
"<dim>expect(</><red>received</><dim>).resolves.toBeDefined(</><dim>)</>
121+
122+
<red>received</> value must be a Promise.
123+
Received:
124+
function: <red>[Function anonymous]</>"
125+
`;
126+
103127
exports[`.resolves fails non-promise value {"a": 1} 1`] = `
104128
"<dim>expect(</><red>received</><dim>).resolves.toBeDefined(</><dim>)</>
105129

@@ -108,6 +132,14 @@ Received:
108132
object: <red>{\\"a\\": 1}</>"
109133
`;
110134

135+
exports[`.resolves fails non-promise value {"a": 1} synchronously 1`] = `
136+
"<dim>expect(</><red>received</><dim>).resolves.toBeDefined(</><dim>)</>
137+
138+
<red>received</> value must be a Promise.
139+
Received:
140+
object: <red>{\\"a\\": 1}</>"
141+
`;
142+
111143
exports[`.resolves fails non-promise value 4 1`] = `
112144
"<dim>expect(</><red>received</><dim>).resolves.toBeDefined(</><dim>)</>
113145

@@ -116,13 +148,28 @@ Received:
116148
number: <red>4</>"
117149
`;
118150

151+
exports[`.resolves fails non-promise value 4 synchronously 1`] = `
152+
"<dim>expect(</><red>received</><dim>).resolves.toBeDefined(</><dim>)</>
153+
154+
<red>received</> value must be a Promise.
155+
Received:
156+
number: <red>4</>"
157+
`;
158+
119159
exports[`.resolves fails non-promise value null 1`] = `
120160
"<dim>expect(</><red>received</><dim>).resolves.toBeDefined(</><dim>)</>
121161

122162
<red>received</> value must be a Promise.
123163
Received: <red>null</>"
124164
`;
125165

166+
exports[`.resolves fails non-promise value null synchronously 1`] = `
167+
"<dim>expect(</><red>received</><dim>).resolves.toBeDefined(</><dim>)</>
168+
169+
<red>received</> value must be a Promise.
170+
Received: <red>null</>"
171+
`;
172+
126173
exports[`.resolves fails non-promise value true 1`] = `
127174
"<dim>expect(</><red>received</><dim>).resolves.toBeDefined(</><dim>)</>
128175

@@ -131,13 +178,28 @@ Received:
131178
boolean: <red>true</>"
132179
`;
133180

181+
exports[`.resolves fails non-promise value true synchronously 1`] = `
182+
"<dim>expect(</><red>received</><dim>).resolves.toBeDefined(</><dim>)</>
183+
184+
<red>received</> value must be a Promise.
185+
Received:
186+
boolean: <red>true</>"
187+
`;
188+
134189
exports[`.resolves fails non-promise value undefined 1`] = `
135190
"<dim>expect(</><red>received</><dim>).resolves.toBeDefined(</><dim>)</>
136191

137192
<red>received</> value must be a Promise.
138193
Received: <red>undefined</>"
139194
`;
140195

196+
exports[`.resolves fails non-promise value undefined synchronously 1`] = `
197+
"<dim>expect(</><red>received</><dim>).resolves.toBeDefined(</><dim>)</>
198+
199+
<red>received</> value must be a Promise.
200+
Received: <red>undefined</>"
201+
`;
202+
141203
exports[`.toBe() does not crash on circular references 1`] = `
142204
"<dim>expect(</><red>received</><dim>).toBe(</><green>expected</><dim>)</>
143205

packages/expect/src/__tests__/matchers.test.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,18 @@ describe('.rejects', () => {
3737
await jestExpect(fn()).rejects.toThrow('some error');
3838
});
3939

40+
[4, [1], {a: 1}, 'a', true, null, undefined, () => {}].forEach(value => {
41+
it(`fails non-promise value ${stringify(value)} synchronously`, () => {
42+
let error;
43+
try {
44+
jestExpect(value).rejects.toBe(111);
45+
} catch (e) {
46+
error = e;
47+
}
48+
expect(error).toBeDefined();
49+
});
50+
});
51+
4052
[4, [1], {a: 1}, 'a', true, null, undefined, () => {}].forEach(value => {
4153
it(`fails non-promise value ${stringify(value)}`, async () => {
4254
let error;
@@ -81,6 +93,19 @@ describe('.resolves', () => {
8193
).resolves.toThrow();
8294
});
8395

96+
[4, [1], {a: 1}, 'a', true, null, undefined, () => {}].forEach(value => {
97+
it(`fails non-promise value ${stringify(value)} synchronously`, () => {
98+
let error;
99+
try {
100+
jestExpect(value).resolves.toBeDefined();
101+
} catch (e) {
102+
error = e;
103+
}
104+
expect(error).toBeDefined();
105+
expect(error.message).toMatchSnapshot();
106+
});
107+
});
108+
84109
[4, [1], {a: 1}, 'a', true, null, undefined, () => {}].forEach(value => {
85110
it(`fails non-promise value ${stringify(value)}`, async () => {
86111
let error;

packages/expect/src/index.js

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ const makeResolveMatcher = (
130130
matcher: RawMatcherFn,
131131
isNot: boolean,
132132
actual: Promise<any>,
133-
): PromiseMatcherFn => async (...args) => {
133+
): PromiseMatcherFn => (...args) => {
134134
const matcherStatement = `.resolves.${isNot ? 'not.' : ''}${matcherName}`;
135135
if (!isPromise(actual)) {
136136
throw new JestAssertionError(
@@ -141,27 +141,27 @@ const makeResolveMatcher = (
141141
);
142142
}
143143

144-
let result;
145-
try {
146-
result = await actual;
147-
} catch (e) {
148-
throw new JestAssertionError(
149-
utils.matcherHint(matcherStatement, 'received', '') +
150-
'\n\n' +
151-
`Expected ${utils.RECEIVED_COLOR('received')} Promise to resolve, ` +
152-
'instead it rejected to value\n' +
153-
` ${utils.printReceived(e)}`,
154-
);
155-
}
156-
return makeThrowingMatcher(matcher, isNot, result).apply(null, args);
144+
return actual.then(
145+
result => makeThrowingMatcher(matcher, isNot, result).apply(null, args),
146+
reason => {
147+
const err = new JestAssertionError(
148+
utils.matcherHint(matcherStatement, 'received', '') +
149+
'\n\n' +
150+
`Expected ${utils.RECEIVED_COLOR('received')} Promise to resolve, ` +
151+
'instead it rejected to value\n' +
152+
` ${utils.printReceived(reason)}`,
153+
);
154+
return Promise.reject(err);
155+
},
156+
);
157157
};
158158

159159
const makeRejectMatcher = (
160160
matcherName: string,
161161
matcher: RawMatcherFn,
162162
isNot: boolean,
163163
actual: Promise<any>,
164-
): PromiseMatcherFn => async (...args) => {
164+
): PromiseMatcherFn => (...args) => {
165165
const matcherStatement = `.rejects.${isNot ? 'not.' : ''}${matcherName}`;
166166
if (!isPromise(actual)) {
167167
throw new JestAssertionError(
@@ -172,19 +172,18 @@ const makeRejectMatcher = (
172172
);
173173
}
174174

175-
let result;
176-
try {
177-
result = await actual;
178-
} catch (e) {
179-
return makeThrowingMatcher(matcher, isNot, e).apply(null, args);
180-
}
181-
182-
throw new JestAssertionError(
183-
utils.matcherHint(matcherStatement, 'received', '') +
184-
'\n\n' +
185-
`Expected ${utils.RECEIVED_COLOR('received')} Promise to reject, ` +
186-
'instead it resolved to value\n' +
187-
` ${utils.printReceived(result)}`,
175+
return actual.then(
176+
result => {
177+
const err = new JestAssertionError(
178+
utils.matcherHint(matcherStatement, 'received', '') +
179+
'\n\n' +
180+
`Expected ${utils.RECEIVED_COLOR('received')} Promise to reject, ` +
181+
'instead it resolved to value\n' +
182+
` ${utils.printReceived(result)}`,
183+
);
184+
return Promise.reject(err);
185+
},
186+
reason => makeThrowingMatcher(matcher, isNot, reason).apply(null, args),
188187
);
189188
};
190189

0 commit comments

Comments
 (0)