@@ -16,28 +16,283 @@ export default class Queue {
1616 private processing : boolean = false ;
1717 private processingSnapshot : string = '' ;
1818 private ctx : Context ;
19+ private snapshotNames : Array < string > = [ ] ;
20+ private variants : Array < string > = [ ] ;
1921
2022 constructor ( ctx : Context ) {
2123 this . ctx = ctx ;
2224 }
2325
24- enqueue ( item : Snapshot ) : void {
26+ enqueue ( item : Snapshot , start : boolean ) : void {
2527 this . snapshots . push ( item ) ;
28+ if ( start ) {
29+ if ( ! this . processing ) {
30+ this . processing = true ;
31+ this . processNext ( ) ;
32+ }
33+ }
34+ }
35+
36+ startProcessingfunc ( ) : void {
2637 if ( ! this . processing ) {
2738 this . processing = true ;
2839 this . processNext ( ) ;
2940 }
3041 }
3142
43+ private generateVariants ( snapshot : Snapshot , config : any ) : void {
44+ // Process web configurations if they exist
45+
46+ if ( config . web ) {
47+ const browsers = config . web . browsers || [ ] ;
48+ const viewports = config . web . viewports || [ ] ;
49+
50+ for ( const browser of browsers ) {
51+ for ( const viewport of viewports ) {
52+ const width = viewport . width ;
53+ const height = viewport . height || 0 ; // Use 0 if height is not provided
54+ const variant = `${ snapshot . name } _${ browser } _viewport[${ width } ]_viewport[${ height } ]` ;
55+ this . variants . push ( variant ) ;
56+ }
57+ }
58+ }
59+
60+ // Process mobile configurations if they exist
61+ if ( config . mobile ) {
62+ const devices = config . mobile . devices || [ ] ;
63+ const orientation = config . mobile . orientation || "portrait" ; // Default to portrait if not provided
64+ const fullPage = config . mobile . fullPage ?? true ; // FullPage defaults to true if not defined
65+
66+ for ( const device of devices ) {
67+ const variant = `${ snapshot . name } _${ device } _${ orientation } _${ fullPage ? 'fullPage' : 'noFullPage' } ` ;
68+ this . variants . push ( variant ) ;
69+ }
70+ }
71+ }
72+
73+
74+ private generateWebVariants ( snapshot : Snapshot , webConfig : any ) : void {
75+ const browsers = webConfig . browsers ?? this . ctx . config . web ?. browsers ?? [ "chrome" , "edge" , "firefox" , "safari" ] ;
76+ const viewports = webConfig . viewports || [ ] ;
77+
78+ for ( const browser of browsers ) {
79+ for ( const viewport of viewports ) {
80+ const width = viewport [ 0 ] ;
81+ const height = viewport [ 1 ] || 0 ; // Use 0 if height is not provided
82+ const variant = `${ snapshot . name } _${ browser } _viewport[${ width } ]_viewport[${ height } ]` ;
83+ this . variants . push ( variant ) ;
84+ }
85+ }
86+ }
87+
88+ private generateMobileVariants ( snapshot : Snapshot , mobileConfig : any ) : void {
89+ const devices = mobileConfig . devices || [ ] ;
90+ const orientation = mobileConfig . orientation ?? this . ctx . config . mobile ?. orientation ?? "portrait" ;
91+ const fullPage = mobileConfig . fullPage ?? this . ctx . config . mobile ?. fullPage ?? true ;
92+
93+ for ( const device of devices ) {
94+ const variant = `${ snapshot . name } _${ device } _${ orientation } _${ fullPage ? 'fullPage' : 'noFullPage' } ` ;
95+ this . variants . push ( variant ) ;
96+ }
97+ }
98+
99+ private filterExistingVariants ( snapshot : Snapshot , config : any ) : boolean {
100+
101+ let drop = true ;
102+
103+ if ( snapshot . options && snapshot . options . web ) {
104+ const webDrop = this . filterWebVariants ( snapshot , snapshot . options . web ) ;
105+ if ( ! webDrop ) drop = false ;
106+ }
107+
108+ if ( snapshot . options && snapshot . options . mobile ) {
109+ const mobileDrop = this . filterMobileVariants ( snapshot , snapshot . options . mobile ) ;
110+ if ( ! mobileDrop ) drop = false ;
111+ }
112+
113+ // Fallback to the global config if neither web nor mobile options are present in snapshot.options
114+ if ( ! snapshot . options || ( snapshot . options && ! snapshot . options . web && ! snapshot . options . mobile ) ) {
115+ const configDrop = this . filterVariants ( snapshot , config ) ;
116+ if ( ! configDrop ) drop = false ;
117+ }
118+ return drop ;
119+ }
120+
121+ private filterVariants ( snapshot : Snapshot , config : any ) : boolean {
122+ let allVariantsDropped = true ;
123+
124+ // Process web configurations if they exist in config
125+ if ( config . web ) {
126+ const browsers = config . web . browsers || [ ] ;
127+ const viewports = config . web . viewports || [ ] ;
128+
129+ for ( const browser of browsers ) {
130+ for ( const viewport of viewports ) {
131+ const width = viewport . width ;
132+ const height = viewport . height || 0 ;
133+ const variant = `${ snapshot . name } _${ browser } _viewport[${ width } ]_viewport[${ height } ]` ;
134+
135+ if ( ! this . variants . includes ( variant ) ) {
136+ allVariantsDropped = false ; // Found a variant that needs processing
137+ if ( ! snapshot . options ) snapshot . options = { } ;
138+ if ( ! snapshot . options . web ) snapshot . options . web = { browsers : [ ] , viewports : [ ] } ;
139+
140+ if ( ! snapshot . options . web . browsers . includes ( browser ) ) {
141+ snapshot . options . web . browsers . push ( browser ) ;
142+ }
143+
144+ // Check for unique viewports to avoid duplicates
145+ const viewportExists = snapshot . options . web . viewports . some ( existingViewport =>
146+ existingViewport [ 0 ] === width &&
147+ ( existingViewport . length < 2 || existingViewport [ 1 ] === height )
148+ ) ;
149+
150+ if ( ! viewportExists ) {
151+ if ( height > 0 ) {
152+ snapshot . options . web . viewports . push ( [ width , height ] ) ;
153+ } else {
154+ snapshot . options . web . viewports . push ( [ width ] ) ;
155+ }
156+ }
157+ }
158+ }
159+ }
160+ }
161+
162+ // Process mobile configurations if they exist in config
163+ if ( config . mobile ) {
164+ const devices = config . mobile . devices || [ ] ;
165+ const orientation = config . mobile . orientation || "portrait" ;
166+ const fullPage = config . mobile . fullPage || true ;
167+
168+ for ( const device of devices ) {
169+ const variant = `${ snapshot . name } _${ device } _${ orientation } _${ fullPage ? 'fullPage' : 'noFullPage' } ` ;
170+
171+ if ( ! this . variants . includes ( variant ) ) {
172+ allVariantsDropped = false ; // Found a variant that needs processing
173+ if ( ! snapshot . options ) snapshot . options = { } ;
174+ if ( ! snapshot . options . mobile ) snapshot . options . mobile = { devices : [ ] , orientation : "portrait" , fullPage : true } ;
175+
176+ if ( ! snapshot . options . mobile . devices . includes ( device ) ) {
177+ snapshot . options . mobile . devices . push ( device ) ;
178+ }
179+ snapshot . options . mobile . orientation = orientation ;
180+ snapshot . options . mobile . fullPage = fullPage ;
181+ }
182+ }
183+ }
184+
185+ return allVariantsDropped ;
186+ }
187+
188+ private filterWebVariants ( snapshot : Snapshot , webConfig : any ) : boolean {
189+ const browsers = webConfig . browsers ?? this . ctx . config . web ?. browsers ?? [ "chrome" , "edge" , "firefox" , "safari" ] ;
190+ const viewports = webConfig . viewports || [ ] ;
191+ let allVariantsDropped = true ;
192+
193+ if ( ! snapshot . options ) {
194+ snapshot . options = { } ;
195+ }
196+
197+ snapshot . options . web = { browsers : [ ] , viewports : [ ] } ;
198+
199+ for ( const browser of browsers ) {
200+ for ( const viewport of viewports ) {
201+ const width = viewport [ 0 ] ;
202+ const height = viewport [ 1 ] || 0 ;
203+ const variant = `${ snapshot . name } _${ browser } _viewport[${ width } ]_viewport[${ height } ]` ;
204+
205+ if ( ! this . variants . includes ( variant ) ) {
206+ allVariantsDropped = false ; // Found a variant that needs processing
207+ if ( ! snapshot . options . web . browsers . includes ( browser ) ) {
208+ snapshot . options . web . browsers . push ( browser ) ;
209+ }
210+ // Only add unique viewports to avoid duplicates
211+ const viewportExists = snapshot . options . web . viewports . some ( existingViewport =>
212+ existingViewport [ 0 ] === width &&
213+ ( existingViewport . length < 2 || existingViewport [ 1 ] === height )
214+ ) ;
215+ console . log ( variant )
216+ console . log ( viewportExists )
217+ if ( ! viewportExists ) {
218+ if ( height > 0 ) {
219+ snapshot . options . web . viewports . push ( [ width , height ] ) ;
220+ } else {
221+ snapshot . options . web . viewports . push ( [ width ] ) ;
222+ }
223+ }
224+ }
225+ }
226+ }
227+ return allVariantsDropped ;
228+ }
229+
230+
231+ private filterMobileVariants ( snapshot : Snapshot , mobileConfig : any ) : boolean {
232+ if ( ! snapshot . options ) {
233+ snapshot . options = { } ;
234+ }
235+
236+ snapshot . options . mobile = { devices : [ ] , orientation : "portrait" , fullPage : true } ;
237+
238+ const devices = mobileConfig . devices || [ ] ;
239+ const orientation = mobileConfig . orientation ?? this . ctx . config . mobile ?. orientation ?? "portrait" ;
240+ const fullPage = mobileConfig . fullPage ?? this . ctx . config . mobile ?. fullPage ?? true ;
241+ let allVariantsDropped = true ;
242+
243+ for ( const device of devices ) {
244+ const variant = `${ snapshot . name } _${ device } _${ orientation } _${ fullPage ? 'fullPage' : 'noFullPage' } ` ;
245+
246+ if ( ! this . variants . includes ( variant ) ) {
247+ allVariantsDropped = false ; // Found a variant that needs processing
248+ snapshot . options . mobile . devices . push ( device ) ;
249+ snapshot . options . mobile . orientation = orientation ;
250+ snapshot . options . mobile . fullPage = fullPage ;
251+ }
252+ }
253+ return allVariantsDropped ;
254+ }
255+
256+
257+
32258 private async processNext ( ) : Promise < void > {
33259 if ( ! this . isEmpty ( ) ) {
34- const snapshot = this . snapshots . shift ( ) ;
260+ let snapshot ;
261+ if ( this . ctx . config . deferUploads ) {
262+ snapshot = this . snapshots . pop ( ) ;
263+ } else {
264+ snapshot = this . snapshots . shift ( ) ;
265+ }
35266 try {
36267 this . processingSnapshot = snapshot ?. name ;
37- let { processedSnapshot, warnings } = await processSnapshot ( snapshot , this . ctx ) ;
38- await this . ctx . client . uploadSnapshot ( this . ctx , processedSnapshot ) ;
39- this . ctx . totalSnapshots ++ ;
40- this . processedSnapshots . push ( { name : snapshot . name , warnings } ) ;
268+ let drop = false ;
269+
270+ if ( snapshot && snapshot . name && this . snapshotNames . includes ( snapshot . name ) ) {
271+ drop = this . filterExistingVariants ( snapshot , this . ctx . config ) ;
272+ }
273+
274+ if ( snapshot && snapshot . name && ! this . snapshotNames . includes ( snapshot . name ) ) {
275+ this . snapshotNames . push ( snapshot . name ) ;
276+ }
277+
278+ if ( snapshot && snapshot . options && snapshot . options . web ) {
279+ this . generateWebVariants ( snapshot , snapshot . options . web ) ;
280+ }
281+
282+ if ( snapshot && snapshot . options && snapshot . options . mobile ) {
283+ this . generateMobileVariants ( snapshot , snapshot . options . mobile )
284+ }
285+
286+ if ( ( snapshot && ! snapshot . options ) || ( snapshot && snapshot . options && ! snapshot . options . web && ! snapshot . options . mobile ) ) {
287+ this . generateVariants ( snapshot , this . ctx . config ) ;
288+ }
289+
290+ if ( ! drop ) {
291+ let { processedSnapshot, warnings } = await processSnapshot ( snapshot , this . ctx ) ;
292+ await this . ctx . client . uploadSnapshot ( this . ctx , processedSnapshot ) ;
293+ this . ctx . totalSnapshots ++ ;
294+ this . processedSnapshots . push ( { name : snapshot . name , warnings } ) ;
295+ }
41296 } catch ( error : any ) {
42297 this . ctx . log . debug ( `snapshot failed; ${ error } ` ) ;
43298 this . processedSnapshots . push ( { name : snapshot . name , error : error . message } ) ;
0 commit comments