import { TSESLint } from '@typescript-eslint/experimental-utils' ; import * as path from 'path' ; const VALID_PARSERS = [ '@angular-eslint/template-parser' , '@typescript-eslint/parser' , ] as const ; type RuleTesterConfig = Omit < TSESLint . RuleTesterConfig , 'parser' > & { parser : typeof VALID_PARSERS [ number ] ; } ; function getFixturesRootDir ( ) { return path . join ( process . cwd ( ) , 'tests/fixtures/' ) ; } function isValidParser ( parser ? ) { return VALID_PARSERS . includes ( parser as typeof VALID_PARSERS [ number ] ) ; } export class RuleTester extends TSESLint . RuleTester { private filename ? : string ; constructor ( options ) { super ( { ... options , parser : require . resolve ( options . parser ) , } ) ; if ( options . parserOptions ?. project ) { this . filename = path . join ( getFixturesRootDir ( ) , 'file.ts' ) ; } afterAll ( ( ) => { try { require ( options . parser ) . clearCaches ( ) ; } catch { } } ) ; } run < TMessageIds extends string , TOptions extends readonly unknown [ ] > ( name , rule , { valid , invalid } ) { const errorMessage = `Do not set the parser at the test level unless you want to use a parser other than ${ VALID_PARSERS . join ( ', ' ) }` ; const parsedTests = { valid : valid . map ( ( test ) => { if ( typeof test !== 'string' && isValidParser ( test . parser ) ) { throw Error ( errorMessage ) ; } return { ... ( typeof test === 'string' ? { code : test } : test ) , filename : this . filename , } ; } ) , invalid : invalid . map ( ( test ) => { if ( isValidParser ( test . parser ) ) { throw Error ( errorMessage ) ; } return { ... test , filename : this . filename , } ; } ) , } ; super . run ( name , rule , parsedTests ) ; } }