@bigbinary/neeto-playwright-commons 3.0.8 → 3.1.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
@@ -8960,6 +8960,27 @@ declare class NeetoAuthServer {
8960
8960
  start: () => Promise<void>;
8961
8961
  stop: () => Promise<void>;
8962
8962
  }
8963
+ declare class NeetoChatWidget {
8964
+ private process;
8965
+ private hasLease;
8966
+ private logStream;
8967
+ private get serverEnv();
8968
+ private withLock;
8969
+ private parseState;
8970
+ private readState;
8971
+ private writeState;
8972
+ private clearState;
8973
+ private getLogContent;
8974
+ private ensureSetup;
8975
+ private patchWebpackPublicPath;
8976
+ private closeLogStream;
8977
+ private waitForProcessExit;
8978
+ private killServer;
8979
+ private killProcessOnWidgetPort;
8980
+ private waitForServer;
8981
+ start: () => Promise<void>;
8982
+ stop: () => Promise<void>;
8983
+ }
8963
8984
  type EmailDeliveryProvider = "gmail" | "outlook" | "sparkpost";
8964
8985
  type OAuthEmailDeliveryProvider = Exclude<EmailDeliveryProvider, "sparkpost">;
8965
8986
  type EmailDeliveryConnectParams = {
@@ -9094,5 +9115,5 @@ interface Overrides {
9094
9115
  * @endexample
9095
9116
  */
9096
9117
  declare const definePlaywrightConfig: (overrides: Overrides) => PlaywrightTestConfig<{}, {}>;
9097
- 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, _default as stealthTest, tableUtils, toCamelCase, updateCredentials, warmup, writeDataToFile };
9118
+ 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, _default as stealthTest, tableUtils, toCamelCase, updateCredentials, warmup, writeDataToFile };
9098
9119
  export type { BaseThemeStyle, BaseThemeStyleType, ColumnMenuAction, CountryProps, CustomFixture, EmailDeliveryConnectParams, EmailDeliveryProvider, EmailDeliveryVerifiedEmail, EmailDeliveryVerifyEmailParams, EmailDeliveryVerifyEmailResponse, EmailMatchCriteria, IntroPageThemeStyle, IntroPageThemeStyleType, OAuthEmailDeliveryProvider, ProjectName, ThemeCategory, ValueOf };
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';
@@ -125103,22 +125103,22 @@ async function warmup({ urls = DEFAULT_WARMUP_URLS, timeout = 60_000, } = {}) {
125103
125103
  }
125104
125104
  }
125105
125105
 
