@applitools/visual-grid-cli-utils 1.21.41 → 1.21.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applitools/visual-grid-cli-utils",
3
- "version": "1.21.41",
3
+ "version": "1.21.43",
4
4
  "description": "",
5
5
  "main": "src/visual-grid-cli-utils.js",
6
6
  "engines": {
@@ -1,10 +1,118 @@
1
1
  'use strict'
2
2
  const {exec} = require('child_process')
3
+ const retry = require('p-retry')
3
4
  const createSession = require('./commons/create-session')
4
5
  const calculateViewRenderingUrl = require('./commons/view-rendering-url')
5
6
  const {fetch, throwErrorFromBadStatus} = require('@applitools/http-commons')
6
7
  const fs = require('fs')
7
8
 
9
+ async function waitForParsedStatus(vgUrl, renderId, authToken, waitTimeout = 5 * 60 * 1000) {
10
+ console.log(`[2/3] Waiting for parsing to complete...`)
11
+ let attemptCount = 0
12
+ const startTime = Date.now()
13
+ return await retry(
14
+ async () => {
15
+ attemptCount++
16
+ const response = await fetch(`${vgUrl}/render-status?render-id=${renderId}`, {
17
+ headers: {'X-Auth-Token': authToken},
18
+ })
19
+ if (!response.ok) {
20
+ throw new Error(
21
+ `failed to get rendering status. Error from Visual Grid: ${await response.text()}`,
22
+ )
23
+ }
24
+ const {status, error, rdvsMetadata, url} = await response.json()
25
+ if (status === 'error') {
26
+ throw new retry.AbortError(`Rendering failed: ${error}`)
27
+ } else if (status === 'parsed') {
28
+ const elapsed = ((Date.now() - startTime) / 1000).toFixed(1)
29
+ console.log(` ✓ Parsing completed (${elapsed}s)`)
30
+ // Return the rdvsMetadata and url from the job
31
+ return {
32
+ rdvsMetadata,
33
+ url,
34
+ }
35
+ } else {
36
+ // Only log every 5 attempts to reduce noise
37
+ if (attemptCount % 5 === 0) {
38
+ const elapsed = ((Date.now() - startTime) / 1000).toFixed(0)
39
+ console.log(` Status: ${status} (${elapsed}s elapsed)...`)
40
+ }
41
+ // Still processing (rendering or other status)
42
+ throw new Error(`Status is ${status}, waiting for parsed`)
43
+ }
44
+ },
45
+ {
46
+ forever: true,
47
+ minTimeout: 1000,
48
+ maxTimeout: 1000,
49
+ maxRetryTime: waitTimeout,
50
+ onFailedAttempt: () => {}, // Suppress default error logging
51
+ },
52
+ )
53
+ }
54
+
55
+ async function tryNewViewRenderingEndpoint(vgUrl, renderId, authToken, apiKey, serverUrl) {
56
+ try {
57
+ console.log(`[1/3] Starting resource parsing for render: ${renderId}`)
58
+ // Step 1: Call rerender API with parseResourcesOnly flag
59
+ const renderUrl = new URL('./render', vgUrl)
60
+ const {webhook, authToken: sessionAuthToken} = await createSession(apiKey, serverUrl)
61
+
62
+ const rerenderResponse = await fetch(renderUrl, {
63
+ method: 'POST',
64
+ headers: {
65
+ 'Content-Type': 'application/json',
66
+ 'X-Auth-Token': sessionAuthToken,
67
+ },
68
+ body: JSON.stringify({
69
+ reRenderId: renderId,
70
+ webhook,
71
+ parseResourcesOnly: true,
72
+ agentId: `visual-grid-cli-utils/${require('../package.json').version}`,
73
+ options: {
74
+ parseResourcesOnly: true,
75
+ },
76
+ }),
77
+ })
78
+
79
+ if (!rerenderResponse.ok) {
80
+ const errorBody = await rerenderResponse.text()
81
+ return {
82
+ success: false,
83
+ error: `Rerender API failed - HTTP ${rerenderResponse.status}: ${errorBody}`,
84
+ }
85
+ }
86
+
87
+ const {renderId: parseRenderId} = await rerenderResponse.json()
88
+ console.log(` ✓ Parse job created: ${parseRenderId}`)
89
+
90
+ // Step 2: Wait for "parsed" status
91
+ const parsedResult = await waitForParsedStatus(vgUrl, parseRenderId, sessionAuthToken)
92
+
93
+ // Step 3: Check if we have the required data
94
+ if (parsedResult.rdvsMetadata && parsedResult.url) {
95
+ console.log(`[3/3] Building view URL...`)
96
+ console.log(` ✓ Resource tree ready`)
97
+ return {
98
+ success: true,
99
+ url: parsedResult.url,
100
+ rdvsMetadata: parsedResult.rdvsMetadata,
101
+ }
102
+ } else {
103
+ return {
104
+ success: false,
105
+ error: `Parsed result missing required fields (rdvsMetadata, url)`,
106
+ }
107
+ }
108
+ } catch (error) {
109
+ return {
110
+ success: false,
111
+ error: error.message || String(error),
112
+ }
113
+ }
114
+ }
115
+
8
116
  async function main({
9
117
  apiKey,
10
118
  browser,
@@ -24,7 +132,26 @@ async function main({
24
132
  ? {authToken}
25
133
  : await createSession(apiKey, serverUrl)
26
134
 
27
- const viewRenderingUrl = calculateViewRenderingUrl(renderId, finalAuthToken, accountOverride)
135
+ const vgUrl = process.env.VG_URL || 'https://render-wus.applitools.com'
136
+
137
+ // Try new view-rendering endpoint with rerender API
138
+ const result = await tryNewViewRenderingEndpoint(
139
+ vgUrl,
140
+ renderId,
141
+ finalAuthToken,
142
+ apiKey,
143
+ serverUrl,
144
+ )
145
+
146
+ let viewRenderingUrl
147
+ if (result.success) {
148
+ console.log('\n✓ Successfully generated view URL via new endpoint')
149
+ viewRenderingUrl = result.url
150
+ } else {
151
+ console.debug(` (${result.error})`)
152
+ console.log('\n⚠ Legacy method used: Render ID predates SSA refactor.')
153
+ viewRenderingUrl = calculateViewRenderingUrl(renderId, finalAuthToken, accountOverride)
154
+ }
28
155
 
29
156
  if (downloadVhsFolder) {
30
157
  let response = await fetch(viewRenderingUrl)
@@ -42,9 +169,12 @@ async function main({
42
169
  const resource = await response.buffer()
43
170
  const fname = `${downloadVhsFolder}/${renderId}.vhs`
44
171
  fs.writeFileSync(fname, resource)
45
- console.log('Wrote file: ' + fname)
172
+ console.log('\n✓ Wrote file: ' + fname)
46
173
  } else {
174
+ console.log('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')
175
+ console.log('View Rendering URL:')
47
176
  console.log(viewRenderingUrl)
177
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')
48
178
  }
49
179
 
50
180
  if (browser) {