@bigbinary/neeto-playwright-commons 3.3.13 → 4.0.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
@@ -4,16 +4,16 @@ import * as fs from 'fs';
4
4
  import fs__default, { readFileSync, promises, existsSync, writeFileSync, unlinkSync, mkdirSync, rmSync, createWriteStream } from 'fs';
5
5
  import os from 'os';
6
6
  import * as path from 'path';
7
- import path__default from 'path';
8
- import test, { expect, test as test$1, chromium as chromium$1, defineConfig, devices } from '@playwright/test';
7
+ import path__default, { dirname } from 'path';
8
+ import test, { expect, test as test$1, chromium, defineConfig, devices } from '@playwright/test';
9
9
  import { getI18nInstance, initI18n } from 'playwright-i18next-fixture';
10
10
  import { curry, isNotNil, not, isEmpty, pluck, mergeAll, isNil, mergeDeepLeft } from 'ramda';
11
11
  import { execSync, spawn } from 'child_process';
12
+ import require$$2$2, { fileURLToPath } from 'url';
12
13
  import dayjs from 'dayjs';
13
14
  import require$$1$3 from 'events';
14
15
  import require$$0$5 from 'assert';
15
16
  import require$$0$4 from 'util';
16
- import require$$2$2 from 'url';
17
17
  import require$$1$2 from 'tty';
18
18
  import require$$0$6 from 'stream';
19
19
  import require$$0$7 from 'crypto';
@@ -25,11 +25,12 @@ import require$$1$5 from 'string_decoder';
25
25
  import require$$0$b from 'node:buffer';
26
26
  import require$$1$6 from 'node:stream';
27
27
  import require$$1$7 from 'zlib';
28
+ import { addExtra } from 'playwright-extra';
28
29
  import stealth$1 from 'puppeteer-extra-plugin-stealth';
29
30
  import { globSync } from 'node:fs';
30
- import customParseFormat from 'dayjs/plugin/customParseFormat';
31
- import timezone from 'dayjs/plugin/timezone';
32
- import utc from 'dayjs/plugin/utc';
31
+ import customParseFormat from 'dayjs/plugin/customParseFormat.js';
32
+ import timezone from 'dayjs/plugin/timezone.js';
33
+ import utc from 'dayjs/plugin/utc.js';
33
34
  import https from 'https';
34
35
  import * as http from 'http';
35
36
 
@@ -1150,6 +1151,7 @@ const readFileSyncIfExists = (path = STORAGE_STATE) => {
1150
1151
  return {};
1151
1152
  }
1152
1153
  };
1154
+ const getDirname = (metaUrl) => dirname(fileURLToPath(metaUrl));
1153
1155
  const getGlobalUserState = () => readFileSyncIfExists()?.user;
