@bigbinary/neeto-playwright-commons 1.26.35 → 1.27.0

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/index.d.ts CHANGED
@@ -751,8 +751,10 @@ declare class ApiKeysApi {
751
751
  declare class CustomDomainApi {
752
752
  private neetoPlaywrightUtilities;
753
753
  constructor(neetoPlaywrightUtilities: CustomCommands);
754
+ create: (hostname: string, baseUrl?: string) => Promise<playwright_core.APIResponse | undefined>;
754
755
  delete: (customDomain: string) => Promise<playwright_core.APIResponse | undefined>;
755
- fetch: () => Promise<playwright_core.APIResponse | undefined>;
756
+ fetch: (baseUrl?: string) => Promise<playwright_core.APIResponse | undefined>;
757
+ validate: (baseUrl?: string) => Promise<playwright_core.APIResponse | undefined>;
756
758
  }
757
759
  interface AllowedIpRange {
758
760
  ipStart: string;
@@ -4773,7 +4775,7 @@ declare class CustomDomainPage {
4773
4775
  customDomainApi: CustomDomainApi;
4774
4776
  subdomain: string;
4775
4777
  loginPage: Page;
4776
- baseURL: string;
4778
+ customDomainURL: string;
4777
4779
  t: TFunction;
4778
4780
  constructor({
4779
4781
  browser,
@@ -4808,6 +4810,7 @@ declare class CustomDomainPage {
4808
4810
  * @endexample
4809
4811
  */
4810
4812
  validateCustomDomain: (domain: string) => Promise<void>;
4813
+ private getDomainStatus;
4811
4814
  private loginToCustomDomain;
4812
4815
  private waitForTrustedSSL;
4813
4816
  private saveCustomDomainState;
@@ -4824,7 +4827,17 @@ declare class CustomDomainPage {
4824
4827
  setupCustomDomain: () => Promise<void>;
4825
4828
  /**
4826
4829
  *
4827
- * Connects and validates a custom domain for the specified product.
4830
+ * Sets up a custom domain using the API instead of the UI.
4831
+ *
4832
+ * @example
4833
+ *
4834
+ * await customDomainPage.setupCustomDomainViaAPI();
4835
+ * @endexample
4836
+ */
4837
+ setupCustomDomainViaAPI: () => Promise<void>;
4838
+ /**
4839
+ *
4840
+ * Connects and validates a custom domain for the specified product via the UI.
4828
4841
  *
4829
4842
  * subdomain (optional): The subdomain to use for generating the custom domain.
4830
4843
  *
@@ -4834,6 +4847,20 @@ declare class CustomDomainPage {
4834
4847
  * @endexample
4835
4848
  */
4836
4849
  connectCustomDomain: (subdomain?: string) => Promise<void>;
4850
+ /**
4851
+ *
4852
+ * Connects and validates a custom domain using only API calls.
4853
+ *
4854
+ * subdomain (optional): The subdomain to use for generating the custom domain. If omitted, uses the subdomain from global user state.
4855
+ *
4856
+ * @example
4857
+ *
4858
+ * await customDomainPage.connectViaAPI("cpt-form-534343434");
4859
+ * @endexample
4860
+ */
4861
+ connectViaAPI: (subdomain?: string) => Promise<void>;
4862
+ private validateDomain;
4863
+ private awaitDomainValidation;
4837
4864
  private getCustomDomainFromAPI;
4838
4865
  /**
4839
4866
  *
@@ -6268,6 +6295,7 @@ declare const COMMON_SELECTORS: {
6268
6295
  columnsDropdownIcon: string;
6269
6296
  columnDragHandle: string;
6270
6297
  reactSelectContainer: string;
6298
+ calloutElement: string;
6271
6299
  };
6272
6300
  /**
6273
6301
  *
package/index.js CHANGED
@@ -131,15 +131,26 @@ class ApiKeysApi {
131
131
  }
132
132
  }
133
133
 
134
+ const CUSTOM_DOMAIN_BASE_URL = `${BASE_URL}/custom_domains`;
134
135
  class CustomDomainApi {
135
136
  constructor(neetoPlaywrightUtilities) {
136
137
  this.neetoPlaywrightUtilities = neetoPlaywrightUtilities;
138
+ this.create = (hostname, baseUrl = "") => this.neetoPlaywrightUtilities.apiRequest({
139
+ url: `${baseUrl}${CUSTOM_DOMAIN_BASE_URL}`,
140
+ method: "post",
141
+ body: { hostname },
142
+ });
137
143
  this.delete = (customDomain) => this.neetoPlaywrightUtilities.apiRequest({
138
- url: `${BASE_URL}/custom_domains/${customDomain}`,
144
+ url: `${CUSTOM_DOMAIN_BASE_URL}/${customDomain}`,
139
145
  method: "delete",
140
146
  });
141
- this.fetch = () => this.neetoPlaywrightUtilities.apiRequest({
142
- url: `${BASE_URL}/custom_domains`,
147
+ this.fetch = (baseUrl = "") => this.neetoPlaywrightUtilities.apiRequest({
148
+ url: `${baseUrl}${CUSTOM_DOMAIN_BASE_URL}`,
149
+ });
150
+ this.validate = (baseUrl = "") => this.neetoPlaywrightUtilities.apiRequest({
151
+ url: `${baseUrl}${CUSTOM_DOMAIN_BASE_URL}/validate_domain`,
152
+ failOnStatusCode: false,
153
+ method: "patch",
143
154
  });
144
155
  }
145
156
  }
@@ -4961,6 +4972,7 @@ const COMMON_SELECTORS = {
4961
4972
  columnsDropdownIcon: "columns-dropdown-icon",
4962
4973
  columnDragHandle: "column-drag-handle",
4963
4974
  reactSelectContainer: ".neeto-ui-react-select__container",
4975
+ calloutElement: "callout-element",
4964
4976
  };
4965
4977
 
4966
4978
  const THANK_YOU_SELECTORS = {
@@ -29063,9 +29075,10 @@ function requireAddressparser () {
29063
29075
  * Converts tokens for a single address into an address object
29064
29076
  *
29065
29077
  * @param {Array} tokens Tokens object
29078
+ * @param {Number} depth Current recursion depth for nested group protection
29066
29079
  * @return {Object} Address object
29067
29080
  */
29068
- function _handleAddress(tokens) {
29081
+ function _handleAddress(tokens, depth) {
29069
29082
  let isGroup = false;
29070
29083
  let state = 'text';
29071
29084
  let address;
@@ -29146,7 +29159,7 @@ function requireAddressparser () {
29146
29159
  // Parse group members, but flatten any nested groups (RFC 5322 doesn't allow nesting)
29147
29160
  let groupMembers = [];
29148
29161
  if (data.group.length) {
29149
- let parsedGroup = addressparser(data.group.join(','));
29162
+ let parsedGroup = addressparser(data.group.join(','), { _depth: depth + 1 });
29150
29163
  // Flatten: if any member is itself a group, extract its members into the sequence
29151
29164
  parsedGroup.forEach(member => {
29152
29165
  if (member.group) {
@@ -29356,6 +29369,13 @@ function requireAddressparser () {
29356
29369
  }
29357
29370
  }
29358
29371
 
29372
+ /**
29373
+ * Maximum recursion depth for parsing nested groups.
29374
+ * RFC 5322 doesn't allow nested groups, so this is a safeguard against
29375
+ * malicious input that could cause stack overflow.
29376
+ */
29377
+ const MAX_NESTED_GROUP_DEPTH = 50;
29378
+
29359
29379
  /**
29360
29380
  * Parses structured e-mail addresses from an address field
29361
29381
  *
@@ -29368,10 +29388,18 @@ function requireAddressparser () {
29368
29388
  * [{name: 'Name', address: 'address@domain'}]
29369
29389
  *
29370
29390
  * @param {String} str Address field
29391
+ * @param {Object} options Optional options object
29392
+ * @param {Number} options._depth Internal recursion depth counter (do not set manually)
29371
29393
  * @return {Array} An array of address objects
29372
29394
  */
29373
29395
  function addressparser(str, options) {
29374
29396
  options = options || {};
29397
+ let depth = options._depth || 0;
29398
+
29399
+ // Prevent stack overflow from deeply nested groups (DoS protection)
29400
+ if (depth > MAX_NESTED_GROUP_DEPTH) {
29401
+ return [];
29402
+ }
29375
29403
 
29376
29404
  let tokenizer = new Tokenizer(str);
29377
29405
  let tokens = tokenizer.tokenize();
@@ -29396,7 +29424,7 @@ function requireAddressparser () {
29396
29424
  }
29397
29425
 
29398
29426
  addresses.forEach(address => {
29399
- address = _handleAddress(address);
29427
+ address = _handleAddress(address, depth);
29400
29428
  if (address.length) {
29401
29429
  parsedAddresses = parsedAddresses.concat(address);
29402
29430
  }
@@ -40908,6 +40936,8 @@ function requireStreams () {
40908
40936
  return streams;
40909
40937
  }
40910
40938
 
40939
+ lib$a.exports;
40940
+
40911
40941
  var hasRequiredLib$a;
40912
40942
 
40913
40943
  function requireLib$a () {
@@ -40919,22 +40949,21 @@ function requireLib$a () {
40919
40949
 
40920
40950
  var bomHandling = requireBomHandling();
40921
40951
  var mergeModules = requireMergeExports();
40922
- var iconv = module.exports;
40923
40952
 
40924
40953
  // All codecs and aliases are kept here, keyed by encoding name/alias.
40925
40954
  // They are lazy loaded in `iconv.getCodec` from `encodings/index.js`.
40926
40955
  // Cannot initialize with { __proto__: null } because Boolean({ __proto__: null }) === true
40927
- iconv.encodings = null;
40956
+ module.exports.encodings = null;
40928
40957
 
40929
40958
  // Characters emitted in case of error.
40930
- iconv.defaultCharUnicode = "�";
40931
- iconv.defaultCharSingleByte = "?";
40959
+ module.exports.defaultCharUnicode = "�";
40960
+ module.exports.defaultCharSingleByte = "?";
40932
40961
 
40933
40962
  // Public API.
40934
- iconv.encode = function encode (str, encoding, options) {
40963
+ module.exports.encode = function encode (str, encoding, options) {
40935
40964
  str = "" + (str || ""); // Ensure string.
40936
40965
 
40937
- var encoder = iconv.getEncoder(encoding, options);
40966
+ var encoder = module.exports.getEncoder(encoding, options);
40938
40967
 
40939
40968
  var res = encoder.write(str);
40940
40969
  var trail = encoder.end();
@@ -40942,17 +40971,17 @@ function requireLib$a () {
40942
40971
  return (trail && trail.length > 0) ? Buffer.concat([res, trail]) : res
40943
40972
  };
40944
40973
 
40945
- iconv.decode = function decode (buf, encoding, options) {
40974
+ module.exports.decode = function decode (buf, encoding, options) {
40946
40975
  if (typeof buf === "string") {
40947
- if (!iconv.skipDecodeWarning) {
40976
+ if (!module.exports.skipDecodeWarning) {
40948
40977
  console.error("Iconv-lite warning: decode()-ing strings is deprecated. Refer to https://github.com/ashtuchkin/iconv-lite/wiki/Use-Buffers-when-decoding");
40949
- iconv.skipDecodeWarning = true;
40978
+ module.exports.skipDecodeWarning = true;
40950
40979
  }
40951
40980
 
40952
40981
  buf = Buffer.from("" + (buf || ""), "binary"); // Ensure buffer.
40953
40982
  }
40954
40983
 
40955
- var decoder = iconv.getDecoder(encoding, options);
40984
+ var decoder = module.exports.getDecoder(encoding, options);
40956
40985
 
40957
40986
  var res = decoder.write(buf);
40958
40987
  var trail = decoder.end();
@@ -40960,9 +40989,9 @@ function requireLib$a () {
40960
40989
  return trail ? (res + trail) : res
40961
40990
  };
40962
40991
 
40963
- iconv.encodingExists = function encodingExists (enc) {
40992
+ module.exports.encodingExists = function encodingExists (enc) {
40964
40993
  try {
40965
- iconv.getCodec(enc);
40994
+ module.exports.getCodec(enc);
40966
40995
  return true
40967
40996
  } catch (e) {
40968
40997
  return false
@@ -40970,31 +40999,31 @@ function requireLib$a () {
40970
40999
  };
40971
41000
 
40972
41001
  // Legacy aliases to convert functions
40973
- iconv.toEncoding = iconv.encode;
40974
- iconv.fromEncoding = iconv.decode;
41002
+ module.exports.toEncoding = module.exports.encode;
41003
+ module.exports.fromEncoding = module.exports.decode;
40975
41004
 
40976
41005
  // Search for a codec in iconv.encodings. Cache codec data in iconv._codecDataCache.
40977
- iconv._codecDataCache = { __proto__: null };
41006
+ module.exports._codecDataCache = { __proto__: null };
40978
41007
 
40979
- iconv.getCodec = function getCodec (encoding) {
40980
- if (!iconv.encodings) {
41008
+ module.exports.getCodec = function getCodec (encoding) {
41009
+ if (!module.exports.encodings) {
40981
41010
  var raw = requireEncodings();
40982
41011
  // TODO: In future versions when old nodejs support is removed can use object.assign
40983
- iconv.encodings = { __proto__: null }; // Initialize as empty object.
40984
- mergeModules(iconv.encodings, raw);
41012
+ module.exports.encodings = { __proto__: null }; // Initialize as empty object.
41013
+ mergeModules(module.exports.encodings, raw);
40985
41014
  }
40986
41015
 
40987
41016
  // Canonicalize encoding name: strip all non-alphanumeric chars and appended year.
40988
- var enc = iconv._canonicalizeEncoding(encoding);
41017
+ var enc = module.exports._canonicalizeEncoding(encoding);
40989
41018
 
40990
41019
  // Traverse iconv.encodings to find actual codec.
40991
41020
  var codecOptions = {};
40992
41021
  while (true) {
40993
- var codec = iconv._codecDataCache[enc];
41022
+ var codec = module.exports._codecDataCache[enc];
40994
41023
 
40995
41024
  if (codec) { return codec }
40996
41025
 
40997
- var codecDef = iconv.encodings[enc];
41026
+ var codecDef = module.exports.encodings[enc];
40998
41027
 
40999
41028
  switch (typeof codecDef) {
41000
41029
  case "string": // Direct alias to other encoding.
@@ -41015,9 +41044,9 @@ function requireLib$a () {
41015
41044
  // The codec function must load all tables and return object with .encoder and .decoder methods.
41016
41045
  // It'll be called only once (for each different options object).
41017
41046
  //
41018
- codec = new codecDef(codecOptions, iconv);
41047
+ codec = new codecDef(codecOptions, module.exports);
41019
41048
 
41020
- iconv._codecDataCache[codecOptions.encodingName] = codec; // Save it to be reused later.
41049
+ module.exports._codecDataCache[codecOptions.encodingName] = codec; // Save it to be reused later.
41021
41050
  return codec
41022
41051
 
41023
41052
  default:
@@ -41026,13 +41055,13 @@ function requireLib$a () {
41026
41055
  }
41027
41056
  };
41028
41057
 
41029
- iconv._canonicalizeEncoding = function (encoding) {
41058
+ module.exports._canonicalizeEncoding = function (encoding) {
41030
41059
  // Canonicalize encoding name: strip all non-alphanumeric chars and appended year.
41031
41060
  return ("" + encoding).toLowerCase().replace(/:\d{4}$|[^0-9a-z]/g, "")
41032
41061
  };
41033
41062
 
41034
- iconv.getEncoder = function getEncoder (encoding, options) {
41035
- var codec = iconv.getCodec(encoding);
41063
+ module.exports.getEncoder = function getEncoder (encoding, options) {
41064
+ var codec = module.exports.getCodec(encoding);
41036
41065
  var encoder = new codec.encoder(options, codec);
41037
41066
 
41038
41067
  if (codec.bomAware && options && options.addBOM) { encoder = new bomHandling.PrependBOM(encoder, options); }
@@ -41040,8 +41069,8 @@ function requireLib$a () {
41040
41069
  return encoder
41041
41070
  };
41042
41071
 
41043
- iconv.getDecoder = function getDecoder (encoding, options) {
41044
- var codec = iconv.getCodec(encoding);
41072
+ module.exports.getDecoder = function getDecoder (encoding, options) {
41073
+ var codec = module.exports.getCodec(encoding);
41045
41074
  var decoder = new codec.decoder(options, codec);
41046
41075
 
41047
41076
  if (codec.bomAware && !(options && options.stripBOM === false)) { decoder = new bomHandling.StripBOM(decoder, options); }
@@ -41054,26 +41083,26 @@ function requireLib$a () {
41054
41083
  // up to 100Kb to the output bundle. To avoid unnecessary code bloat, we don't enable Streaming API in browser by default.
41055
41084
  // If you would like to enable it explicitly, please add the following code to your app:
41056
41085
  // > iconv.enableStreamingAPI(require('stream'));
41057
- iconv.enableStreamingAPI = function enableStreamingAPI (streamModule) {
41058
- if (iconv.supportsStreams) { return }
41086
+ module.exports.enableStreamingAPI = function enableStreamingAPI (streamModule) {
41087
+ if (module.exports.supportsStreams) { return }
41059
41088
 
41060
41089
  // Dependency-inject stream module to create IconvLite stream classes.
41061
41090
  var streams = requireStreams()(streamModule);
41062
41091
 
41063
41092
  // Not public API yet, but expose the stream classes.
41064
- iconv.IconvLiteEncoderStream = streams.IconvLiteEncoderStream;
41065
- iconv.IconvLiteDecoderStream = streams.IconvLiteDecoderStream;
41093
+ module.exports.IconvLiteEncoderStream = streams.IconvLiteEncoderStream;
41094
+ module.exports.IconvLiteDecoderStream = streams.IconvLiteDecoderStream;
41066
41095
 
41067
41096
  // Streaming API.
41068
- iconv.encodeStream = function encodeStream (encoding, options) {
41069
- return new iconv.IconvLiteEncoderStream(iconv.getEncoder(encoding, options), options)
41097
+ module.exports.encodeStream = function encodeStream (encoding, options) {
41098
+ return new module.exports.IconvLiteEncoderStream(module.exports.getEncoder(encoding, options), options)
41070
41099
  };
41071
41100
 
41072
- iconv.decodeStream = function decodeStream (encoding, options) {
41073
- return new iconv.IconvLiteDecoderStream(iconv.getDecoder(encoding, options), options)
41101
+ module.exports.decodeStream = function decodeStream (encoding, options) {
41102
+ return new module.exports.IconvLiteDecoderStream(module.exports.getDecoder(encoding, options), options)
41074
41103
  };
41075
41104
 
41076
- iconv.supportsStreams = true;
41105
+ module.exports.supportsStreams = true;
41077
41106
  };
41078
41107
 
41079
41108
  // Enable Streaming API automatically if 'stream' module is available and non-empty (the majority of environments).
@@ -41083,10 +41112,10 @@ function requireLib$a () {
41083
41112
  } catch (e) {}
41084
41113
 
41085
41114
  if (streamModule && streamModule.Transform) {
41086
- iconv.enableStreamingAPI(streamModule);
41115
+ module.exports.enableStreamingAPI(streamModule);
41087
41116
  } else {
41088
41117
  // In rare cases where 'stream' module is not available by default, throw a helpful exception.
41089
- iconv.encodeStream = iconv.decodeStream = function () {
41118
+ module.exports.encodeStream = module.exports.decodeStream = function () {
41090
41119
  throw new Error("iconv-lite Streaming API is not enabled. Use iconv.enableStreamingAPI(require('stream')); to enable it.")
41091
41120
  };
41092
41121
  }
@@ -51163,7 +51192,6 @@ var require$$11 = [
51163
51192
  "drive",
51164
51193
  "dtv",
51165
51194
  "dubai",
51166
- "dunlop",
51167
51195
  "dupont",
51168
51196
  "durban",
51169
51197
  "dvag",
@@ -53395,7 +53423,11 @@ function requireMailParser () {
53395
53423
  result.push(textPart);
53396
53424
  }
53397
53425
 
53398
- result.push(`<a href="${link.url}">${link.text}</a>`);
53426
+ // Escape quotes in URL to prevent XSS
53427
+ let safeUrl = link.url.replace(/"/g, '&quot;');
53428
+ // Escape HTML entities in link text
53429
+ let safeText = he.encode(link.text, { useNamedReferences: true });
53430
+ result.push(`<a href="${safeUrl}">${safeText}</a>`);
53399
53431
 
53400
53432
  last = link.lastIndex;
53401
53433
  });
@@ -119351,12 +119383,13 @@ class CustomDomainPage {
119351
119383
  .getByRole("cell", { name: domain.split(".")[0] })).toBeVisible(),
119352
119384
  ]);
119353
119385
  await this.neetoPlaywrightUtilities.waitForPageLoad();
119386
+ await validateButton.click();
119387
+ await expect(this.page.getByTestId(COMMON_SELECTORS.calloutElement)).toBeVisible({ timeout: 15000 });
119354
119388
  let isCertificateLimitExceeded = false;
119355
119389
  await expect(async () => {
119356
119390
  isCertificateLimitExceeded = await this.isCertificateLimitExceeded();
119357
119391
  if (isCertificateLimitExceeded)
119358
119392
  return;
119359
- await validateButton.click();
119360
119393
  await this.neetoPlaywrightUtilities.verifyToast({
119361
119394
  message: this.t("neetoCustomDomains.validation.successMessage"),
119362
119395
  });
@@ -119366,13 +119399,21 @@ class CustomDomainPage {
119366
119399
  return;
119367
119400
  }
119368
119401
  await this.neetoPlaywrightUtilities.waitForPageLoad();
119369
- await expect(this.page.getByTestId(CUSTOM_DOMAIN_SELECTORS.activeTagContainer)).toBeVisible();
119402
+ await expect(validateButton).toBeHidden();
119403
+ };
119404
+ this.getDomainStatus = async (hostname, baseURL) => {
119405
+ var _a;
119406
+ const response = await this.customDomainApi
119407
+ .fetch(baseURL)
119408
+ .then(response => response === null || response === void 0 ? void 0 : response.json());
119409
+ const domain = (_a = response === null || response === void 0 ? void 0 : response.custom_domains) === null || _a === void 0 ? void 0 : _a.find((domain) => { var _a; return ((_a = domain.hostname) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === hostname.toLowerCase(); });
119410
+ return domain === null || domain === void 0 ? void 0 : domain.status;
119370
119411
  };
119371
119412
  this.loginToCustomDomain = async () => {
119372
119413
  await this.page.close();
119373
119414
  const loginPage = this.loginPage;
119374
119415
  const { email } = getGlobalUserState();
119375
- const loginUrl = `${this.baseURL}${ROUTES.admin}`;
119416
+ const loginUrl = `${this.customDomainURL}${ROUTES.admin}`;
119376
119417
  const playwrightUtils = new CustomCommands(loginPage, loginPage.request);
119377
119418
  const organizationPage = new OrganizationPage(loginPage, playwrightUtils);
119378
119419
  await loginPage.goto(loginUrl);
@@ -119384,7 +119425,7 @@ class CustomDomainPage {
119384
119425
  this.waitForTrustedSSL = () => expect
119385
119426
  .poll(() => new Promise(resolve => {
119386
119427
  https
119387
- .get(this.baseURL, { rejectUnauthorized: true }, res => {
119428
+ .get(this.customDomainURL, { rejectUnauthorized: true }, res => {
119388
119429
  res.resume();
119389
119430
  resolve(true);
119390
119431
  })
@@ -119398,7 +119439,7 @@ class CustomDomainPage {
119398
119439
  await this.loginPage.context().storageState({ path: STORAGE_STATE });
119399
119440
  const mergedCredentials = mergeAll([readFileSyncIfExists(), { user }]);
119400
119441
  writeDataToFile(JSON.stringify(mergedCredentials, null, 2));
119401
- updateCredentials({ key: "baseUrl", value: this.baseURL });
119442
+ updateCredentials({ key: "baseUrl", value: this.customDomainURL });
119402
119443
  updateCredentials({ key: "domain", value: CUSTOM_DOMAIN_SUFFIX });
119403
119444
  };
119404
119445
  // eslint-disable-next-line playwright/no-wait-for-timeout
@@ -119412,21 +119453,57 @@ class CustomDomainPage {
119412
119453
  await this.loginToCustomDomain();
119413
119454
  await this.saveCustomDomainState();
119414
119455
  };
119456
+ this.setupCustomDomainViaAPI = async () => {
119457
+ if (shouldSkipCustomDomainSetup())
119458
+ return;
119459
+ await this.connectViaAPI();
119460
+ const context = await this.browser.newContext(EMPTY_STORAGE_STATE);
119461
+ this.loginPage = await context.newPage();
119462
+ await this.loginToCustomDomain();
119463
+ await this.saveCustomDomainState();
119464
+ };
119415
119465
  this.connectCustomDomain = async (subdomain) => {
119416
119466
  if (shouldSkipCustomDomainSetup())
119417
119467
  return;
119418
- const baseURL = baseURLGenerator(this.product, subdomain);
119419
119468
  const domain = this.getCustomDomain(subdomain);
119420
- this.baseURL = `https://${domain}`;
119469
+ const baseURL = baseURLGenerator(this.product, this.subdomain);
119470
+ this.customDomainURL = `https://${domain}`;
119421
119471
  await this.neetoPlaywrightUtilities.waitForPageLoad();
119422
119472
  await this.page.goto(`${baseURL}${ROUTES.adminPanel.customDomain}`);
119423
119473
  await this.neetoPlaywrightUtilities.waitForPageLoad();
119424
119474
  await this.addCustomDomain(domain);
119425
119475
  await this.validateCustomDomain(domain);
119426
- process.env.BASE_URL = this.baseURL;
119476
+ process.env.BASE_URL = this.customDomainURL;
119427
119477
  await this.waitForTrustedSSL();
119428
119478
  await this.waitForDomainPropagation();
119429
119479
  };
119480
+ this.connectViaAPI = async (subdomain) => {
119481
+ if (shouldSkipCustomDomainSetup())
119482
+ return;
119483
+ const domain = this.getCustomDomain(subdomain);
119484
+ this.customDomainURL = `https://${domain}`;
119485
+ const baseURL = baseURLGenerator(this.product, this.subdomain);
119486
+ await this.page.goto(`${baseURL}${ROUTES.adminPanel.customDomain}`);
119487
+ await this.page.waitForLoadState("domcontentloaded");
119488
+ await this.customDomainApi.create(domain, baseURL);
119489
+ await this.validateDomain(baseURL);
119490
+ await this.awaitDomainValidation(domain, baseURL);
119491
+ process.env.BASE_URL = this.customDomainURL;
119492
+ await this.waitForTrustedSSL();
119493
+ await this.waitForDomainPropagation();
119494
+ };
119495
+ this.validateDomain = (baseURL) => expect
119496
+ .poll(async () => { var _a; return (_a = (await this.customDomainApi.validate(baseURL))) === null || _a === void 0 ? void 0 : _a.status(); }, {
119497
+ timeout: 2 * 60000,
119498
+ intervals: [10000],
119499
+ })
119500
+ .toBe(200);
119501
+ this.awaitDomainValidation = (hostname, baseURL) => expect
119502
+ .poll(async () => this.getDomainStatus(hostname, baseURL), {
119503
+ timeout: 2 * 60000,
119504
+ intervals: [5000],
119505
+ })
119506
+ .toBe("active");
119430
119507
  this.getCustomDomainFromAPI = async () => {
119431
119508
  const { custom_domains } = await this.customDomainApi
119432
119509
  .fetch()