125106
- const CONFIG = {
125106
+ const CONFIG$1 = {
125107
125107
  DIR: "/tmp/neeto-auth-web",
125108
125108
  LOG: "/tmp/neeto-auth-server.log",
125109
125109
  PORT: 9000,
125110
125110
  MAX_WAIT_MS: 120_000,
125111
125111
  EMAIL_INIT: "/tmp/neeto-auth-web/config/initializers/playwright_email_capture.rb",
125112
125112
  };
125113
- const SCRIPTS_DIR = path$1.join(__dirname, "scripts", "neeto-auth");
125113
+ const SCRIPTS_DIR$1 = path$1.join(__dirname, "scripts", "neeto-auth");
125114
125114
  const escapeRubyString = (value) => value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
125115
125115
  const buildEmailCaptureInitializer = (targetApp) => {
125116
- const template = fs$4.readFileSync(path$1.join(SCRIPTS_DIR, "playwright_email_capture.rb.template"), "utf-8");
125116
+ const template = fs$4.readFileSync(path$1.join(SCRIPTS_DIR$1, "playwright_email_capture.rb.template"), "utf-8");
125117
125117
  return template.replace("{{TARGET_APP}}", escapeRubyString(targetApp));
125118
125118
  };
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 => {
125119
+ const log$1 = (msg) => console.log(`[NeetoAuth] ${msg}`);
125120
+ const sleep$1 = (ms) => new Promise(resolve => setTimeout(resolve, ms));
125121
+ const httpCheck$1 = (port, timeout = 3000) => new Promise(resolve => {
125122
125122
  const req = http.get(`http://localhost:${port}/`, () => resolve(true));
125123
125123
  req.on("error", () => resolve(false));
125124
125124
  req.setTimeout(timeout, () => {
@@ -125145,7 +125145,7 @@ class NeetoAuthServer {
125145
125145
  while (Date.now() < deadline) {
125146
125146
  try {
125147
125147
  process.kill(pid, 0);
125148
- await sleep(500);
125148
+ await sleep$1(500);
125149
125149
  }
125150
125150
  catch {
125151
125151
  return;
@@ -125154,27 +125154,27 @@ class NeetoAuthServer {
125154
125154
  };
125155
125155
  killServerOnPort = async () => {
125156
125156
  try {
125157
- execSync(`lsof -ti tcp:${CONFIG.PORT} | xargs kill -9`, {
125157
+ execSync(`lsof -ti tcp:${CONFIG$1.PORT} | xargs kill -9`, {
125158
125158
  stdio: "ignore",
125159
125159
  });
125160
- await sleep(1000);
125160
+ await sleep$1(1000);
125161
125161
  }
125162
125162
  catch {
125163
125163
  // No process on that port — nothing to kill.
125164
125164
  }
125165
125165
  };
125166
125166
  ensureSetup = () => {
125167
- if (fs$4.existsSync(`${CONFIG.DIR}/Gemfile`)) {
125168
- log("Already set up, skipping.");
125167
+ if (fs$4.existsSync(`${CONFIG$1.DIR}/Gemfile`)) {
125168
+ log$1("Already set up, skipping.");
125169
125169
  return;
125170
125170
  }
125171
125171
  if (!process.env.GITHUB_TOKEN) {
125172
125172
  throw new Error("[NeetoAuth] GITHUB_TOKEN is not set. Cannot clone neeto-auth-web.");
125173
125173
  }
125174
- log("Running first-time setup...");
125175
- const setupScript = path$1.join(SCRIPTS_DIR, "setup.sh");
125174
+ log$1("Running first-time setup...");
125175
+ const setupScript = path$1.join(SCRIPTS_DIR$1, "setup.sh");
125176
125176
  try {
125177
- execSync(`bash "${setupScript}" "${CONFIG.DIR}"`, {
125177
+ execSync(`bash "${setupScript}" "${CONFIG$1.DIR}"`, {
125178
125178
  stdio: "inherit",
125179
125179
  env: this.serverEnv,
125180
125180
  });
@@ -125182,73 +125182,73 @@ class NeetoAuthServer {
125182
125182
  catch {
125183
125183
  throw new Error("[NeetoAuth] First-time setup failed. Check the output above for details.");
125184
125184
  }
125185
- log("Setup complete.");
125185
+ log$1("Setup complete.");
125186
125186
  };
125187
- waitForServer = async (timeoutMs = CONFIG.MAX_WAIT_MS) => {
125187
+ waitForServer = async (timeoutMs = CONFIG$1.MAX_WAIT_MS) => {
125188
125188
  const startTime = Date.now();
125189
125189
  while (Date.now() - startTime < timeoutMs) {
125190
125190
  if (this.process !== null && this.process.exitCode !== null) {
125191
- const logContent = fs$4.existsSync(CONFIG.LOG)
125192
- ? fs$4.readFileSync(CONFIG.LOG, "utf-8")
125191
+ const logContent = fs$4.existsSync(CONFIG$1.LOG)
125192
+ ? fs$4.readFileSync(CONFIG$1.LOG, "utf-8")
125193
125193
  : "<no log file>";
125194
125194
  throw new Error(`[NeetoAuth] Server process exited unexpectedly with code ${this.process.exitCode}.\nLog:\n${logContent}`);
125195
125195
  }
125196
- if (await httpCheck(CONFIG.PORT))
125196
+ if (await httpCheck$1(CONFIG$1.PORT))
125197
125197
  return;
125198
- await sleep(3000);
125198
+ await sleep$1(3000);
125199
125199
  }
125200
- const logContent = fs$4.existsSync(CONFIG.LOG)
125201
- ? fs$4.readFileSync(CONFIG.LOG, "utf-8")
125200
+ const logContent = fs$4.existsSync(CONFIG$1.LOG)
125201
+ ? fs$4.readFileSync(CONFIG$1.LOG, "utf-8")
125202
125202
  : "<no log file>";
125203
125203
  throw new Error(`[NeetoAuth] Server did not start within ${timeoutMs / 1000}s.\nLog:\n${logContent}`);
125204
125204
  };
125205
125205
  injectEmailCaptureInitializer = () => {
125206
- fs$4.writeFileSync(CONFIG.EMAIL_INIT, buildEmailCaptureInitializer(this.targetApp));
125206
+ fs$4.writeFileSync(CONFIG$1.EMAIL_INIT, buildEmailCaptureInitializer(this.targetApp));
125207
125207
  };
125208
125208
  isRunningForCurrentApp = () => {
125209
- if (!fs$4.existsSync(CONFIG.EMAIL_INIT))
125209
+ if (!fs$4.existsSync(CONFIG$1.EMAIL_INIT))
125210
125210
  return false;
125211
- const currentContent = fs$4.readFileSync(CONFIG.EMAIL_INIT, "utf-8");
125211
+ const currentContent = fs$4.readFileSync(CONFIG$1.EMAIL_INIT, "utf-8");
125212
125212
  return currentContent === buildEmailCaptureInitializer(this.targetApp);
125213
125213
  };
125214
125214
  start = async () => {
125215
125215
  if (IS_STAGING_ENV)
125216
125216
  return;
125217
- if (await httpCheck(CONFIG.PORT)) {
125217
+ if (await httpCheck$1(CONFIG$1.PORT)) {
125218
125218
  if (this.isRunningForCurrentApp()) {
125219
- log("Server already running for this app.");
125219
+ log$1("Server already running for this app.");
125220
125220
  return;
125221
125221
  }
125222
- log("Server running for a different app — restarting...");
125222
+ log$1("Server running for a different app — restarting...");
125223
125223
  await this.killServerOnPort();
125224
125224
  }
125225
125225
  this.ensureSetup();
125226
125226
  this.injectEmailCaptureInitializer();
125227
- log("Starting server...");
125228
- const logStream = fs$4.createWriteStream(CONFIG.LOG);
125227
+ log$1("Starting server...");
125228
+ const logStream = fs$4.createWriteStream(CONFIG$1.LOG);
125229
125229
  this.process = spawn("bundle", [
125230
125230
  "exec",
125231
125231
  "rails",
125232
125232
  "server",
125233
125233
  "-p",
125234
- CONFIG.PORT.toString(),
125234
+ CONFIG$1.PORT.toString(),
125235
125235
  "-b",
125236
125236
  "0.0.0.0",
125237
125237
  ], {
125238
- cwd: CONFIG.DIR,
125238
+ cwd: CONFIG$1.DIR,
125239
125239
  stdio: ["ignore", "pipe", "pipe"],
125240
125240
  env: this.serverEnv,
125241
125241
  });
125242
125242
  this.process.stdout?.pipe(logStream);
125243
125243
  this.process.stderr?.pipe(logStream);
125244
125244
  await this.waitForServer();
125245
- log("Server ready.");
125245
+ log$1("Server ready.");
125246
125246
  };
125247
125247
  stop = async () => {
125248
125248
  if (IS_STAGING_ENV || !this.process)
125249
125249
  return;
125250
125250
  const pid = this.process.pid;
125251
- log("Stopping server...");
125251
+ log$1("Stopping server...");
125252
125252
  this.process.kill("SIGTERM");
125253
125253
  this.process = null;
125254
125254
  if (pid) {
@@ -125257,6 +125257,238 @@ class NeetoAuthServer {
125257
125257
  };
125258
125258
  }
125259
125259
 
125260
+ const CONFIG = {
125261
+ DIR: "/tmp/neeto-chat-widget",
125262
+ LOG: "/tmp/neeto-chat-widget.log",
125263
+ PORT: 8081,
125264
+ MAX_WAIT_MS: 180_000,
125265
+ LOCK_RETRY_MS: 500,
125266
+ SERVER_POLL_INTERVAL_MS: 3000,
125267
+ WEBPACK_DEV_FILE: "/tmp/neeto-chat-widget/webpack.dev.js",
125268
+ LOCK_DIR: "/tmp/neeto-chat-widget.lock",
125269
+ STATE_FILE: "/tmp/neeto-chat-widget.state.json",
125270
+ };
125271
+ const DEFAULT_STATE = { pid: null, refCount: 0 };
125272
+ const WIDGET_BASE_URL = `http://localhost:${CONFIG.PORT}`;
125273
+ const SCRIPTS_DIR = path$1.join(__dirname, "scripts", "neeto-chat-widget");
125274
+ const log = (msg) => console.log(`[NeetoChatWidget] ${msg}`);
125275
+ const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
125276
+ const httpCheck = (timeout = 3000) => new Promise(resolve => {
125277
+ const req = http.get(`${WIDGET_BASE_URL}/main.js`, () => resolve(true));
125278
+ req.on("error", () => resolve(false));
125279
+ req.setTimeout(timeout, () => {
125280
+ req.destroy();
125281
+ resolve(false);
125282
+ });
125283
+ });
125284
+ class NeetoChatWidget {
125285
+ process = null;
125286
+ hasLease = false;
125287
+ logStream = null;
125288
+ get serverEnv() {
125289
+ return { ...process.env };
125290
+ }
125291
+ withLock = async (fn) => {
125292
+ while (true) {
125293
+ try {
125294
+ mkdirSync(CONFIG.LOCK_DIR);
125295
+ break;
125296
+ }
125297
+ catch (error) {
125298
+ const nodeError = error;
125299
+ if (nodeError.code !== "EEXIST")
125300
+ throw error;
125301
+ await sleep(CONFIG.LOCK_RETRY_MS);
125302
+ }
125303
+ }
125304
+ try {
125305
+ return await Promise.resolve(fn());
125306
+ }
125307
+ finally {
125308
+ rmSync(CONFIG.LOCK_DIR, { force: true, recursive: true });
125309
+ }
125310
+ };
125311
+ parseState = (raw) => {
125312
+ if (!raw || typeof raw !== "object")
125313
+ return DEFAULT_STATE;
125314
+ const state = raw;
125315
+ const pid = typeof state.pid === "number" ? state.pid : null;
125316
+ const refCount = typeof state.refCount === "number" && state.refCount > 0
125317
+ ? state.refCount
125318
+ : 0;
125319
+ return { pid, refCount };
125320
+ };
125321
+ readState = () => {
125322
+ if (!existsSync(CONFIG.STATE_FILE))
125323
+ return DEFAULT_STATE;
125324
+ try {
125325
+ return this.parseState(JSON.parse(readFileSync(CONFIG.STATE_FILE, "utf-8")));
125326
+ }
125327
+ catch {
125328
+ return DEFAULT_STATE;
125329
+ }
125330
+ };
125331
+ writeState = (state) => {
125332
+ writeFileSync(CONFIG.STATE_FILE, JSON.stringify(state));
125333
+ };
125334
+ clearState = () => {
125335
+ existsSync(CONFIG.STATE_FILE) && rmSync(CONFIG.STATE_FILE, { force: true });
125336
+ };
125337
+ getLogContent = () => existsSync(CONFIG.LOG)
125338
+ ? readFileSync(CONFIG.LOG, "utf-8")
125339
+ : "<no log file>";
125340
+ ensureSetup = () => {
125341
+ if (existsSync(CONFIG.WEBPACK_DEV_FILE)) {
125342
+ this.patchWebpackPublicPath();
125343
+ log("Already set up, skipping.");
125344
+ return;
125345
+ }
125346
+ existsSync(CONFIG.DIR) &&
125347
+ rmSync(CONFIG.DIR, { force: true, recursive: true });
125348
+ const setupScript = path$1.join(SCRIPTS_DIR, "setup.sh");
125349
+ log("Running first-time setup...");
125350
+ try {
125351
+ execSync(`bash "${setupScript}" "${CONFIG.DIR}"`, {
125352
+ stdio: "inherit",
125353
+ env: this.serverEnv,
125354
+ });
125355
+ }
125356
+ catch {
125357
+ throw new Error("[NeetoChatWidget] First-time setup failed. Check the output above for details.");
125358
+ }
125359
+ this.patchWebpackPublicPath();
125360
+ log("Setup complete.");
125361
+ };
125362
+ patchWebpackPublicPath = () => {
125363
+ if (!existsSync(CONFIG.WEBPACK_DEV_FILE)) {
125364
+ throw new Error(`[NeetoChatWidget] Missing webpack config at ${CONFIG.WEBPACK_DEV_FILE}`);
125365
+ }
125366
+ const fileContent = readFileSync(CONFIG.WEBPACK_DEV_FILE, "utf-8");
125367
+ const targetPublicPath = `publicPath: "${WIDGET_BASE_URL}/"`;
125368
+ if (fileContent.includes(targetPublicPath))
125369
+ return;
125370
+ const oldConfig = ` devServer: {\n contentBase: "./src",\n allowedHosts: [".lvh.me"],\n },\n`;
125371
+ 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`;
125372
+ if (!fileContent.includes(oldConfig)) {
125373
+ throw new Error("[NeetoChatWidget] Unable to patch webpack.dev.js for local widget serving.");
125374
+ }
125375
+ writeFileSync(CONFIG.WEBPACK_DEV_FILE, fileContent.replace(oldConfig, newConfig));
125376
+ };
125377
+ closeLogStream = () => {
125378
+ if (this.logStream) {
125379
+ this.logStream.end();
125380
+ this.logStream = null;
125381
+ }
125382
+ };
125383
+ waitForProcessExit = async (pid) => {
125384
+ const deadline = Date.now() + 10_000;
125385
+ while (Date.now() < deadline) {
125386
+ try {
125387
+ process.kill(pid, 0);
125388
+ await sleep(500);
125389
+ }
125390
+ catch {
125391
+ return;
125392
+ }
125393
+ }
125394
+ };
125395
+ killServer = (pid) => {
125396
+ if (!pid)
125397
+ return;
125398
+ try {
125399
+ process.kill(pid, "SIGTERM");
125400
+ }
125401
+ catch {
125402
+ // process may already be gone
125403
+ }
125404
+ };
125405
+ killProcessOnWidgetPort = async () => {
125406
+ try {
125407
+ execSync(`lsof -ti tcp:${CONFIG.PORT} | xargs kill -9`, {
125408
+ stdio: "ignore",
125409
+ });
125410
+ await sleep(1000);
125411
+ }
125412
+ catch {
125413
+ // No process on that port — nothing to kill.
125414
+ }
125415
+ };
125416
+ waitForServer = async (timeoutMs = CONFIG.MAX_WAIT_MS) => {
125417
+ const startTime = Date.now();
125418
+ while (Date.now() - startTime < timeoutMs) {
125419
+ if (this.process !== null && this.process.exitCode !== null) {
125420
+ throw new Error(`[NeetoChatWidget] Server process exited unexpectedly with code ${this.process.exitCode}.\nLog:\n${this.getLogContent()}`);
125421
+ }
125422
+ if (await httpCheck())
125423
+ return;
125424
+ await sleep(CONFIG.SERVER_POLL_INTERVAL_MS);
125425
+ }
125426
+ throw new Error(`[NeetoChatWidget] Widget did not start within ${timeoutMs / 1000}s.\nLog:\n${this.getLogContent()}`);
125427
+ };
125428
+ start = async () => {
125429
+ if (IS_STAGING_ENV)
125430
+ return;
125431
+ await this.withLock(async () => {
125432
+ const state = this.readState();
125433
+ if (await httpCheck()) {
125434
+ this.hasLease = true;
125435
+ this.writeState({ ...state, refCount: state.refCount + 1 });
125436
+ log("Server already running.");
125437
+ return;
125438
+ }
125439
+ this.ensureSetup();
125440
+ log("Starting server...");
125441
+ this.logStream = createWriteStream(CONFIG.LOG);
125442
+ this.process = spawn("yarn", ["start"], {
125443
+ cwd: CONFIG.DIR,
125444
+ stdio: ["ignore", "pipe", "pipe"],
125445
+ });
125446
+ this.process.stdout?.pipe(this.logStream);
125447
+ this.process.stderr?.pipe(this.logStream);
125448
+ try {
125449
+ await this.waitForServer();
125450
+ }
125451
+ catch (error) {
125452
+ const pid = this.process?.pid;
125453
+ this.killServer(pid);
125454
+ pid && (await this.waitForProcessExit(pid));
125455
+ (await httpCheck()) && (await this.killProcessOnWidgetPort());
125456
+ this.process = null;
125457
+ this.closeLogStream();
125458
+ throw error;
125459
+ }
125460
+ this.hasLease = true;
125461
+ this.writeState({
125462
+ pid: this.process.pid ?? null,
125463
+ refCount: state.refCount + 1,
125464
+ });
125465
+ log("Server ready.");
125466
+ });
125467
+ };
125468
+ stop = async () => {
125469
+ if (IS_STAGING_ENV || !this.hasLease)
125470
+ return;
125471
+ await this.withLock(async () => {
125472
+ const state = this.readState();
125473
+ const nextRefCount = Math.max(state.refCount - 1, 0);
125474
+ this.hasLease = false;
125475
+ if (nextRefCount > 0) {
125476
+ this.writeState({ ...state, refCount: nextRefCount });
125477
+ return;
125478
+ }
125479
+ if (state.pid) {
125480
+ log("Stopping server...");
125481
+ this.killServer(state.pid);
125482
+ await this.waitForProcessExit(state.pid);
125483
+ (await httpCheck()) && (await this.killProcessOnWidgetPort());
125484
+ }
125485
+ this.process = null;
125486
+ this.closeLogStream();
125487
+ this.clearState();
125488
+ });
125489
+ };
125490
+ }
125491
+
125260
125492
  const NEETO_EMAIL_DELIVERY_TESTING_BASE_URL = "/neeto_email_delivery/api/v1/testing";
125261
125493
  class NeetoEmailDeliveryApi {
125262
125494
  neetoPlaywrightUtilities;
@@ -126179,5 +126411,5 @@ const definePlaywrightConfig = (overrides) => {
126179
126411
  });
126180
126412
  };
126181
126413
 
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 };
126414
+ 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
126415
  //# sourceMappingURL=index.js.map