@bigbinary/neeto-playwright-commons 4.0.0 → 4.0.2
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 +5 -1
- package/index.js +130 -988
- package/package.json +3 -4
package/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import fs__default, { readFileSync, promises, existsSync, writeFileSync, unlinkS
|
|
|
5
5
|
import os from 'os';
|
|
6
6
|
import * as path from 'path';
|
|
7
7
|
import path__default, { dirname } from 'path';
|
|
8
|
-
import test, { expect, test as test$1, chromium
|
|
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';
|
|
@@ -25,6 +25,7 @@ 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
31
|
import customParseFormat from 'dayjs/plugin/customParseFormat.js';
|
|
@@ -1299,8 +1300,78 @@ const imageRegex = (imageName) => {
|
|
|
1299
1300
|
return new RegExp(`${baseName}.*\\.${extension}$`);
|
|
1300
1301
|
};
|
|
1301
1302
|
|
|
1303
|
+
const DESCRIPTION_EDITOR_TEXTS = {
|
|
1304
|
+
fontSize: "Font size",
|
|
1305
|
+
paragraph: "Paragraph",
|
|
1306
|
+
normalText: "Normal text",
|
|
1307
|
+
pasteLink: "Paste the link here...",
|
|
1308
|
+
invalidURLError: "Please enter a valid URL",
|
|
1309
|
+
pasteURL: "Paste URL",
|
|
1310
|
+
delete: "Delete",
|
|
1311
|
+
linkTag: "a",
|
|
1312
|
+
link: "Link",
|
|
1313
|
+
cannedResponseHeader: "Canned responses",
|
|
1314
|
+
paragraphOption: "paragraph",
|
|
1315
|
+
search: "Search",
|
|
1316
|
+
emoji: "Emoji",
|
|
1317
|
+
};
|
|
1318
|
+
const EXPANDED_FONT_SIZE = {
|
|
1319
|
+
h1: "Heading 1",
|
|
1320
|
+
h2: "Heading 2",
|
|
1321
|
+
h3: "Heading 3",
|
|
1322
|
+
h4: "Heading 4",
|
|
1323
|
+
h5: "Heading 5",
|
|
1324
|
+
};
|
|
1325
|
+
const TEXT_MODIFIER_TAGS = {
|
|
1326
|
+
underline: "u",
|
|
1327
|
+
strike: "s",
|
|
1328
|
+
};
|
|
1329
|
+
const TEXT_MODIFIER_ROLES = {
|
|
1330
|
+
bold: "strong",
|
|
1331
|
+
italic: "emphasis",
|
|
1332
|
+
code: "code",
|
|
1333
|
+
blockquote: "blockquote",
|
|
1334
|
+
codeBlock: "code",
|
|
1335
|
+
};
|
|
1336
|
+
const LIST_MODIFIER_TAGS = {
|
|
1337
|
+
bulletList: "ul",
|
|
1338
|
+
orderedList: "ol",
|
|
1339
|
+
};
|
|
1340
|
+
const EDITOR_VERIFY_TEXT_COLOR = "#e60000";
|
|
1341
|
+
|
|
1342
|
+
const basicHTMLContent = (content) => `
|
|
1343
|
+
<!DOCTYPE html>
|
|
1344
|
+
<html lang="en">
|
|
1345
|
+
<head>
|
|
1346
|
+
<meta charset="UTF-8" />
|
|
1347
|
+
<meta name="viewport" content="width=device-width" />
|
|
1348
|
+
</head>
|
|
1349
|
+
<body>
|
|
1350
|
+
${content}
|
|
1351
|
+
</body>
|
|
1352
|
+
</html>`;
|
|
1353
|
+
const hexToRGB = (hex) => {
|
|
1354
|
+
let r = "", g = "", b = "";
|
|
1355
|
+
if (hex.length === 4) {
|
|
1356
|
+
r = `0x${hex[1]}${hex[1]}`;
|
|
1357
|
+
g = `0x${hex[2]}${hex[2]}`;
|
|
1358
|
+
b = `0x${hex[3]}${hex[3]}`;
|
|
1359
|
+
}
|
|
1360
|
+
else if (hex.length === 7) {
|
|
1361
|
+
r = `0x${hex[1]}${hex[2]}`;
|
|
1362
|
+
g = `0x${hex[3]}${hex[4]}`;
|
|
1363
|
+
b = `0x${hex[5]}${hex[6]}`;
|
|
1364
|
+
}
|
|
1365
|
+
return `rgb(${Number(r)}, ${Number(g)}, ${Number(b)})`;
|
|
1366
|
+
};
|
|
1367
|
+
|
|
1302
1368
|
const optionSelector = (option) => `neeto-editor-fixed-menu-${option}-option`;
|
|
1303
1369
|
const fixedMenuSelector = (selector) => `neeto-editor-fixed-menu-${selector}`;
|
|
1370
|
+
const editorTextColorStylePattern = (hex = EDITOR_VERIFY_TEXT_COLOR) => {
|
|
1371
|
+
const normalized = hex.replace("#", "");
|
|
1372
|
+
const [r, g, b] = hexToRGB(hex).match(/\d+/g) ?? [];
|
|
1373
|
+
return new RegExp(`color:\\s*(#${normalized}|rgb\\(\\s*${r}\\s*,\\s*${g}\\s*,\\s*${b}\\s*\\))`, "i");
|
|
1374
|
+
};
|
|
1304
1375
|
|
|
1305
1376
|
const NEETO_EDITOR_SELECTORS = {
|
|
1306
1377
|
fontSize: optionSelector("font-size"),
|
|
@@ -1310,6 +1381,7 @@ const NEETO_EDITOR_SELECTORS = {
|
|
|
1310
1381
|
strikeOption: optionSelector("strike"),
|
|
1311
1382
|
codeBlockOption: optionSelector("code"),
|
|
1312
1383
|
highlightOption: optionSelector("highlight"),
|
|
1384
|
+
textColorOption: optionSelector("text-color"),
|
|
1313
1385
|
emojiOption: optionSelector("emoji"),
|
|
1314
1386
|
emojiDropdownIcon: "emoji-dropdown-icon",
|
|
1315
1387
|
linkInput: fixedMenuSelector("link-option-input"),
|
|
@@ -4688,7 +4760,7 @@ var dbsize = {
|
|
|
4688
4760
|
keyStop: 0,
|
|
4689
4761
|
step: 0
|
|
4690
4762
|
};
|
|
4691
|
-
var debug$
|
|
4763
|
+
var debug$1 = {
|
|
4692
4764
|
arity: -2,
|
|
4693
4765
|
flags: [
|
|
4694
4766
|
"admin",
|
|
@@ -7014,7 +7086,7 @@ var require$$0$3 = {
|
|
|
7014
7086
|
config: config$1,
|
|
7015
7087
|
copy: copy,
|
|
7016
7088
|
dbsize: dbsize,
|
|
7017
|
-
debug: debug$
|
|
7089
|
+
debug: debug$1,
|
|
7018
7090
|
decr: decr,
|
|
7019
7091
|
decrby: decrby,
|
|
7020
7092
|
del: del,
|
|
@@ -8906,7 +8978,7 @@ function requireLodash () {
|
|
|
8906
8978
|
return lodash;
|
|
8907
8979
|
}
|
|
8908
8980
|
|
|
8909
|
-
var debug
|
|
8981
|
+
var debug = {};
|
|
8910
8982
|
|
|
8911
8983
|
var src$2 = {exports: {}};
|
|
8912
8984
|
|
|
@@ -10099,13 +10171,13 @@ function requireSrc$2 () {
|
|
|
10099
10171
|
var hasRequiredDebug;
|
|
10100
10172
|
|
|
10101
10173
|
function requireDebug () {
|
|
10102
|
-
if (hasRequiredDebug) return debug
|
|
10174
|
+
if (hasRequiredDebug) return debug;
|
|
10103
10175
|
hasRequiredDebug = 1;
|
|
10104
|
-
Object.defineProperty(debug
|
|
10105
|
-
debug
|
|
10176
|
+
Object.defineProperty(debug, "__esModule", { value: true });
|
|
10177
|
+
debug.genRedactedString = debug.getStringValue = debug.MAX_ARGUMENT_LENGTH = void 0;
|
|
10106
10178
|
const debug_1 = requireSrc$2();
|
|
10107
10179
|
const MAX_ARGUMENT_LENGTH = 200;
|
|
10108
|
-
debug
|
|
10180
|
+
debug.MAX_ARGUMENT_LENGTH = MAX_ARGUMENT_LENGTH;
|
|
10109
10181
|
const NAMESPACE_PREFIX = "ioredis";
|
|
10110
10182
|
/**
|
|
10111
10183
|
* helper function that tried to get a string value for
|
|
@@ -10137,7 +10209,7 @@ function requireDebug () {
|
|
|
10137
10209
|
return v;
|
|
10138
10210
|
}
|
|
10139
10211
|
}
|
|
10140
|
-
debug
|
|
10212
|
+
debug.getStringValue = getStringValue;
|
|
10141
10213
|
/**
|
|
10142
10214
|
* helper function that redacts a string representation of a "debug" arg
|
|
10143
10215
|
*/
|
|
@@ -10147,7 +10219,7 @@ function requireDebug () {
|
|
|
10147
10219
|
? str
|
|
10148
10220
|
: str.slice(0, maxLen) + ' ... <REDACTED full-length="' + length + '">';
|
|
10149
10221
|
}
|
|
10150
|
-
debug
|
|
10222
|
+
debug.genRedactedString = genRedactedString;
|
|
10151
10223
|
/**
|
|
10152
10224
|
* a wrapper for the `debug` module, used to generate
|
|
10153
10225
|
* "debug functions" that trim the values in their output
|
|
@@ -10194,8 +10266,8 @@ function requireDebug () {
|
|
|
10194
10266
|
});
|
|
10195
10267
|
return wrappedDebug;
|
|
10196
10268
|
}
|
|
10197
|
-
debug
|
|
10198
|
-
return debug
|
|
10269
|
+
debug.default = genDebugFunction;
|
|
10270
|
+
return debug;
|
|
10199
10271
|
}
|
|
10200
10272
|
|
|
10201
10273
|
var TLSProfiles = {};
|
|
@@ -69525,32 +69597,6 @@ class FastmailApi {
|
|
|
69525
69597
|
});
|
|
69526
69598
|
}
|
|
69527
69599
|
|
|
69528
|
-
const basicHTMLContent = (content) => `
|
|
69529
|
-
<!DOCTYPE html>
|
|
69530
|
-
<html lang="en">
|
|
69531
|
-
<head>
|
|
69532
|
-
<meta charset="UTF-8" />
|
|
69533
|
-
<meta name="viewport" content="width=device-width" />
|
|
69534
|
-
</head>
|
|
69535
|
-
<body>
|
|
69536
|
-
${content}
|
|
69537
|
-
</body>
|
|
69538
|
-
</html>`;
|
|
69539
|
-
const hexToRGB = (hex) => {
|
|
69540
|
-
let r = "", g = "", b = "";
|
|
69541
|
-
if (hex.length === 4) {
|
|
69542
|
-
r = `0x${hex[1]}${hex[1]}`;
|
|
69543
|
-
g = `0x${hex[2]}${hex[2]}`;
|
|
69544
|
-
b = `0x${hex[3]}${hex[3]}`;
|
|
69545
|
-
}
|
|
69546
|
-
else if (hex.length === 7) {
|
|
69547
|
-
r = `0x${hex[1]}${hex[2]}`;
|
|
69548
|
-
g = `0x${hex[3]}${hex[4]}`;
|
|
69549
|
-
b = `0x${hex[5]}${hex[6]}`;
|
|
69550
|
-
}
|
|
69551
|
-
return `rgb(${Number(r)}, ${Number(g)}, ${Number(b)})`;
|
|
69552
|
-
};
|
|
69553
|
-
|
|
69554
69600
|
class RailsEmailUtils {
|
|
69555
69601
|
neetoPlaywrightUtilities;
|
|
69556
69602
|
railsEmailClient;
|
|
@@ -77076,16 +77122,16 @@ function requireSrc () {
|
|
|
77076
77122
|
return src;
|
|
77077
77123
|
}
|
|
77078
77124
|
|
|
77079
|
-
var srcExports
|
|
77125
|
+
var srcExports = requireSrc();
|
|
77080
77126
|
|
|
77081
77127
|
function gif() {
|
|
77082
77128
|
return {
|
|
77083
77129
|
mime: "image/gif",
|
|
77084
77130
|
encode: async (bitmap) => {
|
|
77085
|
-
const gif = new srcExports
|
|
77086
|
-
srcExports
|
|
77087
|
-
const newFrame = new srcExports
|
|
77088
|
-
const gifCodec = new srcExports
|
|
77131
|
+
const gif = new srcExports.BitmapImage(bitmap);
|
|
77132
|
+
srcExports.GifUtil.quantizeDekker(gif, 256);
|
|
77133
|
+
const newFrame = new srcExports.GifFrame(bitmap);
|
|
77134
|
+
const gifCodec = new srcExports.GifCodec();
|
|
77089
77135
|
const newGif = await gifCodec.encodeGif([newFrame], {});
|
|
77090
77136
|
return newGif.buffer;
|
|
77091
77137
|
},
|
|
@@ -116572,904 +116618,11 @@ const commands = {
|
|
|
116572
116618
|
},
|
|
116573
116619
|
};
|
|
116574
116620
|
|
|
116575
|
-
var srcExports = requireSrc$2();
|
|
116576
|
-
var Debug = /*@__PURE__*/getDefaultExportFromCjs(srcExports);
|
|
116577
|
-
|
|
116578
|
-
/*!
|
|
116579
|
-
* playwright-extra v4.3.5 by berstend
|
|
116580
|
-
* https://github.com/berstend/puppeteer-extra/tree/master/packages/playwright-extra#readme
|
|
116581
|
-
* @license MIT
|
|
116582
|
-
*/
|
|
116583
|
-
|
|
116584
|
-
/** Node.js module loader helper */
|
|
116585
|
-
class Loader {
|
|
116586
|
-
constructor(moduleName, packageNames) {
|
|
116587
|
-
this.moduleName = moduleName;
|
|
116588
|
-
this.packageNames = packageNames;
|
|
116589
|
-
}
|
|
116590
|
-
/**
|
|
116591
|
-
* Lazy load a top level export from another module by wrapping it in a JS proxy.
|
|
116592
|
-
*
|
|
116593
|
-
* This allows us to re-export e.g. `devices` from `playwright` while redirecting direct calls
|
|
116594
|
-
* to it to the module version the user has installed, rather than shipping with a hardcoded version.
|
|
116595
|
-
*
|
|
116596
|
-
* 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.
|
|
116597
|
-
*
|
|
116598
|
-
* We use a "super" Proxy defining all traps, so calls like `Object.keys(playwright.devices).length` will return the correct value.
|
|
116599
|
-
*/
|
|
116600
|
-
lazyloadExportOrDie(exportName) {
|
|
116601
|
-
const that = this;
|
|
116602
|
-
const trapHandler = Object.fromEntries(Object.getOwnPropertyNames(Reflect).map((name) => [
|
|
116603
|
-
name,
|
|
116604
|
-
function (target, ...args) {
|
|
116605
|
-
const moduleExport = that.loadModuleOrDie()[exportName];
|
|
116606
|
-
const customTarget = moduleExport;
|
|
116607
|
-
const result = Reflect[name](customTarget || target, ...args);
|
|
116608
|
-
return result;
|
|
116609
|
-
}
|
|
116610
|
-
]));
|
|
116611
|
-
return new Proxy({}, trapHandler);
|
|
116612
|
-
}
|
|
116613
|
-
/** Load the module if possible */
|
|
116614
|
-
loadModule() {
|
|
116615
|
-
return requirePackages(this.packageNames);
|
|
116616
|
-
}
|
|
116617
|
-
/** Load the module if possible or throw */
|
|
116618
|
-
loadModuleOrDie() {
|
|
116619
|
-
const module = requirePackages(this.packageNames);
|
|
116620
|
-
if (module) {
|
|
116621
|
-
return module;
|
|
116622
|
-
}
|
|
116623
|
-
throw this.requireError;
|
|
116624
|
-
}
|
|
116625
|
-
get requireError() {
|
|
116626
|
-
const moduleNamePretty = this.moduleName.charAt(0).toUpperCase() + this.moduleName.slice(1);
|
|
116627
|
-
return new Error(`
|
|
116628
|
-
${moduleNamePretty} is missing. :-)
|
|
116629
|
-
|
|
116630
|
-
I've tried loading ${this.packageNames
|
|
116631
|
-
.map(p => `"${p}"`)
|
|
116632
|
-
.join(', ')} - no luck.
|
|
116633
|
-
|
|
116634
|
-
Make sure you install one of those packages or use the named 'addExtra' export,
|
|
116635
|
-
to patch a specific (and maybe non-standard) implementation of ${moduleNamePretty}.
|
|
116636
|
-
|
|
116637
|
-
To get the latest stable version of ${moduleNamePretty} run:
|
|
116638
|
-
'yarn add ${this.moduleName}' or 'npm i ${this.moduleName}'
|
|
116639
|
-
`);
|
|
116640
|
-
}
|
|
116641
|
-
}
|
|
116642
|
-
function requirePackages(packageNames) {
|
|
116643
|
-
for (const name of packageNames) {
|
|
116644
|
-
try {
|
|
116645
|
-
return require(name);
|
|
116646
|
-
}
|
|
116647
|
-
catch (_) {
|
|
116648
|
-
continue; // noop
|
|
116649
|
-
}
|
|
116650
|
-
}
|
|
116651
|
-
return;
|
|
116652
|
-
}
|
|
116653
|
-
/** Playwright specific module loader */
|
|
116654
|
-
const playwrightLoader = new Loader('playwright', [
|
|
116655
|
-
'playwright-core',
|
|
116656
|
-
'playwright'
|
|
116657
|
-
]);
|
|
116658
|
-
|
|
116659
|
-
const debug = Debug('playwright-extra:puppeteer-compat');
|
|
116660
|
-
const isPlaywrightPage = (obj) => {
|
|
116661
|
-
return 'unroute' in obj;
|
|
116662
|
-
};
|
|
116663
|
-
const isPlaywrightFrame = (obj) => {
|
|
116664
|
-
return ['parentFrame', 'frameLocator'].every(x => x in obj);
|
|
116665
|
-
};
|
|
116666
|
-
const isPlaywrightBrowser = (obj) => {
|
|
116667
|
-
return 'newContext' in obj;
|
|
116668
|
-
};
|
|
116669
|
-
const isPuppeteerCompat = (obj) => {
|
|
116670
|
-
return !!obj && typeof obj === 'object' && !!obj.isCompatShim;
|
|
116671
|
-
};
|
|
116672
|
-
const cache = {
|
|
116673
|
-
objectToShim: new Map(),
|
|
116674
|
-
cdpSession: {
|
|
116675
|
-
page: new Map(),
|
|
116676
|
-
browser: new Map()
|
|
116677
|
-
}
|
|
116678
|
-
};
|
|
116679
|
-
/** Augment a Playwright object with compatibility with certain Puppeteer methods */
|
|
116680
|
-
function addPuppeteerCompat(object) {
|
|
116681
|
-
if (!object || typeof object !== 'object') {
|
|
116682
|
-
return object;
|
|
116683
|
-
}
|
|
116684
|
-
if (cache.objectToShim.has(object)) {
|
|
116685
|
-
return cache.objectToShim.get(object);
|
|
116686
|
-
}
|
|
116687
|
-
if (isPuppeteerCompat(object)) {
|
|
116688
|
-
return object;
|
|
116689
|
-
}
|
|
116690
|
-
debug('addPuppeteerCompat', cache.objectToShim.size);
|
|
116691
|
-
if (isPlaywrightPage(object) || isPlaywrightFrame(object)) {
|
|
116692
|
-
const shim = createPageShim(object);
|
|
116693
|
-
cache.objectToShim.set(object, shim);
|
|
116694
|
-
return shim;
|
|
116695
|
-
}
|
|
116696
|
-
if (isPlaywrightBrowser(object)) {
|
|
116697
|
-
const shim = createBrowserShim(object);
|
|
116698
|
-
cache.objectToShim.set(object, shim);
|
|
116699
|
-
return shim;
|
|
116700
|
-
}
|
|
116701
|
-
debug('Received unknown object:', Reflect.ownKeys(object));
|
|
116702
|
-
return object;
|
|
116703
|
-
}
|
|
116704
|
-
// Only chromium browsers support CDP
|
|
116705
|
-
const dummyCDPClient = {
|
|
116706
|
-
send: async (...args) => {
|
|
116707
|
-
debug('dummy CDP client called', 'send', args);
|
|
116708
|
-
},
|
|
116709
|
-
on: (...args) => {
|
|
116710
|
-
debug('dummy CDP client called', 'on', args);
|
|
116711
|
-
}
|
|
116712
|
-
};
|
|
116713
|
-
async function getPageCDPSession(page) {
|
|
116714
|
-
let session = cache.cdpSession.page.get(page);
|
|
116715
|
-
if (session) {
|
|
116716
|
-
debug('getPageCDPSession: use existing');
|
|
116717
|
-
return session;
|
|
116718
|
-
}
|
|
116719
|
-
debug('getPageCDPSession: use new');
|
|
116720
|
-
const context = isPlaywrightFrame(page)
|
|
116721
|
-
? page.page().context()
|
|
116722
|
-
: page.context();
|
|
116723
|
-
try {
|
|
116724
|
-
session = await context.newCDPSession(page);
|
|
116725
|
-
cache.cdpSession.page.set(page, session);
|
|
116726
|
-
return session;
|
|
116727
|
-
}
|
|
116728
|
-
catch (err) {
|
|
116729
|
-
debug('getPageCDPSession: error while creating session:', err.message);
|
|
116730
|
-
debug('getPageCDPSession: Unable create CDP session (most likely a different browser than chromium) - returning a dummy');
|
|
116731
|
-
}
|
|
116732
|
-
return dummyCDPClient;
|
|
116733
|
-
}
|
|
116734
|
-
async function getBrowserCDPSession(browser) {
|
|
116735
|
-
let session = cache.cdpSession.browser.get(browser);
|
|
116736
|
-
if (session) {
|
|
116737
|
-
debug('getBrowserCDPSession: use existing');
|
|
116738
|
-
return session;
|
|
116739
|
-
}
|
|
116740
|
-
debug('getBrowserCDPSession: use new');
|
|
116741
|
-
try {
|
|
116742
|
-
session = await browser.newBrowserCDPSession();
|
|
116743
|
-
cache.cdpSession.browser.set(browser, session);
|
|
116744
|
-
return session;
|
|
116745
|
-
}
|
|
116746
|
-
catch (err) {
|
|
116747
|
-
debug('getBrowserCDPSession: error while creating session:', err.message);
|
|
116748
|
-
debug('getBrowserCDPSession: Unable create CDP session (most likely a different browser than chromium) - returning a dummy');
|
|
116749
|
-
}
|
|
116750
|
-
return dummyCDPClient;
|
|
116751
|
-
}
|
|
116752
|
-
function createPageShim(page) {
|
|
116753
|
-
const objId = Math.random().toString(36).substring(2, 7);
|
|
116754
|
-
const shim = new Proxy(page, {
|
|
116755
|
-
get(target, prop) {
|
|
116756
|
-
if (prop === 'isCompatShim' || prop === 'isPlaywright') {
|
|
116757
|
-
return true;
|
|
116758
|
-
}
|
|
116759
|
-
debug('page - get', objId, prop);
|
|
116760
|
-
if (prop === '_client') {
|
|
116761
|
-
return () => ({
|
|
116762
|
-
send: async (method, params) => {
|
|
116763
|
-
const session = await getPageCDPSession(page);
|
|
116764
|
-
return await session.send(method, params);
|
|
116765
|
-
},
|
|
116766
|
-
on: (event, listener) => {
|
|
116767
|
-
getPageCDPSession(page).then(session => {
|
|
116768
|
-
session.on(event, listener);
|
|
116769
|
-
});
|
|
116770
|
-
}
|
|
116771
|
-
});
|
|
116772
|
-
}
|
|
116773
|
-
if (prop === 'setBypassCSP') {
|
|
116774
|
-
return async (enabled) => {
|
|
116775
|
-
const session = await getPageCDPSession(page);
|
|
116776
|
-
return await session.send('Page.setBypassCSP', {
|
|
116777
|
-
enabled
|
|
116778
|
-
});
|
|
116779
|
-
};
|
|
116780
|
-
}
|
|
116781
|
-
if (prop === 'setUserAgent') {
|
|
116782
|
-
return async (userAgent, userAgentMetadata) => {
|
|
116783
|
-
const session = await getPageCDPSession(page);
|
|
116784
|
-
return await session.send('Emulation.setUserAgentOverride', {
|
|
116785
|
-
userAgent,
|
|
116786
|
-
userAgentMetadata
|
|
116787
|
-
});
|
|
116788
|
-
};
|
|
116789
|
-
}
|
|
116790
|
-
if (prop === 'browser') {
|
|
116791
|
-
if (isPlaywrightPage(page)) {
|
|
116792
|
-
return () => {
|
|
116793
|
-
let browser = page.context().browser();
|
|
116794
|
-
if (!browser) {
|
|
116795
|
-
debug('page.browser() - not available, most likely due to launchPersistentContext');
|
|
116796
|
-
// Use a page shim as quick drop-in (so browser.userAgent() still works)
|
|
116797
|
-
browser = page;
|
|
116798
|
-
}
|
|
116799
|
-
return addPuppeteerCompat(browser);
|
|
116800
|
-
};
|
|
116801
|
-
}
|
|
116802
|
-
}
|
|
116803
|
-
if (prop === 'evaluateOnNewDocument') {
|
|
116804
|
-
if (isPlaywrightPage(page)) {
|
|
116805
|
-
return async function (pageFunction, ...args) {
|
|
116806
|
-
return await page.addInitScript(pageFunction, args[0]);
|
|
116807
|
-
};
|
|
116808
|
-
}
|
|
116809
|
-
}
|
|
116810
|
-
// Only relevant when page is being used a pseudo stand-in for the browser object (launchPersistentContext)
|
|
116811
|
-
if (prop === 'userAgent') {
|
|
116812
|
-
return async (enabled) => {
|
|
116813
|
-
const session = await getPageCDPSession(page);
|
|
116814
|
-
const data = await session.send('Browser.getVersion');
|
|
116815
|
-
return data.userAgent;
|
|
116816
|
-
};
|
|
116817
|
-
}
|
|
116818
|
-
return Reflect.get(target, prop);
|
|
116819
|
-
}
|
|
116820
|
-
});
|
|
116821
|
-
return shim;
|
|
116822
|
-
}
|
|
116823
|
-
function createBrowserShim(browser) {
|
|
116824
|
-
const objId = Math.random().toString(36).substring(2, 7);
|
|
116825
|
-
const shim = new Proxy(browser, {
|
|
116826
|
-
get(target, prop) {
|
|
116827
|
-
if (prop === 'isCompatShim' || prop === 'isPlaywright') {
|
|
116828
|
-
return true;
|
|
116829
|
-
}
|
|
116830
|
-
debug('browser - get', objId, prop);
|
|
116831
|
-
if (prop === 'pages') {
|
|
116832
|
-
return () => browser
|
|
116833
|
-
.contexts()
|
|
116834
|
-
.flatMap(c => c.pages().map(page => addPuppeteerCompat(page)));
|
|
116835
|
-
}
|
|
116836
|
-
if (prop === 'userAgent') {
|
|
116837
|
-
return async () => {
|
|
116838
|
-
const session = await getBrowserCDPSession(browser);
|
|
116839
|
-
const data = await session.send('Browser.getVersion');
|
|
116840
|
-
return data.userAgent;
|
|
116841
|
-
};
|
|
116842
|
-
}
|
|
116843
|
-
return Reflect.get(target, prop);
|
|
116844
|
-
}
|
|
116845
|
-
});
|
|
116846
|
-
return shim;
|
|
116847
|
-
}
|
|
116848
|
-
|
|
116849
|
-
const debug$1 = Debug('playwright-extra:plugins');
|
|
116850
|
-
class PluginList {
|
|
116851
|
-
constructor() {
|
|
116852
|
-
this._plugins = [];
|
|
116853
|
-
this._dependencyDefaults = new Map();
|
|
116854
|
-
this._dependencyResolution = new Map();
|
|
116855
|
-
}
|
|
116856
|
-
/**
|
|
116857
|
-
* Get a list of all registered plugins.
|
|
116858
|
-
*/
|
|
116859
|
-
get list() {
|
|
116860
|
-
return this._plugins;
|
|
116861
|
-
}
|
|
116862
|
-
/**
|
|
116863
|
-
* Get the names of all registered plugins.
|
|
116864
|
-
*/
|
|
116865
|
-
get names() {
|
|
116866
|
-
return this._plugins.map(p => p.name);
|
|
116867
|
-
}
|
|
116868
|
-
/**
|
|
116869
|
-
* Add a new plugin to the list (after checking if it's well-formed).
|
|
116870
|
-
*
|
|
116871
|
-
* @param plugin
|
|
116872
|
-
* @internal
|
|
116873
|
-
*/
|
|
116874
|
-
add(plugin) {
|
|
116875
|
-
var _a;
|
|
116876
|
-
if (!this.isValidPluginInstance(plugin)) {
|
|
116877
|
-
return false;
|
|
116878
|
-
}
|
|
116879
|
-
if (!!plugin.onPluginRegistered) {
|
|
116880
|
-
plugin.onPluginRegistered({ framework: 'playwright' });
|
|
116881
|
-
}
|
|
116882
|
-
// PuppeteerExtraPlugin: Populate `_childClassMembers` list containing methods defined by the plugin
|
|
116883
|
-
if (!!plugin._registerChildClassMembers) {
|
|
116884
|
-
plugin._registerChildClassMembers(Object.getPrototypeOf(plugin));
|
|
116885
|
-
}
|
|
116886
|
-
if ((_a = plugin.requirements) === null || _a === void 0 ? void 0 : _a.has('dataFromPlugins')) {
|
|
116887
|
-
plugin.getDataFromPlugins = this.getData.bind(this);
|
|
116888
|
-
}
|
|
116889
|
-
this._plugins.push(plugin);
|
|
116890
|
-
return true;
|
|
116891
|
-
}
|
|
116892
|
-
/** Check if the shape of a plugin is correct or warn */
|
|
116893
|
-
isValidPluginInstance(plugin) {
|
|
116894
|
-
if (!plugin ||
|
|
116895
|
-
typeof plugin !== 'object' ||
|
|
116896
|
-
!plugin._isPuppeteerExtraPlugin) {
|
|
116897
|
-
console.error(`Warning: Plugin is not derived from PuppeteerExtraPlugin, ignoring.`, plugin);
|
|
116898
|
-
return false;
|
|
116899
|
-
}
|
|
116900
|
-
if (!plugin.name) {
|
|
116901
|
-
console.error(`Warning: Plugin with no name registering, ignoring.`, plugin);
|
|
116902
|
-
return false;
|
|
116903
|
-
}
|
|
116904
|
-
return true;
|
|
116905
|
-
}
|
|
116906
|
-
/** Error callback in case calling a plugin method throws an error. Can be overwritten. */
|
|
116907
|
-
onPluginError(plugin, method, err) {
|
|
116908
|
-
console.warn(`An error occured while executing "${method}" in plugin "${plugin.name}":`, err);
|
|
116909
|
-
}
|
|
116910
|
-
/**
|
|
116911
|
-
* Define default values for plugins implicitly required through the `dependencies` plugin stanza.
|
|
116912
|
-
*
|
|
116913
|
-
* @param dependencyPath - The string by which the dependency is listed (not the plugin name)
|
|
116914
|
-
*
|
|
116915
|
-
* @example
|
|
116916
|
-
* chromium.use(stealth)
|
|
116917
|
-
* chromium.plugins.setDependencyDefaults('stealth/evasions/webgl.vendor', { vendor: 'Bob', renderer: 'Alice' })
|
|
116918
|
-
*/
|
|
116919
|
-
setDependencyDefaults(dependencyPath, opts) {
|
|
116920
|
-
this._dependencyDefaults.set(dependencyPath, opts);
|
|
116921
|
-
return this;
|
|
116922
|
-
}
|
|
116923
|
-
/**
|
|
116924
|
-
* Define custom plugin modules for plugins implicitly required through the `dependencies` plugin stanza.
|
|
116925
|
-
*
|
|
116926
|
-
* Using this will prevent dynamic imports from being used, which JS bundlers often have issues with.
|
|
116927
|
-
*
|
|
116928
|
-
* @example
|
|
116929
|
-
* chromium.use(stealth)
|
|
116930
|
-
* chromium.plugins.setDependencyResolution('stealth/evasions/webgl.vendor', VendorPlugin)
|
|
116931
|
-
*/
|
|
116932
|
-
setDependencyResolution(dependencyPath, pluginModule) {
|
|
116933
|
-
this._dependencyResolution.set(dependencyPath, pluginModule);
|
|
116934
|
-
return this;
|
|
116935
|
-
}
|
|
116936
|
-
/**
|
|
116937
|
-
* Prepare plugins to be used (resolve dependencies, ordering)
|
|
116938
|
-
* @internal
|
|
116939
|
-
*/
|
|
116940
|
-
prepare() {
|
|
116941
|
-
this.resolveDependencies();
|
|
116942
|
-
this.order();
|
|
116943
|
-
}
|
|
116944
|
-
/** Return all plugins using the supplied method */
|
|
116945
|
-
filterByMethod(methodName) {
|
|
116946
|
-
return this._plugins.filter(plugin => {
|
|
116947
|
-
// PuppeteerExtraPlugin: The base class will already define all methods, hence we need to do a different check
|
|
116948
|
-
if (!!plugin._childClassMembers &&
|
|
116949
|
-
Array.isArray(plugin._childClassMembers)) {
|
|
116950
|
-
return plugin._childClassMembers.includes(methodName);
|
|
116951
|
-
}
|
|
116952
|
-
return methodName in plugin;
|
|
116953
|
-
});
|
|
116954
|
-
}
|
|
116955
|
-
/** Conditionally add puppeteer compatibility to values provided to the plugins */
|
|
116956
|
-
_addPuppeteerCompatIfNeeded(plugin, method, args) {
|
|
116957
|
-
const canUseShim = plugin._isPuppeteerExtraPlugin && !plugin.noPuppeteerShim;
|
|
116958
|
-
const methodWhitelist = [
|
|
116959
|
-
'onBrowser',
|
|
116960
|
-
'onPageCreated',
|
|
116961
|
-
'onPageClose',
|
|
116962
|
-
'afterConnect',
|
|
116963
|
-
'afterLaunch'
|
|
116964
|
-
];
|
|
116965
|
-
const shouldUseShim = methodWhitelist.includes(method);
|
|
116966
|
-
if (!canUseShim || !shouldUseShim) {
|
|
116967
|
-
return args;
|
|
116968
|
-
}
|
|
116969
|
-
debug$1('add puppeteer compatibility', plugin.name, method);
|
|
116970
|
-
return [...args.map(arg => addPuppeteerCompat(arg))];
|
|
116971
|
-
}
|
|
116972
|
-
/**
|
|
116973
|
-
* Dispatch plugin lifecycle events in a typesafe way.
|
|
116974
|
-
* Only Plugins that expose the supplied property will be called.
|
|
116975
|
-
*
|
|
116976
|
-
* Will not await results to dispatch events as fast as possible to all plugins.
|
|
116977
|
-
*
|
|
116978
|
-
* @param method - The lifecycle method name
|
|
116979
|
-
* @param args - Optional: Any arguments to be supplied to the plugin methods
|
|
116980
|
-
* @internal
|
|
116981
|
-
*/
|
|
116982
|
-
dispatch(method, ...args) {
|
|
116983
|
-
var _a, _b;
|
|
116984
|
-
const plugins = this.filterByMethod(method);
|
|
116985
|
-
debug$1('dispatch', method, {
|
|
116986
|
-
all: this._plugins.length,
|
|
116987
|
-
filteredByMethod: plugins.length
|
|
116988
|
-
});
|
|
116989
|
-
for (const plugin of plugins) {
|
|
116990
|
-
try {
|
|
116991
|
-
args = this._addPuppeteerCompatIfNeeded.bind(this)(plugin, method, args);
|
|
116992
|
-
const fnType = (_b = (_a = plugin[method]) === null || _a === void 0 ? void 0 : _a.constructor) === null || _b === void 0 ? void 0 : _b.name;
|
|
116993
|
-
debug$1('dispatch to plugin', {
|
|
116994
|
-
plugin: plugin.name,
|
|
116995
|
-
method,
|
|
116996
|
-
fnType
|
|
116997
|
-
});
|
|
116998
|
-
if (fnType === 'AsyncFunction') {
|
|
116999
|
-
;
|
|
117000
|
-
plugin[method](...args).catch((err) => this.onPluginError(plugin, method, err));
|
|
117001
|
-
}
|
|
117002
|
-
else {
|
|
117003
|
-
;
|
|
117004
|
-
plugin[method](...args);
|
|
117005
|
-
}
|
|
117006
|
-
}
|
|
117007
|
-
catch (err) {
|
|
117008
|
-
this.onPluginError(plugin, method, err);
|
|
117009
|
-
}
|
|
117010
|
-
}
|
|
117011
|
-
}
|
|
117012
|
-
/**
|
|
117013
|
-
* Dispatch plugin lifecycle events in a typesafe way.
|
|
117014
|
-
* Only Plugins that expose the supplied property will be called.
|
|
117015
|
-
*
|
|
117016
|
-
* Can also be used to get a definite return value after passing it to plugins:
|
|
117017
|
-
* Calls plugins sequentially and passes on a value (waterfall style).
|
|
117018
|
-
*
|
|
117019
|
-
* The plugins can either modify the value or return an updated one.
|
|
117020
|
-
* Will return the latest, updated value which ran through all plugins.
|
|
117021
|
-
*
|
|
117022
|
-
* By convention only the first argument will be used as the updated value.
|
|
117023
|
-
*
|
|
117024
|
-
* @param method - The lifecycle method name
|
|
117025
|
-
* @param args - Optional: Any arguments to be supplied to the plugin methods
|
|
117026
|
-
* @internal
|
|
117027
|
-
*/
|
|
117028
|
-
async dispatchBlocking(method, ...args) {
|
|
117029
|
-
const plugins = this.filterByMethod(method);
|
|
117030
|
-
debug$1('dispatchBlocking', method, {
|
|
117031
|
-
all: this._plugins.length,
|
|
117032
|
-
filteredByMethod: plugins.length
|
|
117033
|
-
});
|
|
117034
|
-
let retValue = null;
|
|
117035
|
-
for (const plugin of plugins) {
|
|
117036
|
-
try {
|
|
117037
|
-
args = this._addPuppeteerCompatIfNeeded.bind(this)(plugin, method, args);
|
|
117038
|
-
retValue = await plugin[method](...args);
|
|
117039
|
-
// In case we got a return value use that as new first argument for followup function calls
|
|
117040
|
-
if (retValue !== undefined) {
|
|
117041
|
-
args[0] = retValue;
|
|
117042
|
-
}
|
|
117043
|
-
}
|
|
117044
|
-
catch (err) {
|
|
117045
|
-
this.onPluginError(plugin, method, err);
|
|
117046
|
-
return retValue;
|
|
117047
|
-
}
|
|
117048
|
-
}
|
|
117049
|
-
return retValue;
|
|
117050
|
-
}
|
|
117051
|
-
/**
|
|
117052
|
-
* Order plugins that have expressed a special placement requirement.
|
|
117053
|
-
*
|
|
117054
|
-
* This is useful/necessary for e.g. plugins that depend on the data from other plugins.
|
|
117055
|
-
*
|
|
117056
|
-
* @private
|
|
117057
|
-
*/
|
|
117058
|
-
order() {
|
|
117059
|
-
debug$1('order:before', this.names);
|
|
117060
|
-
const runLast = this._plugins
|
|
117061
|
-
.filter(p => { var _a; return (_a = p.requirements) === null || _a === void 0 ? void 0 : _a.has('runLast'); })
|
|
117062
|
-
.map(p => p.name);
|
|
117063
|
-
for (const name of runLast) {
|
|
117064
|
-
const index = this._plugins.findIndex(p => p.name === name);
|
|
117065
|
-
this._plugins.push(this._plugins.splice(index, 1)[0]);
|
|
117066
|
-
}
|
|
117067
|
-
debug$1('order:after', this.names);
|
|
117068
|
-
}
|
|
117069
|
-
/**
|
|
117070
|
-
* Collects the exposed `data` property of all registered plugins.
|
|
117071
|
-
* Will be reduced/flattened to a single array.
|
|
117072
|
-
*
|
|
117073
|
-
* Can be accessed by plugins that listed the `dataFromPlugins` requirement.
|
|
117074
|
-
*
|
|
117075
|
-
* Implemented mainly for plugins that need data from other plugins (e.g. `user-preferences`).
|
|
117076
|
-
*
|
|
117077
|
-
* @see [PuppeteerExtraPlugin]/data
|
|
117078
|
-
* @param name - Filter data by optional name
|
|
117079
|
-
*
|
|
117080
|
-
* @private
|
|
117081
|
-
*/
|
|
117082
|
-
getData(name) {
|
|
117083
|
-
const data = this._plugins
|
|
117084
|
-
.filter((p) => !!p.data)
|
|
117085
|
-
.map((p) => (Array.isArray(p.data) ? p.data : [p.data]))
|
|
117086
|
-
.reduce((acc, arr) => [...acc, ...arr], []);
|
|
117087
|
-
return name ? data.filter((d) => d.name === name) : data;
|
|
117088
|
-
}
|
|
117089
|
-
/**
|
|
117090
|
-
* Handle `plugins` stanza (already instantiated plugins that don't require dynamic imports)
|
|
117091
|
-
*/
|
|
117092
|
-
resolvePluginsStanza() {
|
|
117093
|
-
debug$1('resolvePluginsStanza');
|
|
117094
|
-
const pluginNames = new Set(this.names);
|
|
117095
|
-
this._plugins
|
|
117096
|
-
.filter(p => !!p.plugins && p.plugins.length)
|
|
117097
|
-
.filter(p => !pluginNames.has(p.name)) // TBD: Do we want to filter out existing?
|
|
117098
|
-
.forEach(parent => {
|
|
117099
|
-
(parent.plugins || []).forEach(p => {
|
|
117100
|
-
debug$1(parent.name, 'adding missing plugin', p.name);
|
|
117101
|
-
this.add(p);
|
|
117102
|
-
});
|
|
117103
|
-
});
|
|
117104
|
-
}
|
|
117105
|
-
/**
|
|
117106
|
-
* Handle `dependencies` stanza (which requires dynamic imports)
|
|
117107
|
-
*
|
|
117108
|
-
* Plugins can define `dependencies` as a Set or Array of dependency paths, or a Map with additional opts
|
|
117109
|
-
*
|
|
117110
|
-
* @note
|
|
117111
|
-
* - The default opts for implicit dependencies can be defined using `setDependencyDefaults()`
|
|
117112
|
-
* - Dynamic imports can be avoided by providing plugin modules with `setDependencyResolution()`
|
|
117113
|
-
*/
|
|
117114
|
-
resolveDependenciesStanza() {
|
|
117115
|
-
debug$1('resolveDependenciesStanza');
|
|
117116
|
-
/** Attempt to dynamically require a plugin module */
|
|
117117
|
-
const requireDependencyOrDie = (parentName, dependencyPath) => {
|
|
117118
|
-
// If the user provided the plugin module already we use that
|
|
117119
|
-
if (this._dependencyResolution.has(dependencyPath)) {
|
|
117120
|
-
return this._dependencyResolution.get(dependencyPath);
|
|
117121
|
-
}
|
|
117122
|
-
const possiblePrefixes = ['puppeteer-extra-plugin-']; // could be extended later
|
|
117123
|
-
const isAlreadyPrefixed = possiblePrefixes.some(prefix => dependencyPath.startsWith(prefix));
|
|
117124
|
-
const packagePaths = [];
|
|
117125
|
-
// If the dependency is not already prefixed we attempt to require all possible combinations to find one that works
|
|
117126
|
-
if (!isAlreadyPrefixed) {
|
|
117127
|
-
packagePaths.push(...possiblePrefixes.map(prefix => prefix + dependencyPath));
|
|
117128
|
-
}
|
|
117129
|
-
// We always attempt to require the path verbatim (as a last resort)
|
|
117130
|
-
packagePaths.push(dependencyPath);
|
|
117131
|
-
const pluginModule = requirePackages(packagePaths);
|
|
117132
|
-
if (pluginModule) {
|
|
117133
|
-
return pluginModule;
|
|
117134
|
-
}
|
|
117135
|
-
const explanation = `
|
|
117136
|
-
The plugin '${parentName}' listed '${dependencyPath}' as dependency,
|
|
117137
|
-
which could not be found. Please install it:
|
|
117138
|
-
|
|
117139
|
-
${packagePaths
|
|
117140
|
-
.map(packagePath => `yarn add ${packagePath.split('/')[0]}`)
|
|
117141
|
-
.join(`\n or:\n`)}
|
|
117142
|
-
|
|
117143
|
-
Note: You don't need to require the plugin yourself,
|
|
117144
|
-
unless you want to modify it's default settings.
|
|
117145
|
-
|
|
117146
|
-
If your bundler has issues with dynamic imports take a look at '.plugins.setDependencyResolution()'.
|
|
117147
|
-
`;
|
|
117148
|
-
console.warn(explanation);
|
|
117149
|
-
throw new Error('Plugin dependency not found');
|
|
117150
|
-
};
|
|
117151
|
-
const existingPluginNames = new Set(this.names);
|
|
117152
|
-
const recursivelyLoadMissingDependencies = ({ name: parentName, dependencies }) => {
|
|
117153
|
-
if (!dependencies) {
|
|
117154
|
-
return;
|
|
117155
|
-
}
|
|
117156
|
-
const processDependency = (dependencyPath, opts) => {
|
|
117157
|
-
const pluginModule = requireDependencyOrDie(parentName, dependencyPath);
|
|
117158
|
-
opts = opts || this._dependencyDefaults.get(dependencyPath) || {};
|
|
117159
|
-
const plugin = pluginModule(opts);
|
|
117160
|
-
if (existingPluginNames.has(plugin.name)) {
|
|
117161
|
-
debug$1(parentName, '=> dependency already exists:', plugin.name);
|
|
117162
|
-
return;
|
|
117163
|
-
}
|
|
117164
|
-
existingPluginNames.add(plugin.name);
|
|
117165
|
-
debug$1(parentName, '=> adding new dependency:', plugin.name, opts);
|
|
117166
|
-
this.add(plugin);
|
|
117167
|
-
return recursivelyLoadMissingDependencies(plugin);
|
|
117168
|
-
};
|
|
117169
|
-
if (dependencies instanceof Set || Array.isArray(dependencies)) {
|
|
117170
|
-
return [...dependencies].forEach(dependencyPath => processDependency(dependencyPath));
|
|
117171
|
-
}
|
|
117172
|
-
if (dependencies instanceof Map) {
|
|
117173
|
-
// Note: `k,v => v,k` (Map + forEach will reverse the order)
|
|
117174
|
-
return dependencies.forEach((v, k) => processDependency(k, v));
|
|
117175
|
-
}
|
|
117176
|
-
};
|
|
117177
|
-
this.list.forEach(recursivelyLoadMissingDependencies);
|
|
117178
|
-
}
|
|
117179
|
-
/**
|
|
117180
|
-
* Lightweight plugin dependency management to require plugins and code mods on demand.
|
|
117181
|
-
* @private
|
|
117182
|
-
*/
|
|
117183
|
-
resolveDependencies() {
|
|
117184
|
-
debug$1('resolveDependencies');
|
|
117185
|
-
this.resolvePluginsStanza();
|
|
117186
|
-
this.resolveDependenciesStanza();
|
|
117187
|
-
}
|
|
117188
|
-
}
|
|
117189
|
-
|
|
117190
|
-
const debug$2 = Debug('playwright-extra');
|
|
117191
|
-
/**
|
|
117192
|
-
* Modular plugin framework to teach `playwright` new tricks.
|
|
117193
|
-
*/
|
|
117194
|
-
class PlaywrightExtraClass {
|
|
117195
|
-
constructor(_launcher) {
|
|
117196
|
-
this._launcher = _launcher;
|
|
117197
|
-
this.plugins = new PluginList();
|
|
117198
|
-
}
|
|
117199
|
-
/**
|
|
117200
|
-
* The **main interface** to register plugins.
|
|
117201
|
-
*
|
|
117202
|
-
* Can be called multiple times to enable multiple plugins.
|
|
117203
|
-
*
|
|
117204
|
-
* Plugins derived from `PuppeteerExtraPlugin` will be used with a compatiblity layer.
|
|
117205
|
-
*
|
|
117206
|
-
* @example
|
|
117207
|
-
* chromium.use(plugin1).use(plugin2)
|
|
117208
|
-
* firefox.use(plugin1).use(plugin2)
|
|
117209
|
-
*
|
|
117210
|
-
* @see [PuppeteerExtraPlugin]
|
|
117211
|
-
*
|
|
117212
|
-
* @return The same `PlaywrightExtra` instance (for optional chaining)
|
|
117213
|
-
*/
|
|
117214
|
-
use(plugin) {
|
|
117215
|
-
const isValid = plugin && 'name' in plugin;
|
|
117216
|
-
if (!isValid) {
|
|
117217
|
-
throw new Error('A plugin must be provided to .use()');
|
|
117218
|
-
}
|
|
117219
|
-
if (this.plugins.add(plugin)) {
|
|
117220
|
-
debug$2('Plugin registered', plugin.name);
|
|
117221
|
-
}
|
|
117222
|
-
return this;
|
|
117223
|
-
}
|
|
117224
|
-
/**
|
|
117225
|
-
* In order to support a default export which will require vanilla playwright automatically,
|
|
117226
|
-
* as well as `addExtra` to patch a provided launcher, we need to so some gymnastics here.
|
|
117227
|
-
*
|
|
117228
|
-
* Otherwise this would throw immediately, even when only using the `addExtra` export with an arbitrary compatible launcher.
|
|
117229
|
-
*
|
|
117230
|
-
* The solution is to make the vanilla launcher optional and only throw once we try to effectively use and can't find it.
|
|
117231
|
-
*
|
|
117232
|
-
* @internal
|
|
117233
|
-
*/
|
|
117234
|
-
get launcher() {
|
|
117235
|
-
if (!this._launcher) {
|
|
117236
|
-
throw playwrightLoader.requireError;
|
|
117237
|
-
}
|
|
117238
|
-
return this._launcher;
|
|
117239
|
-
}
|
|
117240
|
-
async launch(...args) {
|
|
117241
|
-
if (!this.launcher.launch) {
|
|
117242
|
-
throw new Error('Launcher does not support "launch"');
|
|
117243
|
-
}
|
|
117244
|
-
let [options] = args;
|
|
117245
|
-
options = Object.assign({ args: [] }, (options || {})); // Initialize args array
|
|
117246
|
-
debug$2('launch', options);
|
|
117247
|
-
this.plugins.prepare();
|
|
117248
|
-
// Give plugins the chance to modify the options before continuing
|
|
117249
|
-
options =
|
|
117250
|
-
(await this.plugins.dispatchBlocking('beforeLaunch', options)) || options;
|
|
117251
|
-
debug$2('launch with options', options);
|
|
117252
|
-
if ('userDataDir' in options) {
|
|
117253
|
-
debug$2("A plugin defined userDataDir during .launch, which isn't supported by playwright - ignoring");
|
|
117254
|
-
delete options.userDataDir;
|
|
117255
|
-
}
|
|
117256
|
-
const browser = await this.launcher['launch'](options);
|
|
117257
|
-
await this.plugins.dispatchBlocking('onBrowser', browser);
|
|
117258
|
-
await this._bindBrowserEvents(browser);
|
|
117259
|
-
await this.plugins.dispatchBlocking('afterLaunch', browser);
|
|
117260
|
-
return browser;
|
|
117261
|
-
}
|
|
117262
|
-
async launchPersistentContext(...args) {
|
|
117263
|
-
if (!this.launcher.launchPersistentContext) {
|
|
117264
|
-
throw new Error('Launcher does not support "launchPersistentContext"');
|
|
117265
|
-
}
|
|
117266
|
-
let [userDataDir, options] = args;
|
|
117267
|
-
options = Object.assign({ args: [] }, (options || {})); // Initialize args array
|
|
117268
|
-
debug$2('launchPersistentContext', options);
|
|
117269
|
-
this.plugins.prepare();
|
|
117270
|
-
// Give plugins the chance to modify the options before continuing
|
|
117271
|
-
options =
|
|
117272
|
-
(await this.plugins.dispatchBlocking('beforeLaunch', options)) || options;
|
|
117273
|
-
const context = await this.launcher['launchPersistentContext'](userDataDir, options);
|
|
117274
|
-
await this.plugins.dispatchBlocking('afterLaunch', context);
|
|
117275
|
-
this._bindBrowserContextEvents(context);
|
|
117276
|
-
return context;
|
|
117277
|
-
}
|
|
117278
|
-
async connect(wsEndpointOrOptions, wsOptions = {}) {
|
|
117279
|
-
if (!this.launcher.connect) {
|
|
117280
|
-
throw new Error('Launcher does not support "connect"');
|
|
117281
|
-
}
|
|
117282
|
-
this.plugins.prepare();
|
|
117283
|
-
// Playwright currently supports two function signatures for .connect
|
|
117284
|
-
let options = {};
|
|
117285
|
-
let wsEndpointAsString = false;
|
|
117286
|
-
if (typeof wsEndpointOrOptions === 'object') {
|
|
117287
|
-
options = Object.assign(Object.assign({}, wsEndpointOrOptions), wsOptions);
|
|
117288
|
-
}
|
|
117289
|
-
else {
|
|
117290
|
-
wsEndpointAsString = true;
|
|
117291
|
-
options = Object.assign({ wsEndpoint: wsEndpointOrOptions }, wsOptions);
|
|
117292
|
-
}
|
|
117293
|
-
debug$2('connect', options);
|
|
117294
|
-
// Give plugins the chance to modify the options before launch/connect
|
|
117295
|
-
options =
|
|
117296
|
-
(await this.plugins.dispatchBlocking('beforeConnect', options)) || options;
|
|
117297
|
-
// Follow call signature of end user
|
|
117298
|
-
const args = [];
|
|
117299
|
-
const wsEndpoint = options.wsEndpoint;
|
|
117300
|
-
if (wsEndpointAsString) {
|
|
117301
|
-
delete options.wsEndpoint;
|
|
117302
|
-
args.push(wsEndpoint, options);
|
|
117303
|
-
}
|
|
117304
|
-
else {
|
|
117305
|
-
args.push(options);
|
|
117306
|
-
}
|
|
117307
|
-
const browser = (await this.launcher['connect'](...args));
|
|
117308
|
-
await this.plugins.dispatchBlocking('onBrowser', browser);
|
|
117309
|
-
await this._bindBrowserEvents(browser);
|
|
117310
|
-
await this.plugins.dispatchBlocking('afterConnect', browser);
|
|
117311
|
-
return browser;
|
|
117312
|
-
}
|
|
117313
|
-
async connectOverCDP(wsEndpointOrOptions, wsOptions = {}) {
|
|
117314
|
-
if (!this.launcher.connectOverCDP) {
|
|
117315
|
-
throw new Error(`Launcher does not implement 'connectOverCDP'`);
|
|
117316
|
-
}
|
|
117317
|
-
this.plugins.prepare();
|
|
117318
|
-
// Playwright currently supports two function signatures for .connectOverCDP
|
|
117319
|
-
let options = {};
|
|
117320
|
-
let wsEndpointAsString = false;
|
|
117321
|
-
if (typeof wsEndpointOrOptions === 'object') {
|
|
117322
|
-
options = Object.assign(Object.assign({}, wsEndpointOrOptions), wsOptions);
|
|
117323
|
-
}
|
|
117324
|
-
else {
|
|
117325
|
-
wsEndpointAsString = true;
|
|
117326
|
-
options = Object.assign({ endpointURL: wsEndpointOrOptions }, wsOptions);
|
|
117327
|
-
}
|
|
117328
|
-
debug$2('connectOverCDP');
|
|
117329
|
-
// Give plugins the chance to modify the options before launch/connect
|
|
117330
|
-
options =
|
|
117331
|
-
(await this.plugins.dispatchBlocking('beforeConnect', options)) || options;
|
|
117332
|
-
// Follow call signature of end user
|
|
117333
|
-
const args = [];
|
|
117334
|
-
const endpointURL = options.endpointURL;
|
|
117335
|
-
if (wsEndpointAsString) {
|
|
117336
|
-
delete options.endpointURL;
|
|
117337
|
-
args.push(endpointURL, options);
|
|
117338
|
-
}
|
|
117339
|
-
else {
|
|
117340
|
-
args.push(options);
|
|
117341
|
-
}
|
|
117342
|
-
const browser = (await this.launcher['connectOverCDP'](...args));
|
|
117343
|
-
await this.plugins.dispatchBlocking('onBrowser', browser);
|
|
117344
|
-
await this._bindBrowserEvents(browser);
|
|
117345
|
-
await this.plugins.dispatchBlocking('afterConnect', browser);
|
|
117346
|
-
return browser;
|
|
117347
|
-
}
|
|
117348
|
-
async _bindBrowserContextEvents(context, contextOptions) {
|
|
117349
|
-
debug$2('_bindBrowserContextEvents');
|
|
117350
|
-
this.plugins.dispatch('onContextCreated', context, contextOptions);
|
|
117351
|
-
// Make sure things like `addInitScript` show an effect on the very first page as well
|
|
117352
|
-
context.newPage = ((originalMethod, ctx) => {
|
|
117353
|
-
return async () => {
|
|
117354
|
-
const page = await originalMethod.call(ctx);
|
|
117355
|
-
await page.goto('about:blank');
|
|
117356
|
-
return page;
|
|
117357
|
-
};
|
|
117358
|
-
})(context.newPage, context);
|
|
117359
|
-
context.on('close', () => {
|
|
117360
|
-
// When using `launchPersistentContext` context closing is the same as browser closing
|
|
117361
|
-
if (!context.browser()) {
|
|
117362
|
-
this.plugins.dispatch('onDisconnected');
|
|
117363
|
-
}
|
|
117364
|
-
});
|
|
117365
|
-
context.on('page', page => {
|
|
117366
|
-
this.plugins.dispatch('onPageCreated', page);
|
|
117367
|
-
page.on('close', () => {
|
|
117368
|
-
this.plugins.dispatch('onPageClose', page);
|
|
117369
|
-
});
|
|
117370
|
-
});
|
|
117371
|
-
}
|
|
117372
|
-
async _bindBrowserEvents(browser) {
|
|
117373
|
-
debug$2('_bindPlaywrightBrowserEvents');
|
|
117374
|
-
browser.on('disconnected', () => {
|
|
117375
|
-
this.plugins.dispatch('onDisconnected', browser);
|
|
117376
|
-
});
|
|
117377
|
-
// Note: `browser.newPage` will implicitly call `browser.newContext` as well
|
|
117378
|
-
browser.newContext = ((originalMethod, ctx) => {
|
|
117379
|
-
return async (options = {}) => {
|
|
117380
|
-
const contextOptions = (await this.plugins.dispatchBlocking('beforeContext', options, browser)) || options;
|
|
117381
|
-
const context = await originalMethod.call(ctx, contextOptions);
|
|
117382
|
-
this._bindBrowserContextEvents(context, contextOptions);
|
|
117383
|
-
return context;
|
|
117384
|
-
};
|
|
117385
|
-
})(browser.newContext, browser);
|
|
117386
|
-
}
|
|
117387
|
-
}
|
|
117388
|
-
/**
|
|
117389
|
-
* PlaywrightExtra class with additional launcher methods.
|
|
117390
|
-
*
|
|
117391
|
-
* Augments the class with an instance proxy to pass on methods that are not augmented to the original target.
|
|
117392
|
-
*
|
|
117393
|
-
*/
|
|
117394
|
-
const PlaywrightExtra = new Proxy(PlaywrightExtraClass, {
|
|
117395
|
-
construct(classTarget, args) {
|
|
117396
|
-
debug$2(`create instance of ${classTarget.name}`);
|
|
117397
|
-
const result = Reflect.construct(classTarget, args);
|
|
117398
|
-
return new Proxy(result, {
|
|
117399
|
-
get(target, prop) {
|
|
117400
|
-
if (prop in target) {
|
|
117401
|
-
return Reflect.get(target, prop);
|
|
117402
|
-
}
|
|
117403
|
-
debug$2('proxying property to original launcher: ', prop);
|
|
117404
|
-
return Reflect.get(target.launcher, prop);
|
|
117405
|
-
}
|
|
117406
|
-
});
|
|
117407
|
-
}
|
|
117408
|
-
});
|
|
117409
|
-
|
|
117410
|
-
/**
|
|
117411
|
-
* Augment the provided Playwright browser launcher with plugin functionality.
|
|
117412
|
-
*
|
|
117413
|
-
* Using `addExtra` will always create a fresh PlaywrightExtra instance.
|
|
117414
|
-
*
|
|
117415
|
-
* @example
|
|
117416
|
-
* import playwright from 'playwright'
|
|
117417
|
-
* import { addExtra } from 'playwright-extra'
|
|
117418
|
-
*
|
|
117419
|
-
* const chromium = addExtra(playwright.chromium)
|
|
117420
|
-
* chromium.use(plugin)
|
|
117421
|
-
*
|
|
117422
|
-
* @param launcher - Playwright (or compatible) browser launcher
|
|
117423
|
-
*/
|
|
117424
|
-
const addExtra = (launcher) => new PlaywrightExtra(launcher);
|
|
117425
|
-
/**
|
|
117426
|
-
* This object can be used to launch or connect to Chromium with plugin functionality.
|
|
117427
|
-
*
|
|
117428
|
-
* This default export will behave exactly the same as the regular playwright
|
|
117429
|
-
* (just with extra plugin functionality) and can be used as a drop-in replacement.
|
|
117430
|
-
*
|
|
117431
|
-
* Behind the scenes it will try to require either the `playwright-core`
|
|
117432
|
-
* or `playwright` module from the installed dependencies.
|
|
117433
|
-
*
|
|
117434
|
-
* @note
|
|
117435
|
-
* Due to Node.js import caching this will result in a single
|
|
117436
|
-
* PlaywrightExtra instance, even when used in different files. If you need multiple
|
|
117437
|
-
* instances with different plugins please use `addExtra`.
|
|
117438
|
-
*
|
|
117439
|
-
* @example
|
|
117440
|
-
* // javascript import
|
|
117441
|
-
* const { chromium } = require('playwright-extra')
|
|
117442
|
-
*
|
|
117443
|
-
* // typescript/es6 module import
|
|
117444
|
-
* import { chromium } from 'playwright-extra'
|
|
117445
|
-
*
|
|
117446
|
-
* // Add plugins
|
|
117447
|
-
* chromium.use(...)
|
|
117448
|
-
*/
|
|
117449
|
-
const chromium = addExtra((playwrightLoader.loadModule() || {}).chromium);
|
|
117450
|
-
/**
|
|
117451
|
-
* This object can be used to launch or connect to Firefox with plugin functionality
|
|
117452
|
-
* @note This export will always return the same instance, if you wish to use multiple instances with different plugins use `addExtra`
|
|
117453
|
-
*/
|
|
117454
|
-
addExtra((playwrightLoader.loadModule() || {}).firefox);
|
|
117455
|
-
/**
|
|
117456
|
-
* This object can be used to launch or connect to Webkit with plugin functionality
|
|
117457
|
-
* @note This export will always return the same instance, if you wish to use multiple instances with different plugins use `addExtra`
|
|
117458
|
-
*/
|
|
117459
|
-
addExtra((playwrightLoader.loadModule() || {}).webkit);
|
|
117460
|
-
// Other playwright module exports we simply re-export with lazy loading
|
|
117461
|
-
playwrightLoader.lazyloadExportOrDie('_android');
|
|
117462
|
-
playwrightLoader.lazyloadExportOrDie('_electron');
|
|
117463
|
-
playwrightLoader.lazyloadExportOrDie('request');
|
|
117464
|
-
playwrightLoader.lazyloadExportOrDie('selectors');
|
|
117465
|
-
playwrightLoader.lazyloadExportOrDie('devices');
|
|
117466
|
-
playwrightLoader.lazyloadExportOrDie('errors');
|
|
117467
|
-
|
|
117468
116621
|
var stealth = test$1.extend({
|
|
117469
|
-
browser: async ({
|
|
117470
|
-
|
|
117471
|
-
|
|
117472
|
-
const stealthBrowser = await
|
|
116622
|
+
browser: async ({}, use) => {
|
|
116623
|
+
const chromiumBrowser = addExtra(chromium);
|
|
116624
|
+
chromiumBrowser.use(stealth$1());
|
|
116625
|
+
const stealthBrowser = await chromiumBrowser.launch();
|
|
117473
116626
|
await use(stealthBrowser);
|
|
117474
116627
|
await stealthBrowser.close();
|
|
117475
116628
|
},
|
|
@@ -117569,7 +116722,7 @@ const i18nFixture = {
|
|
|
117569
116722
|
i18n: [
|
|
117570
116723
|
async ({}, use) => {
|
|
117571
116724
|
const translation = readTranslations();
|
|
117572
|
-
const page = await (await chromium
|
|
116725
|
+
const page = await (await chromium.launch()).newPage();
|
|
117573
116726
|
const taxonomies = await mergeTaxonomies(translation, page);
|
|
117574
116727
|
const options = {
|
|
117575
116728
|
debug: false,
|
|
@@ -120418,44 +119571,6 @@ class Member {
|
|
|
120418
119571
|
};
|
|
120419
119572
|
}
|
|
120420
119573
|
|
|
120421
|
-
const DESCRIPTION_EDITOR_TEXTS = {
|
|
120422
|
-
fontSize: "Font size",
|
|
120423
|
-
paragraph: "Paragraph",
|
|
120424
|
-
normalText: "Normal text",
|
|
120425
|
-
pasteLink: "Paste the link here...",
|
|
120426
|
-
invalidURLError: "Please enter a valid URL",
|
|
120427
|
-
pasteURL: "Paste URL",
|
|
120428
|
-
delete: "Delete",
|
|
120429
|
-
linkTag: "a",
|
|
120430
|
-
link: "Link",
|
|
120431
|
-
cannedResponseHeader: "Canned responses",
|
|
120432
|
-
paragraphOption: "paragraph",
|
|
120433
|
-
search: "Search",
|
|
120434
|
-
emoji: "Emoji",
|
|
120435
|
-
};
|
|
120436
|
-
const EXPANDED_FONT_SIZE = {
|
|
120437
|
-
h1: "Heading 1",
|
|
120438
|
-
h2: "Heading 2",
|
|
120439
|
-
h3: "Heading 3",
|
|
120440
|
-
h4: "Heading 4",
|
|
120441
|
-
h5: "Heading 5",
|
|
120442
|
-
};
|
|
120443
|
-
const TEXT_MODIFIER_TAGS = {
|
|
120444
|
-
underline: "u",
|
|
120445
|
-
strike: "s",
|
|
120446
|
-
};
|
|
120447
|
-
const TEXT_MODIFIER_ROLES = {
|
|
120448
|
-
bold: "strong",
|
|
120449
|
-
italic: "emphasis",
|
|
120450
|
-
code: "code",
|
|
120451
|
-
blockquote: "blockquote",
|
|
120452
|
-
codeBlock: "code",
|
|
120453
|
-
};
|
|
120454
|
-
const LIST_MODIFIER_TAGS = {
|
|
120455
|
-
bulletList: "ul",
|
|
120456
|
-
orderedList: "ol",
|
|
120457
|
-
};
|
|
120458
|
-
|
|
120459
119574
|
const __dirname$4 = getDirname(import.meta.url);
|
|
120460
119575
|
class SlashCommandEditorPage {
|
|
120461
119576
|
page;
|
|
@@ -120679,6 +119794,7 @@ class EditorPage {
|
|
|
120679
119794
|
calloutSelector;
|
|
120680
119795
|
videoUploadOption;
|
|
120681
119796
|
todoListSelector;
|
|
119797
|
+
textColorSelector;
|
|
120682
119798
|
filePath = "../../../e2e/assets/images/sample.png";
|
|
120683
119799
|
videoPath = "../../../e2e/assets/files/sample.mp4";
|
|
120684
119800
|
linkUrl = faker.internet.url();
|
|
@@ -120716,6 +119832,7 @@ class EditorPage {
|
|
|
120716
119832
|
this.tableOption = this.editorWrapper.getByTestId(NEETO_EDITOR_SELECTORS.tableOption);
|
|
120717
119833
|
this.videoUploadOption = this.editorWrapper.getByTestId(NEETO_EDITOR_SELECTORS.videoUploadOption);
|
|
120718
119834
|
this.todoListSelector = this.editorWrapper.getByTestId(NEETO_EDITOR_SELECTORS.todoListOption);
|
|
119835
|
+
this.textColorSelector = this.editorWrapper.getByTestId(NEETO_EDITOR_SELECTORS.textColorOption);
|
|
120719
119836
|
}
|
|
120720
119837
|
cleanString = (selector = "") => selector?.replace("neeto-editor-fixed-menu-", "").replace("-option", "") ||
|
|
120721
119838
|
"";
|
|
@@ -120784,10 +119901,9 @@ class EditorPage {
|
|
|
120784
119901
|
.filter({ hasText: randomText })).toBeVisible();
|
|
120785
119902
|
await this.neetoPlaywrightUtilities.moveCursorAtBottom();
|
|
120786
119903
|
await this.page.keyboard.press("Enter");
|
|
120787
|
-
|
|
120788
|
-
|
|
120789
|
-
|
|
120790
|
-
}
|
|
119904
|
+
await this.contentField.click();
|
|
119905
|
+
isButtonInMoreMenu && (await this.moreMenuSelector.click());
|
|
119906
|
+
await textModifierSelector.click();
|
|
120791
119907
|
return [{ key: modifierKey, value: randomText }];
|
|
120792
119908
|
};
|
|
120793
119909
|
verifyTextDeskModifier = async (modifier, isButtonInMoreMenu) => {
|
|
@@ -120857,7 +119973,6 @@ class EditorPage {
|
|
|
120857
119973
|
await expect(this.contentField
|
|
120858
119974
|
.locator(LIST_MODIFIER_TAGS[modifierKey])
|
|
120859
119975
|
.filter({ hasText: randomText })).toBeVisible();
|
|
120860
|
-
await this.neetoPlaywrightUtilities.moveCursorAtBottom();
|
|
120861
119976
|
isButtonInMoreMenu && (await this.moreMenuSelector.click());
|
|
120862
119977
|
await listModifierSelector.click();
|
|
120863
119978
|
return [{ key: modifierKey, value: randomText }];
|
|
@@ -121052,6 +120167,31 @@ class EditorPage {
|
|
|
121052
120167
|
await expect(this.contentField.getByText(truncate(`${key}:${value}`, 25))).toBeVisible();
|
|
121053
120168
|
}
|
|
121054
120169
|
};
|
|
120170
|
+
verifyTextColor = async (isButtonInMoreMenu) => {
|
|
120171
|
+
const randomText = await this.fillRandomText();
|
|
120172
|
+
const colorPickerInput = this.page
|
|
120173
|
+
.getByTestId(COMMON_SELECTORS.customDropdownContainer())
|
|
120174
|
+
.getByTestId(COMMON_SELECTORS.inputField);
|
|
120175
|
+
await expect(async () => {
|
|
120176
|
+
isButtonInMoreMenu && (await this.moreMenuSelector.click());
|
|
120177
|
+
await this.textColorSelector.click();
|
|
120178
|
+
await expect(colorPickerInput).toBeVisible({ timeout: 5_000 });
|
|
120179
|
+
await colorPickerInput.fill(EDITOR_VERIFY_TEXT_COLOR);
|
|
120180
|
+
// Using .first() to target the button rendered by the Formik editor.
|
|
120181
|
+
await this.page
|
|
120182
|
+
.getByTestId(COMMON_SELECTORS.customDropdownContainer())
|
|
120183
|
+
.getByRole("button")
|
|
120184
|
+
// eslint-disable-next-line playwright/no-nth-methods
|
|
120185
|
+
.first()
|
|
120186
|
+
.click();
|
|
120187
|
+
await expect(colorPickerInput).toBeHidden({ timeout: 5_000 });
|
|
120188
|
+
}).toPass({ timeout: 40_000 });
|
|
120189
|
+
const coloredText = this.contentField.locator("[style]", {
|
|
120190
|
+
hasText: randomText,
|
|
120191
|
+
});
|
|
120192
|
+
await expect(coloredText).toHaveAttribute("style", editorTextColorStylePattern());
|
|
120193
|
+
return [{ key: "text-color", value: randomText }];
|
|
120194
|
+
};
|
|
121055
120195
|
verifyCalloutSelector = async (isButtonInMoreMenu) => {
|
|
121056
120196
|
isButtonInMoreMenu && (await this.moreMenuSelector.click());
|
|
121057
120197
|
const calloutTypes = ["default", "info", "warning", "error", "success"];
|
|
@@ -121087,6 +120227,7 @@ class EditorPage {
|
|
|
121087
120227
|
underline: isButtonInMoreMenu => this.verifyTextDeskModifier("underline", isButtonInMoreMenu),
|
|
121088
120228
|
strike: isButtonInMoreMenu => this.verifyTextDeskModifier("strike", isButtonInMoreMenu),
|
|
121089
120229
|
highlight: isButtonInMoreMenu => this.verifyTextHighlighter(isButtonInMoreMenu),
|
|
120230
|
+
"text-color": isButtonInMoreMenu => this.verifyTextColor(isButtonInMoreMenu),
|
|
121090
120231
|
bulletList: isButtonInMoreMenu => this.verifyListModifiers("bulletList", isButtonInMoreMenu),
|
|
121091
120232
|
orderedList: isButtonInMoreMenu => this.verifyListModifiers("orderedList", isButtonInMoreMenu),
|
|
121092
120233
|
link: isButtonInMoreMenu => this.verifyEditorLinkButton(this.linkUrl, isButtonInMoreMenu),
|
|
@@ -121095,6 +120236,7 @@ class EditorPage {
|
|
|
121095
120236
|
imageUrl: this.imageUrl,
|
|
121096
120237
|
filePath: this.filePath,
|
|
121097
120238
|
isButtonInMoreMenu,
|
|
120239
|
+
shouldRemoveImage: true,
|
|
121098
120240
|
}),
|
|
121099
120241
|
"canned-responses": isButtonInMoreMenu => this.verifyCannedResponseOption(isButtonInMoreMenu),
|
|
121100
120242
|
"video-embed": isButtonInMoreMenu => this.verifyVideoEmbedOption(this.videoUrl, isButtonInMoreMenu),
|
|
@@ -121113,9 +120255,9 @@ class EditorPage {
|
|
|
121113
120255
|
do {
|
|
121114
120256
|
randomText = faker.lorem.word(10);
|
|
121115
120257
|
} while (this.wordsUsedInEditor.includes(randomText));
|
|
121116
|
-
await this.contentField.
|
|
120258
|
+
await this.contentField.click();
|
|
121117
120259
|
await this.neetoPlaywrightUtilities.moveCursorAtBottom();
|
|
121118
|
-
await this.
|
|
120260
|
+
await this.contentField.fill(randomText);
|
|
121119
120261
|
this.wordsUsedInEditor.push(randomText);
|
|
121120
120262
|
const randomTextLocator = this.contentField.getByText(randomText);
|
|
121121
120263
|
await randomTextLocator.scrollIntoViewIfNeeded();
|
|
@@ -125760,7 +124902,7 @@ async function warmup({ urls = DEFAULT_WARMUP_URLS, timeout = 60_000, } = {}) {
|
|
|
125760
124902
|
throw new Error("RAILS_SERVER_PORT is not defined in environment variables.");
|
|
125761
124903
|
}
|
|
125762
124904
|
const baseURL = `http://${SUBDOMAIN}.lvh.me:${RAILS_SERVER_PORT}`;
|
|
125763
|
-
const browser = await chromium
|
|
124905
|
+
const browser = await chromium.launch();
|
|
125764
124906
|
const page = await browser.newPage();
|
|
125765
124907
|
try {
|
|
125766
124908
|
for (const url of urls) {
|
|
@@ -126975,4 +126117,4 @@ const definePlaywrightConfig = (overrides) => {
|
|
|
126975
126117
|
});
|
|
126976
126118
|
};
|
|
126977
126119
|
|
|
126978
|
-
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 };
|
|
126120
|
+
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, EDITOR_VERIFY_TEXT_COLOR, 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 };
|