import * as Lint from 'tslint' ; import * as fs from 'fs' ; import * as chai from 'chai' ; import * as ts from 'typescript' ; import { ErrorTolerantWalker } from '../utils/ErrorTolerantWalker' ; /**
 * Test Utilities.
 */ export namespace TestHelper { let program ; /**
     * This setting must point to your rule .js files. 3rd party libraries may reuse this class and change value.
     */ export let RULES_DIRECTORY = 'dist/src/' ; /**
     * This setting must point to your formatter .js files. 3rd party libraries may reuse this class and change value.
     */ export let FORMATTER_DIRECTORY = 'customFormatters/' ; /**
     * You must specify an encoding for file read/writes. 3rd party libraries may reuse this class and change value.
     */ export let FILE_ENCODING = 'utf8' ; export interface FailurePosition { character : number ; line : number ; position ? : number ; } export interface ExpectedFailure { ruleName : string ; name : string ; failure ? : string ; ruleSeverity ? : string ; endPosition ? : FailurePosition ; startPosition : FailurePosition ; } export function assertNoViolation ( ruleName , inputFileOrScript , useTypeChecker = false ) { runRuleAndEnforceAssertions ( ruleName , null , inputFileOrScript , [ ] , useTypeChecker ) ; } export function assertNoViolationWithOptions ( ruleName , options , inputFileOrScript , useTypeChecker = false ) { runRuleAndEnforceAssertions ( ruleName , options , inputFileOrScript , [ ] , useTypeChecker ) ; } export function assertViolationsWithOptions ( ruleName , options , inputFileOrScript , expectedFailures , useTypeChecker = false ) { runRuleAndEnforceAssertions ( ruleName , options , inputFileOrScript , expectedFailures , useTypeChecker ) ; } export function assertViolations ( ruleName , inputFileOrScript , expectedFailures , useTypeChecker = false ) { runRuleAndEnforceAssertions ( ruleName , null , inputFileOrScript , expectedFailures , useTypeChecker ) ; } export function assertViolationsWithTypeChecker ( ruleName , inputFileOrScript , expectedFailures ) { runRuleAndEnforceAssertions ( ruleName , null , inputFileOrScript , expectedFailures , true ) ; } export function runRule ( ruleName , userOptions , inputFileOrScript , useTypeChecker = false ) { const configuration = { extends : [ ] , jsRules : new Map < string , Partial < Lint . IOptions > > ( ) , linterOptions : { } , rules : new Map < string , Partial < Lint . IOptions > > ( ) , rulesDirectory : [ ] , } ; if ( userOptions != null && userOptions . length > 0 ) { configuration . rules . set ( ruleName , { ruleName , ruleArguments : userOptions , } ) ; } else { configuration . rules . set ( ruleName , { ruleName , } ) ; } const options = { formatter : 'json' , fix : false , rulesDirectory : RULES_DIRECTORY , formattersDirectory : FORMATTER_DIRECTORY , } ; const debug = ErrorTolerantWalker . DEBUG ; ErrorTolerantWalker . DEBUG = true ; let result ; if ( useTypeChecker ) { program = ts . createProgram ( [ inputFileOrScript ] , { } ) ; } if ( inputFileOrScript . match ( /.*\.ts(x)?$/ ) ) { const contents = fs . readFileSync ( inputFileOrScript , FILE_ENCODING ) ; const linter = new Lint . Linter ( options , useTypeChecker ? program : undefined ) ; linter . lint ( inputFileOrScript , contents , configuration ) ; result = linter . getResult ( ) ; } else { let filename ; if ( inputFileOrScript . indexOf ( 'import React' ) > - 1 ) { filename = 'file.tsx' ; } else { filename = 'file.ts' ; } const linter = new Lint . Linter ( options , useTypeChecker ? program : undefined ) ; linter . lint ( filename , inputFileOrScript , configuration ) ; result = linter . getResult ( ) ; } ErrorTolerantWalker . DEBUG = debug ; return result ; } function runRuleAndEnforceAssertions ( ruleName , userOptions , inputFileOrScript , expectedFailures , useTypeChecker = false ) { const lintResult = runRule ( ruleName , userOptions , inputFileOrScript , useTypeChecker ) ; const actualFailures = JSON . parse ( lintResult . output ) ; actualFailures . forEach ( ( actual ) : void => { delete actual . startPosition . position ; delete actual . endPosition ; actual . startPosition . line = actual . startPosition . line + 1 ; actual . startPosition . character = actual . startPosition . character + 1 ; } ) ; expectedFailures . forEach ( ( expected ) : void => { delete expected . startPosition . position ; delete expected . endPosition ; if ( ! expected . ruleSeverity ) { expected . ruleSeverity = 'ERROR' ; } } ) ; const errorMessage = `Wrong # of failures: \n${ JSON . stringify ( actualFailures , null , 2 ) }` ; chai . assert . equal ( actualFailures . length , expectedFailures . length , errorMessage ) ; expectedFailures . forEach ( ( expected , index ) : void => { const actual = actualFailures [ index ] ; chai . assert . deepEqual ( actual , expected ) ; } ) ; } }