@applitools/eyes-playwright 1.38.2 → 1.39.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,79 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.39.1](https://github.com/Applitools-Dev/sdk/compare/js/eyes-playwright@1.39.0...js/eyes-playwright@1.39.1) (2025-08-10)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * save pw reporter temp files using the backend | FLD-3427 ([#3132](https://github.com/Applitools-Dev/sdk/issues/3132)) ([5d3e756](https://github.com/Applitools-Dev/sdk/commit/5d3e756aea742b1758032037f56d62a932c805a2))
9
+
10
+ ## [1.39.0](https://github.com/Applitools-Dev/sdk/compare/js/eyes-playwright@1.38.2...js/eyes-playwright@1.39.0) (2025-08-05)
11
+
12
+
13
+ ### Features
14
+
15
+ * release java ([7bc39e6](https://github.com/Applitools-Dev/sdk/commit/7bc39e679eab27a19322ca4b121177da7437c106))
16
+
17
+
18
+ ### Dependencies
19
+
20
+ * @applitools/utils bumped to 1.11.0
21
+ #### Features
22
+
23
+ * improve configuration handling ([#3130](https://github.com/Applitools-Dev/sdk/issues/3130)) ([def7be1](https://github.com/Applitools-Dev/sdk/commit/def7be1dd07460f49142cddfe55203baa884e6c3))
24
+ * make utils.general.guid crypto secured ([#3137](https://github.com/Applitools-Dev/sdk/issues/3137)) ([775df08](https://github.com/Applitools-Dev/sdk/commit/775df08307e41402a6603812205bc857bd3f936e))
25
+ * @applitools/logger bumped to 2.2.1
26
+
27
+ * @applitools/dom-snapshot bumped to 4.13.1
28
+
29
+ * @applitools/socket bumped to 1.3.1
30
+
31
+ * @applitools/req bumped to 1.8.1
32
+
33
+ * @applitools/image bumped to 1.2.1
34
+
35
+ * @applitools/dom-capture bumped to 11.6.1
36
+
37
+ * @applitools/driver bumped to 1.23.1
38
+
39
+ * @applitools/spec-driver-webdriver bumped to 1.4.1
40
+
41
+ * @applitools/spec-driver-selenium bumped to 1.7.1
42
+
43
+ * @applitools/spec-driver-playwright bumped to 1.7.1
44
+
45
+ * @applitools/spec-driver-puppeteer bumped to 1.6.1
46
+
47
+ * @applitools/screenshoter bumped to 3.12.1
48
+
49
+ * @applitools/nml-client bumped to 1.11.1
50
+
51
+ * @applitools/tunnel-client bumped to 1.10.2
52
+
53
+ * @applitools/ufg-client bumped to 1.17.1
54
+
55
+ * @applitools/core-base bumped to 1.27.1
56
+
57
+ * @applitools/ec-client bumped to 1.12.2
58
+
59
+ * @applitools/core bumped to 4.44.2
60
+
61
+ * @applitools/eyes bumped to 1.36.0
62
+ #### Features
63
+
64
+ * improve configuration handling ([#3130](https://github.com/Applitools-Dev/sdk/issues/3130)) ([def7be1](https://github.com/Applitools-Dev/sdk/commit/def7be1dd07460f49142cddfe55203baa884e6c3))
65
+ * release java ([7bc39e6](https://github.com/Applitools-Dev/sdk/commit/7bc39e679eab27a19322ca4b121177da7437c106))
66
+
67
+
68
+
69
+ * @applitools/test-server bumped to 1.3.0
70
+ #### Features
71
+
72
+ * release java ([7bc39e6](https://github.com/Applitools-Dev/sdk/commit/7bc39e679eab27a19322ca4b121177da7437c106))
73
+
74
+
75
+
76
+
3
77
  ## [1.38.2](https://github.com/Applitools-Dev/sdk/compare/js/eyes-playwright@1.38.1...js/eyes-playwright@1.38.2) (2025-07-23)
4
78
 
5
79
 
@@ -1,30 +1,4 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- var __importDefault = (this && this.__importDefault) || function (mod) {
26
- return (mod && mod.__esModule) ? mod : { "default": mod };
27
- };
28
2
  Object.defineProperty(exports, "__esModule", { value: true });
29
3
  exports.test = exports.expect = void 0;
30
4
  /* eslint-disable no-console */
@@ -33,10 +7,9 @@ const test_1 = require("@playwright/test");
33
7
  const getEyes_1 = require("./getEyes");
34
8
  var toHaveScreenshot_1 = require("./toHaveScreenshot");
35
9
  Object.defineProperty(exports, "expect", { enumerable: true, get: function () { return toHaveScreenshot_1.expect; } });
36
- const utils = __importStar(require("@applitools/utils"));
37
10
  const reporter_1 = require("./reporter");
38
11
  const url_1 = require("url");
39
- const path_1 = __importDefault(require("path"));
12
+ const utils_1 = require("@applitools/utils");
40
13
  exports.test = test_1.test.extend({
41
14
  eyesConfig: [{}, { option: true }],
42
15
  eyesRunner: [
@@ -89,27 +62,15 @@ exports.test = test_1.test.extend({
89
62
  ],
90
63
  closeEyesIfNeeded: [
91
64
  async ({ page, eyesConfig, eyesRunner: runner }, use, testInfo) => {
92
- var _a, _b, _c, _d, _e, _f;
93
65
  const isUsingEyesReporter = testInfo.config.reporter.some(
94
66
  // typeof testInfo.config.reporter is [string, ReporterOptions][], that's why [0] is the reporter name
95
67
  r => r[0].includes('eyes-playwright') || r[0].includes('blob'));
96
- const blobSettings = (_b = (_a = testInfo.config.reporter.find(r => r[0].includes('blob'))) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : {};
97
- const blobFolder = (_d = (_c = blobSettings.outputDir) !== null && _c !== void 0 ? _c : process.env.PLAYWRIGHT_BLOB_OUTPUT_DIR) !== null && _d !== void 0 ? _d : (((_e = process.env.PLAYWRIGHT_BLOB_OUTPUT_FILE) !== null && _e !== void 0 ? _e : blobSettings.outputFile)
98
- ? path_1.default.basename((_f = process.env.PLAYWRIGHT_BLOB_OUTPUT_FILE) !== null && _f !== void 0 ? _f : blobSettings.outputFile)
99
- : '');
100
- if (isUsingEyesReporter) {
101
- const applitoolsIdentifier = utils.general.guid();
102
- // Create an identifier that will be collected by the html or reporter
103
- await testInfo.attach('applitoolsIdentifier', {
104
- body: `${applitoolsIdentifier}|${blobFolder}`,
105
- });
106
- }
107
68
  await use();
108
69
  const eyes = page.__eyes;
109
70
  if (eyes) {
110
71
  await eyes.closeAsync();
111
72
  if (isUsingEyesReporter) {
112
- writeResultsWhenReady({ eyes, runner, testInfo });
73
+ await writeResultsWhenReady({ eyes, runner, testInfo });
113
74
  }
114
75
  if (eyesConfig.failTestsOnDiff === 'afterEach') {
115
76
  await eyes.getResults(true);
@@ -131,13 +92,17 @@ function outputDigest(workerInfo, results) {
131
92
  function output(...args) {
132
93
  console.log('👀', ...args);
133
94
  }
134
- function writeResultsWhenReady({ eyes, runner, testInfo }) {
135
- var _a;
95
+ async function writeResultsWhenReady({ eyes, runner, testInfo }) {
96
+ var _a, _b;
136
97
  const fixturePromises = ((_a = runner.fixturePromises) !== null && _a !== void 0 ? _a : (runner.fixturePromises = []));
98
+ const uuid = utils_1.general.guid();
99
+ await testInfo.attach('applitoolsIdentifier', {
100
+ body: `${uuid}|${(_b = eyes.getServerUrl()) !== null && _b !== void 0 ? _b : 'https://eyes.applitools.com'}|${eyes.getApiKey()}`,
101
+ });
137
102
  fixturePromises.push(eyes
138
103
  .getResults(false)
139
104
  .then(async (testResults) => {
140
- await reporter_1.InternalData.write({ testInfo, data: testResults });
105
+ await reporter_1.InternalData.write({ testInfo, data: testResults, eyes, uuid });
141
106
  })
142
107
  .catch((e) => {
143
108
  var _a;
@@ -26,7 +26,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.InternalData = void 0;
27
27
  const fs = __importStar(require("fs"));
28
28
  const path = __importStar(require("path"));
29
- const os = __importStar(require("os"));
29
+ const req_1 = require("@applitools/req");
30
+ const utils = __importStar(require("@applitools/utils"));
31
+ const logger_1 = require("@applitools/logger");
32
+ const storage_blob_1 = require("@azure/storage-blob");
30
33
  const playwrightPath = require.resolve('playwright');
31
34
  const HtmlReporter = require(path.join(path.dirname(playwrightPath), '/lib/reporters/html')).default;
32
35
  const pluginsFile = require.resolve('../../dist/fixture/reportRenderer.js');
@@ -46,20 +49,15 @@ const createInjectedScript = (testResultsMap) => `
46
49
  class EyesReporter extends HtmlReporter {
47
50
  constructor(options) {
48
51
  super(options);
49
- this.stdoutData = '';
50
- this.applitoolsIdentifiersAndFolders = [];
51
- }
52
- onStdOut(chunk) {
53
- // Capture stdout data for blob reporter scenarios
54
- this.stdoutData += chunk.toString();
52
+ this.applitoolsIdentifiers = [];
55
53
  }
56
54
  onTestEnd(test, result) {
57
55
  var _a;
58
56
  (_a = super.onTestEnd) === null || _a === void 0 ? void 0 : _a.call(this, test, result);
59
57
  const index = result.attachments.findIndex(a => a.name === 'applitoolsIdentifier');
60
58
  if (index > -1) {
61
- const applitoolsIdentifierAndFolder = result.attachments[index].body.toString();
62
- this.applitoolsIdentifiersAndFolders.push(applitoolsIdentifierAndFolder);
59
+ const applitoolsIdentifier = result.attachments[index].body.toString();
60
+ this.applitoolsIdentifiers.push(applitoolsIdentifier);
63
61
  this.removeInternalIdAttachment(result);
64
62
  }
65
63
  }
@@ -79,10 +77,20 @@ class EyesReporter extends HtmlReporter {
79
77
  async onEnd(result) {
80
78
  await super.onEnd(result);
81
79
  const testResultsMap = {};
82
- for (const applitoolsIdentifierAndFolder of this.applitoolsIdentifiersAndFolders) {
83
- const content = await exports.InternalData.consume(applitoolsIdentifierAndFolder, this.stdoutData);
84
- if (content) {
85
- testResultsMap[content.key] = content.data;
80
+ for (const applitoolsIdentifier of this.applitoolsIdentifiers) {
81
+ // Parse the identifier format: uuid|serverUrl|apiKey
82
+ const [uuid, serverUrl, apiKey] = applitoolsIdentifier.split('|');
83
+ if (uuid && serverUrl && apiKey) {
84
+ // Create a minimal eyes object for the consume call
85
+ const eyes = {
86
+ getServerUrl: () => serverUrl,
87
+ getApiKey: () => apiKey,
88
+ // No getLogger method - will use makeLogger() fallback
89
+ };
90
+ const content = await exports.InternalData.consume(uuid, eyes);
91
+ if (content) {
92
+ testResultsMap[content.key] = content.data;
93
+ }
86
94
  }
87
95
  }
88
96
  try {
@@ -96,85 +104,104 @@ class EyesReporter extends HtmlReporter {
96
104
  }
97
105
  }
98
106
  exports.default = EyesReporter;
99
- const defaultDataDirectory = path.join(os.tmpdir(), 'eyes-playwright-data');
107
+ const getLogger = utils.general.cachify((settings) => {
108
+ return settings.logger || (0, logger_1.makeLogger)({ level: 'info' });
109
+ }, ([settings]) => settings.serverUrl + settings.apiKey);
110
+ const makeReporterRequest = (settings) => {
111
+ var _a;
112
+ const logger = getLogger(settings);
113
+ const req = (0, req_1.makeReq)({
114
+ baseUrl: (_a = settings.serverUrl) !== null && _a !== void 0 ? _a : 'https://eyes.applitools.com',
115
+ headers: {
116
+ Accept: 'application/json',
117
+ 'Content-Type': 'application/json',
118
+ 'x-applitools-eyes-client': 'eyes-playwright-reporter',
119
+ 'User-Agent': 'eyes-playwright-reporter',
120
+ 'X-Eyes-Api-Key': settings.apiKey,
121
+ },
122
+ retry: [
123
+ {
124
+ limit: 3,
125
+ timeout: 200,
126
+ },
127
+ ],
128
+ hooks: {
129
+ beforeRequest: request => {
130
+ var _a;
131
+ logger.log(`Making request to ${request.request.url} with body: ${(_a = request.options) === null || _a === void 0 ? void 0 : _a.body}`);
132
+ },
133
+ afterResponse: async (response) => {
134
+ logger.log(`Received response from ${response.response.url} with status ${response.response.status} and body: ${await response.response.clone().text()}`);
135
+ if (response.response.status >= 400) {
136
+ logger.error(`Request to ${response.response.url} failed with status ${response.response.status}`, `and body: ${await response.response.clone().text()}`);
137
+ throw new Error(`Request to ${response.response.url} failed with status ${response.response.status}`);
138
+ }
139
+ },
140
+ },
141
+ });
142
+ return {
143
+ upload,
144
+ download,
145
+ };
146
+ async function upload(uuid, data) {
147
+ const blobClient = new storage_blob_1.BlockBlobClient(settings.uploadUrl);
148
+ const [response1, response2] = await Promise.all([
149
+ req(`/batch/${uuid}/report/${uuid}`, {
150
+ method: 'POST',
151
+ }),
152
+ blobClient.upload(JSON.stringify(data), JSON.stringify(data).length),
153
+ ]);
154
+ return {
155
+ respCreateUpload: await response1.json(),
156
+ respUpload: JSON.stringify(response2),
157
+ };
158
+ }
159
+ async function download(uuid) {
160
+ const response = await req(`/batch/${uuid}/report/${uuid}`, {
161
+ method: 'GET',
162
+ });
163
+ return response.json();
164
+ }
165
+ };
100
166
  exports.InternalData = {
101
- determineDirectory(testInfo) {
102
- var _a;
103
- const blobReporter = testInfo.config.reporter.find(r => r[0].includes('blob'));
104
- const customOutputDir = (_a = blobReporter === null || blobReporter === void 0 ? void 0 : blobReporter[1]) === null || _a === void 0 ? void 0 : _a.outputDir;
105
- return customOutputDir ? path.join(customOutputDir, 'eyes-report-files') : defaultDataDirectory;
106
- },
107
- hasBlobReporter(testInfo) {
108
- return testInfo.config.reporter.some(r => r[0].includes('blob'));
109
- },
110
- async write({ testInfo, data }) {
111
- const [applitoolsIdentifier, folder] = testInfo.attachments
112
- .find(a => a.name === 'applitoolsIdentifier')
113
- .body.toString()
114
- .split('|')
115
- .map(s => s.trim())
116
- .filter(Boolean); // if the directory is not specified, it will be empty
117
- const key = `${testInfo.testId}--${testInfo.retry}`;
118
- if (this.hasBlobReporter(testInfo)) {
119
- // Use stdout approach for blob reporter scenarios
120
- // eslint-disable-next-line no-console
121
- console.log(`EYES_DATA:${applitoolsIdentifier}:${JSON.stringify({ key, data })}`);
122
- }
123
- else {
124
- // Use file approach for direct reporter scenarios
125
- const targetFolder = folder || this.determineDirectory(testInfo);
126
- this.ensureFolder(targetFolder);
127
- await fs.promises.writeFile(this.getPathForInternalId(applitoolsIdentifier, targetFolder), JSON.stringify({ key, data }));
128
- }
167
+ async write({ testInfo, data, eyes, uuid }) {
168
+ var _a, _b;
169
+ const logger = ((_a = eyes.getLogger) === null || _a === void 0 ? void 0 : _a.call(eyes)) || (0, logger_1.makeLogger)();
170
+ const uploadUrl = eyes._eyes.test.account.batchExecReportsUrl
171
+ .replace('__batch_id__', uuid)
172
+ .replace('__report_id__', uuid);
173
+ const { upload } = makeReporterRequest({
174
+ serverUrl: (_b = eyes.getServerUrl()) !== null && _b !== void 0 ? _b : 'https://eyes.applitools.com',
175
+ apiKey: eyes.getApiKey(),
176
+ uploadUrl,
177
+ logger: logger,
178
+ });
179
+ const response = await upload(uuid, {
180
+ key: `${testInfo.testId}--${testInfo.retry}`,
181
+ data,
182
+ });
183
+ logger.log('Data written successfully:', response);
129
184
  },
130
- async consume(applitoolsIdentifierAndFolder, stdoutData) {
131
- const [name, folder] = applitoolsIdentifierAndFolder
132
- .split('|')
133
- .map(s => s.trim())
134
- .filter(Boolean); // if the directory is not specified, it will be empty
135
- // Try stdout data first (for blob reporter scenarios), then fall back to files
136
- if (stdoutData) {
137
- // Parse from stdout for blob reporter scenarios
138
- const results = this.parseStdoutLine(name, stdoutData);
139
- // Return the last result if multiple exist, or undefined if none
140
- return results.length > 0 ? results[results.length - 1] : undefined;
141
- }
142
- else {
143
- // Read from file for direct reporter scenarios
144
- const targetFolder = folder || defaultDataDirectory;
145
- const filepath = this.getPathForInternalId(name, targetFolder);
146
- try {
147
- const content = await fs.promises.readFile(filepath, 'utf-8').then(JSON.parse);
148
- return content;
149
- }
150
- catch (err) {
151
- // TODO no eyes results for test - this is ok, could be that no visual tests occurred for this playwright test
152
- }
153
- }
154
- },
155
- parseStdoutLine(identifier, stdoutData) {
156
- const lines = stdoutData.split('\n');
157
- const eyesLines = lines.filter(line => line.startsWith(`EYES_DATA:${identifier}:`));
158
- const results = [];
159
- for (const eyesLine of eyesLines) {
160
- const jsonPart = eyesLine.replace(`EYES_DATA:${identifier}:`, '');
185
+ async consume(uuid, eyes) {
186
+ var _a;
187
+ const logger = ((_a = eyes.getLogger) === null || _a === void 0 ? void 0 : _a.call(eyes)) || (0, logger_1.makeLogger)();
188
+ const { download } = makeReporterRequest({
189
+ serverUrl: eyes.getServerUrl(),
190
+ apiKey: eyes.getApiKey(),
191
+ logger: logger,
192
+ });
193
+ for (let retry = 0; retry < 3; retry++) {
161
194
  try {
162
- const parsed = JSON.parse(jsonPart);
163
- results.push(parsed);
195
+ const response = await download(uuid);
196
+ if (utils.types.has(response, 'status') && response.status !== 200) {
197
+ throw new Error(`Failed to consume data for UUID ${uuid}: ${response.status} - ${JSON.stringify(response)}`);
198
+ }
199
+ return { key: response.key, data: response.data };
164
200
  }
165
- catch (err) {
166
- // Skip invalid JSON lines
167
- continue;
201
+ catch (error) {
202
+ logger.warn('Failed to consume data:', error, ". Perhaps the test doesn't include Applitools tests?");
168
203
  }
204
+ await utils.general.sleep(1000 * (retry + 1)); // the backend might need a few seconds to process the upload
169
205
  }
170
- return results;
171
- },
172
- ensureFolder(folderPath = defaultDataDirectory) {
173
- if (!fs.existsSync(folderPath)) {
174
- fs.mkdirSync(folderPath, { recursive: true });
175
- }
176
- },
177
- getPathForInternalId(applitoolsIdentifier, folderPath = defaultDataDirectory) {
178
- return path.join(folderPath, applitoolsIdentifier);
179
206
  },
180
207
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applitools/eyes-playwright",
3
- "version": "1.38.2",
3
+ "version": "1.39.1",
4
4
  "description": "Applitools Eyes SDK for Playwright",
5
5
  "keywords": [
6
6
  "eyes-playwright",
@@ -59,9 +59,11 @@
59
59
  "up:framework": "echo \"$(jq '.devDependencies.playwright = $ENV.APPLITOOLS_FRAMEWORK_VERSION' ./package.json)\" > ./package.json"
60
60
  },
61
61
  "dependencies": {
62
- "@applitools/eyes": "1.35.3",
63
- "@applitools/spec-driver-playwright": "1.6.1",
64
- "@applitools/utils": "1.9.0",
62
+ "@applitools/eyes": "1.36.0",
63
+ "@applitools/req": "1.8.1",
64
+ "@applitools/spec-driver-playwright": "1.7.1",
65
+ "@applitools/utils": "1.11.0",
66
+ "@azure/storage-blob": "^12.28.0",
65
67
  "@inquirer/prompts": "7.0.1",
66
68
  "chalk": "4.1.2",
67
69
  "yargs": "17.7.2"
@@ -77,6 +79,7 @@
77
79
  "@rollup/plugin-typescript": "^12.1.0",
78
80
  "@types/node": "^12.20.55",
79
81
  "jszip": "^3.10.1",
82
+ "nock": "^13.3.2",
80
83
  "playwright": "1.49.0",
81
84
  "rollup": "^4.1.4"
82
85
  },
package/types/index.d.ts CHANGED
@@ -470,7 +470,7 @@ export type ConfigurationPlain = {
470
470
  baselineEnvName?: undefined | string;
471
471
  batch?: undefined | BatchInfoPlain;
472
472
  branchName?: undefined | string;
473
- browsersInfo?: undefined | Array<(DesktopBrowserInfo | ChromeEmulationInfo | IOSDeviceInfo | { iosDeviceInfo: { deviceName: "iPhone X" | "iPhone 14 Plus" | "iPhone 14 Pro" | "iPhone XR" | "iPhone 11" | "iPhone 11 Pro Max" | "iPhone 11 Pro" | "iPhone SE (2nd generation)" | "iPhone SE (3rd generation)" | "iPhone Xs" | "iPhone 12" | "iPhone 12 mini" | "iPhone 12 Pro Max" | "iPhone 12 Pro" | "iPhone 13" | "iPhone 13 mini" | "iPhone 13 Pro Max" | "iPhone 13 Pro" | "iPhone 14" | "iPhone 14 Pro Max" | "iPhone 8" | "iPhone 8 Plus" | "iPhone Xs Max"; }; })>;
473
+ browsersInfo?: undefined | Array<(DesktopBrowserInfo | ChromeEmulationInfo | IOSDeviceInfo | IOSMultiDeviceInfo)>;
474
474
  captureStatusBar?: undefined | boolean;
475
475
  compareWithParentBranch?: undefined | boolean;
476
476
  concurrentSessions?: undefined | number;
@@ -564,9 +564,9 @@ export class Configuration implements Required<ConfigurationPlain> {
564
564
  set branchName(branchName: string);
565
565
  getBranchName(): string;
566
566
  setBranchName(branchName: string): Configuration;
567
- get browsersInfo(): Array<(DesktopBrowserInfo | ChromeEmulationInfo | IOSDeviceInfo | { iosDeviceInfo: { deviceName: "iPhone X" | "iPhone 14 Plus" | "iPhone 14 Pro" | "iPhone XR" | "iPhone 11" | "iPhone 11 Pro Max" | "iPhone 11 Pro" | "iPhone SE (2nd generation)" | "iPhone SE (3rd generation)" | "iPhone Xs" | "iPhone 12" | "iPhone 12 mini" | "iPhone 12 Pro Max" | "iPhone 12 Pro" | "iPhone 13" | "iPhone 13 mini" | "iPhone 13 Pro Max" | "iPhone 13 Pro" | "iPhone 14" | "iPhone 14 Pro Max" | "iPhone 8" | "iPhone 8 Plus" | "iPhone Xs Max"; }; })>;
568
- set browsersInfo(browsersInfo: Array<(DesktopBrowserInfo | ChromeEmulationInfo | IOSDeviceInfo | { iosDeviceInfo: { deviceName: "iPhone X" | "iPhone 14 Plus" | "iPhone 14 Pro" | "iPhone XR" | "iPhone 11" | "iPhone 11 Pro Max" | "iPhone 11 Pro" | "iPhone SE (2nd generation)" | "iPhone SE (3rd generation)" | "iPhone Xs" | "iPhone 12" | "iPhone 12 mini" | "iPhone 12 Pro Max" | "iPhone 12 Pro" | "iPhone 13" | "iPhone 13 mini" | "iPhone 13 Pro Max" | "iPhone 13 Pro" | "iPhone 14" | "iPhone 14 Pro Max" | "iPhone 8" | "iPhone 8 Plus" | "iPhone Xs Max"; }; })>);
569
- getBrowsersInfo(): Array<(DesktopBrowserInfo | ChromeEmulationInfo | IOSDeviceInfo | { iosDeviceInfo: { deviceName: "iPhone X" | "iPhone 14 Plus" | "iPhone 14 Pro" | "iPhone XR" | "iPhone 11" | "iPhone 11 Pro Max" | "iPhone 11 Pro" | "iPhone SE (2nd generation)" | "iPhone SE (3rd generation)" | "iPhone Xs" | "iPhone 12" | "iPhone 12 mini" | "iPhone 12 Pro Max" | "iPhone 12 Pro" | "iPhone 13" | "iPhone 13 mini" | "iPhone 13 Pro Max" | "iPhone 13 Pro" | "iPhone 14" | "iPhone 14 Pro Max" | "iPhone 8" | "iPhone 8 Plus" | "iPhone Xs Max"; }; })>;
567
+ get browsersInfo(): Array<(DesktopBrowserInfo | ChromeEmulationInfo | IOSDeviceInfo | IOSMultiDeviceInfo)>;
568
+ set browsersInfo(browsersInfo: Array<(DesktopBrowserInfo | ChromeEmulationInfo | IOSDeviceInfo | IOSMultiDeviceInfo)>);
569
+ getBrowsersInfo(): Array<(DesktopBrowserInfo | ChromeEmulationInfo | IOSDeviceInfo | IOSMultiDeviceInfo)>;
570
570
  setBrowsersInfo(browsersInfo: Array<(DesktopBrowserInfo | ChromeEmulationInfo | IOSDeviceInfo | { deviceName: DeviceNamePlain; screenOrientation?: undefined | ScreenOrientationPlain; })>): Configuration;
571
571
  addBrowsers(...browsersInfo: Array<(DesktopBrowserInfo | ChromeEmulationInfo | IOSDeviceInfo | { deviceName: DeviceNamePlain; screenOrientation?: undefined | ScreenOrientationPlain; })>): Configuration;
572
572
  addBrowser(browserInfo: (DesktopBrowserInfo | ChromeEmulationInfo | IOSDeviceInfo | { deviceName: DeviceNamePlain; screenOrientation?: undefined | ScreenOrientationPlain; })): Configuration;
@@ -575,6 +575,7 @@ export class Configuration implements Required<ConfigurationPlain> {
575
575
  addMultiDeviceTarget(deviceName: "iPhone X"): Configuration;
576
576
  addMultiDeviceTarget(deviceName: "iPhone 14 Plus"): Configuration;
577
577
  addMultiDeviceTarget(deviceName: "iPhone 14 Pro"): Configuration;
578
+ addMultiDeviceTarget(deviceName: "iPhone 15 Pro"): Configuration;
578
579
  addMultiDeviceTarget(deviceName: "iPhone XR"): Configuration;
579
580
  addMultiDeviceTarget(deviceName: "iPhone 11"): Configuration;
580
581
  addMultiDeviceTarget(deviceName: "iPhone 11 Pro Max"): Configuration;
@@ -592,6 +593,18 @@ export class Configuration implements Required<ConfigurationPlain> {
592
593
  addMultiDeviceTarget(deviceName: "iPhone 13 Pro"): Configuration;
593
594
  addMultiDeviceTarget(deviceName: "iPhone 14"): Configuration;
594
595
  addMultiDeviceTarget(deviceName: "iPhone 14 Pro Max"): Configuration;
596
+ addMultiDeviceTarget(deviceName: "iPhone 15"): Configuration;
597
+ addMultiDeviceTarget(deviceName: "iPhone 15 Pro Max"): Configuration;
598
+ addMultiDeviceTarget(deviceName: "iPhone 15 Plus"): Configuration;
599
+ addMultiDeviceTarget(deviceName: "iPhone 16"): Configuration;
600
+ addMultiDeviceTarget(deviceName: "iPhone 16 Pro Max"): Configuration;
601
+ addMultiDeviceTarget(deviceName: "iPhone 16 Pro"): Configuration;
602
+ addMultiDeviceTarget(deviceName: "iPhone 16 Plus"): Configuration;
603
+ addMultiDeviceTarget(deviceName: "iPhone SE (1st generation)"): Configuration;
604
+ addMultiDeviceTarget(deviceName: "iPhone 6"): Configuration;
605
+ addMultiDeviceTarget(deviceName: "iPhone 6 Plus"): Configuration;
606
+ addMultiDeviceTarget(deviceName: "iPhone 7"): Configuration;
607
+ addMultiDeviceTarget(deviceName: "iPhone 7 Plus"): Configuration;
595
608
  addMultiDeviceTarget(deviceName: "iPhone 8"): Configuration;
596
609
  addMultiDeviceTarget(deviceName: "iPhone 8 Plus"): Configuration;
597
610
  addMultiDeviceTarget(deviceName: "iPhone Xs Max"): Configuration;
@@ -1615,6 +1628,7 @@ export class Region implements Required<RegionPlain> {
1615
1628
  export type DesktopBrowserInfo = { name?: undefined | BrowserTypePlain; width: number; height: number; };
1616
1629
  export type ChromeEmulationInfo = { chromeEmulationInfo: { deviceName: DeviceNamePlain; screenOrientation?: undefined | ScreenOrientationPlain; }; };
1617
1630
  export type IOSDeviceInfo = { iosDeviceInfo: { deviceName: IosDeviceNamePlain; iosVersion?: undefined | IosVersionPlain; screenOrientation?: undefined | ScreenOrientationPlain; }; };
1631
+ export type IOSMultiDeviceInfo = { iosDeviceInfo: { deviceName: "iPhone X" | "iPhone 14 Plus" | "iPhone 14 Pro" | "iPhone 15 Pro" | "iPhone XR" | "iPhone 11" | "iPhone 11 Pro Max" | "iPhone 11 Pro" | "iPhone SE (2nd generation)" | "iPhone SE (3rd generation)" | "iPhone Xs" | "iPhone 12" | "iPhone 12 mini" | "iPhone 12 Pro Max" | "iPhone 12 Pro" | "iPhone 13" | "iPhone 13 mini" | "iPhone 13 Pro Max" | "iPhone 13 Pro" | "iPhone 14" | "iPhone 14 Pro Max" | "iPhone 15" | "iPhone 15 Pro Max" | "iPhone 15 Plus" | "iPhone 16" | "iPhone 16 Pro Max" | "iPhone 16 Pro" | "iPhone 16 Plus" | "iPhone SE (1st generation)" | "iPhone 6" | "iPhone 6 Plus" | "iPhone 7" | "iPhone 7 Plus" | "iPhone 8" | "iPhone 8 Plus" | "iPhone Xs Max"; }; };
1618
1632
  export type RunnerOptionsPlain = { testConcurrency?: undefined | number; fetchConcurrency?: undefined | number; removeDuplicateTests?: undefined | boolean; maskLog?: undefined | boolean; };
1619
1633
  export class RunnerOptionsFluent {
1620
1634
  testConcurrency(concurrency: number): RunnerOptionsFluent;