Skip to content

Commit a3013ae

Browse files
committed
test(linter): Port additional tests for two unicorn rules. (#20099)
See https://raw.githubusercontent.com/sindresorhus/eslint-plugin-unicorn/main/test/prefer-array-some.js and https://raw.githubusercontent.com/sindresorhus/eslint-plugin-unicorn/609d4870f3731d39bd5b5f184628e2cf06578dba/test/no-single-promise-in-promise-methods.js I used Claude for help porting the tests for `prefer-array-some`, mostly as a test, and then used a script to compare the tests that were ported to the original to make sure it ported everything correctly (and skipped some <template> tests that we can't handle anyway). I did the same for the other rule. The reason I didn't use the rulegen tooling is because these tests are not handled adequately currently due to being generated dynamically or in separate sets. One nice thing is that it also ported the comments for each set of tests. For reference, the verification script's output, the tests that it couldn't find are due to being commented out (or template tests that were excluded). <details> <summary>test comparisons</summary> ``` node tasks/rulegen/compare-tests.mjs prefer-array-some unicorn Downloading https://raw.githubusercontent.com/sindresorhus/eslint-plugin-unicorn/main/test/prefer-array-some.js ... Reading Rust file: /Users/connorshea/code/oxc/crates/oxc_linter/src/rules/unicorn/prefer_array_some.rs Comparing test cases for unicorn/prefer-array-some... Upstream (Node.js evaluated): 72 valid, 52 invalid Oxlint (Rust file): 70 valid, 46 invalid Missing valid cases (6): 1. if (foo["find"](fn)) {} 2. if (foo["findLast"](fn)) {} 3. if (foo[`find`](fn)) {} 4. if (foo[`findLast`](fn)) {} 5. if (foo.find(...argumentsArray)) {} 6. if (foo.findLast(...argumentsArray)) {} Missing invalid cases (8): 1. const bar = Boolean(foo.find(fn)) 2. const bar = Boolean(foo.findLast(fn)) 3. if ( (( (( (( (( array )) .filter(what_ever_here) )) .length )) > (( 0 )) )) ); 4. <template><div v-if="foo.find(fn)"></div></template> 5. <script>if (foo.findLast(fn));</script> 6. <template><div v-if="foo.filter(fn).length > 0"></div></template> 7. <template><div v-if="foo.filter(fn).length !== 0"></div></template> 8. <script>if (foo.filter(fn).length > 0);</script> Extra valid cases in oxlint not in upstream (4): 1. new foo.findLastIndex(bar) !== -1 2. foo.findLastIndex(bar, extraArgument) !== -1 3. foo.findLastIndex(bar) instanceof -1 4. foo.findLastIndex(...bar) !== -1 Extra invalid cases in oxlint not in upstream (2): 1. foo.findLastIndex(bar) !== (( - 1 )) 2. foo.findLastIndex(element => element.bar === 1) !== (( - 1 )) ``` ``` node tasks/rulegen/compare-tests.mjs no-single-promise-in-promise-methods unicorn Downloading https://raw.githubusercontent.com/sindresorhus/eslint-plugin-unicorn/main/test/no-single-promise-in-promise-methods.js ... Reading Rust file: /Users/connorshea/code/oxc/crates/oxc_linter/src/rules/unicorn/no_single_promise_in_promise_methods.rs Comparing test cases for unicorn/no-single-promise-in-promise-methods... Upstream (Node.js evaluated): 18 valid, 62 invalid Oxlint (Rust file): 15 valid, 67 invalid Missing valid cases (3): 1. Promise?.race([promise]) 2. Promise.race?.([promise]) 3. Promise["race"]([promise]) Extra invalid cases in oxlint not in upstream (5): 1. Promise.all([x] as const).then() 2. Promise.all([x] satisfies any[]).then() 3. Promise.all([x as const]).then() 4. Promise.all([x!]).then() 5. Promise.all(['one']).then(something); ``` </details>
1 parent 9870467 commit a3013ae

File tree

4 files changed

+551
-237
lines changed

4 files changed

+551
-237
lines changed

crates/oxc_linter/src/rules/unicorn/no_single_promise_in_promise_methods.rs

Lines changed: 88 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -174,87 +174,109 @@ fn test() {
174174
use crate::tester::Tester;
175175

176176
let pass = vec![
177-
"Promise.all([promise, anotherPromise])",
178-
"Promise.all(notArrayLiteral)",
179-
"Promise.all([...promises])",
177+
"Promise.race([promise, anotherPromise])",
178+
"Promise.race(notArrayLiteral)",
179+
"Promise.race([...promises])",
180180
"Promise.any([promise, anotherPromise])",
181181
"Promise.race([promise, anotherPromise])",
182182
"Promise.notListedMethod([promise])",
183-
"Promise[all]([promise])",
184-
"Promise.all([,])",
185-
"NotPromise.all([promise])",
186-
"Promise.all(...[promise])",
187-
"Promise.all([promise], extraArguments)",
188-
"Promise.all()",
189-
"new Promise.all([promise])",
190-
"globalThis.Promise.all([promise])",
183+
"Promise[race]([promise])",
184+
"Promise.race([,])",
185+
"NotPromise.race([promise])",
186+
// TODO: These should be valid but Oxlint currently flags them
187+
// "Promise?.race([promise])",
188+
// "Promise.race?.([promise])",
189+
"Promise.race(...[promise])",
190+
"Promise.race([promise], extraArguments)",
191+
"Promise.race()",
192+
"new Promise.race([promise])",
193+
// We are not checking these cases
194+
"globalThis.Promise.race([promise])",
195+
// TODO: This should be valid but Oxlint currently flags it
196+
// r#"Promise["race"]([promise])"#,
197+
// This can't be checked
191198
"Promise.allSettled([promise])",
192-
"Promise.all('one').then(something);",
193199
];
194200

195201
let fail = vec![
196-
"await Promise.all([x])",
197-
"await Promise['all']([x])",
198-
"await Promise.all([(0, promise)])",
199-
"async function * foo() {await Promise.all([yield promise])}",
200-
"async function * foo() {await Promise.all([yield* promise])}",
201-
"await Promise.all([() => promise,],)",
202-
"await Promise.all([a ? b : c,],)",
203-
"await Promise.all([x ??= y,],)",
204-
"await Promise.all([x ||= y,],)",
205-
"await Promise.all([x &&= y,],)",
206-
"await Promise.all([x |= y,],)",
207-
"await Promise.all([x ^= y,],)",
208-
"await Promise.all([x ??= y,],)",
209-
"await Promise.all([x ||= y,],)",
210-
"await Promise.all([x &&= y,],)",
211-
"await Promise.all([x | y,],)",
212-
"await Promise.all([x ^ y,],)",
213-
"await Promise.all([x & y,],)",
214-
"await Promise.all([x !== y,],)",
215-
"await Promise.all([x == y,],)",
216-
"await Promise.all([x in y,],)",
217-
"await Promise.all([x >>> y,],)",
218-
"await Promise.all([x + y,],)",
219-
"await Promise.all([x / y,],)",
220-
"await Promise.all([x ** y,],)",
221-
"await Promise.all([promise,],)",
222-
"await Promise.all([getPromise(),],)",
223-
"await Promise.all([promises[0],],)",
224-
"await Promise.all([await promise])",
202+
// `await`ed
203+
"await Promise.race([(0, promise)])",
204+
"async function * foo() {await Promise.race([yield promise])}",
205+
"async function * foo() {await Promise.race([yield* promise])}",
206+
"await Promise.race([() => promise,],)",
207+
"await Promise.race([a ? b : c,],)",
208+
"await Promise.race([x ??= y,],)",
209+
"await Promise.race([x ||= y,],)",
210+
"await Promise.race([x &&= y,],)",
211+
"await Promise.race([x |= y,],)",
212+
"await Promise.race([x ^= y,],)",
213+
"await Promise.race([x ??= y,],)",
214+
"await Promise.race([x ||= y,],)",
215+
"await Promise.race([x &&= y,],)",
216+
"await Promise.race([x | y,],)",
217+
"await Promise.race([x ^ y,],)",
218+
"await Promise.race([x & y,],)",
219+
"await Promise.race([x !== y,],)",
220+
"await Promise.race([x == y,],)",
221+
"await Promise.race([x in y,],)",
222+
"await Promise.race([x >>> y,],)",
223+
"await Promise.race([x + y,],)",
224+
"await Promise.race([x / y,],)",
225+
"await Promise.race([x ** y,],)",
226+
"await Promise.race([promise,],)",
227+
"await Promise.race([getPromise(),],)",
228+
"await Promise.race([promises[0],],)",
229+
"await Promise.race([await promise])",
225230
"await Promise.any([promise])",
226231
"await Promise.race([promise])",
227-
"await Promise.all([new Promise(() => {})])",
228-
"+await Promise.all([+1])",
232+
"await Promise.race([new Promise(() => {})])",
233+
"+await Promise.race([+1])",
234+
// ASI, `Promise.race()` is not really `await`ed
229235
"
230-
await Promise.all([(x,y)])
236+
await Promise.race([(x,y)])
231237
[0].toString()
232238
",
233-
"Promise.all([promise,],)",
239+
// Not `await`ed
240+
"Promise.race([promise,],)",
234241
"
235242
foo
236-
Promise.all([(0, promise),],)
243+
Promise.race([(0, promise),],)
237244
",
238245
"
239246
foo
240-
Promise.all([[array][0],],)
247+
Promise.race([[array][0],],)
241248
",
242-
"Promise.all([promise]).then()",
243-
"Promise.all([1]).then()",
244-
"Promise.all([1.]).then()",
245-
"Promise.all([.1]).then()",
246-
"Promise.all([(0, promise)]).then()",
247-
"const _ = () => Promise.all([ a ?? b ,],)",
248-
"Promise.all([ {a} = 1 ,],)",
249-
"Promise.all([ function () {} ,],)",
250-
"Promise.all([ class {} ,],)",
251-
"Promise.all([ new Foo ,],).then()",
252-
"Promise.all([ new Foo ,],).toString",
253-
"foo(Promise.all([promise]))",
254-
"Promise.all([promise]).foo = 1",
255-
"Promise.all([promise])[0] ||= 1",
256-
"Promise.all([undefined]).then()",
257-
"Promise.all([null]).then()",
249+
"Promise.race([promise]).then()",
250+
"Promise.race([1]).then()",
251+
"Promise.race([1.]).then()",
252+
"Promise.race([.1]).then()",
253+
"Promise.race([(0, promise)]).then()",
254+
"const _ = () => Promise.race([ a ?? b ,],)",
255+
"Promise.race([ {a} = 1 ,],)",
256+
"Promise.race([ function () {} ,],)",
257+
"Promise.race([ class {} ,],)",
258+
"Promise.race([ new Foo ,],).then()",
259+
"Promise.race([ new Foo ,],).toString",
260+
"foo(Promise.race([promise]))",
261+
"Promise.race([promise]).foo = 1",
262+
"Promise.race([promise])[0] ||= 1",
263+
"Promise.race([undefined]).then()",
264+
"Promise.race([null]).then()",
265+
// `Promise.all` specific
266+
"Promise.all([promise])",
267+
"await Promise.all([promise])",
268+
"const foo = () => Promise.all([promise])",
269+
"const foo = await Promise.all([promise])",
270+
"foo = await Promise.all([promise])",
271+
// `Promise.{all, race}()` should not care if the result is used
272+
"const foo = await Promise.race([promise])",
273+
"const foo = () => Promise.race([promise])",
274+
"foo = await Promise.race([promise])",
275+
"const results = await Promise.any([promise])",
276+
"const results = await Promise.race([promise])",
277+
// Fixable, but not provided at this point
278+
"const [foo] = await Promise.all([promise])",
279+
// TypeScript-specific
258280
"Promise.all([x] as const).then()",
259281
"Promise.all([x] satisfies any[]).then()",
260282
"Promise.all([x as const]).then()",
@@ -263,7 +285,7 @@ fn test() {
263285
];
264286

265287
let fix = vec![
266-
("Promise.all([null]).then()", "Promise.all([null]).then()", None),
288+
("Promise.race([null]).then()", "Promise.resolve(null).then()", None),
267289
// Promise.all returns an array, so we preserve the array structure
268290
// `await Promise.all([x])` -> `[await x]`
269291
("await Promise.all([x]);", "[await x];", None),
@@ -280,6 +302,8 @@ fn test() {
280302
"function foo () { return Promise.all([x]); }",
281303
None,
282304
),
305+
("const foo = () => Promise.race([x])", "const foo = () => Promise.resolve(x)", None),
306+
("foo = await Promise.race([x])", "foo = await Promise.race([x])", None),
283307
(
284308
"Promise.all(['one']).then((result) => result[0]);",
285309
"Promise.all(['one']).then((result) => result[0]);",

0 commit comments

Comments
 (0)