fileoverview author Yann Braga
  import { isImportDefaultSpecifier } from '../utils/ast' ; import { CategoryId } from '../utils/constants' ; import { createStorybookRule } from '../utils/create-storybook-rule' ; export = createStorybookRule ( { name : 'use-storybook-testing-library' , defaultOptions : [ ] , meta : { type : 'suggestion' , fixable : 'code' , hasSuggestions : true , docs : { description : 'Do not use testing-library directly on stories' , categories : [ CategoryId . ADDON_INTERACTIONS , CategoryId . RECOMMENDED ] , recommended : 'error' , } , schema : [ ] , messages : { updateImports : 'Update imports' , dontUseTestingLibraryDirectly : 'Do not use `{{library}}` directly in the story. You should import the functions from `@storybook/testing-library` instead.' , } , } , create ( context ) { const getRangeWithoutQuotes = ( source ) => { return [ source . range [ 0 ] + 1 , source . range [ 1 ] - 1 , ] ; } ; const hasDefaultImport = ( specifiers ) => specifiers . find ( ( s ) => isImportDefaultSpecifier ( s ) ) ; const getSpecifiers = ( node ) => { const { specifiers } = node ; const start = specifiers [ 0 ] . range [ 0 ] ; let end = specifiers [ specifiers . length - 1 ] . range [ 1 ] ; const fullText = context . getSourceCode ( ) . text ; const importEnd = node . range [ 1 ] ; const closingBrace = fullText . indexOf ( '}' , end - 1 ) ; if ( closingBrace > - 1 && closingBrace <= importEnd ) { end = closingBrace + 1 ; } const text = fullText . substring ( start , end ) ; return { range : [ start , end ] , text } ; } ; const fixSpecifiers = ( specifiersText ) => { const flattened = specifiersText . replace ( '{' , '' ) . replace ( '}' , '' ) . replace ( /\s\s+/g , ' ' ) . trim ( ) ; return `{ ${ flattened } }` ; } ; return { ImportDeclaration ( node ) { if ( node . source . value . includes ( '@testing-library' ) ) { context . report ( { node , messageId : 'dontUseTestingLibraryDirectly' , data : { library : node . source . value , } , * fix ( fixer ) { yield fixer . replaceTextRange ( getRangeWithoutQuotes ( node . source ) , '@storybook/testing-library' ) ; if ( hasDefaultImport ( node . specifiers ) ) { const { range , text } = getSpecifiers ( node ) ; yield fixer . replaceTextRange ( range , fixSpecifiers ( text ) ) ; } } , suggest : [ { messageId : 'updateImports' , * fix ( fixer ) { yield fixer . replaceTextRange ( getRangeWithoutQuotes ( node . source ) , '@storybook/testing-library' ) ; if ( hasDefaultImport ( node . specifiers ) ) { const { range , text } = getSpecifiers ( node ) ; yield fixer . replaceTextRange ( range , fixSpecifiers ( text ) ) ; } } , } , ] , } ) ; } } , } ; } , } ) ;