@bigbinary/neeto-playwright-commons 3.0.8 → 3.1.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/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { keysToSnakeCase, isPresent, hyphenate, isNotPresent, humanize, dynamicArray, findBy, truncate, isNotEmpty, isNotEqualDeep, randomPick } from '@bigbinary/neeto-cist';
2
2
  import { faker } from '@faker-js/faker';
3
3
  import * as fs$4 from 'fs';
4
- import fs__default, { readFileSync, promises, existsSync, writeFileSync, unlinkSync } from 'fs';
4
+ import fs__default, { readFileSync, promises, existsSync, writeFileSync, unlinkSync, mkdirSync, rmSync, createWriteStream } from 'fs';
5
5
  import require$$0$4 from 'os';
6
6
  import * as path$1 from 'path';
7
7
  import path__default from 'path';
@@ -60508,7 +60508,7 @@ class RailsEmailUtils {
60508
60508
  });
60509
60509
  return otp || undefined;
60510
60510
  };
60511
- getEmailAttachment = async (attachmentName, messageSearchCriteria = {}, { receivedAfter = new Date(new Date().valueOf() - 60 * 60 * 1000), expectedEmailCount = 1, timeout = 10_000, } = {}, shouldThrowErrorOnTimeout = true) => {
60511
+ getEmailAttachment = async ({ name, type }, messageSearchCriteria = {}, { receivedAfter = new Date(new Date().valueOf() - 60 * 60 * 1000), expectedEmailCount = 1, timeout = 10_000, } = {}, shouldThrowErrorOnTimeout = true) => {
60512
60512
  const attachmentDetails = (await this.neetoPlaywrightUtilities.executeRecursively({
60513
60513
  callback: async () => {
60514
60514
  const railsEmail = await this.railsEmailClient.getLatestEmail({
@@ -60517,7 +60517,11 @@ class RailsEmailUtils {
60517
60517
  });
60518
60518
  if (!railsEmail)
60519
60519
  return null;
60520
- const attachment = railsEmail.attachments?.find(att => att.name.includes(attachmentName));
60520
+ const attachment = railsEmail.attachments?.find(att => {
60521
+ const matchesName = name ? att.name?.includes(name) : true;
60522
+ const matchesType = type ? att.type?.startsWith(type) : true;
60523
+ return matchesName && matchesType;
60524
+ });
60521
60525
  if (!attachment)
60522
60526
  return null;
60523
60527
  return {
@@ -60701,19 +60705,26 @@ class MailerUtils {
60701
60705
  return codes?.[0];
60702
60706
  };
60703
60707
  generateRandomEmail = () => faker.internet.email({ provider: process.env.FASTMAIL_DOMAIN_NAME });
60704
- getEmailAttachment = async (attachmentName, messageSearchCriteria = {}, { timeout = 10_000, receivedAfter = dateTimeOneHourAgo(), expectedEmailCount = 1, } = {}, shouldThrowErrorOnTimeout = true) => {
60705
- if (IS_DEV_ENV) {
60706
- return this.railsEmailUtils.getEmailAttachment(attachmentName, messageSearchCriteria, { receivedAfter, expectedEmailCount, timeout: timeout / 3 }, shouldThrowErrorOnTimeout);
60707
- }
60708
+ getEmailAttachment = async ({ name, type }, messageSearchCriteria = {}, { timeout = 10_000, receivedAfter = dateTimeOneHourAgo(), expectedEmailCount = 1, } = {}, shouldThrowErrorOnTimeout = true) => {
60709
+ if (IS_DEV_ENV)
60710
+ return this.railsEmailUtils.getEmailAttachment({ name, type }, messageSearchCriteria, { receivedAfter, expectedEmailCount, timeout: timeout / 3 }, shouldThrowErrorOnTimeout);
60708
60711
  const { blobId, attachments: attachmentNameAndTypes } = await this.findMessage(messageSearchCriteria, { expectedEmailCount, receivedAfter, timeout }, shouldThrowErrorOnTimeout);
60709
- const attachment = attachmentNameAndTypes.find(attachment => attachment.name.includes(attachmentName));
60712
+ const attachment = attachmentNameAndTypes.find(att => {
60713
+ const matchesName = name ? att.name?.includes(name) : true;
60714
+ const matchesType = type ? att.type?.startsWith(type) : true;
60715
+ return matchesName && matchesType;
60716
+ });
60710
60717
  if (!attachment)
60711
60718
  throw new Error("No such attachment exists");
60712
60719
  const emailAttachment = await this.fastmailApi.fetchAttachments(blobId, attachment.name);
60713
60720
  const buffer = await emailAttachment.body();
60714
60721
  const parsedEmail = await mailparserExports.simpleParser(buffer);
60715
60722
  const attachments = parsedEmail.attachments;
60716
- return attachments.find(attachment => attachment.filename.includes(attachmentName));
60723
+ return attachments.find(att => {
60724
+ const matchesName = name ? att.filename?.includes(name) : true;
60725
+ const matchesType = type ? att.contentType?.startsWith(type) : true;
60726
+ return matchesName && matchesType;
60727
+ });
60717
60728
  };
60718
60729
  }
60719
60730
 
@@ -125103,22 +125114,22 @@ async function warmup({ urls = DEFAULT_WARMUP_URLS, timeout = 60_000, } = {}) {
125103
125114
  }
125104
125115
  }
125105
125116
 
125106
- const CONFIG = {
125117
+ const CONFIG$1 = {
125107
125118
  DIR: "/tmp/neeto-auth-web",
125108
125119
  LOG: "/tmp/neeto-auth-server.log",
125109
125120
  PORT: 9000,
125110
125121
  MAX_WAIT_MS: 120_000,
125111
125122
  EMAIL_INIT: "/tmp/neeto-auth-web/config/initializers/playwright_email_capture.rb",
125112
125123
  };
125113
- const SCRIPTS_DIR = path$1.join(__dirname, "scripts", "neeto-auth");
125124
+ const SCRIPTS_DIR$1 = path$1.join(__dirname, "scripts", "neeto-auth");
125114
125125
  const escapeRubyString = (value) => value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
125115
125126
  const buildEmailCaptureInitializer = (targetApp) => {
125116
- const template = fs$4.readFileSync(path$1.join(SCRIPTS_DIR, "playwright_email_capture.rb.template"), "utf-8");
125127
+ const template = fs$4.readFileSync(path$1.join(SCRIPTS_DIR$1, "playwright_email_capture.rb.template"), "utf-8");
125117
125128
  return template.replace("{{TARGET_APP}}", escapeRubyString(targetApp));
125118
125129
  };
125119
- const log = (msg) => console.log(`[NeetoAuth] ${msg}`);
125120
- const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
125121
- const httpCheck = (port, timeout = 3000) => new Promise(resolve => {
125130
+ const log$1 = (msg) => console.log(`[NeetoAuth] ${msg}`);
125131
+ const sleep$1 = (ms) => new Promise(resolve => setTimeout(resolve, ms));
125132
+ const httpCheck$1 = (port, timeout = 3000) => new Promise(resolve => {
125122
125133
  const req = http.get(`http://localhost:${port}/`, () => resolve(true));
125123
125134
  req.on("error", () => resolve(false));
125124
125135
  req.setTimeout(timeout, () => {
@@ -125145,7 +125156,7 @@ class NeetoAuthServer {
125145
125156
  while (Date.now() < deadline) {
125146
125157
  try {
125147
125158
  process.kill(pid, 0);
125148
- await sleep(500);
125159
+ await sleep$1(500);
125149
125160
  }
125150
125161
  catch {
125151
125162
  return;
@@ -125154,27 +125165,27 @@ class NeetoAuthServer {
125154
125165
  };
125155
125166
  killServerOnPort = async () => {
125156
125167
  try {
125157
- execSync(`lsof -ti tcp:${CONFIG.PORT} | xargs kill -9`, {
125168
+ execSync(`lsof -ti tcp:${CONFIG$1.PORT} | xargs kill -9`, {
125158
125169
  stdio: "ignore",
125159
125170
  });
125160
- await sleep(1000);
125171
+ await sleep$1(1000);
125161
125172
  }
125162
125173
  catch {
125163
125174
  // No process on that port — nothing to kill.
125164
125175
  }
125165
125176
  };
125166
125177
  ensureSetup = () => {
125167
- if (fs$4.existsSync(`${CONFIG.DIR}/Gemfile`)) {
125168
- log("Already set up, skipping.");
125178
+ if (fs$4.existsSync(`${CONFIG$1.DIR}/Gemfile`)) {
125179
+ log$1("Already set up, skipping.");
125169
125180
  return;
125170
125181
  }
125171
125182
  if (!process.env.GITHUB_TOKEN) {
125172
125183
  throw new Error("[NeetoAuth] GITHUB_TOKEN is not set. Cannot clone neeto-auth-web.");
125173
125184
  }
125174
- log("Running first-time setup...");
125175
- const setupScript = path$1.join(SCRIPTS_DIR, "setup.sh");
125185
+ log$1("Running first-time setup...");
125186
+ const setupScript = path$1.join(SCRIPTS_DIR$1, "setup.sh");
125176
125187
  try {
125177
- execSync(`bash "${setupScript}" "${CONFIG.DIR}"`, {
125188
+ execSync(`bash "${setupScript}" "${CONFIG$1.DIR}"`, {
125178
125189
  stdio: "inherit",
125179
125190
  env: this.serverEnv,
125180
125191
  });
@@ -125182,73 +125193,73 @@ class NeetoAuthServer {
125182
125193
  catch {
125183
125194
  throw new Error("[NeetoAuth] First-time setup failed. Check the output above for details.");
125184
125195
  }
125185
- log("Setup complete.");
125196
+ log$1("Setup complete.");
125186
125197
  };
125187
- waitForServer = async (timeoutMs = CONFIG.MAX_WAIT_MS) => {
125198
+ waitForServer = async (timeoutMs = CONFIG$1.MAX_WAIT_MS) => {
125188
125199
  const startTime = Date.now();
125189
125200
  while (Date.now() - startTime < timeoutMs) {
125190
125201
  if (this.process !== null && this.process.exitCode !== null) {
125191
- const logContent = fs$4.existsSync(CONFIG.LOG)
125192
- ? fs$4.readFileSync(CONFIG.LOG, "utf-8")
125202
+ const logContent = fs$4.existsSync(CONFIG$1.LOG)
125203
+ ? fs$4.readFileSync(CONFIG$1.LOG, "utf-8")
125193
125204
  : "<no log file>";
125194
125205
  throw new Error(`[NeetoAuth] Server process exited unexpectedly with code ${this.process.exitCode}.\nLog:\n${logContent}`);
125195
125206
  }
125196
- if (await httpCheck(CONFIG.PORT))
125207
+ if (await httpCheck$1(CONFIG$1.PORT))
125197
125208
  return;
125198
- await sleep(3000);
125209
+ await sleep$1(3000);
125199
125210
  }
125200
- const logContent = fs$4.existsSync(CONFIG.LOG)
125201
- ? fs$4.readFileSync(CONFIG.LOG, "utf-8")
125211
+ const logContent = fs$4.existsSync(CONFIG$1.LOG)
125212
+ ? fs$4.readFileSync(CONFIG$1.LOG, "utf-8")
125202
125213
  : "<no log file>";
125203
125214
  throw new Error(`[NeetoAuth] Server did not start within ${timeoutMs / 1000}s.\nLog:\n${logContent}`);
125204
125215
  };
125205
125216
  injectEmailCaptureInitializer = () => {
125206
- fs$4.writeFileSync(CONFIG.EMAIL_INIT, buildEmailCaptureInitializer(this.targetApp));
125217
+ fs$4.writeFileSync(CONFIG$1.EMAIL_INIT, buildEmailCaptureInitializer(this.targetApp));
125207
125218
  };
125208
125219
  isRunningForCurrentApp = () => {
125209
- if (!fs$4.existsSync(CONFIG.EMAIL_INIT))
125220
+ if (!fs$4.existsSync(CONFIG$1.EMAIL_INIT))
125210
125221
  return false;
125211
- const currentContent = fs$4.readFileSync(CONFIG.EMAIL_INIT, "utf-8");
125222
+ const currentContent = fs$4.readFileSync(CONFIG$1.EMAIL_INIT, "utf-8");
125212
125223
  return currentContent === buildEmailCaptureInitializer(this.targetApp);
125213
125224
  };
125214
125225
  start = async () => {
125215
125226
  if (IS_STAGING_ENV)
125216
125227
  return;
125217
- if (await httpCheck(CONFIG.PORT)) {
125228
+ if (await httpCheck$1(CONFIG$1.PORT)) {
125218
125229
  if (this.isRunningForCurrentApp()) {
125219
- log("Server already running for this app.");
125230
+ log$1("Server already running for this app.");
125220
125231
  return;
125221
125232
  }
125222
- log("Server running for a different app — restarting...");
125233
+ log$1("Server running for a different app — restarting...");
125223
125234
  await this.killServerOnPort();
125224
125235
  }
125225
125236
  this.ensureSetup();
125226
125237
  this.injectEmailCaptureInitializer();
125227
- log("Starting server...");
125228
- const logStream = fs$4.createWriteStream(CONFIG.LOG);
125238
+ log$1("Starting server...");
125239
+ const logStream = fs$4.createWriteStream(CONFIG$1.LOG);
125229
125240
  this.process = spawn("bundle", [
125230
125241
  "exec",
125231
125242
  "rails",
125232
125243
  "server",
125233
125244
  "-p",
125234
- CONFIG.PORT.toString(),
125245
+ CONFIG$1.PORT.toString(),
125235
125246
  "-b",
125236
125247
  "0.0.0.0",
125237
125248
  ], {
125238
- cwd: CONFIG.DIR,
125249
+ cwd: CONFIG$1.DIR,
125239
125250
  stdio: ["ignore", "pipe", "pipe"],
125240
125251
  env: this.serverEnv,
125241
125252
  });
125242
125253
  this.process.stdout?.pipe(logStream);
125243
125254
  this.process.stderr?.pipe(logStream);
125244
125255
  await this.waitForServer();
125245
- log("Server ready.");
125256
+ log$1("Server ready.");
125246
125257
  };
125247
125258
  stop = async () => {
125248
125259
  if (IS_STAGING_ENV || !this.process)
125249
125260
  return;
125250
125261
  const pid = this.process.pid;
125251
- log("Stopping server...");
125262
+ log$1("Stopping server...");
125252
125263
  this.process.kill("SIGTERM");
125253
125264
  this.process = null;
125254
125265
  if (pid) {
@@ -125257,6 +125268,238 @@ class NeetoAuthServer {
125257
125268
  };
125258
125269
  }
125259
125270
 
125271
+ const CONFIG = {
125272
+ DIR: "/tmp/neeto-chat-widget",
125273
+ LOG: "/tmp/neeto-chat-widget.log",
125274
+ PORT: 8081,
125275
+ MAX_WAIT_MS: 180_000,
125276
+ LOCK_RETRY_MS: 500,
125277
+ SERVER_POLL_INTERVAL_MS: 3000,
125278
+ WEBPACK_DEV_FILE: "/tmp/neeto-chat-widget/webpack.dev.js",
125279
+ LOCK_DIR: "/tmp/neeto-chat-widget.lock",
125280
+ STATE_FILE: "/tmp/neeto-chat-widget.state.json",
125281
+ };
125282
+ const DEFAULT_STATE = { pid: null, refCount: 0 };
125283
+ const WIDGET_BASE_URL = `http://localhost:${CONFIG.PORT}`;
125284
+ const SCRIPTS_DIR = path$1.join(__dirname, "scripts", "neeto-chat-widget");
125285
+ const log = (msg) => console.log(`[NeetoChatWidget] ${msg}`);
125286
+ const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
125287
+ const httpCheck = (timeout = 3000) => new Promise(resolve => {
125288
+ const req = http.get(`${WIDGET_BASE_URL}/main.js`, () => resolve(true));
125289
+ req.on("error", () => resolve(false));
125290
+ req.setTimeout(timeout, () => {
125291
+ req.destroy();
125292
+ resolve(false);
125293
+ });
125294
+ });
125295
+ class NeetoChatWidget {
125296
+ process = null;
125297
+ hasLease = false;
125298
+ logStream = null;
125299
+ get serverEnv() {
125300
+ return { ...process.env };
125301
+ }
125302
+ withLock = async (fn) => {
125303
+ while (true) {
125304
+ try {
125305
+ mkdirSync(CONFIG.LOCK_DIR);
125306
+ break;
125307
+ }
125308
+ catch (error) {
125309
+ const nodeError = error;
125310
+ if (nodeError.code !== "EEXIST")
125311
+ throw error;
125312
+ await sleep(CONFIG.LOCK_RETRY_MS);
125313
+ }
125314
+ }
125315
+ try {
125316
+ return await Promise.resolve(fn());
125317
+ }
125318
+ finally {
125319
+ rmSync(CONFIG.LOCK_DIR, { force: true, recursive: true });
125320
+ }
125321
+ };
125322
+ parseState = (raw) => {
125323
+ if (!raw || typeof raw !== "object")
125324
+ return DEFAULT_STATE;
125325
+ const state = raw;
125326
+ const pid = typeof state.pid === "number" ? state.pid : null;
125327
+ const refCount = typeof state.refCount === "number" && state.refCount > 0
125328
+ ? state.refCount
125329
+ : 0;
125330
+ return { pid, refCount };
125331
+ };
125332
+ readState = () => {
125333
+ if (!existsSync(CONFIG.STATE_FILE))
125334
+ return DEFAULT_STATE;
125335
+ try {
125336
+ return this.parseState(JSON.parse(readFileSync(CONFIG.STATE_FILE, "utf-8")));
125337
+ }
125338
+ catch {
125339
+ return DEFAULT_STATE;
125340
+ }
125341
+ };
125342
+ writeState = (state) => {
125343
+ writeFileSync(CONFIG.STATE_FILE, JSON.stringify(state));
125344
+ };
125345
+ clearState = () => {
125346
+ existsSync(CONFIG.STATE_FILE) && rmSync(CONFIG.STATE_FILE, { force: true });
125347
+ };
125348
+ getLogContent = () => existsSync(CONFIG.LOG)
125349
+ ? readFileSync(CONFIG.LOG, "utf-8")
125350
+ : "<no log file>";
125351
+ ensureSetup = () => {
125352
+ if (existsSync(CONFIG.WEBPACK_DEV_FILE)) {
125353
+ this.patchWebpackPublicPath();
125354
+ log("Already set up, skipping.");
125355
+ return;
125356
+ }
125357
+ existsSync(CONFIG.DIR) &&
125358
+ rmSync(CONFIG.DIR, { force: true, recursive: true });
125359
+ const setupScript = path$1.join(SCRIPTS_DIR, "setup.sh");
125360
+ log("Running first-time setup...");
125361
+ try {
125362
+ execSync(`bash "${setupScript}" "${CONFIG.DIR}"`, {
125363
+ stdio: "inherit",
125364
+ env: this.serverEnv,
125365
+ });
125366
+ }
125367
+ catch {
125368
+ throw new Error("[NeetoChatWidget] First-time setup failed. Check the output above for details.");
125369
+ }
125370
+ this.patchWebpackPublicPath();
125371
+ log("Setup complete.");
125372
+ };
125373
+ patchWebpackPublicPath = () => {
125374
+ if (!existsSync(CONFIG.WEBPACK_DEV_FILE)) {
125375
+ throw new Error(`[NeetoChatWidget] Missing webpack config at ${CONFIG.WEBPACK_DEV_FILE}`);
125376
+ }
125377
+ const fileContent = readFileSync(CONFIG.WEBPACK_DEV_FILE, "utf-8");
125378
+ const targetPublicPath = `publicPath: "${WIDGET_BASE_URL}/"`;
125379
+ if (fileContent.includes(targetPublicPath))
125380
+ return;
125381
+ const oldConfig = ` devServer: {\n contentBase: "./src",\n allowedHosts: [".lvh.me"],\n },\n`;
125382
+ const newConfig = ` devServer: {\n contentBase: "./src",\n allowedHosts: [".lvh.me"],\n publicPath: "${WIDGET_BASE_URL}/",\n },\n output: {\n publicPath: "${WIDGET_BASE_URL}/",\n },\n`;
125383
+ if (!fileContent.includes(oldConfig)) {
125384
+ throw new Error("[NeetoChatWidget] Unable to patch webpack.dev.js for local widget serving.");
125385
+ }
125386
+ writeFileSync(CONFIG.WEBPACK_DEV_FILE, fileContent.replace(oldConfig, newConfig));
125387
+ };
125388
+ closeLogStream = () => {
125389
+ if (this.logStream) {
125390
+ this.logStream.end();
125391
+ this.logStream = null;
125392
+ }
125393
+ };
125394
+ waitForProcessExit = async (pid) => {
125395
+ const deadline = Date.now() + 10_000;
125396
+ while (Date.now() < deadline) {
125397
+ try {
125398
+ process.kill(pid, 0);
125399
+ await sleep(500);
125400
+ }
125401
+ catch {
125402
+ return;
125403
+ }
125404
+ }
125405
+ };
125406
+ killServer = (pid) => {
125407
+ if (!pid)
125408
+ return;
125409
+ try {
125410
+ process.kill(pid, "SIGTERM");
125411
+ }
125412
+ catch {
125413
+ // process may already be gone
125414
+ }
125415
+ };
125416
+ killProcessOnWidgetPort = async () => {
125417
+ try {
125418
+ execSync(`lsof -ti tcp:${CONFIG.PORT} | xargs kill -9`, {
125419
+ stdio: "ignore",
125420
+ });
125421
+ await sleep(1000);
125422
+ }
125423
+ catch {
125424
+ // No process on that port — nothing to kill.
125425
+ }
125426
+ };
125427
+ waitForServer = async (timeoutMs = CONFIG.MAX_WAIT_MS) => {
125428
+ const startTime = Date.now();
125429
+ while (Date.now() - startTime < timeoutMs) {
125430
+ if (this.process !== null && this.process.exitCode !== null) {
125431
+ throw new Error(`[NeetoChatWidget] Server process exited unexpectedly with code ${this.process.exitCode}.\nLog:\n${this.getLogContent()}`);
125432
+ }
125433
+ if (await httpCheck())
125434
+ return;
125435
+ await sleep(CONFIG.SERVER_POLL_INTERVAL_MS);
125436
+ }
125437
+ throw new Error(`[NeetoChatWidget] Widget did not start within ${timeoutMs / 1000}s.\nLog:\n${this.getLogContent()}`);
125438
+ };
125439
+ start = async () => {
125440
+ if (IS_STAGING_ENV)
125441
+ return;
125442
+ await this.withLock(async () => {
125443
+ const state = this.readState();
125444
+ if (await httpCheck()) {
125445
+ this.hasLease = true;
125446
+ this.writeState({ ...state, refCount: state.refCount + 1 });
125447
+ log("Server already running.");
125448
+ return;
125449
+ }
125450
+ this.ensureSetup();
125451
+ log("Starting server...");
125452
+ this.logStream = createWriteStream(CONFIG.LOG);
125453
+ this.process = spawn("yarn", ["start"], {
125454
+ cwd: CONFIG.DIR,
125455
+ stdio: ["ignore", "pipe", "pipe"],
125456
+ });
125457
+ this.process.stdout?.pipe(this.logStream);
125458
+ this.process.stderr?.pipe(this.logStream);
125459
+ try {
125460
+ await this.waitForServer();
125461
+ }
125462
+ catch (error) {
125463
+ const pid = this.process?.pid;
125464
+ this.killServer(pid);
125465
+ pid && (await this.waitForProcessExit(pid));
125466
+ (await httpCheck()) && (await this.killProcessOnWidgetPort());
125467
+ this.process = null;
125468
+ this.closeLogStream();
125469
+ throw error;
125470
+ }
125471
+ this.hasLease = true;
125472
+ this.writeState({
125473
+ pid: this.process.pid ?? null,
125474
+ refCount: state.refCount + 1,
125475
+ });
125476
+ log("Server ready.");
125477
+ });
125478
+ };
125479
+ stop = async () => {
125480
+ if (IS_STAGING_ENV || !this.hasLease)
125481
+ return;
125482
+ await this.withLock(async () => {
125483
+ const state = this.readState();
125484
+ const nextRefCount = Math.max(state.refCount - 1, 0);
125485
+ this.hasLease = false;
125486
+ if (nextRefCount > 0) {
125487
+ this.writeState({ ...state, refCount: nextRefCount });
125488
+ return;
125489
+ }
125490
+ if (state.pid) {
125491
+ log("Stopping server...");
125492
+ this.killServer(state.pid);
125493
+ await this.waitForProcessExit(state.pid);
125494
+ (await httpCheck()) && (await this.killProcessOnWidgetPort());
125495
+ }
125496
+ this.process = null;
125497
+ this.closeLogStream();
125498
+ this.clearState();
125499
+ });
125500
+ };
125501
+ }
125502
+
125260
125503
  const NEETO_EMAIL_DELIVERY_TESTING_BASE_URL = "/neeto_email_delivery/api/v1/testing";
125261
125504
  class NeetoEmailDeliveryApi {
125262
125505
  neetoPlaywrightUtilities;
@@ -126179,5 +126422,5 @@ const definePlaywrightConfig = (overrides) => {
126179
126422
  });
126180
126423
  };
126181
126424
 
126182
- export { ACTIONS, ADMIN_PANEL_SELECTORS, ALL_RESOURCES, ANALYTICS_RESOURCES, API_KEYS_SELECTORS, API_ROUTES, APP_RESOURCES, AUDIT_LOGS_SELECTORS, ApiKeysApi, ApiKeysPage, AuditLogsPage, BASE_URL, CALENDAR_LABELS, CERTIFICATE_LIMIT_EXCEEDED_MESSAGE, CERTIFICATE_LIMIT_EXCEEDED_REGEXP, CHANGELOG_WIDGET_SELECTORS, CHAT_WIDGET_SELECTORS, CHAT_WIDGET_TEXTS, COLOR, COMMON_SELECTORS, COMMON_TEXTS, COMMUNITY_TEXTS, CREDENTIALS, CURRENT_TIME_RANGES, CUSTOM_DOMAIN_SELECTORS, CUSTOM_DOMAIN_SUFFIX, CustomCommands, CustomDomainApi, CustomDomainPage, DATE_FORMATS, DATE_PICKER_SELECTORS, DATE_RANGES, DATE_TEXTS, DEFAULT_WEBHOOKS_RESPONSE_TEXT, DESCRIPTION_EDITOR_TEXTS, EMBED_SELECTORS, EMOJI_LABEL, EMPTY_STORAGE_STATE, ENGAGE_TEXTS, ENVIRONMENT, EXAMPLE_URL, EXPANDED_FONT_SIZE, EXPORT_FILE_TYPES, EditorPage, EmailDeliveryUtils, EmbedBase, FILE_FORMATS, FONTS_RESOURCES, FONT_SIZE_SELECTORS, FROM_EMAIL_ENV_KEYS, GLOBAL_TRANSLATIONS_PATTERN, GOOGLE_ANALYTICS_SELECTORS, GOOGLE_CALENDAR_DATE_FORMAT, GOOGLE_LOGIN_SELECTORS, GOOGLE_LOGIN_TEXTS, GOOGLE_SHEETS_SELECTORS, GooglePage, HELP_CENTER_ROUTES, HELP_CENTER_SELECTORS, HelpAndProfilePage, INTEGRATIONS_TEXTS, INTEGRATION_SELECTORS, IPRestrictionsPage, IP_RESTRICTIONS_SELECTORS, IS_CI, IS_DEV_ENV, IS_STAGING_ENV, ImageUploader, IntegrationBase, IpRestrictionsApi, KEYBOARD_SHORTCUTS_SELECTORS, KEYBOARD_SHORTCUT_TEST_CASES, LIST_MODIFIER_SELECTORS, LIST_MODIFIER_TAGS, LOGIN_SELECTORS, MEMBER_FORM_SELECTORS, MEMBER_SELECTORS, MEMBER_TEXTS, MERGE_TAGS_SELECTORS, MICROSOFT_LOGIN_SELECTORS, MICROSOFT_LOGIN_TEXTS, MailerUtils, Member, MemberApis, MicrosoftPage, NEETO_AUTH_BASE_URL, NEETO_EDITOR_SELECTORS, NEETO_FILTERS_SELECTORS, NEETO_IMAGE_UPLOADER_SELECTORS, NEETO_ROUTES, NEETO_SEO_SELECTORS, NEETO_TEXT_MODIFIER_SELECTORS, NeetoAuthServer, NeetoEmailDeliveryApi, NeetoTowerApi, ONBOARDING_SELECTORS, ORGANIZATION_TEXTS, OTP_EMAIL_PATTERN, OrganizationPage, PAST_TIME_RANGES, PHONE_NUMBER_FORMATS, PLURAL, PROFILE_LINKS, PROFILE_SECTION_SELECTORS, PROJECT_NAMES, PROJECT_TRANSLATIONS_PATH, ROLES_SELECTORS, ROUTES, RailsEmailApiClient, RailsEmailUtils, RoleApis, RolesPage, SIGNUP_SELECTORS, SINGULAR, SLACK_DATA_QA_SELECTORS, SLACK_DEFAULT_CHANNEL, SLACK_SELECTORS, SLACK_WEB_TEXTS, STATUS_TEXTS, STORAGE_STATE, SecurityApi, SidebarSection, SlackApi, SlackPage, TABLE_SELECTORS, TAB_SELECTORS, TAGS_SELECTORS, TEAM_MEMBER_TEXTS, TEXT_MODIFIER_ROLES, TEXT_MODIFIER_SELECTORS, TEXT_MODIFIER_TAGS, THANK_YOU_SELECTORS, THEMES_SELECTORS, THEMES_TEXTS, THIRD_PARTY_RESOURCES, THIRD_PARTY_ROUTES, TIME_RANGES, TOASTR_MESSAGES, TWILIO_SELECTORS, TagsApi, TagsPage, TeamMembers, ThankYouApi, ThankYouPage, TwilioApi, USER_AGENTS, WEBHOOK_SELECTORS, WebhookSiteApi, WebhooksPage, ZAPIER_LIMIT_EXHAUSTED_MESSAGE, ZAPIER_SELECTORS, ZAPIER_TEST_EMAIL, ZAPIER_WEB_TEXTS, ZapierPage, baseURLGenerator, basicHTMLContent, clearCredentials, commands, cpuThrottlingUsingCDP, createOrganizationViaRake, currencyUtils, dataQa, decodeQRCodeFromFile, definePlaywrightConfig, executeWithThrottledResources, extractSubdomainFromError, fillCredentialsAndSubmit, filterUtils, generatePhoneNumber, generatePhoneNumberDetails, generateRandomBypassEmail, generateRandomFile, generateStagingData, getByDataQA, getClipboardContent, getFormattedPhoneNumber, getFullUrl, getGlobalUserProps, getGlobalUserState, getImagePathAndName, getIsoCodeFromPhoneCode, getListCount, globalShortcuts, grantClipboardPermissions, hexToRGB, hexToRGBA, i18nFixture, imageRegex, initializeCredentials, initializeTestData, initializeTotp, isGithubIssueOpen, joinHyphenCase, joinString, login, loginWithoutSSO, networkConditions, networkThrottlingUsingCDP, readFileSyncIfExists, removeCredentialFile, serializeFileForBrowser, shouldSkipCustomDomainSetup, shouldSkipSetupAndTeardown, simulateClickWithDelay, simulateTypingWithDelay, skipTest, squish, stealth as stealthTest, tableUtils, toCamelCase, updateCredentials, warmup, writeDataToFile };
126425
+ export { ACTIONS, ADMIN_PANEL_SELECTORS, ALL_RESOURCES, ANALYTICS_RESOURCES, API_KEYS_SELECTORS, API_ROUTES, APP_RESOURCES, AUDIT_LOGS_SELECTORS, ApiKeysApi, ApiKeysPage, AuditLogsPage, BASE_URL, CALENDAR_LABELS, CERTIFICATE_LIMIT_EXCEEDED_MESSAGE, CERTIFICATE_LIMIT_EXCEEDED_REGEXP, CHANGELOG_WIDGET_SELECTORS, CHAT_WIDGET_SELECTORS, CHAT_WIDGET_TEXTS, COLOR, COMMON_SELECTORS, COMMON_TEXTS, COMMUNITY_TEXTS, CREDENTIALS, CURRENT_TIME_RANGES, CUSTOM_DOMAIN_SELECTORS, CUSTOM_DOMAIN_SUFFIX, ColorPickerUtils, CustomCommands, CustomDomainApi, CustomDomainPage, DATE_FORMATS, DATE_PICKER_SELECTORS, DATE_RANGES, DATE_TEXTS, DEFAULT_WEBHOOKS_RESPONSE_TEXT, DESCRIPTION_EDITOR_TEXTS, EMBED_SELECTORS, EMOJI_LABEL, EMPTY_STORAGE_STATE, ENGAGE_TEXTS, ENVIRONMENT, EXAMPLE_URL, EXPANDED_FONT_SIZE, EXPORT_FILE_TYPES, EditorPage, EmailDeliveryUtils, EmbedBase, FILE_FORMATS, FONTS_RESOURCES, FONT_SIZE_SELECTORS, FROM_EMAIL_ENV_KEYS, GLOBAL_TRANSLATIONS_PATTERN, GOOGLE_ANALYTICS_SELECTORS, GOOGLE_CALENDAR_DATE_FORMAT, GOOGLE_LOGIN_SELECTORS, GOOGLE_LOGIN_TEXTS, GOOGLE_SHEETS_SELECTORS, GooglePage, HELP_CENTER_ROUTES, HELP_CENTER_SELECTORS, HelpAndProfilePage, INTEGRATIONS_TEXTS, INTEGRATION_SELECTORS, IPRestrictionsPage, IP_RESTRICTIONS_SELECTORS, IS_CI, IS_DEV_ENV, IS_STAGING_ENV, ImageUploader, IntegrationBase, IpRestrictionsApi, KEYBOARD_SHORTCUTS_SELECTORS, KEYBOARD_SHORTCUT_TEST_CASES, LIST_MODIFIER_SELECTORS, LIST_MODIFIER_TAGS, LOGIN_SELECTORS, MEMBER_FORM_SELECTORS, MEMBER_SELECTORS, MEMBER_TEXTS, MERGE_TAGS_SELECTORS, MICROSOFT_LOGIN_SELECTORS, MICROSOFT_LOGIN_TEXTS, MailerUtils, Member, MemberApis, MicrosoftPage, NEETO_AUTH_BASE_URL, NEETO_EDITOR_SELECTORS, NEETO_FILTERS_SELECTORS, NEETO_IMAGE_UPLOADER_SELECTORS, NEETO_ROUTES, NEETO_SEO_SELECTORS, NEETO_TEXT_MODIFIER_SELECTORS, NeetoAuthServer, NeetoChatWidget, NeetoEmailDeliveryApi, NeetoTowerApi, ONBOARDING_SELECTORS, ORGANIZATION_TEXTS, OTP_EMAIL_PATTERN, OrganizationPage, PAST_TIME_RANGES, PHONE_NUMBER_FORMATS, PLURAL, PROFILE_LINKS, PROFILE_SECTION_SELECTORS, PROJECT_NAMES, PROJECT_TRANSLATIONS_PATH, ROLES_SELECTORS, ROUTES, RailsEmailApiClient, RailsEmailUtils, RoleApis, RolesPage, SIGNUP_SELECTORS, SINGULAR, SLACK_DATA_QA_SELECTORS, SLACK_DEFAULT_CHANNEL, SLACK_SELECTORS, SLACK_WEB_TEXTS, STATUS_TEXTS, STORAGE_STATE, SecurityApi, SidebarSection, SlackApi, SlackPage, TABLE_SELECTORS, TAB_SELECTORS, TAGS_SELECTORS, TEAM_MEMBER_TEXTS, TEXT_MODIFIER_ROLES, TEXT_MODIFIER_SELECTORS, TEXT_MODIFIER_TAGS, THANK_YOU_SELECTORS, THEMES_SELECTORS, THEMES_TEXTS, THIRD_PARTY_RESOURCES, THIRD_PARTY_ROUTES, TIME_RANGES, TOASTR_MESSAGES, TWILIO_SELECTORS, TagsApi, TagsPage, TeamMembers, ThankYouApi, ThankYouPage, TwilioApi, USER_AGENTS, WEBHOOK_SELECTORS, WebhookSiteApi, WebhooksPage, ZAPIER_LIMIT_EXHAUSTED_MESSAGE, ZAPIER_SELECTORS, ZAPIER_TEST_EMAIL, ZAPIER_WEB_TEXTS, ZapierPage, baseURLGenerator, basicHTMLContent, clearCredentials, commands, cpuThrottlingUsingCDP, createOrganizationViaRake, currencyUtils, dataQa, decodeQRCodeFromFile, definePlaywrightConfig, executeWithThrottledResources, extractSubdomainFromError, fillCredentialsAndSubmit, filterUtils, generatePhoneNumber, generatePhoneNumberDetails, generateRandomBypassEmail, generateRandomFile, generateStagingData, getByDataQA, getClipboardContent, getFormattedPhoneNumber, getFullUrl, getGlobalUserProps, getGlobalUserState, getImagePathAndName, getIsoCodeFromPhoneCode, getListCount, globalShortcuts, grantClipboardPermissions, hexToRGB, hexToRGBA, i18nFixture, imageRegex, initializeCredentials, initializeTestData, initializeTotp, isGithubIssueOpen, joinHyphenCase, joinString, login, loginWithoutSSO, networkConditions, networkThrottlingUsingCDP, readFileSyncIfExists, removeCredentialFile, serializeFileForBrowser, shouldSkipCustomDomainSetup, shouldSkipSetupAndTeardown, simulateClickWithDelay, simulateTypingWithDelay, skipTest, squish, stealth as stealthTest, tableUtils, toCamelCase, updateCredentials, warmup, writeDataToFile };
126183
126426
  //# sourceMappingURL=index.js.map