import * as messages from '@cucumber/messages' ; import { getWorstTestStepResult } from '@cucumber/messages' ; import { ArrayMultimap } from '@teppeis/multimaps' ; export default class Query { private readonly testStepResultByPickleId = new ArrayMultimap < string , messages . TestStepResult > ( ) ; private readonly testStepResultsByPickleStepId = new ArrayMultimap < string , messages . TestStepResult > ( ) ; private readonly testStepById = new Map < string , messages . TestStep > ( ) ; private readonly testCaseByPickleId = new Map < string , messages . TestCase > ( ) ; private readonly testCaseByTestCaseId = new Map < string , messages . TestCase > ( ) ; private readonly pickleIdByTestStepId = new Map < string , string > ( ) ; private readonly pickleStepIdByTestStepId = new Map < string , string > ( ) ; private readonly testStepResultsbyTestStepId = new ArrayMultimap < string , messages . TestStepResult > ( ) ; private readonly testStepIdsByPickleStepId = new ArrayMultimap < string , string > ( ) ; private readonly hooksById = new Map < string , messages . Hook > ( ) ; private readonly attachmentsByTestStepId = new ArrayMultimap < string , messages . Attachment > ( ) ; private readonly stepMatchArgumentsListsByPickleStepId = new Map < string , readonly messages . StepMatchArgumentsList [ ] > ( ) ; public update ( envelope ) { if ( envelope . testCase ) { this . testCaseByTestCaseId . set ( envelope . testCase . id , envelope . testCase ) ; this . testCaseByPickleId . set ( envelope . testCase . pickleId , envelope . testCase ) ; for ( const testStep of envelope . testCase . testSteps ) { this . testStepById . set ( testStep . id , testStep ) ; this . pickleIdByTestStepId . set ( testStep . id , envelope . testCase . pickleId ) ; this . pickleStepIdByTestStepId . set ( testStep . id , testStep . pickleStepId ) ; this . testStepIdsByPickleStepId . put ( testStep . pickleStepId , testStep . id ) ; this . stepMatchArgumentsListsByPickleStepId . set ( testStep . pickleStepId , testStep . stepMatchArgumentsLists ) ; } } if ( envelope . testCaseStarted && envelope . testCaseStarted . attempt > 0 ) { const testCase = this . testCaseByTestCaseId . get ( envelope . testCaseStarted . testCaseId ) ; this . testStepResultByPickleId . delete ( testCase . pickleId ) ; for ( const testStep of testCase . testSteps ) { this . testStepResultsByPickleStepId . delete ( testStep . pickleStepId ) ; this . testStepResultsbyTestStepId . delete ( testStep . id ) ; this . attachmentsByTestStepId . delete ( testStep . id ) ; } } if ( envelope . testStepFinished ) { const pickleId = this . pickleIdByTestStepId . get ( envelope . testStepFinished . testStepId ) ; this . testStepResultByPickleId . put ( pickleId , envelope . testStepFinished . testStepResult ) ; const testStep = this . testStepById . get ( envelope . testStepFinished . testStepId ) ; this . testStepResultsByPickleStepId . put ( testStep . pickleStepId , envelope . testStepFinished . testStepResult ) ; this . testStepResultsbyTestStepId . put ( testStep . id , envelope . testStepFinished . testStepResult ) ; } if ( envelope . hook ) { this . hooksById . set ( envelope . hook . id , envelope . hook ) ; } if ( envelope . attachment ) { this . attachmentsByTestStepId . put ( envelope . attachment . testStepId , envelope . attachment ) ; } } param pickleStepIds public getPickleStepTestStepResults ( pickleStepIds ) { if ( pickleStepIds . length === 0 ) { return [ { status : messages . TestStepResultStatus . UNKNOWN , duration : messages . TimeConversion . millisecondsToDuration ( 0 ) , } , ] ; } return pickleStepIds . reduce ( ( testStepResults , pickleId ) => { return testStepResults . concat ( this . testStepResultsByPickleStepId . get ( pickleId ) ) ; } , [ ] ) ; } param pickleIds public getPickleTestStepResults ( pickleIds ) { if ( pickleIds . length === 0 ) { return [ { status : messages . TestStepResultStatus . UNKNOWN , duration : messages . TimeConversion . millisecondsToDuration ( 0 ) , } , ] ; } return pickleIds . reduce ( ( testStepResults , pickleId ) => { return testStepResults . concat ( this . testStepResultByPickleId . get ( pickleId ) ) ; } , [ ] ) ; } param pickleStepIds public getPickleStepAttachments ( pickleStepIds ) { return this . getTestStepsAttachments ( pickleStepIds . reduce ( ( testStepIds , pickleStepId ) => { return testStepIds . concat ( this . testStepIdsByPickleStepId . get ( pickleStepId ) ) ; } , [ ] ) ) ; } public getTestStepsAttachments ( testStepIds ) { return testStepIds . reduce ( ( attachments , testStepId ) => { return attachments . concat ( this . attachmentsByTestStepId . get ( testStepId ) ) ; } , [ ] ) ; } param pickleStepId public getStepMatchArgumentsLists ( pickleStepId ) { return this . stepMatchArgumentsListsByPickleStepId . get ( pickleStepId ) ; } public getHook ( hookId ) { return this . hooksById . get ( hookId ) ; } public getBeforeHookSteps ( pickleId ) { const hookSteps = [ ] ; this . identifyHookSteps ( pickleId , ( hook ) => hookSteps . push ( hook ) , ( ) => null ) ; return hookSteps ; } public getAfterHookSteps ( pickleId ) { const hookSteps = [ ] ; this . identifyHookSteps ( pickleId , ( ) => null , ( hook ) => hookSteps . push ( hook ) ) ; return hookSteps ; } private identifyHookSteps ( pickleId , onBeforeHookFound , onAfterHookFound ) { const testCase = this . testCaseByPickleId . get ( pickleId ) ; if ( ! testCase ) { return ; } let pickleStepFound = false ; for ( const step of testCase . testSteps ) { if ( step . hookId ) { pickleStepFound ? onAfterHookFound ( step ) : onBeforeHookFound ( step ) ; } else { pickleStepFound = true ; } } } public getTestStepResults ( testStepId ) { return this . testStepResultsbyTestStepId . get ( testStepId ) ; } public getStatusCounts ( pickleIds ) { const result = { } ; for ( const pickleId of pickleIds ) { const testStepResult = getWorstTestStepResult ( this . getPickleTestStepResults ( [ pickleId ] ) ) ; const count = result [ testStepResult . status ] || 0 ; result [ testStepResult . status ] = count + 1 ; } return result ; } }