@skyramp/skyramp 1.3.9 → 1.3.11

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": "@skyramp/skyramp",
3
- "version": "1.3.9",
3
+ "version": "1.3.11",
4
4
  "description": "module for leveraging skyramp cli functionality",
5
5
  "scripts": {
6
6
  "lint": "eslint 'src/**/*.js' 'src/**/*.ts' --fix",
@@ -14,7 +14,9 @@
14
14
  "src/*.js",
15
15
  "src/*.ts",
16
16
  "src/classes/*.js",
17
- "src/classes/*.ts"
17
+ "src/classes/*.ts",
18
+ "src/pdfViewer/*.js",
19
+ "src/pdfViewer/*.ts"
18
20
  ],
19
21
  "main": "src/index.js",
20
22
  "types": "src/index.d.ts",
@@ -32,4 +34,4 @@
32
34
  "@typescript-eslint/parser": "^6.14.0",
33
35
  "eslint": "^8.55.0"
34
36
  }
35
- }
37
+ }
@@ -0,0 +1,141 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Builds bundle.js from Playwright's pdfJsViewer.ts using TypeScript's transpileModule.
5
+ * This correctly handles all TypeScript syntax without regex-based stripping.
6
+ *
7
+ * Usage:
8
+ * node scripts/build-pdf-bundle.js [playwright-root-path]
9
+ * PLAYWRIGHT_ROOT=/path/to/playwright node scripts/build-pdf-bundle.js
10
+ *
11
+ * NOTE: This replaces the regex-based generate-pdf-bundle.js approach which had
12
+ * issues stripping complex TypeScript types and template literal strings.
13
+ */
14
+
15
+ const fs = require('fs');
16
+ const path = require('path');
17
+
18
+ // Get Playwright root from env var, command line arg, or default relative path
19
+ const PLAYWRIGHT_ROOT = process.env.PLAYWRIGHT_ROOT
20
+ || process.argv[2]
21
+ || path.resolve(__dirname, '../../../..');
22
+
23
+ const VIEWER_SOURCE = path.join(PLAYWRIGHT_ROOT, 'packages/injected/src/recorder/skyramp/pdfJsViewer.ts');
24
+ const EXECUTION_HELPERS = path.join(__dirname, 'pdf-execution-helpers.js');
25
+ const OUTPUT_FILE = path.join(__dirname, '../src/pdfViewer/bundle.js');
26
+
27
+ // TypeScript is available in the Playwright repo
28
+ const TS_MODULE = path.join(PLAYWRIGHT_ROOT, 'node_modules/typescript');
29
+
30
+ console.log('[PDF Bundle Builder]');
31
+ console.log('Playwright root:', PLAYWRIGHT_ROOT);
32
+ console.log('Source:', VIEWER_SOURCE);
33
+ console.log('Helpers:', EXECUTION_HELPERS);
34
+ console.log('Output:', OUTPUT_FILE);
35
+ console.log();
36
+
37
+ if (!fs.existsSync(VIEWER_SOURCE)) {
38
+ console.error('Error: pdfJsViewer.ts not found at:', VIEWER_SOURCE);
39
+ process.exit(1);
40
+ }
41
+ if (!fs.existsSync(EXECUTION_HELPERS)) {
42
+ console.error('Error: pdf-execution-helpers.js not found at:', EXECUTION_HELPERS);
43
+ process.exit(1);
44
+ }
45
+ if (!fs.existsSync(TS_MODULE)) {
46
+ console.error('Error: typescript not found at:', TS_MODULE);
47
+ process.exit(1);
48
+ }
49
+
50
+ const ts = require(TS_MODULE);
51
+
52
+ // Step 1: Use TypeScript's transpileModule to get clean JS (no regex stripping needed)
53
+ console.log('Transpiling TypeScript...');
54
+ const source = fs.readFileSync(VIEWER_SOURCE, 'utf8');
55
+ const result = ts.transpileModule(source, {
56
+ compilerOptions: {
57
+ target: ts.ScriptTarget.ES2020,
58
+ module: ts.ModuleKind.None,
59
+ removeComments: false,
60
+ }
61
+ });
62
+
63
+ const transpiledCode = result.outputText;
64
+
65
+ // Step 2: Extract just the class (strip CommonJS boilerplate added by transpileModule)
66
+ const classStart = transpiledCode.indexOf('class PdfJsViewer');
67
+ const exportsLine = transpiledCode.lastIndexOf('exports.PdfJsViewer = PdfJsViewer;');
68
+ if (classStart === -1 || exportsLine === -1) {
69
+ console.error('Error: Could not locate PdfJsViewer class in transpiled output');
70
+ process.exit(1);
71
+ }
72
+ const classCode = transpiledCode.substring(classStart, exportsLine).trim();
73
+ console.log('Class extracted:', classCode.length, 'bytes');
74
+
75
+ // Step 3: Read execution helpers
76
+ const executionHelpers = fs.readFileSync(EXECUTION_HELPERS, 'utf8');
77
+
78
+ // Step 4: Escape for embedding inside the outer template literal in bundle.js.
79
+ // JS template literals process escape sequences, so backslashes must be doubled,
80
+ // backticks must be escaped, and ${ must be escaped to prevent interpolation.
81
+ function escapeForTemplateLiteral(code) {
82
+ return code
83
+ .replace(/\\/g, '\\\\') // \ -> \\
84
+ .replace(/`/g, '\\`') // ` -> \`
85
+ .replace(/\$\{/g, '\\${'); // ${ -> \${
86
+ }
87
+
88
+ const classEscaped = escapeForTemplateLiteral(classCode);
89
+ const helpersEscaped = escapeForTemplateLiteral(executionHelpers);
90
+
91
+ // Step 5: Build the bundle
92
+ const bundle = `/**
93
+ * Copyright (c) Skyramp Corporation.
94
+ *
95
+ * Bundled PDF.js viewer for execution-time injection
96
+ * This is a self-contained JavaScript string that can be injected via page.addInitScript()
97
+ *
98
+ * AUTO-GENERATED from Playwright sources by scripts/build-pdf-bundle.js
99
+ * DO NOT EDIT THIS FILE DIRECTLY - edit pdfJsViewer.ts instead and regenerate
100
+ *
101
+ * Source files:
102
+ * - PdfJsViewer class: ${VIEWER_SOURCE}
103
+ * - Execution helpers: ${EXECUTION_HELPERS}
104
+ */
105
+
106
+ /**
107
+ * Self-contained PDF viewer injection script
108
+ * This script will be injected into pages during test execution to replace Chrome's PDF plugin with PDF.js
109
+ */
110
+ const PDF_VIEWER_INJECTION_SCRIPT = \`
111
+ (function() {
112
+ 'use strict';
113
+
114
+ console.log('[PW-PDF] PDF viewer injection script initializing...');
115
+
116
+ // =============================================================================
117
+ // PDF.js Viewer Class (auto-generated from pdfJsViewer.ts)
118
+ // =============================================================================
119
+
120
+ ${classEscaped}
121
+
122
+ ${helpersEscaped}
123
+
124
+ console.log('[PW-PDF] PDF viewer injection script loaded');
125
+ })();
126
+ \`;
127
+
128
+ module.exports = { PDF_VIEWER_INJECTION_SCRIPT };
129
+ `;
130
+
131
+ fs.writeFileSync(OUTPUT_FILE, bundle, 'utf8');
132
+ const stats = fs.statSync(OUTPUT_FILE);
133
+ console.log();
134
+ console.log('Bundle generated successfully!');
135
+ console.log(' Output:', OUTPUT_FILE);
136
+ console.log(' Size:', (stats.size / 1024).toFixed(2), 'KB');
137
+ console.log();
138
+ console.log('Next steps:');
139
+ console.log(' 1. Validate: node -e "const {PDF_VIEWER_INJECTION_SCRIPT}=require(\'./src/pdfViewer/bundle.js\');require(\'fs\').writeFileSync(\'/tmp/t.js\',PDF_VIEWER_INJECTION_SCRIPT)" && node --check /tmp/t.js');
140
+ console.log(' 2. Pack: npm pack');
141
+ console.log(' 3. Install: npm install <path-to-.tgz>');
@@ -0,0 +1,340 @@
1
+ // =============================================================================
2
+ // Helper Functions (execution-specific)
3
+ // =============================================================================
4
+
5
+ /**
6
+ * Fetches a PDF from a URL and converts it to a data URL
7
+ * Uses fetch() which will be intercepted by route handler during execution
8
+ */
9
+ async function fetchPdfAsDataUrl(pdfUrl) {
10
+ try {
11
+ console.log('[PW-PDF] Fetching PDF:', pdfUrl.substring(0, 100));
12
+
13
+ // During execution, this fetch will be intercepted by Playwright's route handler
14
+ const response = await fetch(pdfUrl);
15
+
16
+ if (!response.ok) {
17
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
18
+ }
19
+
20
+ const arrayBuffer = await response.arrayBuffer();
21
+ const base64 = btoa(
22
+ new Uint8Array(arrayBuffer).reduce((data, byte) => data + String.fromCharCode(byte), '')
23
+ );
24
+
25
+ const dataUrl = `data:application/pdf;base64,${base64}`;
26
+ console.log('[PW-PDF] ✅ PDF fetched successfully');
27
+
28
+ return dataUrl;
29
+ } catch (error) {
30
+ console.error('[PW-PDF] ❌ Failed to fetch PDF:', error);
31
+ return null;
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Checks if the current page itself is a PDF document
37
+ */
38
+ function isCurrentPagePdf() {
39
+ const url = window.location.href;
40
+
41
+ // Check URL ends with .pdf
42
+ if (url.toLowerCase().endsWith('.pdf')) {
43
+ console.log('[PW-PDF] URL ends with .pdf:', url);
44
+ return true;
45
+ }
46
+
47
+ // Check for PDF plugin embed that takes up the whole page
48
+ const fullPageEmbed = document.querySelector('embed[type="application/pdf"]');
49
+ if (fullPageEmbed && document.body.children.length === 1) {
50
+ console.log('[PW-PDF] Found full-page PDF embed');
51
+ return true;
52
+ }
53
+
54
+ // Check if URL contains .pdf (including S3 URLs with .pdf)
55
+ if (url.toLowerCase().includes('.pdf')) {
56
+ console.log('[PW-PDF] PDF URL detected:', url);
57
+ return true;
58
+ }
59
+
60
+ return false;
61
+ }
62
+
63
+ /**
64
+ * Replaces the entire page with PDF.js viewer when the page itself is a PDF
65
+ */
66
+ async function replacePdfPage() {
67
+ try {
68
+ // Get PDF URL from current page URL
69
+ const pdfUrl = window.location.href;
70
+ console.log('[PW-PDF] Replacing full-page PDF with PDF.js viewer:', pdfUrl.substring(0, 100));
71
+
72
+ // Fetch PDF
73
+ const dataUrl = await fetchPdfAsDataUrl(pdfUrl);
74
+ if (!dataUrl) {
75
+ throw new Error('Failed to fetch PDF');
76
+ }
77
+
78
+ // Clear the document body
79
+ document.body.innerHTML = '';
80
+
81
+ // Create container for PDF.js viewer
82
+ const container = document.createElement('div');
83
+ container.setAttribute('data-pw-pdf-viewer', 'true');
84
+ container.id = 'pw-pdf-viewer-container';
85
+ container.style.cssText = `
86
+ position: fixed;
87
+ top: 0;
88
+ left: 0;
89
+ width: 100%;
90
+ height: 100%;
91
+ z-index: 2147483647;
92
+ background: #525252;
93
+ `;
94
+
95
+ document.body.appendChild(container);
96
+
97
+ // Extract filename from URL
98
+ let filename = 'Document.pdf';
99
+ try {
100
+ const url = new URL(pdfUrl);
101
+ const pathname = url.pathname;
102
+ const lastSlash = pathname.lastIndexOf('/');
103
+ if (lastSlash !== -1) {
104
+ filename = pathname.substring(lastSlash + 1);
105
+ filename = decodeURIComponent(filename);
106
+ }
107
+ } catch (e) {
108
+ console.warn('[PW-PDF] Failed to extract filename from URL:', e);
109
+ }
110
+
111
+ // Create PDF.js viewer
112
+ const viewer = new PdfJsViewer(container);
113
+
114
+ // Render the PDF
115
+ await viewer.renderPdf({
116
+ pdfDataUrl: dataUrl,
117
+ filename,
118
+ onReady: () => {
119
+ console.log('[PW-PDF] ✅ Full-page PDF replaced with PDF.js viewer');
120
+ },
121
+ onError: (error) => {
122
+ console.error('[PW-PDF] ❌ Failed to render full-page PDF:', error);
123
+ }
124
+ });
125
+
126
+ return true;
127
+ } catch (error) {
128
+ console.error('[PW-PDF] Error replacing full-page PDF:', error);
129
+ return false;
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Replaces a single PDF embed with PDF.js viewer
135
+ */
136
+ async function replacePdfEmbed(embed) {
137
+ try {
138
+ // Get PDF URL
139
+ let pdfUrl = embed.getAttribute('src');
140
+
141
+ // If src is about:blank, use the page URL (the page itself is the PDF)
142
+ if (!pdfUrl || pdfUrl === 'about:blank') {
143
+ console.log('[PW-PDF] Embed has src="about:blank", using page URL as PDF URL...');
144
+ pdfUrl = window.location.href;
145
+
146
+ // Verify it looks like a PDF URL
147
+ if (!pdfUrl.includes('.pdf')) {
148
+ console.log('[PW-PDF] Page URL does not appear to be a PDF, skipping');
149
+ return false;
150
+ }
151
+
152
+ console.log('[PW-PDF] Using page URL as PDF:', pdfUrl.substring(0, 100));
153
+ }
154
+
155
+ console.log('[PW-PDF] Replacing PDF embed with PDF.js viewer:', pdfUrl.substring(0, 100));
156
+
157
+ // Fetch PDF
158
+ const dataUrl = await fetchPdfAsDataUrl(pdfUrl);
159
+ if (!dataUrl) {
160
+ throw new Error('Failed to fetch PDF');
161
+ }
162
+
163
+ // Create container for PDF.js viewer
164
+ const container = document.createElement('div');
165
+ container.setAttribute('data-pw-pdf-viewer', 'true');
166
+ container.style.cssText = `
167
+ position: absolute;
168
+ top: ${embed.offsetTop}px;
169
+ left: ${embed.offsetLeft}px;
170
+ width: ${embed.offsetWidth || 800}px;
171
+ height: ${embed.offsetHeight || 600}px;
172
+ z-index: 2147483647;
173
+ background: #525252;
174
+ `;
175
+
176
+ // Insert container next to embed
177
+ const parent = embed.parentNode;
178
+ if (!parent) return false;
179
+
180
+ parent.insertBefore(container, embed);
181
+
182
+ // Hide original embed
183
+ embed.style.display = 'none';
184
+
185
+ // Extract filename from URL
186
+ let filename = 'Document.pdf';
187
+ try {
188
+ const url = new URL(pdfUrl);
189
+ const pathname = url.pathname;
190
+ const lastSlash = pathname.lastIndexOf('/');
191
+ if (lastSlash !== -1) {
192
+ filename = pathname.substring(lastSlash + 1);
193
+ filename = decodeURIComponent(filename);
194
+ }
195
+ } catch (e) {
196
+ console.warn('[PW-PDF] Failed to extract filename from URL:', e);
197
+ }
198
+
199
+ // Create PDF.js viewer
200
+ const viewer = new PdfJsViewer(container);
201
+
202
+ // Render the PDF
203
+ await viewer.renderPdf({
204
+ pdfDataUrl: dataUrl,
205
+ filename,
206
+ onReady: () => {
207
+ console.log('[PW-PDF] ✅ PDF embed replaced successfully');
208
+ },
209
+ onError: (error) => {
210
+ console.error('[PW-PDF] ❌ Failed to render PDF:', error);
211
+ // Restore original embed on error
212
+ embed.style.display = '';
213
+ if (container.parentNode) {
214
+ container.parentNode.removeChild(container);
215
+ }
216
+ }
217
+ });
218
+
219
+ return true;
220
+ } catch (error) {
221
+ console.error('[PW-PDF] Error replacing PDF embed:', error);
222
+ return false;
223
+ }
224
+ }
225
+
226
+ /**
227
+ * Detects and replaces PDF embeds with PDF.js viewers
228
+ */
229
+ async function detectAndReplacePdfs() {
230
+ console.log('[PW-PDF] Scanning for PDF embeds...');
231
+
232
+ // Check if we've already replaced a full-page PDF (prevent infinite loop)
233
+ if (window.__pwPdfPageReplaced) {
234
+ console.log('[PW-PDF] PDF page already replaced, skipping detection');
235
+ return;
236
+ }
237
+
238
+ // Check if the current page itself is a PDF document
239
+ const isPdfPage = isCurrentPagePdf();
240
+ if (isPdfPage) {
241
+ console.log('[PW-PDF] Current page is a PDF document, replacing with PDF.js viewer...');
242
+ window.__pwPdfPageReplaced = true;
243
+ await replacePdfPage();
244
+ return;
245
+ }
246
+
247
+ // Find all embed and iframe elements
248
+ const embeds = document.querySelectorAll('embed[type="application/pdf"], iframe[src*=".pdf"]');
249
+
250
+ if (embeds.length === 0) {
251
+ console.log('[PW-PDF] No PDF embeds found');
252
+ return;
253
+ }
254
+
255
+ console.log(`[PW-PDF] Found ${embeds.length} PDF embed(s)`);
256
+
257
+ for (const embed of embeds) {
258
+ await replacePdfEmbed(embed);
259
+ }
260
+ }
261
+
262
+ // =============================================================================
263
+ // Window.open() Interception (for headless mode)
264
+ // =============================================================================
265
+
266
+ /**
267
+ * Sets up window.open() interception to detect PDF URLs
268
+ */
269
+ function setupPdfPopupInterception() {
270
+ const originalOpen = window.open;
271
+ window.open = function(url, target, features) {
272
+ // Check if URL is a PDF (ends with .pdf or contains PDF indicators)
273
+ const isPdf = url && url.toLowerCase().includes('.pdf');
274
+
275
+ if (isPdf) {
276
+ console.log('[PW-PDF] Intercepted window.open() to PDF:', url);
277
+
278
+ // Let the popup open normally (to about:blank or target URL)
279
+ const popup = originalOpen.call(this, url, target, features);
280
+
281
+ // If popup opened successfully, store PDF URL for it to access
282
+ if (popup && !popup.closed) {
283
+ popup.__pw_pdfUrl = url;
284
+
285
+ // The popup will detect __pw_pdfUrl and render with PDF.js
286
+ setTimeout(() => {
287
+ if (popup.__pw_detectAndReplacePdfs) {
288
+ popup.__pw_detectAndReplacePdfs();
289
+ }
290
+ }, 100);
291
+ }
292
+
293
+ return popup;
294
+ }
295
+
296
+ // Not a PDF, let window.open() work normally
297
+ return originalOpen.apply(this, arguments);
298
+ };
299
+ }
300
+
301
+ // =============================================================================
302
+ // Expose Functions and Classes Globally
303
+ // =============================================================================
304
+
305
+ window.PdfJsViewer = PdfJsViewer; // Expose class for direct instantiation
306
+ window.__pw_detectAndReplacePdfs = detectAndReplacePdfs;
307
+ window.__pw_setupPdfPopupInterception = setupPdfPopupInterception;
308
+
309
+ // =============================================================================
310
+ // Auto-detect PDFs on page load
311
+ // =============================================================================
312
+
313
+ // Auto-detect if current page is a PDF popup that needs rendering
314
+ if (window.__pw_pdfUrl && !window.__pwPdfRendered) {
315
+ window.__pwPdfRendered = true;
316
+
317
+ // Wait for DOM ready
318
+ if (document.readyState === 'loading') {
319
+ document.addEventListener('DOMContentLoaded', () => {
320
+ window.__pw_detectAndReplacePdfs();
321
+ });
322
+ } else {
323
+ window.__pw_detectAndReplacePdfs();
324
+ }
325
+ }
326
+
327
+ // Also auto-detect on every page load (for direct navigation to PDFs)
328
+ // This runs after the page has fully loaded
329
+ if (document.readyState === 'loading') {
330
+ document.addEventListener('DOMContentLoaded', () => {
331
+ console.log('[PW-PDF] DOMContentLoaded - checking for PDFs...');
332
+ window.__pw_detectAndReplacePdfs();
333
+ });
334
+ } else if (document.readyState === 'interactive' || document.readyState === 'complete') {
335
+ // If DOM is already ready, run detection immediately
336
+ console.log('[PW-PDF] DOM already ready - checking for PDFs...');
337
+ setTimeout(() => {
338
+ window.__pw_detectAndReplacePdfs();
339
+ }, 100); // Small delay to let browser plugin initialize
340
+ }
@@ -12,15 +12,10 @@ export class MockV2 {
12
12
  URL: string;
13
13
 
14
14
  /**
15
- * The endpoint path to mock (e.g., "/api/v1/products")
15
+ * The path to mock (e.g., "/api/v1/products")
16
16
  */
17
- endpoint: string;
18
-
19
- /**
20
- * The port number of the service
21
- */
22
- port: number;
23
-
17
+ path: string;
18
+
24
19
  /**
25
20
  * The HTTP method (GET, POST, PUT, DELETE, etc.)
26
21
  */
@@ -29,7 +24,7 @@ export class MockV2 {
29
24
  /**
30
25
  * The HTTP status code to return
31
26
  */
32
- responseStatusCode: number;
27
+ statusCode: number;
33
28
 
34
29
  /**
35
30
  * The response body to return
@@ -49,8 +44,7 @@ export class MockV2 {
49
44
  /**
50
45
  * Creates a new MockV2 instance
51
46
  * @param URL - The URL of the service to mock
52
- * @param endpoint - The endpoint path to mock (e.g., "/api/v1/products")
53
- * @param port - The port number of the service
47
+ * @param path - The path path to mock (e.g., "/api/v1/products")
54
48
  * @param method - The HTTP method (GET, POST, PUT, DELETE, etc.)
55
49
  * @param responseStatusCode - The HTTP status code to return
56
50
  * @param responseBody - The response body to return
@@ -59,10 +53,9 @@ export class MockV2 {
59
53
  */
60
54
  constructor(
61
55
  URL: string,
62
- endpoint: string,
63
- port: number,
56
+ path: string,
64
57
  method: string,
65
- responseStatusCode: number,
58
+ statusCode: number,
66
59
  responseBody: string,
67
60
  requestBody?: string | null,
68
61
  dataOverride?: Record<string, unknown> | null
@@ -74,8 +67,7 @@ export class MockV2 {
74
67
  */
75
68
  toDict(): {
76
69
  url: string;
77
- endpoint: string;
78
- port: number;
70
+ path: string;
79
71
  method: string;
80
72
  status_code: number;
81
73
  response_body: string;
@@ -90,4 +82,4 @@ export class MockV2 {
90
82
  toJSON(): string;
91
83
  }
92
84
 
93
- export default MockV2;
85
+ export default MockV2;
@@ -5,24 +5,23 @@
5
5
  class MockV2 {
6
6
  /**
7
7
  * Represents a mock object configuration for API endpoint mocking.
8
- * @param {string} URL - The URL of the service to mock
9
- * @param {string} endpoint - The endpoint path to mock (e.g., "/api/v1/products")
10
- * @param {number} port - The port number of the service
11
- * @param {string} method - The HTTP method (GET, POST, PUT, DELETE, etc.)
12
- * @param {number} responseStatusCode - The HTTP status code to return
13
- * @param {string} responseBody - The response body to return
14
- * @param {string} [requestBody] - Optional request body to match
15
- * @param {Object} [dataOverride] - Optional data override object
8
+ * @param {Object} [options={}] - The options for creating the mock.
9
+ * @param {string} [options.url=''] - The URL of the service to mock
10
+ * @param {string} [options.path=''] - The path to mock (e.g., "/api/v1/products")
11
+ * @param {string} [options.method=''] - The HTTP method (GET, POST, PUT, DELETE, etc.)
12
+ * @param {number} [options.statusCode=201] - The HTTP status code to return
13
+ * @param {string} [options.responseBody=''] - The response body to return
14
+ * @param {string} [options.requestBody=''] - Optional request body to match
15
+ * @param {Object.<string, *>} [options.dataOverride={}] - Optional data override object
16
16
  */
17
- constructor(URL, endpoint, port, method, responseStatusCode, responseBody, requestBody = null, dataOverride = null) {
18
- this.URL = URL;
19
- this.endpoint = endpoint;
20
- this.port = port;
21
- this.method = method;
22
- this.responseStatusCode = responseStatusCode;
23
- this.responseBody = responseBody;
24
- this.requestBody = requestBody;
25
- this.dataOverride = dataOverride;
17
+ constructor(options = {}) {
18
+ this.url = options.url || '';
19
+ this.path = options.path || '';
20
+ this.method = options.method || '';
21
+ this.statusCode = options.statusCode || 201;
22
+ this.responseBody = options.responseBody || '';
23
+ this.requestBody = options.requestBody || '';
24
+ this.dataOverride = options.dataOverride || {};
26
25
  }
27
26
 
28
27
  /**
@@ -31,11 +30,10 @@ class MockV2 {
31
30
  */
32
31
  toDict() {
33
32
  const result = {
34
- url: this.URL,
35
- endpoint: this.endpoint,
36
- port: this.port,
33
+ url: this.url,
34
+ path: this.path,
37
35
  method: this.method,
38
- status_code: this.responseStatusCode,
36
+ status_code: this.statusCode,
39
37
  response_body: this.responseBody
40
38
  };
41
39
 
@@ -59,4 +57,4 @@ class MockV2 {
59
57
  }
60
58
  }
61
59
 
62
- module.exports = MockV2;
60
+ module.exports = MockV2;
@@ -126,6 +126,8 @@ interface GenerateRestTestOptions {
126
126
  playwrightViewportSize?: string;
127
127
  playwrightStoragePath?: string;
128
128
  playwrightSaveStoragePath?: string;
129
+ browser?: string;
130
+ device?: string;
129
131
  loadCount?: string;
130
132
  loadDuration?: string;
131
133
  loadNumThreads?: string;
@@ -51,7 +51,7 @@ const initTargetWrapper = lib.func('initTargetWrapper', 'string', ['string']);
51
51
  const deployTargetWrapper = lib.func('deployTargetWrapper', 'string', ['string', 'string', 'string', 'string', 'string', 'string', 'bool']);
52
52
  const deleteTargetWrapper = lib.func('deleteTargetWrapper', 'string', ['string', 'string', 'string', 'string', 'string']);
53
53
 
54
- const generateRestTestWrapper = lib.func('generateRestTestWrapper', 'string', ['string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'bool', 'bool', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'bool', 'string', 'bool', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'bool', 'string', 'string']);
54
+ const generateRestTestWrapper = lib.func('generateRestTestWrapper', 'string', ['string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'bool', 'bool', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'bool', 'string', 'bool', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'bool', 'string', 'string']);
55
55
  const generateRestMockWrapper = lib.func('generateRestMockWrapper', 'string', ['string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'string', 'bool', 'bool', 'string', 'string', 'string', 'string', 'string', 'string']);
56
56
  const traceCollectWrapper = lib.func('traceCollectWrapper', 'string', ['string', 'string', 'bool', 'string', 'string']);
57
57
  const analyzeOpenapiWrapper = lib.func('analyzeOpenapiWrapper', 'string', ['string', 'string']);
@@ -98,8 +98,6 @@ class SkyrampClient {
98
98
  this.local_image = false;
99
99
  this.timestamp = Date.now();
100
100
 
101
- checkForUpdate("npm")
102
-
103
101
  if (typeof kubeconfigPathOrOptions === 'object') {
104
102
  const options = kubeconfigPathOrOptions;
105
103
  this.workerNamespaces = [];
@@ -827,6 +825,8 @@ class SkyrampClient {
827
825
  options.playwrightViewportSize || "",
828
826
  options.playwrightStoragePath || "",
829
827
  options.playwrightSaveStoragePath || "",
828
+ options.browser || "",
829
+ options.device || "",
830
830
  options.loadCount || "0",
831
831
  options.loadDuration || "0",
832
832
  options.loadNumThreads || "0",
@@ -1013,6 +1013,7 @@ class SkyrampClient {
1013
1013
  * @returns {Promise<string>} A promise that resolves with the initialization output message.
1014
1014
  */
1015
1015
  async initAgent(options) {
1016
+ await checkForUpdate("npm");
1016
1017
  return new Promise((resolve, reject) => {
1017
1018
  initAgentWrapper.async(
1018
1019
  options.version || "",