1+ import { InvalidTestCase , ValidTestCase } from '@typescript-eslint/rule-tester' ;
12import { TSESLint } from '@typescript-eslint/utils' ;
23
3- import rule , { RULE_NAME } from '../../../lib/rules/await-async-queries' ;
4+ import rule , {
5+ RULE_NAME ,
6+ MessageIds ,
7+ } from '../../../lib/rules/await-async-queries' ;
48import {
59 ASYNC_QUERIES_COMBINATIONS ,
610 ASYNC_QUERIES_VARIANTS ,
@@ -11,6 +15,9 @@ import { createRuleTester } from '../test-utils';
1115
1216const ruleTester = createRuleTester ( ) ;
1317
18+ type RuleValidTestCase = ValidTestCase < [ ] > ;
19+ type RuleInvalidTestCase = InvalidTestCase < MessageIds , [ ] > ;
20+
1421const SUPPORTED_TESTING_FRAMEWORKS = [
1522 '@testing-library/dom' ,
1623 '@testing-library/angular' ,
@@ -306,10 +313,8 @@ ruleTester.run(RULE_NAME, rule, {
306313 } ) ) ,
307314
308315 // handled promise assigned to variable returned from async query wrapper is valid
309- ...ALL_ASYNC_COMBINATIONS_TO_TEST . map (
310- ( query ) =>
311- ( {
312- code : `
316+ ...ALL_ASYNC_COMBINATIONS_TO_TEST . map < RuleValidTestCase > ( ( query ) => ( {
317+ code : `
313318 const queryWrapper = () => {
314319 return screen.${ query } ('foo')
315320 }
@@ -319,8 +324,7 @@ ruleTester.run(RULE_NAME, rule, {
319324 expect(element).toBeVisible()
320325 })
321326 ` ,
322- } ) as const
323- ) ,
327+ } ) ) ,
324328
325329 // non-matching query is valid
326330 `
@@ -413,66 +417,78 @@ ruleTester.run(RULE_NAME, rule, {
413417
414418 invalid : [
415419 ...SUPPORTED_TESTING_FRAMEWORKS . flatMap ( ( testingFramework ) =>
416- ALL_ASYNC_COMBINATIONS_TO_TEST . map (
417- ( query ) =>
418- ( {
419- code : `// async queries without await operator or then method are not valid
420+ ALL_ASYNC_COMBINATIONS_TO_TEST . map < RuleInvalidTestCase > ( ( query ) => ( {
421+ code : `// async queries without await operator or then method are not valid
420422 import { render } from '${ testingFramework } '
421423
422424 test("An example test", async () => {
423425 doSomething()
424426 const foo = ${ query } ('foo')
425427 });
426428 ` ,
427- errors : [ { messageId : 'awaitAsyncQuery' , line : 6 , column : 21 } ] ,
428- } ) as const
429- )
429+ errors : [ { messageId : 'awaitAsyncQuery' , line : 6 , column : 21 } ] ,
430+ output : `// async queries without await operator or then method are not valid
431+ import { render } from '${ testingFramework } '
432+
433+ test("An example test", async () => {
434+ doSomething()
435+ const foo = await ${ query } ('foo')
436+ });
437+ ` ,
438+ } ) )
430439 ) ,
431- ...ALL_ASYNC_COMBINATIONS_TO_TEST . map (
432- ( query ) =>
433- ( {
434- code : `// async screen queries without await operator or then method are not valid
440+ ...ALL_ASYNC_COMBINATIONS_TO_TEST . map < RuleInvalidTestCase > ( ( query ) => ( {
441+ code : `// async screen queries without await operator or then method are not valid
435442 import { render } from '@testing-library/react'
436443
437444 test("An example test", async () => {
438445 screen.${ query } ('foo')
439446 });
440447 ` ,
441- errors : [
442- {
443- messageId : 'awaitAsyncQuery' ,
444- line : 5 ,
445- column : 16 ,
446- data : { name : query } ,
447- } ,
448- ] ,
449- } ) as const
450- ) ,
451- ...ALL_ASYNC_COMBINATIONS_TO_TEST . map (
452- ( query ) =>
453- ( {
454- code : `
448+ errors : [
449+ {
450+ messageId : 'awaitAsyncQuery' ,
451+ line : 5 ,
452+ column : 16 ,
453+ data : { name : query } ,
454+ } ,
455+ ] ,
456+ output : `// async screen queries without await operator or then method are not valid
457+ import { render } from '@testing-library/react'
458+
459+ test("An example test", async () => {
460+ await screen.${ query } ('foo')
461+ });
462+ ` ,
463+ } ) ) ,
464+ ...ALL_ASYNC_COMBINATIONS_TO_TEST . map < RuleInvalidTestCase > ( ( query ) => ( {
465+ code : `
455466 import { render } from '@testing-library/react'
456467
457468 test("An example test", async () => {
458469 doSomething()
459470 const foo = ${ query } ('foo')
460471 });
461472 ` ,
462- errors : [
463- {
464- messageId : 'awaitAsyncQuery' ,
465- line : 6 ,
466- column : 21 ,
467- data : { name : query } ,
468- } ,
469- ] ,
470- } ) as const
471- ) ,
472- ...ALL_ASYNC_COMBINATIONS_TO_TEST . map (
473- ( query ) =>
474- ( {
475- code : `
473+ errors : [
474+ {
475+ messageId : 'awaitAsyncQuery' ,
476+ line : 6 ,
477+ column : 21 ,
478+ data : { name : query } ,
479+ } ,
480+ ] ,
481+ output : `
482+ import { render } from '@testing-library/react'
483+
484+ test("An example test", async () => {
485+ doSomething()
486+ const foo = await ${ query } ('foo')
487+ });
488+ ` ,
489+ } ) ) ,
490+ ...ALL_ASYNC_COMBINATIONS_TO_TEST . map < RuleInvalidTestCase > ( ( query ) => ( {
491+ code : `
476492 import { render } from '@testing-library/react'
477493
478494 test("An example test", async () => {
@@ -481,37 +497,47 @@ ruleTester.run(RULE_NAME, rule, {
481497 expect(foo).toHaveAttribute('src', 'bar');
482498 });
483499 ` ,
484- errors : [
485- {
486- messageId : 'awaitAsyncQuery' ,
487- line : 5 ,
488- column : 21 ,
489- data : { name : query } ,
490- } ,
491- ] ,
492- } ) as const
493- ) ,
500+ errors : [
501+ {
502+ messageId : 'awaitAsyncQuery' ,
503+ line : 5 ,
504+ column : 21 ,
505+ data : { name : query } ,
506+ } ,
507+ ] ,
508+ output : `
509+ import { render } from '@testing-library/react'
510+
511+ test("An example test", async () => {
512+ const foo = ${ query } ('foo')
513+ expect(await foo).toBeInTheDocument()
514+ expect(await foo).toHaveAttribute('src', 'bar');
515+ });
516+ ` ,
517+ } ) ) ,
494518
495519 // unresolved async queries are not valid (aggressive reporting)
496- ...ALL_ASYNC_COMBINATIONS_TO_TEST . map (
497- ( query ) =>
498- ( {
499- code : `
520+ ...ALL_ASYNC_COMBINATIONS_TO_TEST . map < RuleInvalidTestCase > ( ( query ) => ( {
521+ code : `
500522 import { render } from "another-library"
501523
502524 test('An example test', async () => {
503525 const example = ${ query } ("my example")
504526 })
505527 ` ,
506- errors : [ { messageId : 'awaitAsyncQuery' , line : 5 , column : 27 } ] ,
507- } ) as const
508- ) ,
528+ errors : [ { messageId : 'awaitAsyncQuery' , line : 5 , column : 27 } ] ,
529+ output : `
530+ import { render } from "another-library"
531+
532+ test('An example test', async () => {
533+ const example = await ${ query } ("my example")
534+ })
535+ ` ,
536+ } ) ) ,
509537
510538 // unhandled promise from async query function wrapper is invalid
511- ...ALL_ASYNC_COMBINATIONS_TO_TEST . map (
512- ( query ) =>
513- ( {
514- code : `
539+ ...ALL_ASYNC_COMBINATIONS_TO_TEST . map < RuleInvalidTestCase > ( ( query ) => ( {
540+ code : `
515541 function queryWrapper() {
516542 doSomethingElse();
517543
@@ -526,14 +552,26 @@ ruleTester.run(RULE_NAME, rule, {
526552 const element = await queryWrapper()
527553 })
528554 ` ,
529- errors : [ { messageId : 'asyncQueryWrapper' , line : 9 , column : 27 } ] ,
530- } ) as const
531- ) ,
555+ errors : [ { messageId : 'asyncQueryWrapper' , line : 9 , column : 27 } ] ,
556+ output : `
557+ function queryWrapper() {
558+ doSomethingElse();
559+
560+ return screen.${ query } ('foo')
561+ }
562+
563+ test("An invalid example test", async () => {
564+ const element = await queryWrapper()
565+ })
566+
567+ test("An invalid example test", async () => {
568+ const element = await queryWrapper()
569+ })
570+ ` ,
571+ } ) ) ,
532572 // unhandled promise from async query arrow function wrapper is invalid
533- ...ALL_ASYNC_COMBINATIONS_TO_TEST . map (
534- ( query ) =>
535- ( {
536- code : `
573+ ...ALL_ASYNC_COMBINATIONS_TO_TEST . map < RuleInvalidTestCase > ( ( query ) => ( {
574+ code : `
537575 const queryWrapper = () => {
538576 doSomethingElse();
539577
@@ -548,14 +586,26 @@ ruleTester.run(RULE_NAME, rule, {
548586 const element = await queryWrapper()
549587 })
550588 ` ,
551- errors : [ { messageId : 'asyncQueryWrapper' , line : 9 , column : 27 } ] ,
552- } ) as const
553- ) ,
589+ errors : [ { messageId : 'asyncQueryWrapper' , line : 9 , column : 27 } ] ,
590+ output : `
591+ const queryWrapper = () => {
592+ doSomethingElse();
593+
594+ return ${ query } ('foo')
595+ }
596+
597+ test("An invalid example test", async () => {
598+ const element = await queryWrapper()
599+ })
600+
601+ test("An invalid example test", async () => {
602+ const element = await queryWrapper()
603+ })
604+ ` ,
605+ } ) ) ,
554606 // unhandled promise implicitly returned from async query arrow function wrapper is invalid
555- ...ALL_ASYNC_COMBINATIONS_TO_TEST . map (
556- ( query ) =>
557- ( {
558- code : `
607+ ...ALL_ASYNC_COMBINATIONS_TO_TEST . map < RuleInvalidTestCase > ( ( query ) => ( {
608+ code : `
559609 const queryWrapper = () => screen.${ query } ('foo')
560610
561611 test("An invalid example test", () => {
@@ -566,9 +616,19 @@ ruleTester.run(RULE_NAME, rule, {
566616 const element = await queryWrapper()
567617 })
568618 ` ,
569- errors : [ { messageId : 'asyncQueryWrapper' , line : 5 , column : 27 } ] ,
570- } ) as const
571- ) ,
619+ errors : [ { messageId : 'asyncQueryWrapper' , line : 5 , column : 27 } ] ,
620+ output : `
621+ const queryWrapper = () => screen.${ query } ('foo')
622+
623+ test("An invalid example test", async () => {
624+ const element = await queryWrapper()
625+ })
626+
627+ test("An invalid example test", async () => {
628+ const element = await queryWrapper()
629+ })
630+ ` ,
631+ } ) ) ,
572632
573633 // unhandled promise from custom query matching custom-queries setting is invalid
574634 {
@@ -581,6 +641,11 @@ ruleTester.run(RULE_NAME, rule, {
581641 })
582642 ` ,
583643 errors : [ { messageId : 'awaitAsyncQuery' , line : 3 , column : 25 } ] ,
644+ output : `
645+ test('An invalid example test', () => {
646+ const element = await findByIcon('search')
647+ })
648+ ` ,
584649 } ,
585650
586651 {
@@ -609,6 +674,30 @@ ruleTester.run(RULE_NAME, rule, {
609674 })
610675 ` ,
611676 errors : [ { messageId : 'asyncQueryWrapper' , line : 19 , column : 34 } ] ,
677+ output : `// similar to issue #359 but forcing an error in no-awaited wrapper
678+ import { render, screen } from 'mocks/test-utils'
679+ import userEvent from '@testing-library/user-event'
680+
681+ const testData = {
682+ name: 'John Doe',
683+ email: 'john@doe.com',
684+ password: 'extremeSecret',
685+ }
686+
687+ const selectors = {
688+ username: () => screen.findByRole('textbox', { name: /username/i }),
689+ email: () => screen.findByRole('textbox', { name: /e-mail/i }),
690+ password: () => screen.findByLabelText(/password/i),
691+ }
692+
693+ test('this is a valid case', async () => {
694+ render(<SomeComponent />)
695+ userEvent.type(await selectors.username(), testData.name) // <-- unhandled here
696+ userEvent.type(await selectors.email(), testData.email)
697+ userEvent.type(await selectors.password(), testData.password)
698+ // ...
699+ })
700+ ` ,
612701 } ,
613702 ] ,
614703} ) ;
0 commit comments