@@ -10,335 +10,7 @@ const ALLOWED_STATUSES = [200, 201];
1010const REQUEST_TIMEOUT = 10000 ;
1111const MIN_VIEWPORT_HEIGHT = 1080 ;
1212
13- export default class Queue {
14- private snapshots : Array < Snapshot > = [ ] ;
15- private processedSnapshots : Array < Record < string , any > > = [ ] ;
16- private processing : boolean = false ;
17- private processingSnapshot : string = '' ;
18- private ctx : Context ;
19- private snapshotNames : Array < string > = [ ] ;
20- private variants : Array < string > = [ ] ;
21-
22- constructor ( ctx : Context ) {
23- this . ctx = ctx ;
24- }
25-
26- enqueue ( item : Snapshot , start : boolean ) : void {
27- 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 {
37- if ( ! this . processing ) {
38- this . processing = true ;
39- this . processNext ( ) ;
40- }
41- }
42-
43- private processGenerateVariants ( snapshot : Snapshot ) : void {
44- if ( snapshot . options ) {
45- if ( snapshot . options . web ) {
46- this . generateWebVariants ( snapshot , snapshot . options . web ) ;
47- }
48- if ( snapshot . options . mobile ) {
49- this . generateMobileVariants ( snapshot , snapshot . options . mobile ) ;
50- }
51- }
52-
53- if ( ! snapshot . options || ( snapshot . options && ! snapshot . options . web && ! snapshot . options . mobile ) ) {
54- this . generateVariants ( snapshot , this . ctx . config ) ;
55- }
56- }
57-
58-
59- private generateVariants ( snapshot : Snapshot , config : any ) : void {
60- // Process web configurations if they exist
61-
62- if ( config . web ) {
63- const browsers = config . web . browsers || [ ] ;
64- const viewports = config . web . viewports || [ ] ;
65-
66- for ( const browser of browsers ) {
67- for ( const viewport of viewports ) {
68- const width = viewport . width ;
69- const height = viewport . height || 0 ; // Use 0 if height is not provided
70- const variant = `${ snapshot . name } _${ browser } _viewport[${ width } ]_viewport[${ height } ]` ;
71- this . variants . push ( variant ) ;
72- }
73- }
74- }
75-
76- // Process mobile configurations if they exist
77- if ( config . mobile ) {
78- const devices = config . mobile . devices || [ ] ;
79- const orientation = config . mobile . orientation || constants . MOBILE_ORIENTATION_PORTRAIT ;
80-
81- for ( const device of devices ) {
82- const variant = `${ snapshot . name } _${ device } _${ orientation } ` ;
83- this . variants . push ( variant ) ;
84- }
85- }
86- }
87-
88-
89- private generateWebVariants ( snapshot : Snapshot , webConfig : any ) : void {
90- const browsers = webConfig . browsers ?? this . ctx . config . web ?. browsers ?? [ constants . CHROME , constants . EDGE , constants . FIREFOX , constants . SAFARI ] ;
91- const viewports = webConfig . viewports || [ ] ;
92-
93- for ( const browser of browsers ) {
94- for ( const viewport of viewports ) {
95- const width = viewport [ 0 ] ;
96- const height = viewport [ 1 ] || 0 ; // Use 0 if height is not provided
97- const variant = `${ snapshot . name } _${ browser } _viewport[${ width } ]_viewport[${ height } ]` ;
98- this . variants . push ( variant ) ;
99- }
100- }
101- }
102-
103- private generateMobileVariants ( snapshot : Snapshot , mobileConfig : any ) : void {
104- const devices = mobileConfig . devices || [ ] ;
105- const orientation = mobileConfig . orientation ?? this . ctx . config . mobile ?. orientation ?? constants . MOBILE_ORIENTATION_PORTRAIT ;
106-
107- for ( const device of devices ) {
108- const variant = `${ snapshot . name } _${ device } _${ orientation } ` ;
109- this . variants . push ( variant ) ;
110- }
111- }
112-
113-
114- private filterExistingVariants ( snapshot : Snapshot , config : any ) : boolean {
115-
116- let drop = true ;
117-
118- if ( snapshot . options && snapshot . options . web ) {
119- const webDrop = this . filterWebVariants ( snapshot , snapshot . options . web ) ;
120- if ( ! webDrop ) drop = false ;
121- }
122-
123- if ( snapshot . options && snapshot . options . mobile ) {
124- const mobileDrop = this . filterMobileVariants ( snapshot , snapshot . options . mobile ) ;
125- if ( ! mobileDrop ) drop = false ;
126- }
127-
128- // Fallback to the global config if neither web nor mobile options are present in snapshot.options
129- if ( ! snapshot . options || ( snapshot . options && ! snapshot . options . web && ! snapshot . options . mobile ) ) {
130- const configDrop = this . filterVariants ( snapshot , config ) ;
131- if ( ! configDrop ) drop = false ;
132- }
133- return drop ;
134- }
135-
136- private filterVariants ( snapshot : Snapshot , config : any ) : boolean {
137- let allVariantsDropped = true ;
138-
139- // Process web configurations if they exist in config
140- if ( config . web ) {
141- const browsers = config . web . browsers || [ ] ;
142- const viewports = config . web . viewports || [ ] ;
143-
144- for ( const browser of browsers ) {
145- for ( const viewport of viewports ) {
146- const width = viewport . width ;
147- const height = viewport . height || 0 ;
148- const variant = `${ snapshot . name } _${ browser } _viewport[${ width } ]_viewport[${ height } ]` ;
149-
150- if ( ! this . variants . includes ( variant ) ) {
151- allVariantsDropped = false ; // Found a variant that needs processing
152- if ( ! snapshot . options ) snapshot . options = { } ;
153- if ( ! snapshot . options . web ) snapshot . options . web = { browsers : [ ] , viewports : [ ] } ;
154-
155- if ( ! snapshot . options . web . browsers . includes ( browser ) ) {
156- snapshot . options . web . browsers . push ( browser ) ;
157- }
158-
159- // Check for unique viewports to avoid duplicates
160- const viewportExists = snapshot . options . web . viewports . some ( existingViewport =>
161- existingViewport [ 0 ] === width &&
162- ( existingViewport . length < 2 || existingViewport [ 1 ] === height )
163- ) ;
164-
165- if ( ! viewportExists ) {
166- if ( height > 0 ) {
167- snapshot . options . web . viewports . push ( [ width , height ] ) ;
168- } else {
169- snapshot . options . web . viewports . push ( [ width ] ) ;
170- }
171- }
172- }
173- }
174- }
175- }
176-
177- // Process mobile configurations if they exist in config
178- if ( config . mobile ) {
179- const devices = config . mobile . devices || [ ] ;
180- const orientation = config . mobile . orientation || constants . MOBILE_ORIENTATION_PORTRAIT ;
181- const fullPage = config . mobile . fullPage || true ;
182-
183- for ( const device of devices ) {
184- const variant = `${ snapshot . name } _${ device } _${ orientation } ` ;
185-
186- if ( ! this . variants . includes ( variant ) ) {
187- allVariantsDropped = false ; // Found a variant that needs processing
188- if ( ! snapshot . options ) snapshot . options = { } ;
189- if ( ! snapshot . options . mobile ) snapshot . options . mobile = { devices : [ ] , orientation : constants . MOBILE_ORIENTATION_PORTRAIT } ;
190-
191- if ( ! snapshot . options . mobile . devices . includes ( device ) ) {
192- snapshot . options . mobile . devices . push ( device ) ;
193- }
194- snapshot . options . mobile . orientation = orientation ;
195- }
196- }
197- }
198-
199-
200- return allVariantsDropped ;
201- }
202-
203- private filterWebVariants ( snapshot : Snapshot , webConfig : any ) : boolean {
204- const browsers = webConfig . browsers ?? this . ctx . config . web ?. browsers ?? [ constants . CHROME , constants . EDGE , constants . FIREFOX , constants . SAFARI ] ;
205- const viewports = webConfig . viewports || [ ] ;
206- let allVariantsDropped = true ;
207-
208- if ( ! snapshot . options ) {
209- snapshot . options = { } ;
210- }
211-
212- snapshot . options . web = { browsers : [ ] , viewports : [ ] } ;
213-
214- for ( const browser of browsers ) {
215- for ( const viewport of viewports ) {
216- const width = viewport [ 0 ] ;
217- const height = viewport [ 1 ] || 0 ;
218- const variant = `${ snapshot . name } _${ browser } _viewport[${ width } ]_viewport[${ height } ]` ;
219-
220- if ( ! this . variants . includes ( variant ) ) {
221- allVariantsDropped = false ; // Found a variant that needs processing
222- if ( ! snapshot . options . web . browsers . includes ( browser ) ) {
223- snapshot . options . web . browsers . push ( browser ) ;
224- }
225- // Only add unique viewports to avoid duplicates
226- const viewportExists = snapshot . options . web . viewports . some ( existingViewport =>
227- existingViewport [ 0 ] === width &&
228- ( existingViewport . length < 2 || existingViewport [ 1 ] === height )
229- ) ;
230- if ( ! viewportExists ) {
231- if ( height > 0 ) {
232- snapshot . options . web . viewports . push ( [ width , height ] ) ;
233- } else {
234- snapshot . options . web . viewports . push ( [ width ] ) ;
235- }
236- }
237- }
238- }
239- }
240- return allVariantsDropped ;
241- }
242-
243-
244- private filterMobileVariants ( snapshot : Snapshot , mobileConfig : any ) : boolean {
245- if ( ! snapshot . options ) {
246- snapshot . options = { } ;
247- }
248-
249- snapshot . options . mobile = { devices : [ ] , orientation : constants . MOBILE_ORIENTATION_PORTRAIT } ;
250-
251- const devices = mobileConfig . devices || [ ] ;
252- const orientation = mobileConfig . orientation ?? this . ctx . config . mobile ?. orientation ?? constants . MOBILE_ORIENTATION_PORTRAIT ;
253- const fullPage = mobileConfig . fullPage ?? this . ctx . config . mobile ?. fullPage ?? true ;
254- let allVariantsDropped = true ;
255-
256- for ( const device of devices ) {
257- const variant = `${ snapshot . name } _${ device } _${ orientation } ` ;
258-
259- if ( ! this . variants . includes ( variant ) ) {
260- allVariantsDropped = false ; // Found a variant that needs processing
261- snapshot . options . mobile . devices . push ( device ) ;
262- snapshot . options . mobile . orientation = orientation ;
263- }
264- }
265- return allVariantsDropped ;
266- }
267-
268- private async processNext ( ) : Promise < void > {
269- if ( ! this . isEmpty ( ) ) {
270- let snapshot ;
271- if ( this . ctx . config . deferUploads ) {
272- snapshot = this . snapshots . pop ( ) ;
273- } else {
274- snapshot = this . snapshots . shift ( ) ;
275- }
276- try {
277- this . processingSnapshot = snapshot ?. name ;
278- let drop = false ;
279-
280- if ( snapshot && snapshot . name && this . snapshotNames . includes ( snapshot . name ) ) {
281- if ( ! this . ctx . config . deferUploads ) {
282- drop = true ;
283- this . ctx . log . debug ( `snapshot failed; Same snapshot has been encountered with defer Uploads being false` ) ;
284- } else {
285- drop = this . filterExistingVariants ( snapshot , this . ctx . config ) ;
286- }
287- }
288-
289- if ( snapshot && snapshot . name && ! this . snapshotNames . includes ( snapshot . name ) && ! drop ) {
290- this . snapshotNames . push ( snapshot . name ) ;
291- }
292-
293- if ( snapshot && ! drop ) {
294- this . processGenerateVariants ( snapshot ) ;
295- }
296-
297- if ( ! drop ) {
298- let { processedSnapshot, warnings } = await processSnapshot ( snapshot , this . ctx ) ;
299- await this . ctx . client . uploadSnapshot ( this . ctx , processedSnapshot ) ;
300- this . ctx . totalSnapshots ++ ;
301- this . processedSnapshots . push ( { name : snapshot . name , warnings } ) ;
302- }
303- } catch ( error : any ) {
304- this . ctx . log . debug ( `snapshot failed; ${ error } ` ) ;
305- this . processedSnapshots . push ( { name : snapshot . name , error : error . message } ) ;
306- }
307- // Close open browser contexts and pages
308- if ( this . ctx . browser ) {
309- for ( let context of this . ctx . browser . contexts ( ) ) {
310- for ( let page of context . pages ( ) ) {
311- await page . close ( ) ;
312- this . ctx . log . debug ( `Closed browser page for snapshot ${ snapshot . name } ` ) ;
313- }
314- await context . close ( ) ;
315- this . ctx . log . debug ( `Closed browser context for snapshot ${ snapshot . name } ` ) ;
316- }
317- }
318- this . processNext ( ) ;
319- } else {
320- this . processing = false ;
321- }
322- }
323-
324- isProcessing ( ) : boolean {
325- return this . processing ;
326- }
327-
328- getProcessingSnapshot ( ) : string {
329- return this . processingSnapshot ;
330- }
331-
332- getProcessedSnapshots ( ) : Array < Record < string , any > > {
333- return this . processedSnapshots ;
334- }
335-
336- isEmpty ( ) : boolean {
337- return this . snapshots && this . snapshots . length ? false : true ;
338- }
339- }
340-
341- async function processSnapshot ( snapshot : Snapshot , ctx : Context ) : Promise < Record < string , any > > {
13+ export default async function processSnapshot ( snapshot : Snapshot , ctx : Context ) : Promise < Record < string , any > > {
34214 updateLogContext ( { task : 'discovery' } ) ;
34315 ctx . log . debug ( `Processing snapshot ${ snapshot . name } ${ snapshot . url } ` ) ;
34416
0 commit comments