1- import type { TestTagDefinition } from '@vitest/runner'
21import type { TestError } from '@vitest/utils'
2+ import type {
3+ RunnerTask ,
4+ RunnerTaskResultPack ,
5+ RunnerTestFile ,
6+ TestTagDefinition ,
7+ UserConsoleLog ,
8+ } from 'vitest'
39import type { Ref } from 'vue'
410import type { RunState } from '../../../types'
11+ import { createFileTask } from '@vitest/runner/utils'
512import { computed , ref } from 'vue'
613import { config } from '.'
714
@@ -15,3 +22,130 @@ export const tagsDefinitions = computed(() => {
1522 return acc
1623 } , { } as Record < string , TestTagDefinition > )
1724} )
25+
26+ export class StateManager {
27+ filesMap : Map < string , RunnerTestFile [ ] > = new Map ( )
28+ pathsSet : Set < string > = new Set ( )
29+ idMap : Map < string , RunnerTask > = new Map ( )
30+
31+ getPaths ( ) : string [ ] {
32+ return Array . from ( this . pathsSet )
33+ }
34+
35+ /**
36+ * Return files that were running or collected.
37+ */
38+ getFiles ( keys ?: string [ ] ) : RunnerTestFile [ ] {
39+ if ( keys ) {
40+ return keys
41+ . map ( key => this . filesMap . get ( key ) ! )
42+ . flat ( )
43+ . filter ( file => file && ! file . local )
44+ }
45+ return Array . from ( this . filesMap . values ( ) ) . flat ( ) . filter ( file => ! file . local )
46+ }
47+
48+ getFilepaths ( ) : string [ ] {
49+ return Array . from ( this . filesMap . keys ( ) )
50+ }
51+
52+ getFailedFilepaths ( ) : string [ ] {
53+ return this . getFiles ( )
54+ . filter ( i => i . result ?. state === 'fail' )
55+ . map ( i => i . filepath )
56+ }
57+
58+ collectPaths ( paths : string [ ] = [ ] ) : void {
59+ paths . forEach ( ( path ) => {
60+ this . pathsSet . add ( path )
61+ } )
62+ }
63+
64+ collectFiles ( files : RunnerTestFile [ ] = [ ] ) : void {
65+ files . forEach ( ( file ) => {
66+ const existing = this . filesMap . get ( file . filepath ) || [ ]
67+ const otherProject = existing . filter (
68+ i => i . projectName !== file . projectName || i . meta . typecheck !== file . meta . typecheck ,
69+ )
70+ const currentFile = existing . find (
71+ i => i . projectName === file . projectName ,
72+ )
73+ // keep logs for the previous file because it should always be initiated before the collections phase
74+ // which means that all logs are collected during the collection and not inside tests
75+ if ( currentFile ) {
76+ file . logs = currentFile . logs
77+ }
78+ otherProject . push ( file )
79+ this . filesMap . set ( file . filepath , otherProject )
80+ this . updateId ( file )
81+ } )
82+ }
83+
84+ // this file is reused by ws-client, and should not rely on heavy dependencies like workspace
85+ clearFiles (
86+ _project : { config : { name : string | undefined ; root : string } } ,
87+ paths : string [ ] = [ ] ,
88+ ) : void {
89+ const project = _project
90+ paths . forEach ( ( path ) => {
91+ const files = this . filesMap . get ( path )
92+ const fileTask = createFileTask (
93+ path ,
94+ project . config . root ,
95+ project . config . name || '' ,
96+ )
97+ fileTask . local = true
98+ this . idMap . set ( fileTask . id , fileTask )
99+ if ( ! files ) {
100+ this . filesMap . set ( path , [ fileTask ] )
101+ return
102+ }
103+ const filtered = files . filter (
104+ file => file . projectName !== project . config . name ,
105+ )
106+ // always keep a File task, so we can associate logs with it
107+ if ( ! filtered . length ) {
108+ this . filesMap . set ( path , [ fileTask ] )
109+ }
110+ else {
111+ this . filesMap . set ( path , [ ...filtered , fileTask ] )
112+ }
113+ } )
114+ }
115+
116+ updateId ( task : RunnerTask ) : void {
117+ if ( this . idMap . get ( task . id ) === task ) {
118+ return
119+ }
120+ this . idMap . set ( task . id , task )
121+ if ( task . type === 'suite' ) {
122+ task . tasks . forEach ( ( task ) => {
123+ this . updateId ( task )
124+ } )
125+ }
126+ }
127+
128+ updateTasks ( packs : RunnerTaskResultPack [ ] ) : void {
129+ for ( const [ id , result , meta ] of packs ) {
130+ const task = this . idMap . get ( id )
131+ if ( task ) {
132+ task . result = result
133+ task . meta = meta
134+ // skipped with new PendingError
135+ if ( result ?. state === 'skip' ) {
136+ task . mode = 'skip'
137+ }
138+ }
139+ }
140+ }
141+
142+ updateUserLog ( log : UserConsoleLog ) : void {
143+ const task = log . taskId && this . idMap . get ( log . taskId )
144+ if ( task ) {
145+ if ( ! task . logs ) {
146+ task . logs = [ ]
147+ }
148+ task . logs . push ( log )
149+ }
150+ }
151+ }
0 commit comments