1154
1156
  const writeDataToFile = data => {
1155
1157
  try {
@@ -1979,12 +1981,14 @@ const generateRandomFile = ({ sizeInKB, fileType, fileName = `sample.${fileType}
1979
1981
  return { file, fileName };
1980
1982
  };
1981
1983
 
1984
+ const __dirname$6 = getDirname(import.meta.url);
1982
1985
  const getImagePathAndName = (localImagePath) => {
1983
- const imagePath = path__default.join(__dirname, localImagePath);
1986
+ const imagePath = path__default.join(__dirname$6, localImagePath);
1984
1987
  const imageName = path__default.basename(localImagePath, path__default.extname(localImagePath));
1985
1988
  return { imagePath, imageName };
1986
1989
  };
1987
1990
 
1991
+ const __dirname$5 = getDirname(import.meta.url);
1988
1992
  class CustomCommands {
1989
1993
  page;
1990
1994
  t;
@@ -2157,7 +2161,7 @@ class CustomCommands {
2157
2161
  await expect(this.page.getByTestId(NEETO_IMAGE_UPLOADER_SELECTORS.uploadedImage)).toHaveAttribute("src", new RegExp(imageName), { timeout: 20_000 });
2158
2162
  };
2159
2163
  uploadFileViaDispatch = async ({ fileNameWithType, assetsPath = "../../../e2e/assets/", dispatchEvent = "drop", droppableZone = this.page.getByTestId(COMMON_SELECTORS.fileUploadBody), }) => {
2160
- const filePath = path__default.join(__dirname, `${assetsPath}/${fileNameWithType}`);
2164
+ const filePath = path__default.join(__dirname$5, `${assetsPath}/${fileNameWithType}`);
2161
2165
  const buffer = readFileSync(filePath).toString("base64");
2162
2166
  const dataTransfer = await droppableZone.evaluateHandle((_, { buffer, fileNameWithType }) => {
2163
2167
  const dataTransfer = new DataTransfer();
@@ -4685,7 +4689,7 @@ var dbsize = {
4685
4689
  keyStop: 0,
4686
4690
  step: 0
4687
4691
  };
4688
- var debug$4 = {
4692
+ var debug$1 = {
4689
4693
  arity: -2,
4690
4694
  flags: [
4691
4695
  "admin",
@@ -7011,7 +7015,7 @@ var require$$0$3 = {
7011
7015
  config: config$1,
7012
7016
  copy: copy,
7013
7017
  dbsize: dbsize,
7014
- debug: debug$4,
7018
+ debug: debug$1,
7015
7019
  decr: decr,
7016
7020
  decrby: decrby,
7017
7021
  del: del,
@@ -8903,7 +8907,7 @@ function requireLodash () {
8903
8907
  return lodash;
8904
8908
  }
8905
8909
 
8906
- var debug$3 = {};
8910
+ var debug = {};
8907
8911
 
8908
8912
  var src$2 = {exports: {}};
8909
8913
 
@@ -10096,13 +10100,13 @@ function requireSrc$2 () {
10096
10100
  var hasRequiredDebug;
10097
10101
 
10098
10102
  function requireDebug () {
10099
- if (hasRequiredDebug) return debug$3;
10103
+ if (hasRequiredDebug) return debug;
10100
10104
  hasRequiredDebug = 1;
10101
- Object.defineProperty(debug$3, "__esModule", { value: true });
10102
- debug$3.genRedactedString = debug$3.getStringValue = debug$3.MAX_ARGUMENT_LENGTH = void 0;
10105
+ Object.defineProperty(debug, "__esModule", { value: true });
10106
+ debug.genRedactedString = debug.getStringValue = debug.MAX_ARGUMENT_LENGTH = void 0;
10103
10107
  const debug_1 = requireSrc$2();
10104
10108
  const MAX_ARGUMENT_LENGTH = 200;
10105
- debug$3.MAX_ARGUMENT_LENGTH = MAX_ARGUMENT_LENGTH;
10109
+ debug.MAX_ARGUMENT_LENGTH = MAX_ARGUMENT_LENGTH;
10106
10110
  const NAMESPACE_PREFIX = "ioredis";
10107
10111
  /**
10108
10112
  * helper function that tried to get a string value for
@@ -10134,7 +10138,7 @@ function requireDebug () {
10134
10138
  return v;
10135
10139
  }
10136
10140
  }
10137
- debug$3.getStringValue = getStringValue;
10141
+ debug.getStringValue = getStringValue;
10138
10142
  /**
10139
10143
  * helper function that redacts a string representation of a "debug" arg
10140
10144
  */
@@ -10144,7 +10148,7 @@ function requireDebug () {
10144
10148
  ? str
10145
10149
  : str.slice(0, maxLen) + ' ... <REDACTED full-length="' + length + '">';
10146
10150
  }
10147
- debug$3.genRedactedString = genRedactedString;
10151
+ debug.genRedactedString = genRedactedString;
10148
10152
  /**
10149
10153
  * a wrapper for the `debug` module, used to generate
10150
10154
  * "debug functions" that trim the values in their output
@@ -10191,8 +10195,8 @@ function requireDebug () {
10191
10195
  });
10192
10196
  return wrappedDebug;
10193
10197
  }
10194
- debug$3.default = genDebugFunction;
10195
- return debug$3;
10198
+ debug.default = genDebugFunction;
10199
+ return debug;
10196
10200
  }
10197
10201
 
10198
10202
  var TLSProfiles = {};
@@ -77073,16 +77077,16 @@ function requireSrc () {
77073
77077
  return src;
77074
77078
  }
77075
77079
 
77076
- var srcExports$1 = requireSrc();
77080
+ var srcExports = requireSrc();
77077
77081
 
77078
77082
  function gif() {
77079
77083
  return {
77080
77084
  mime: "image/gif",
77081
77085
  encode: async (bitmap) => {
77082
- const gif = new srcExports$1.BitmapImage(bitmap);
77083
- srcExports$1.GifUtil.quantizeDekker(gif, 256);
77084
- const newFrame = new srcExports$1.GifFrame(bitmap);
77085
- const gifCodec = new srcExports$1.GifCodec();
77086
+ const gif = new srcExports.BitmapImage(bitmap);
77087
+ srcExports.GifUtil.quantizeDekker(gif, 256);
77088
+ const newFrame = new srcExports.GifFrame(bitmap);
77089
+ const gifCodec = new srcExports.GifCodec();
77086
77090
  const newGif = await gifCodec.encodeGif([newFrame], {});
77087
77091
  return newGif.buffer;
77088
77092
  },
@@ -116569,904 +116573,11 @@ const commands = {
116569
116573
  },
116570
116574
  };
116571
116575
 
116572
- var srcExports = requireSrc$2();
116573
- var Debug = /*@__PURE__*/getDefaultExportFromCjs(srcExports);
116574
-
116575
- /*!
116576
- * playwright-extra v4.3.5 by berstend
116577
- * https://github.com/berstend/puppeteer-extra/tree/master/packages/playwright-extra#readme
116578
- * @license MIT
116579
- */
116580
-
116581
- /** Node.js module loader helper */
116582
- class Loader {
116583
- constructor(moduleName, packageNames) {
116584
- this.moduleName = moduleName;
116585
- this.packageNames = packageNames;
116586
- }
116587
- /**
116588
- * Lazy load a top level export from another module by wrapping it in a JS proxy.
116589
- *
116590
- * This allows us to re-export e.g. `devices` from `playwright` while redirecting direct calls
116591
- * to it to the module version the user has installed, rather than shipping with a hardcoded version.
116592
- *
116593
- * If we don't do this and the user doesn't have the target module installed we'd throw immediately when our code is imported.
116594
- *
116595
- * We use a "super" Proxy defining all traps, so calls like `Object.keys(playwright.devices).length` will return the correct value.
116596
- */
116597
- lazyloadExportOrDie(exportName) {
116598
- const that = this;
116599
- const trapHandler = Object.fromEntries(Object.getOwnPropertyNames(Reflect).map((name) => [
116600
- name,
116601
- function (target, ...args) {
116602
- const moduleExport = that.loadModuleOrDie()[exportName];
116603
- const customTarget = moduleExport;
116604
- const result = Reflect[name](customTarget || target, ...args);
116605
- return result;
116606
- }
116607
- ]));
116608
- return new Proxy({}, trapHandler);
116609
- }
116610
- /** Load the module if possible */
116611
- loadModule() {
116612
- return requirePackages(this.packageNames);
116613
- }
116614
- /** Load the module if possible or throw */
116615
- loadModuleOrDie() {
116616
- const module = requirePackages(this.packageNames);
116617
- if (module) {
116618
- return module;
116619
- }
116620
- throw this.requireError;
116621
- }
116622
- get requireError() {
116623
- const moduleNamePretty = this.moduleName.charAt(0).toUpperCase() + this.moduleName.slice(1);
116624
- return new Error(`
116625
- ${moduleNamePretty} is missing. :-)
116626
-
116627
- I've tried loading ${this.packageNames
116628
- .map(p => `"${p}"`)
116629
- .join(', ')} - no luck.
116630
-
116631
- Make sure you install one of those packages or use the named 'addExtra' export,
116632
- to patch a specific (and maybe non-standard) implementation of ${moduleNamePretty}.
116633
-
116634
- To get the latest stable version of ${moduleNamePretty} run:
116635
- 'yarn add ${this.moduleName}' or 'npm i ${this.moduleName}'
116636
- `);
116637
- }
116638
- }
116639
- function requirePackages(packageNames) {
116640
- for (const name of packageNames) {
116641
- try {
116642
- return require(name);
116643
- }
116644
- catch (_) {
116645
- continue; // noop
116646
- }
116647
- }
116648
- return;
116649
- }
116650
- /** Playwright specific module loader */
116651
- const playwrightLoader = new Loader('playwright', [
116652
- 'playwright-core',
116653
- 'playwright'
116654
- ]);
116655
-
116656
- const debug = Debug('playwright-extra:puppeteer-compat');
116657
- const isPlaywrightPage = (obj) => {
116658
- return 'unroute' in obj;
116659
- };
116660
- const isPlaywrightFrame = (obj) => {
116661
- return ['parentFrame', 'frameLocator'].every(x => x in obj);
116662
- };
116663
- const isPlaywrightBrowser = (obj) => {
116664
- return 'newContext' in obj;
116665
- };
116666
- const isPuppeteerCompat = (obj) => {
116667
- return !!obj && typeof obj === 'object' && !!obj.isCompatShim;
116668
- };
116669
- const cache = {
116670
- objectToShim: new Map(),
116671
- cdpSession: {
116672
- page: new Map(),
116673
- browser: new Map()
116674
- }
116675
- };
116676
- /** Augment a Playwright object with compatibility with certain Puppeteer methods */
116677
- function addPuppeteerCompat(object) {
116678
- if (!object || typeof object !== 'object') {
116679
- return object;
116680
- }
116681
- if (cache.objectToShim.has(object)) {
116682
- return cache.objectToShim.get(object);
116683
- }
116684
- if (isPuppeteerCompat(object)) {
116685
- return object;
116686
- }
116687
- debug('addPuppeteerCompat', cache.objectToShim.size);
116688
- if (isPlaywrightPage(object) || isPlaywrightFrame(object)) {
116689
- const shim = createPageShim(object);
116690
- cache.objectToShim.set(object, shim);
116691
- return shim;
116692
- }
116693
- if (isPlaywrightBrowser(object)) {
116694
- const shim = createBrowserShim(object);
116695
- cache.objectToShim.set(object, shim);
116696
- return shim;
116697
- }
116698
- debug('Received unknown object:', Reflect.ownKeys(object));
116699
- return object;
116700
- }
116701
- // Only chromium browsers support CDP
116702
- const dummyCDPClient = {
116703
- send: async (...args) => {
116704
- debug('dummy CDP client called', 'send', args);
116705
- },
116706
- on: (...args) => {
116707
- debug('dummy CDP client called', 'on', args);
116708
- }
116709
- };
116710
- async function getPageCDPSession(page) {
116711
- let session = cache.cdpSession.page.get(page);
116712
- if (session) {
116713
- debug('getPageCDPSession: use existing');
116714
- return session;
116715
- }
116716
- debug('getPageCDPSession: use new');
116717
- const context = isPlaywrightFrame(page)
116718
- ? page.page().context()
116719
- : page.context();
116720
- try {
116721
- session = await context.newCDPSession(page);
116722
- cache.cdpSession.page.set(page, session);
116723
- return session;
116724
- }
116725
- catch (err) {
116726
- debug('getPageCDPSession: error while creating session:', err.message);
116727
- debug('getPageCDPSession: Unable create CDP session (most likely a different browser than chromium) - returning a dummy');
116728
- }
116729
- return dummyCDPClient;
116730
- }
116731
- async function getBrowserCDPSession(browser) {
116732
- let session = cache.cdpSession.browser.get(browser);
116733
- if (session) {
116734
- debug('getBrowserCDPSession: use existing');
116735
- return session;
116736
- }
116737
- debug('getBrowserCDPSession: use new');
116738
- try {
116739
- session = await browser.newBrowserCDPSession();
116740
- cache.cdpSession.browser.set(browser, session);
116741
- return session;
116742
- }
116743
- catch (err) {
116744
- debug('getBrowserCDPSession: error while creating session:', err.message);
116745
- debug('getBrowserCDPSession: Unable create CDP session (most likely a different browser than chromium) - returning a dummy');
116746
- }
116747
- return dummyCDPClient;
116748
- }
116749
- function createPageShim(page) {
116750
- const objId = Math.random().toString(36).substring(2, 7);
116751
- const shim = new Proxy(page, {
116752
- get(target, prop) {
116753
- if (prop === 'isCompatShim' || prop === 'isPlaywright') {
116754
- return true;
116755
- }
116756
- debug('page - get', objId, prop);
116757
- if (prop === '_client') {
116758
- return () => ({
116759
- send: async (method, params) => {
116760
- const session = await getPageCDPSession(page);
116761
- return await session.send(method, params);
116762
- },
116763
- on: (event, listener) => {
116764
- getPageCDPSession(page).then(session => {
116765
- session.on(event, listener);
116766
- });
116767
- }
116768
- });
116769
- }
116770
- if (prop === 'setBypassCSP') {
116771
- return async (enabled) => {
116772
- const session = await getPageCDPSession(page);
116773
- return await session.send('Page.setBypassCSP', {
116774
- enabled
116775
- });
116776
- };
116777
- }
116778
- if (prop === 'setUserAgent') {
116779
- return async (userAgent, userAgentMetadata) => {
116780
- const session = await getPageCDPSession(page);
116781
- return await session.send('Emulation.setUserAgentOverride', {
116782
- userAgent,
116783
- userAgentMetadata
116784
- });
116785
- };
116786
- }
116787
- if (prop === 'browser') {
116788
- if (isPlaywrightPage(page)) {
116789
- return () => {
116790
- let browser = page.context().browser();
116791
- if (!browser) {
116792
- debug('page.browser() - not available, most likely due to launchPersistentContext');
116793
- // Use a page shim as quick drop-in (so browser.userAgent() still works)
116794
- browser = page;
116795
- }
116796
- return addPuppeteerCompat(browser);
116797
- };
116798
- }
116799
- }
116800
- if (prop === 'evaluateOnNewDocument') {
116801
- if (isPlaywrightPage(page)) {
116802
- return async function (pageFunction, ...args) {
116803
- return await page.addInitScript(pageFunction, args[0]);
116804
- };
116805
- }
116806
- }
116807
- // Only relevant when page is being used a pseudo stand-in for the browser object (launchPersistentContext)
116808
- if (prop === 'userAgent') {
116809
- return async (enabled) => {
116810
- const session = await getPageCDPSession(page);
116811
- const data = await session.send('Browser.getVersion');
116812
- return data.userAgent;
116813
- };
116814
- }
116815
- return Reflect.get(target, prop);
116816
- }
116817
- });
116818
- return shim;
116819
- }
116820
- function createBrowserShim(browser) {
116821
- const objId = Math.random().toString(36).substring(2, 7);
116822
- const shim = new Proxy(browser, {
116823
- get(target, prop) {
116824
- if (prop === 'isCompatShim' || prop === 'isPlaywright') {
116825
- return true;
116826
- }
116827
- debug('browser - get', objId, prop);
116828
- if (prop === 'pages') {
116829
- return () => browser
116830
- .contexts()
116831
- .flatMap(c => c.pages().map(page => addPuppeteerCompat(page)));
116832
- }
116833
- if (prop === 'userAgent') {
116834
- return async () => {
116835
- const session = await getBrowserCDPSession(browser);
116836
- const data = await session.send('Browser.getVersion');
116837
- return data.userAgent;
116838
- };
116839
- }
116840
- return Reflect.get(target, prop);
116841
- }
116842
- });
116843
- return shim;
116844
- }
116845
-
116846
- const debug$1 = Debug('playwright-extra:plugins');
116847
- class PluginList {
116848
- constructor() {
116849
- this._plugins = [];
116850
- this._dependencyDefaults = new Map();
116851
- this._dependencyResolution = new Map();
116852
- }
116853
- /**
116854
- * Get a list of all registered plugins.
116855
- */
116856
- get list() {
116857
- return this._plugins;
116858
- }
116859
- /**
116860
- * Get the names of all registered plugins.
116861
- */
116862
- get names() {
116863
- return this._plugins.map(p => p.name);
116864
- }
116865
- /**
116866
- * Add a new plugin to the list (after checking if it's well-formed).
116867
- *
116868
- * @param plugin
116869
- * @internal
116870
- */
116871
- add(plugin) {
116872
- var _a;
116873
- if (!this.isValidPluginInstance(plugin)) {
116874
- return false;
116875
- }
116876
- if (!!plugin.onPluginRegistered) {
116877
- plugin.onPluginRegistered({ framework: 'playwright' });
116878
- }
116879
- // PuppeteerExtraPlugin: Populate `_childClassMembers` list containing methods defined by the plugin
116880
- if (!!plugin._registerChildClassMembers) {
116881
- plugin._registerChildClassMembers(Object.getPrototypeOf(plugin));
116882
- }
116883
- if ((_a = plugin.requirements) === null || _a === void 0 ? void 0 : _a.has('dataFromPlugins')) {
116884
- plugin.getDataFromPlugins = this.getData.bind(this);
116885
- }
116886
- this._plugins.push(plugin);
116887
- return true;
116888
- }
116889
- /** Check if the shape of a plugin is correct or warn */
116890
- isValidPluginInstance(plugin) {
116891
- if (!plugin ||
116892
- typeof plugin !== 'object' ||
116893
- !plugin._isPuppeteerExtraPlugin) {
116894
- console.error(`Warning: Plugin is not derived from PuppeteerExtraPlugin, ignoring.`, plugin);
116895
- return false;
116896
- }
116897
- if (!plugin.name) {
116898
- console.error(`Warning: Plugin with no name registering, ignoring.`, plugin);
116899
- return false;
116900
- }
116901
- return true;
116902
- }
116903
- /** Error callback in case calling a plugin method throws an error. Can be overwritten. */
116904
- onPluginError(plugin, method, err) {
116905
- console.warn(`An error occured while executing "${method}" in plugin "${plugin.name}":`, err);
116906
- }
116907
- /**
116908
- * Define default values for plugins implicitly required through the `dependencies` plugin stanza.
116909
- *
116910
- * @param dependencyPath - The string by which the dependency is listed (not the plugin name)
116911
- *
116912
- * @example
116913
- * chromium.use(stealth)
116914
- * chromium.plugins.setDependencyDefaults('stealth/evasions/webgl.vendor', { vendor: 'Bob', renderer: 'Alice' })
116915
- */
116916
- setDependencyDefaults(dependencyPath, opts) {
116917
- this._dependencyDefaults.set(dependencyPath, opts);
116918
- return this;
116919
- }
116920
- /**
116921
- * Define custom plugin modules for plugins implicitly required through the `dependencies` plugin stanza.
116922
- *
116923
- * Using this will prevent dynamic imports from being used, which JS bundlers often have issues with.
116924
- *
116925
- * @example
116926
- * chromium.use(stealth)
116927
- * chromium.plugins.setDependencyResolution('stealth/evasions/webgl.vendor', VendorPlugin)
116928
- */
116929
- setDependencyResolution(dependencyPath, pluginModule) {
116930
- this._dependencyResolution.set(dependencyPath, pluginModule);
116931
- return this;
116932
- }
116933
- /**
116934
- * Prepare plugins to be used (resolve dependencies, ordering)
116935
- * @internal
116936
- */
116937
- prepare() {
116938
- this.resolveDependencies();
116939
- this.order();
116940
- }
116941
- /** Return all plugins using the supplied method */
116942
- filterByMethod(methodName) {
116943
- return this._plugins.filter(plugin => {
116944
- // PuppeteerExtraPlugin: The base class will already define all methods, hence we need to do a different check
116945
- if (!!plugin._childClassMembers &&
116946
- Array.isArray(plugin._childClassMembers)) {
116947
- return plugin._childClassMembers.includes(methodName);
116948
- }
116949
- return methodName in plugin;
116950
- });
116951
- }
116952
- /** Conditionally add puppeteer compatibility to values provided to the plugins */
116953
- _addPuppeteerCompatIfNeeded(plugin, method, args) {
116954
- const canUseShim = plugin._isPuppeteerExtraPlugin && !plugin.noPuppeteerShim;
116955
- const methodWhitelist = [
116956
- 'onBrowser',
116957
- 'onPageCreated',
116958
- 'onPageClose',
116959
- 'afterConnect',
116960
- 'afterLaunch'
116961
- ];
116962
- const shouldUseShim = methodWhitelist.includes(method);
116963
- if (!canUseShim || !shouldUseShim) {
116964
- return args;
116965
- }
116966
- debug$1('add puppeteer compatibility', plugin.name, method);
116967
- return [...args.map(arg => addPuppeteerCompat(arg))];
116968
- }
116969
- /**
116970
- * Dispatch plugin lifecycle events in a typesafe way.
116971
- * Only Plugins that expose the supplied property will be called.
116972
- *
116973
- * Will not await results to dispatch events as fast as possible to all plugins.
116974
- *
116975
- * @param method - The lifecycle method name
116976
- * @param args - Optional: Any arguments to be supplied to the plugin methods
116977
- * @internal
116978
- */
116979
- dispatch(method, ...args) {
116980
- var _a, _b;
116981
- const plugins = this.filterByMethod(method);
116982
- debug$1('dispatch', method, {
116983
- all: this._plugins.length,
116984
- filteredByMethod: plugins.length
116985
- });
116986
- for (const plugin of plugins) {
116987
- try {
116988
- args = this._addPuppeteerCompatIfNeeded.bind(this)(plugin, method, args);
116989
- const fnType = (_b = (_a = plugin[method]) === null || _a === void 0 ? void 0 : _a.constructor) === null || _b === void 0 ? void 0 : _b.name;
116990
- debug$1('dispatch to plugin', {
116991
- plugin: plugin.name,
116992
- method,
116993
- fnType
116994
- });
116995
- if (fnType === 'AsyncFunction') {
116996
- ;
116997
- plugin[method](...args).catch((err) => this.onPluginError(plugin, method, err));
116998
- }
116999
- else {
117000
- ;
117001
- plugin[method](...args);
117002
- }
117003
- }
117004
- catch (err) {
117005
- this.onPluginError(plugin, method, err);
117006
- }
117007
- }
117008
- }
117009
- /**
117010
- * Dispatch plugin lifecycle events in a typesafe way.
117011
- * Only Plugins that expose the supplied property will be called.
117012
- *
117013
- * Can also be used to get a definite return value after passing it to plugins:
117014
- * Calls plugins sequentially and passes on a value (waterfall style).
117015
- *
117016
- * The plugins can either modify the value or return an updated one.
117017
- * Will return the latest, updated value which ran through all plugins.
117018
- *
117019
- * By convention only the first argument will be used as the updated value.
117020
- *
117021
- * @param method - The lifecycle method name
117022
- * @param args - Optional: Any arguments to be supplied to the plugin methods
117023
- * @internal
117024
- */
117025
- async dispatchBlocking(method, ...args) {
117026
- const plugins = this.filterByMethod(method);
117027
- debug$1('dispatchBlocking', method, {
117028
- all: this._plugins.length,
117029
- filteredByMethod: plugins.length
117030
- });
117031
- let retValue = null;
117032
- for (const plugin of plugins) {
117033
- try {
117034
- args = this._addPuppeteerCompatIfNeeded.bind(this)(plugin, method, args);
117035
- retValue = await plugin[method](...args);
117036
- // In case we got a return value use that as new first argument for followup function calls
117037
- if (retValue !== undefined) {
117038
- args[0] = retValue;
117039
- }
117040
- }
117041
- catch (err) {
117042
- this.onPluginError(plugin, method, err);
117043
- return retValue;
117044
- }
117045
- }
117046
- return retValue;
117047
- }
117048
- /**
117049
- * Order plugins that have expressed a special placement requirement.
117050
- *
117051
- * This is useful/necessary for e.g. plugins that depend on the data from other plugins.
117052
- *
117053
- * @private
117054
- */
117055
- order() {
117056
- debug$1('order:before', this.names);
117057
- const runLast = this._plugins
117058
- .filter(p => { var _a; return (_a = p.requirements) === null || _a === void 0 ? void 0 : _a.has('runLast'); })
117059
- .map(p => p.name);
117060
- for (const name of runLast) {
117061
- const index = this._plugins.findIndex(p => p.name === name);
117062
- this._plugins.push(this._plugins.splice(index, 1)[0]);
117063
- }
117064
- debug$1('order:after', this.names);
117065
- }
117066
- /**
117067
- * Collects the exposed `data` property of all registered plugins.
117068
- * Will be reduced/flattened to a single array.
117069
- *
117070
- * Can be accessed by plugins that listed the `dataFromPlugins` requirement.
117071
- *
117072
- * Implemented mainly for plugins that need data from other plugins (e.g. `user-preferences`).
117073
- *
117074
- * @see [PuppeteerExtraPlugin]/data
117075
- * @param name - Filter data by optional name
117076
- *
117077
- * @private
117078
- */
117079
- getData(name) {
117080
- const data = this._plugins
117081
- .filter((p) => !!p.data)
117082
- .map((p) => (Array.isArray(p.data) ? p.data : [p.data]))
117083
- .reduce((acc, arr) => [...acc, ...arr], []);
117084
- return name ? data.filter((d) => d.name === name) : data;
117085
- }
117086
- /**
117087
- * Handle `plugins` stanza (already instantiated plugins that don't require dynamic imports)
117088
- */
117089
- resolvePluginsStanza() {
117090
- debug$1('resolvePluginsStanza');
117091
- const pluginNames = new Set(this.names);
117092
- this._plugins
117093
- .filter(p => !!p.plugins && p.plugins.length)
117094
- .filter(p => !pluginNames.has(p.name)) // TBD: Do we want to filter out existing?
117095
- .forEach(parent => {
117096
- (parent.plugins || []).forEach(p => {
117097
- debug$1(parent.name, 'adding missing plugin', p.name);
117098
- this.add(p);
117099
- });
117100
- });
117101
- }
117102
- /**
117103
- * Handle `dependencies` stanza (which requires dynamic imports)
117104
- *
117105
- * Plugins can define `dependencies` as a Set or Array of dependency paths, or a Map with additional opts
117106
- *
117107
- * @note
117108
- * - The default opts for implicit dependencies can be defined using `setDependencyDefaults()`
117109
- * - Dynamic imports can be avoided by providing plugin modules with `setDependencyResolution()`
117110
- */
117111
- resolveDependenciesStanza() {
117112
- debug$1('resolveDependenciesStanza');
117113
- /** Attempt to dynamically require a plugin module */
117114
- const requireDependencyOrDie = (parentName, dependencyPath) => {
117115
- // If the user provided the plugin module already we use that
117116
- if (this._dependencyResolution.has(dependencyPath)) {
117117
- return this._dependencyResolution.get(dependencyPath);
117118
- }
117119
- const possiblePrefixes = ['puppeteer-extra-plugin-']; // could be extended later
117120
- const isAlreadyPrefixed = possiblePrefixes.some(prefix => dependencyPath.startsWith(prefix));
117121
- const packagePaths = [];
117122
- // If the dependency is not already prefixed we attempt to require all possible combinations to find one that works
117123
- if (!isAlreadyPrefixed) {
117124
- packagePaths.push(...possiblePrefixes.map(prefix => prefix + dependencyPath));
117125
- }
117126
- // We always attempt to require the path verbatim (as a last resort)
117127
- packagePaths.push(dependencyPath);
117128
- const pluginModule = requirePackages(packagePaths);
117129
- if (pluginModule) {
117130
- return pluginModule;
117131
- }
117132
- const explanation = `
117133
- The plugin '${parentName}' listed '${dependencyPath}' as dependency,
117134
- which could not be found. Please install it:
117135
-
117136
- ${packagePaths
117137
- .map(packagePath => `yarn add ${packagePath.split('/')[0]}`)
117138
- .join(`\n or:\n`)}
117139
-
117140
- Note: You don't need to require the plugin yourself,
117141
- unless you want to modify it's default settings.
117142
-
117143
- If your bundler has issues with dynamic imports take a look at '.plugins.setDependencyResolution()'.
117144
- `;
117145
- console.warn(explanation);
117146
- throw new Error('Plugin dependency not found');
117147
- };
117148
- const existingPluginNames = new Set(this.names);
117149
- const recursivelyLoadMissingDependencies = ({ name: parentName, dependencies }) => {
117150
- if (!dependencies) {
117151
- return;
117152
- }
117153
- const processDependency = (dependencyPath, opts) => {
117154
- const pluginModule = requireDependencyOrDie(parentName, dependencyPath);
117155
- opts = opts || this._dependencyDefaults.get(dependencyPath) || {};
117156
- const plugin = pluginModule(opts);
117157
- if (existingPluginNames.has(plugin.name)) {
117158
- debug$1(parentName, '=> dependency already exists:', plugin.name);
117159
- return;
117160
- }
117161
- existingPluginNames.add(plugin.name);
117162
- debug$1(parentName, '=> adding new dependency:', plugin.name, opts);
117163
- this.add(plugin);
117164
- return recursivelyLoadMissingDependencies(plugin);
117165
- };
117166
- if (dependencies instanceof Set || Array.isArray(dependencies)) {
117167
- return [...dependencies].forEach(dependencyPath => processDependency(dependencyPath));
117168
- }
117169
- if (dependencies instanceof Map) {
117170
- // Note: `k,v => v,k` (Map + forEach will reverse the order)
117171
- return dependencies.forEach((v, k) => processDependency(k, v));
117172
- }
117173
- };
117174
- this.list.forEach(recursivelyLoadMissingDependencies);
117175
- }
117176
- /**
117177
- * Lightweight plugin dependency management to require plugins and code mods on demand.
117178
- * @private
117179
- */
117180
- resolveDependencies() {
117181
- debug$1('resolveDependencies');
117182
- this.resolvePluginsStanza();
117183
- this.resolveDependenciesStanza();
117184
- }
117185
- }
117186
-
117187
- const debug$2 = Debug('playwright-extra');
117188
- /**
117189
- * Modular plugin framework to teach `playwright` new tricks.
117190
- */
117191
- class PlaywrightExtraClass {
117192
- constructor(_launcher) {
117193
- this._launcher = _launcher;
117194
- this.plugins = new PluginList();
117195
- }
117196
- /**
117197
- * The **main interface** to register plugins.
117198
- *
117199
- * Can be called multiple times to enable multiple plugins.
117200
- *
117201
- * Plugins derived from `PuppeteerExtraPlugin` will be used with a compatiblity layer.
117202
- *
117203
- * @example
117204
- * chromium.use(plugin1).use(plugin2)
117205
- * firefox.use(plugin1).use(plugin2)
117206
- *
117207
- * @see [PuppeteerExtraPlugin]
117208
- *
117209
- * @return The same `PlaywrightExtra` instance (for optional chaining)
117210
- */
117211
- use(plugin) {
117212
- const isValid = plugin && 'name' in plugin;
117213
- if (!isValid) {
117214
- throw new Error('A plugin must be provided to .use()');
117215
- }
117216
- if (this.plugins.add(plugin)) {
117217
- debug$2('Plugin registered', plugin.name);
117218
- }
117219
- return this;
117220
- }
117221
- /**
117222
- * In order to support a default export which will require vanilla playwright automatically,
117223
- * as well as `addExtra` to patch a provided launcher, we need to so some gymnastics here.
117224
- *
117225
- * Otherwise this would throw immediately, even when only using the `addExtra` export with an arbitrary compatible launcher.
117226
- *
117227
- * The solution is to make the vanilla launcher optional and only throw once we try to effectively use and can't find it.
117228
- *
117229
- * @internal
117230
- */
117231
- get launcher() {
117232
- if (!this._launcher) {
117233
- throw playwrightLoader.requireError;
117234
- }
117235
- return this._launcher;
117236
- }
117237
- async launch(...args) {
117238
- if (!this.launcher.launch) {
117239
- throw new Error('Launcher does not support "launch"');
117240
- }
117241
- let [options] = args;
117242
- options = Object.assign({ args: [] }, (options || {})); // Initialize args array
117243
- debug$2('launch', options);
117244
- this.plugins.prepare();
117245
- // Give plugins the chance to modify the options before continuing
117246
- options =
117247
- (await this.plugins.dispatchBlocking('beforeLaunch', options)) || options;
117248
- debug$2('launch with options', options);
117249
- if ('userDataDir' in options) {
117250
- debug$2("A plugin defined userDataDir during .launch, which isn't supported by playwright - ignoring");
117251
- delete options.userDataDir;
117252
- }
117253
- const browser = await this.launcher['launch'](options);
117254
- await this.plugins.dispatchBlocking('onBrowser', browser);
117255
- await this._bindBrowserEvents(browser);
117256
- await this.plugins.dispatchBlocking('afterLaunch', browser);
117257
- return browser;
117258
- }
117259
- async launchPersistentContext(...args) {
117260
- if (!this.launcher.launchPersistentContext) {
117261
- throw new Error('Launcher does not support "launchPersistentContext"');
117262
- }
117263
- let [userDataDir, options] = args;
117264
- options = Object.assign({ args: [] }, (options || {})); // Initialize args array
117265
- debug$2('launchPersistentContext', options);
117266
- this.plugins.prepare();
117267
- // Give plugins the chance to modify the options before continuing
117268
- options =
117269
- (await this.plugins.dispatchBlocking('beforeLaunch', options)) || options;
117270
- const context = await this.launcher['launchPersistentContext'](userDataDir, options);
117271
- await this.plugins.dispatchBlocking('afterLaunch', context);
117272
- this._bindBrowserContextEvents(context);
117273
- return context;
117274
- }
117275
- async connect(wsEndpointOrOptions, wsOptions = {}) {
117276
- if (!this.launcher.connect) {
117277
- throw new Error('Launcher does not support "connect"');
117278
- }
117279
- this.plugins.prepare();
117280
- // Playwright currently supports two function signatures for .connect
117281
- let options = {};
117282
- let wsEndpointAsString = false;
117283
- if (typeof wsEndpointOrOptions === 'object') {
117284
- options = Object.assign(Object.assign({}, wsEndpointOrOptions), wsOptions);
117285
- }
117286
- else {
117287
- wsEndpointAsString = true;
117288
- options = Object.assign({ wsEndpoint: wsEndpointOrOptions }, wsOptions);
117289
- }
117290
- debug$2('connect', options);
117291
- // Give plugins the chance to modify the options before launch/connect
117292
- options =
117293
- (await this.plugins.dispatchBlocking('beforeConnect', options)) || options;
117294
- // Follow call signature of end user
117295
- const args = [];
117296
- const wsEndpoint = options.wsEndpoint;
117297
- if (wsEndpointAsString) {
117298
- delete options.wsEndpoint;
117299
- args.push(wsEndpoint, options);
117300
- }
117301
- else {
117302
- args.push(options);
117303
- }
117304
- const browser = (await this.launcher['connect'](...args));
117305
- await this.plugins.dispatchBlocking('onBrowser', browser);
117306
- await this._bindBrowserEvents(browser);
117307
- await this.plugins.dispatchBlocking('afterConnect', browser);
117308
- return browser;
117309
- }
117310
- async connectOverCDP(wsEndpointOrOptions, wsOptions = {}) {
117311
- if (!this.launcher.connectOverCDP) {
117312
- throw new Error(`Launcher does not implement 'connectOverCDP'`);
117313
- }
117314
- this.plugins.prepare();
117315
- // Playwright currently supports two function signatures for .connectOverCDP
117316
- let options = {};
117317
- let wsEndpointAsString = false;
117318
- if (typeof wsEndpointOrOptions === 'object') {
117319
- options = Object.assign(Object.assign({}, wsEndpointOrOptions), wsOptions);
117320
- }
117321
- else {
117322
- wsEndpointAsString = true;
117323
- options = Object.assign({ endpointURL: wsEndpointOrOptions }, wsOptions);
117324
- }
117325
- debug$2('connectOverCDP');
117326
- // Give plugins the chance to modify the options before launch/connect
117327
- options =
117328
- (await this.plugins.dispatchBlocking('beforeConnect', options)) || options;
117329
- // Follow call signature of end user
117330
- const args = [];
117331
- const endpointURL = options.endpointURL;
117332
- if (wsEndpointAsString) {
117333
- delete options.endpointURL;
117334
- args.push(endpointURL, options);
117335
- }
117336
- else {
117337
- args.push(options);
117338
- }
117339
- const browser = (await this.launcher['connectOverCDP'](...args));
117340
- await this.plugins.dispatchBlocking('onBrowser', browser);
117341
- await this._bindBrowserEvents(browser);
117342
- await this.plugins.dispatchBlocking('afterConnect', browser);
117343
- return browser;
117344
- }
117345
- async _bindBrowserContextEvents(context, contextOptions) {
117346
- debug$2('_bindBrowserContextEvents');
117347
- this.plugins.dispatch('onContextCreated', context, contextOptions);
117348
- // Make sure things like `addInitScript` show an effect on the very first page as well
117349
- context.newPage = ((originalMethod, ctx) => {
117350
- return async () => {
117351
- const page = await originalMethod.call(ctx);
117352
- await page.goto('about:blank');
117353
- return page;
117354
- };
117355
- })(context.newPage, context);
117356
- context.on('close', () => {
117357
- // When using `launchPersistentContext` context closing is the same as browser closing
117358
- if (!context.browser()) {
117359
- this.plugins.dispatch('onDisconnected');
117360
- }
117361
- });
117362
- context.on('page', page => {
117363
- this.plugins.dispatch('onPageCreated', page);
117364
- page.on('close', () => {
117365
- this.plugins.dispatch('onPageClose', page);
117366
- });
117367
- });
117368
- }
117369
- async _bindBrowserEvents(browser) {
117370
- debug$2('_bindPlaywrightBrowserEvents');
117371
- browser.on('disconnected', () => {
117372
- this.plugins.dispatch('onDisconnected', browser);
117373
- });
117374
- // Note: `browser.newPage` will implicitly call `browser.newContext` as well
117375
- browser.newContext = ((originalMethod, ctx) => {
117376
- return async (options = {}) => {
117377
- const contextOptions = (await this.plugins.dispatchBlocking('beforeContext', options, browser)) || options;
117378
- const context = await originalMethod.call(ctx, contextOptions);
117379
- this._bindBrowserContextEvents(context, contextOptions);
117380
- return context;
117381
- };
117382
- })(browser.newContext, browser);
117383
- }
117384
- }
117385
- /**
117386
- * PlaywrightExtra class with additional launcher methods.
117387
- *
117388
- * Augments the class with an instance proxy to pass on methods that are not augmented to the original target.
117389
- *
117390
- */
117391
- const PlaywrightExtra = new Proxy(PlaywrightExtraClass, {
117392
- construct(classTarget, args) {
117393
- debug$2(`create instance of ${classTarget.name}`);
117394
- const result = Reflect.construct(classTarget, args);
117395
- return new Proxy(result, {
117396
- get(target, prop) {
117397
- if (prop in target) {
117398
- return Reflect.get(target, prop);
117399
- }
117400
- debug$2('proxying property to original launcher: ', prop);
117401
- return Reflect.get(target.launcher, prop);
117402
- }
117403
- });
117404
- }
117405
- });
117406
-
117407
- /**
117408
- * Augment the provided Playwright browser launcher with plugin functionality.
117409
- *
117410
- * Using `addExtra` will always create a fresh PlaywrightExtra instance.
117411
- *
117412
- * @example
117413
- * import playwright from 'playwright'
117414
- * import { addExtra } from 'playwright-extra'
117415
- *
117416
- * const chromium = addExtra(playwright.chromium)
117417
- * chromium.use(plugin)
117418
- *
117419
- * @param launcher - Playwright (or compatible) browser launcher
117420
- */
117421
- const addExtra = (launcher) => new PlaywrightExtra(launcher);
117422
- /**
117423
- * This object can be used to launch or connect to Chromium with plugin functionality.
117424
- *
117425
- * This default export will behave exactly the same as the regular playwright
117426
- * (just with extra plugin functionality) and can be used as a drop-in replacement.
117427
- *
117428
- * Behind the scenes it will try to require either the `playwright-core`
117429
- * or `playwright` module from the installed dependencies.
117430
- *
117431
- * @note
117432
- * Due to Node.js import caching this will result in a single
117433
- * PlaywrightExtra instance, even when used in different files. If you need multiple
117434
- * instances with different plugins please use `addExtra`.
117435
- *
117436
- * @example
117437
- * // javascript import
117438
- * const { chromium } = require('playwright-extra')
117439
- *
117440
- * // typescript/es6 module import
117441
- * import { chromium } from 'playwright-extra'
117442
- *
117443
- * // Add plugins
117444
- * chromium.use(...)
117445
- */
117446
- const chromium = addExtra((playwrightLoader.loadModule() || {}).chromium);
117447
- /**
117448
- * This object can be used to launch or connect to Firefox with plugin functionality
117449
- * @note This export will always return the same instance, if you wish to use multiple instances with different plugins use `addExtra`
117450
- */
117451
- addExtra((playwrightLoader.loadModule() || {}).firefox);
117452
- /**
117453
- * This object can be used to launch or connect to Webkit with plugin functionality
117454
- * @note This export will always return the same instance, if you wish to use multiple instances with different plugins use `addExtra`
117455
- */
117456
- addExtra((playwrightLoader.loadModule() || {}).webkit);
117457
- // Other playwright module exports we simply re-export with lazy loading
117458
- playwrightLoader.lazyloadExportOrDie('_android');
117459
- playwrightLoader.lazyloadExportOrDie('_electron');
117460
- playwrightLoader.lazyloadExportOrDie('request');
117461
- playwrightLoader.lazyloadExportOrDie('selectors');
117462
- playwrightLoader.lazyloadExportOrDie('devices');
117463
- playwrightLoader.lazyloadExportOrDie('errors');
117464
-
117465
116576
  var stealth = test$1.extend({
117466
- browser: async ({ browser }, use) => {
117467
- await browser.close();
117468
- chromium.use(stealth$1());
117469
- const stealthBrowser = await chromium.launch();
116577
+ browser: async ({}, use) => {
116578
+ const chromiumBrowser = addExtra(chromium);
116579
+ chromiumBrowser.use(stealth$1());
116580
+ const stealthBrowser = await chromiumBrowser.launch();
117470
116581
  await use(stealthBrowser);
117471
116582
  await stealthBrowser.close();
117472
116583
  },
@@ -117566,7 +116677,7 @@ const i18nFixture = {
117566
116677
  i18n: [
117567
116678
  async ({}, use) => {
117568
116679
  const translation = readTranslations();
117569
- const page = await (await chromium$1.launch()).newPage();
116680
+ const page = await (await chromium.launch()).newPage();
117570
116681
  const taxonomies = await mergeTaxonomies(translation, page);
117571
116682
  const options = {
117572
116683
  debug: false,
@@ -119675,31 +118786,6 @@ class HelpAndProfilePage {
119675
118786
  })).toHaveScreenshot(expectedScreenshot, { maxDiffPixelRatio: 0.1 });
119676
118787
  });
119677
118788
  };
119678
- /**
119679
- * @deprecated This method is deprecated. Use updateBasicInfo instead.
119680
- */
119681
- updateProfile = async ({ firstName, lastName }) => {
119682
- await this.openHelpCenter();
119683
- await this.page
119684
- .getByTestId(PROFILE_SECTION_SELECTORS.myProfileButton)
119685
- .click();
119686
- await this.page
119687
- .getByTestId(COMMON_SELECTORS.pane)
119688
- .getByTestId(COMMON_SELECTORS.dropdownIcon)
119689
- .click();
119690
- await this.page.getByTestId(PROFILE_SECTION_SELECTORS.editBtn).click();
119691
- firstName &&
119692
- (await this.page
119693
- .getByTestId(PROFILE_SECTION_SELECTORS.firstNameTextField)
119694
- .fill(firstName));
119695
- lastName &&
119696
- (await this.page
119697
- .getByTestId(PROFILE_SECTION_SELECTORS.lastNameTextField)
119698
- .fill(lastName));
119699
- await this.page.getByTestId(PROFILE_SECTION_SELECTORS.submitButton).click();
119700
- await this.neetoPlaywrightUtilities.waitForPageLoad();
119701
- await expect(this.page.getByTestId(COMMON_SELECTORS.paneModalCrossIcon)).toBeHidden();
119702
- };
119703
118789
  }
119704
118790
 
119705
118791
  class MicrosoftPage extends IntegrationBase {
@@ -120030,32 +119116,6 @@ class SlackPage extends IntegrationBase {
120030
119116
  await nextButton.click();
120031
119117
  await this.slackWebappPageDataQa(SLACK_DATA_QA_SELECTORS.inviteToWorkspaceSkipButton).click();
120032
119118
  };
120033
- /**
120034
- * @deprecated Use {@link SlackPage.archiveChannelViaAPI} instead. This flow
120035
- * drives the Slack web UI to permanently delete a channel and is brittle;
120036
- * `archiveChannelViaAPI` archives via the Slack Web API (requires
120037
- * `SLACK_BOT_TOKEN`).
120038
- */
120039
- deleteSlackChannel = async (channel) => {
120040
- const channelItem = this.slackWebappPage.locator(SLACK_SELECTORS.channelItems, { hasText: channel });
120041
- await channelItem.click({ button: "right" });
120042
- await this.slackWebappPageDataQa([
120043
- SLACK_DATA_QA_SELECTORS.menuItems,
120044
- SLACK_DATA_QA_SELECTORS.channelDetailsModal,
120045
- ]).click();
120046
- await expect(this.slackWebappPageDataQa(SLACK_DATA_QA_SELECTORS.channelDetailsModal)).toBeVisible();
120047
- await this.slackWebappPageDataQa(SLACK_DATA_QA_SELECTORS.channelDetailsSettingsTab).click();
120048
- await this.slackWebappPageDataQa(SLACK_DATA_QA_SELECTORS.skModalContent)
120049
- .getByRole("button", { name: SLACK_WEB_TEXTS.deleteThisChannel })
120050
- .click();
120051
- await this.slackWebappPage
120052
- .getByLabel(SLACK_WEB_TEXTS.permanentlyDeleteTheChannel)
120053
- .check();
120054
- await this.slackWebappPage
120055
- .getByRole("button", { name: SLACK_WEB_TEXTS.deleteChannel })
120056
- .click();
120057
- await expect(channelItem).toBeHidden();
120058
- };
120059
119119
  archiveChannelViaAPI = async (name) => {
120060
119120
  const response = await this.slackApi.listChannels();
120061
119121
  const { channels } = (await response?.json());
@@ -120367,7 +119427,7 @@ class ZapierPage extends IntegrationBase {
120367
119427
  message: TOASTR_MESSAGES.zapierApiKeyGenerated,
120368
119428
  });
120369
119429
  await this.page.getByTestId(COMMON_SELECTORS.copyToClipboardButton).click();
120370
- const apiKey = await this.page.evaluate(() => navigator.clipboard.readText());
119430
+ const apiKey = await getClipboardContent(this.page);
120371
119431
  await this.verifyIntegrationStatus();
120372
119432
  return apiKey;
120373
119433
  };
@@ -120504,6 +119564,7 @@ const LIST_MODIFIER_TAGS = {
120504
119564
  orderedList: "ol",
120505
119565
  };
120506
119566
 
119567
+ const __dirname$4 = getDirname(import.meta.url);
120507
119568
  class SlashCommandEditorPage {
120508
119569
  page;
120509
119570
  neetoPlaywrightUtilities;
@@ -120623,7 +119684,7 @@ class SlashCommandEditorPage {
120623
119684
  .getByTestId(NEETO_IMAGE_UPLOADER_SELECTORS.browseText)
120624
119685
  .click();
120625
119686
  const fileUploader = await fileUploaderPromise;
120626
- const imagePath = path.join(__dirname, filePath);
119687
+ const imagePath = path.join(__dirname$4, filePath);
120627
119688
  await fileUploader.setFiles(imagePath);
120628
119689
  await expect(this.imageWrapper).toBeVisible({ timeout: 15_000 });
120629
119690
  if (shouldRemoveImage) {
@@ -120698,6 +119759,7 @@ class SlashCommandEditorPage {
120698
119759
  };
120699
119760
  }
120700
119761
 
119762
+ const __dirname$3 = getDirname(import.meta.url);
120701
119763
  class EditorPage {
120702
119764
  page;
120703
119765
  neetoPlaywrightUtilities;
@@ -120928,7 +119990,7 @@ class EditorPage {
120928
119990
  isButtonInMoreMenu && (await this.moreMenuSelector.click());
120929
119991
  await this.editorAttachmentsButton.click();
120930
119992
  const fileUploader = await fileUploaderPromise;
120931
- const imagePath = path.join(__dirname, filePath);
119993
+ const imagePath = path.join(__dirname$3, filePath);
120932
119994
  await fileUploader.setFiles(imagePath);
120933
119995
  await expect(this.attachmentPreview).toBeVisible();
120934
119996
  if (shouldRemoveAttachment) {
@@ -120954,7 +120016,7 @@ class EditorPage {
120954
120016
  .getByTestId(NEETO_IMAGE_UPLOADER_SELECTORS.browseText)
120955
120017
  .click();
120956
120018
  const fileUploader = await fileUploaderPromise;
120957
- const imagePath = path.join(__dirname, filePath);
120019
+ const imagePath = path.join(__dirname$3, filePath);
120958
120020
  await fileUploader.setFiles(imagePath);
120959
120021
  await expect(this.imageWrapper).toBeVisible({ timeout: 15_000 });
120960
120022
  if (shouldRemoveImage) {
@@ -121061,7 +120123,7 @@ class EditorPage {
121061
120123
  .getByTestId(NEETO_EDITOR_SELECTORS.imageUploadButton)
121062
120124
  .click();
121063
120125
  const fileUploader = await fileUploaderPromise;
121064
- const imagePath = path.join(__dirname, filePath);
120126
+ const imagePath = path.join(__dirname$3, filePath);
121065
120127
  await fileUploader.setFiles(imagePath);
121066
120128
  await expect(this.page.getByRole("figure")).toBeVisible({
121067
120129
  timeout: 20_000,
@@ -122645,12 +121707,8 @@ const PHONE_NUMBER_FORMATS = [
122645
121707
  const initializeCredentials = (product) => {
122646
121708
  if (process.env.SKIP_SETUP === "true" && getGlobalUserState()) {
122647
121709
  const { email } = getGlobalUserState();
122648
- if (IS_STAGING_ENV) {
122649
- email.endsWith("example.com") && removeCredentialFile();
122650
- }
122651
- else {
122652
- email.endsWith("bigbinary.com") && removeCredentialFile();
122653
- }
121710
+ const domain = IS_STAGING_ENV ? "example.com" : "bigbinary.com";
121711
+ email.endsWith(domain) && removeCredentialFile();
122654
121712
  readFileSyncIfExists();
122655
121713
  }
122656
121714
  isStagingOrganizationExpired(getGlobalUserState()?.subdomainName) &&
@@ -125810,15 +124868,13 @@ async function warmup({ urls = DEFAULT_WARMUP_URLS, timeout = 60_000, } = {}) {
125810
124868
  throw new Error("RAILS_SERVER_PORT is not defined in environment variables.");
125811
124869
  }
125812
124870
  const baseURL = `http://${SUBDOMAIN}.lvh.me:${RAILS_SERVER_PORT}`;
125813
- const browser = await chromium$1.launch();
124871
+ const browser = await chromium.launch();
125814
124872
  const page = await browser.newPage();
125815
124873
  try {
125816
124874
  for (const url of urls) {
125817
124875
  const fullUrl = url.startsWith("http") ? url : `${baseURL}${url}`;
125818
- await page.goto(fullUrl, {
125819
- waitUntil: "networkidle", // eslint-disable-line playwright/no-networkidle
125820
- timeout,
125821
- });
124876
+ // eslint-disable-next-line playwright/no-networkidle
124877
+ await page.goto(fullUrl, { waitUntil: "networkidle", timeout });
125822
124878
  }
125823
124879
  }
125824
124880
  finally {
@@ -125833,7 +124889,8 @@ const CONFIG$1 = {
125833
124889
  MAX_WAIT_MS: 120_000,
125834
124890
  EMAIL_INIT: "/tmp/neeto-auth-web/config/initializers/playwright_email_capture.rb",
125835
124891
  };
125836
- const SCRIPTS_DIR$1 = path.join(__dirname, "scripts", "neeto-auth");
124892
+ const __dirname$2 = getDirname(import.meta.url);
124893
+ const SCRIPTS_DIR$1 = path.join(__dirname$2, "scripts", "neeto-auth");
125837
124894
  const escapeRubyString = (value) => value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
125838
124895
  const buildEmailCaptureInitializer = (targetApp) => {
125839
124896
  const template = fs.readFileSync(path.join(SCRIPTS_DIR$1, "playwright_email_capture.rb.template"), "utf-8");
@@ -125993,7 +125050,8 @@ const CONFIG = {
125993
125050
  };
125994
125051
  const DEFAULT_STATE = { pid: null, refCount: 0 };
125995
125052
  const WIDGET_BASE_URL = `http://localhost:${CONFIG.PORT}`;
125996
- const SCRIPTS_DIR = path.join(__dirname, "scripts", "neeto-chat-widget");
125053
+ const __dirname$1 = getDirname(import.meta.url);
125054
+ const SCRIPTS_DIR = path.join(__dirname$1, "scripts", "neeto-chat-widget");
125997
125055
  const log = (msg) => console.log(`[NeetoChatWidget] ${msg}`);
125998
125056
  const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
125999
125057
  const httpCheck = (timeout = 3000) => new Promise(resolve => {
@@ -126310,17 +125368,17 @@ class EmailDeliveryUtils {
126310
125368
  };
126311
125369
  }
126312
125370
 
126313
- var main$1 = {exports: {}};
125371
+ var main = {exports: {}};
126314
125372
 
126315
125373
  var version = "17.3.1";
126316
125374
  var require$$4 = {
126317
125375
  version: version};
126318
125376
 
126319
- var hasRequiredMain$1;
125377
+ var hasRequiredMain;
126320
125378
 
126321
- function requireMain$1 () {
126322
- if (hasRequiredMain$1) return main$1.exports;
126323
- hasRequiredMain$1 = 1;
125379
+ function requireMain () {
125380
+ if (hasRequiredMain) return main.exports;
125381
+ hasRequiredMain = 1;
126324
125382
  const fs = fs__default;
126325
125383
  const path = path__default;
126326
125384
  const os$1 = os;
@@ -126743,130 +125801,20 @@ function requireMain$1 () {
126743
125801
  populate
126744
125802
  };
126745
125803
 
126746
- main$1.exports.configDotenv = DotenvModule.configDotenv;
126747
- main$1.exports._configVault = DotenvModule._configVault;
126748
- main$1.exports._parseVault = DotenvModule._parseVault;
126749
- main$1.exports.config = DotenvModule.config;
126750
- main$1.exports.decrypt = DotenvModule.decrypt;
126751
- main$1.exports.parse = DotenvModule.parse;
126752
- main$1.exports.populate = DotenvModule.populate;
126753
-
126754
- main$1.exports = DotenvModule;
126755
- return main$1.exports;
126756
- }
126757
-
126758
- var mainExports$1 = requireMain$1();
126759
- var dotenv = /*@__PURE__*/getDefaultExportFromCjs(mainExports$1);
126760
-
126761
- var main = {};
126762
-
126763
- var hasRequiredMain;
126764
-
126765
- function requireMain () {
126766
- if (hasRequiredMain) return main;
126767
- hasRequiredMain = 1;
126768
-
126769
- function _resolveEscapeSequences (value) {
126770
- return value.replace(/\\\$/g, '$')
126771
- }
126772
-
126773
- function expandValue (value, processEnv, runningParsed) {
126774
- const env = { ...runningParsed, ...processEnv }; // process.env wins
126775
-
126776
- const regex = /(?<!\\)\${([^{}]+)}|(?<!\\)\$([A-Za-z_][A-Za-z0-9_]*)/g;
126777
-
126778
- let result = value;
126779
- let match;
126780
- const seen = new Set(); // self-referential checker
126781
-
126782
- while ((match = regex.exec(result)) !== null) {
126783
- seen.add(result);
126784
-
126785
- const [template, bracedExpression, unbracedExpression] = match;
126786
- const expression = bracedExpression || unbracedExpression;
126787
-
126788
- // match the operators `:+`, `+`, `:-`, and `-`
126789
- const opRegex = /(:\+|\+|:-|-)/;
126790
- // find first match
126791
- const opMatch = expression.match(opRegex);
126792
- const splitter = opMatch ? opMatch[0] : null;
126793
-
126794
- const r = expression.split(splitter);
126795
-
126796
- let defaultValue;
126797
- let value;
126798
-
126799
- const key = r.shift();
126800
-
126801
- if ([':+', '+'].includes(splitter)) {
126802
- defaultValue = env[key] ? r.join(splitter) : '';
126803
- value = null;
126804
- } else {
126805
- defaultValue = r.join(splitter);
126806
- value = env[key];
126807
- }
126808
-
126809
- if (value) {
126810
- // self-referential check
126811
- if (seen.has(value)) {
126812
- result = result.replace(template, defaultValue);
126813
- } else {
126814
- result = result.replace(template, value);
126815
- }
126816
- } else {
126817
- result = result.replace(template, defaultValue);
126818
- }
126819
-
126820
- // if the result equaled what was in process.env and runningParsed then stop expanding
126821
- if (result === runningParsed[key]) {
126822
- break
126823
- }
126824
-
126825
- regex.lastIndex = 0; // reset regex search position to re-evaluate after each replacement
126826
- }
126827
-
126828
- return result
126829
- }
126830
-
126831
- function expand (options) {
126832
- // for use with progressive expansion
126833
- const runningParsed = {};
126834
-
126835
- let processEnv = process.env;
126836
- if (options && options.processEnv != null) {
126837
- processEnv = options.processEnv;
126838
- }
126839
-
126840
- // dotenv.config() ran before this so the assumption is process.env has already been set
126841
- for (const key in options.parsed) {
126842
- let value = options.parsed[key];
126843
-
126844
- // short-circuit scenario: process.env was already set prior to the file value
126845
- if (processEnv[key] && processEnv[key] !== value) {
126846
- value = processEnv[key];
126847
- } else {
126848
- value = expandValue(value, processEnv, runningParsed);
126849
- }
126850
-
126851
- options.parsed[key] = _resolveEscapeSequences(value);
126852
-
126853
- // for use with progressive expansion
126854
- runningParsed[key] = _resolveEscapeSequences(value);
126855
- }
126856
-
126857
- for (const processKey in options.parsed) {
126858
- processEnv[processKey] = options.parsed[processKey];
126859
- }
126860
-
126861
- return options
126862
- }
125804
+ main.exports.configDotenv = DotenvModule.configDotenv;
125805
+ main.exports._configVault = DotenvModule._configVault;
125806
+ main.exports._parseVault = DotenvModule._parseVault;
125807
+ main.exports.config = DotenvModule.config;
125808
+ main.exports.decrypt = DotenvModule.decrypt;
125809
+ main.exports.parse = DotenvModule.parse;
125810
+ main.exports.populate = DotenvModule.populate;
126863
125811
 
126864
- main.expand = expand;
126865
- return main;
125812
+ main.exports = DotenvModule;
125813
+ return main.exports;
126866
125814
  }
126867
125815
 
126868
125816
  var mainExports = requireMain();
126869
- var dotenvExpand = /*@__PURE__*/getDefaultExportFromCjs(mainExports);
125817
+ var dotenv = /*@__PURE__*/getDefaultExportFromCjs(mainExports);
126870
125818
 
126871
125819
  const E2E_TEST_DIR = "e2e/tests";
126872
125820
  const LOG_PREFIX = "[playwright.config]";
@@ -126927,11 +125875,11 @@ const parseSpecPatterns = () => {
126927
125875
  };
126928
125876
 
126929
125877
  // @ts-check
126930
- const loadEnv = (path) => dotenvExpand.expand(dotenv.config({ path, quiet: true }));
126931
125878
  const envBasePath = "./e2e/config/.env";
126932
125879
  const envLocalPath = `${envBasePath}.local`;
126933
125880
  const reporterPackageName = "@bigbinary/neeto-playwright-reporter";
126934
125881
  process.env.TEST_ENV = process.env.TEST_ENV ?? ENVIRONMENT.development;
125882
+ const loadEnv = (path) => dotenv.config({ path, quiet: true });
126935
125883
  loadEnv(`${envBasePath}.${process.env.TEST_ENV}`);
126936
125884
  fs.existsSync(envLocalPath) && loadEnv(envLocalPath);
126937
125885
  const playdashStagingConfig = {
@@ -127135,5 +126083,4 @@ const definePlaywrightConfig = (overrides) => {
127135
126083
  });
127136
126084
  };
127137
126085
 
127138
- 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, PRODUCT_ROLES_ROUTE_MAP, 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, isStagingOrganizationExpired, joinHyphenCase, joinString, login, loginWithoutSSO, networkConditions, networkThrottlingUsingCDP, readFileSyncIfExists, removeCredentialFile, serializeFileForBrowser, shouldSkipCustomDomainSetup, shouldSkipSetupAndTeardown, simulateClickWithDelay, simulateTypingWithDelay, skipTest, squish, stealth as stealthTest, tableUtils, toCamelCase, updateCredentials, warmup, withCookieCache, writeDataToFile };
127139
- //# sourceMappingURL=index.js.map
126086
+ 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, PRODUCT_ROLES_ROUTE_MAP, 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, getDirname, getFormattedPhoneNumber, getFullUrl, getGlobalUserProps, getGlobalUserState, getImagePathAndName, getIsoCodeFromPhoneCode, getListCount, globalShortcuts, grantClipboardPermissions, hexToRGB, hexToRGBA, i18nFixture, imageRegex, initializeCredentials, initializeTestData, initializeTotp, isGithubIssueOpen, isStagingOrganizationExpired, joinHyphenCase, joinString, login, loginWithoutSSO, networkConditions, networkThrottlingUsingCDP, readFileSyncIfExists, removeCredentialFile, serializeFileForBrowser, shouldSkipCustomDomainSetup, shouldSkipSetupAndTeardown, simulateClickWithDelay, simulateTypingWithDelay, skipTest, squish, stealth as stealthTest, tableUtils, toCamelCase, updateCredentials, warmup, withCookieCache, writeDataToFile };