@bigbinary/neeto-playwright-commons 1.4.6 → 1.5.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.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import * as _playwright_test from '@playwright/test';
2
2
  import { Page, APIRequestContext, Response, APIResponse, Fixtures, PlaywrightWorkerArgs, PlaywrightWorkerOptions, PlaywrightTestArgs, PlaywrightTestOptions } from '@playwright/test';
3
+ import MailosaurClient from 'mailosaur';
3
4
  import { I18nPlaywrightFixture } from 'playwright-i18next-fixture';
4
5
 
5
6
  interface InterceptMultipleResponsesParams {
@@ -16,7 +17,7 @@ interface ExecuteRecursivelyParams {
16
17
  }
17
18
  type ExecuteRecursively = (params: ExecuteRecursivelyParams) => Promise<void>;
18
19
  interface VerifySuccessToastParams {
19
- message: string;
20
+ message?: string;
20
21
  closeAfterVerification: boolean;
21
22
  }
22
23
  type VerifySuccessToast = (params: VerifySuccessToastParams) => Promise<void>;
@@ -49,9 +50,26 @@ declare class CustomCommands {
49
50
  verifyFieldValue: VerifyFieldValue;
50
51
  }
51
52
 
53
+ interface FetchOtpFromEmailFilterParameters {
54
+ email: string;
55
+ subjectSubstring?: string;
56
+ timeout?: number;
57
+ receivedAfter?: Date;
58
+ }
59
+ type FetchOtpFromEmail = (props: FetchOtpFromEmailFilterParameters) => Promise<string | undefined>;
60
+ declare class MailosaurUtils {
61
+ mailosaur: MailosaurClient;
62
+ serverId: string;
63
+ constructor(mailosaur: MailosaurClient);
64
+ fetchOtpFromEmail: FetchOtpFromEmail;
65
+ generateRandomMailosaurEmail: () => string;
66
+ }
67
+
52
68
  interface CustomFixture {
53
69
  neetoPlaywrightUtilities: CustomCommands;
54
70
  page: Page;
71
+ mailosaur: MailosaurClient;
72
+ mailosaurUtils: MailosaurUtils;
55
73
  }
56
74
  type Commands = Fixtures<CustomFixture, PlaywrightWorkerArgs & PlaywrightWorkerOptions, PlaywrightTestArgs & PlaywrightTestOptions, PlaywrightWorkerArgs & PlaywrightWorkerOptions>;
57
75
  declare const commands: Commands;
@@ -100,6 +118,7 @@ declare const CREDENTIALS: {
100
118
  email: string;
101
119
  password: string;
102
120
  };
121
+ declare const OTP_EMAIL_PATTERN = "is your login code";
103
122
 
104
123
  declare const BASE_URL = "/api/v1";
105
124
  declare const ROUTES: {
@@ -350,6 +369,11 @@ declare const updateCredentials: UpdateCredentials;
350
369
  declare const clearCredentials: ClearCredentials;
351
370
  declare const hyphenize: Hyphenize;
352
371
  declare const joinHyphenCase: JoinHyphenCase;
372
+ declare const skipTest: {
373
+ forDevelopmentEnv: () => void;
374
+ forReviewEnv: () => void;
375
+ forAllExceptStagingEnv: () => void;
376
+ };
353
377
 
354
378
  interface LoginProps {
355
379
  page: Page;
@@ -373,4 +397,4 @@ interface Overrides {
373
397
  }
374
398
  declare const definePlaywrightConfig: (overrides: Overrides) => _playwright_test.PlaywrightTestConfig<{}, {}>;
375
399
 
376
- export { BASE_URL, CHAT_WIDGET_SELECTORS, COMMON_SELECTORS, CREDENTIALS, CustomCommands, type CustomFixture, ENVIRONMENT, GLOBAL_TRANSLATIONS_PATTERN, HELP_CENTER_SELECTORS, IS_STAGING_ENV, LOGIN_SELECTORS, MEMBER_FORM_SELECTORS, MEMBER_SELECTORS, MERGE_TAGS_SELECTORS, NEETO_EDITOR_SELECTORS, NEETO_FILTERS_SELECTORS, OrganizationPage, PROJECT_TRANSLATIONS_PATH, ROLES_SELECTORS, ROUTES, SIGNUP_SELECTORS, STORAGE_STATE, TAGS_SELECTORS, clearCredentials, commands, definePlaywrightConfig, extractSubdomainFromError, generateStagingData, hyphenize, i18nFixture, initializeCredentials, joinHyphenCase, joinString, login, loginWithoutSSO, readFileSyncIfExists, updateCredentials, writeDataToFile };
400
+ export { BASE_URL, CHAT_WIDGET_SELECTORS, COMMON_SELECTORS, CREDENTIALS, CustomCommands, type CustomFixture, ENVIRONMENT, GLOBAL_TRANSLATIONS_PATTERN, HELP_CENTER_SELECTORS, IS_STAGING_ENV, LOGIN_SELECTORS, MEMBER_FORM_SELECTORS, MEMBER_SELECTORS, MERGE_TAGS_SELECTORS, MailosaurUtils, NEETO_EDITOR_SELECTORS, NEETO_FILTERS_SELECTORS, OTP_EMAIL_PATTERN, OrganizationPage, PROJECT_TRANSLATIONS_PATH, ROLES_SELECTORS, ROUTES, SIGNUP_SELECTORS, STORAGE_STATE, TAGS_SELECTORS, clearCredentials, commands, definePlaywrightConfig, extractSubdomainFromError, generateStagingData, hyphenize, i18nFixture, initializeCredentials, joinHyphenCase, joinString, login, loginWithoutSSO, readFileSyncIfExists, skipTest, updateCredentials, writeDataToFile };
package/index.js CHANGED
@@ -1,6 +1,9 @@
1
- import { expect, defineConfig, devices } from '@playwright/test';
1
+ import test, { expect, defineConfig, devices } from '@playwright/test';
2
2
  import * as require$$0 from 'fs';
3
3
  import require$$0__default from 'fs';
4
+ import { faker } from '@faker-js/faker';
5
+ import { isNil, isNotNil, mergeDeepLeft, mergeAll } from 'ramda';
6
+ import MailosaurClient from 'mailosaur';
4
7
  import dayjs from 'dayjs';
5
8
  import { getI18nInstance, initI18n } from 'playwright-i18next-fixture';
6
9
  import require$$2 from 'os';
@@ -8,7 +11,6 @@ import require$$0$1 from 'path';
8
11
  import require$$0$2 from 'util';
9
12
  import require$$0$3 from 'stream';
10
13
  import require$$0$4 from 'events';
11
- import { mergeDeepLeft, mergeAll } from 'ramda';
12
14
  import require$$3 from 'crypto';
13
15
 
14
16
  const ENVIRONMENT = {
@@ -25,7 +27,9 @@ const CREDENTIALS = {
25
27
  email: "oliver@example.com",
26
28
  password: "welcome",
27
29
  };
30
+ const OTP_EMAIL_PATTERN = "is your login code";
28
31
 
32
+ /* eslint-disable playwright/no-skipped-test */
29
33
  const joinString = (string1, string2, string3 = "", separator = " ") => {
30
34
  if (string3 === "") {
31
35
  return string1 + separator + string2;
@@ -75,6 +79,11 @@ const hyphenize = input => {
75
79
  return fallbackString;
76
80
  };
77
81
  const joinHyphenCase = (...args) => args.join(" ").replace(/\s+/g, "-").toLowerCase();
82
+ const skipTest = {
83
+ forDevelopmentEnv: () => test.skip(process.env.TEST_ENV === ENVIRONMENT.development),
84
+ forReviewEnv: () => test.skip(process.env.TEST_ENV === ENVIRONMENT.review),
85
+ forAllExceptStagingEnv: () => test.skip(process.env.TEST_ENV !== ENVIRONMENT.staging),
86
+ };
78
87
 
79
88
  const COMMON_SELECTORS = {
80
89
  spinner: ".neeto-ui-spinner",
@@ -157,7 +166,7 @@ class CustomCommands {
157
166
  const startTime = Date.now();
158
167
  await this.recursiveMethod(callback, condition, timeout, startTime);
159
168
  };
160
- this.verifySuccessToast = async ({ message, closeAfterVerification = true, }) => {
169
+ this.verifySuccessToast = async ({ message = null, closeAfterVerification = true, }) => {
161
170
  if (message) {
162
171
  await expect(this.page.getByTestId(COMMON_SELECTORS.toastMessage)).toContainText(message);
163
172
  }
@@ -166,6 +175,7 @@ class CustomCommands {
166
175
  }
167
176
  closeAfterVerification &&
168
177
  (await this.page.getByTestId(COMMON_SELECTORS.toastCloseButton).click());
178
+ await expect(this.page.locator(COMMON_SELECTORS.toastIcon)).toBeHidden();
169
179
  };
170
180
  this.reloadAndWait = async (requestCount) => {
171
181
  const reloadRequests = this.interceptMultipleResponses({
@@ -208,16 +218,53 @@ class CustomCommands {
208
218
  }
209
219
  }
210
220
 
221
+ class MailosaurUtils {
222
+ constructor(mailosaur) {
223
+ this.fetchOtpFromEmail = async ({ email, subjectSubstring = OTP_EMAIL_PATTERN, timeout = 2 * 60 * 1000, receivedAfter = new Date(), }) => {
224
+ var _a, _b, _c;
225
+ const receivedEmail = await this.mailosaur.messages.get(this.serverId, { sentTo: email, subject: subjectSubstring }, { timeout, receivedAfter });
226
+ const otp = (_c = (_b = (_a = receivedEmail === null || receivedEmail === void 0 ? void 0 : receivedEmail.text) === null || _a === void 0 ? void 0 : _a.codes) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.value;
227
+ if (isNil(otp)) {
228
+ throw new Error(`No codes found in the email with subject: ${receivedEmail.subject}. Please re-evaluate the filtering parameters.`);
229
+ }
230
+ return otp;
231
+ };
232
+ this.generateRandomMailosaurEmail = () => faker.internet.email({ provider: `${this.serverId}.mailosaur.net` });
233
+ this.mailosaur = mailosaur;
234
+ if (isNotNil(process.env.MAILOSAUR_SERVER_ID)) {
235
+ this.serverId = process.env.MAILOSAUR_SERVER_ID;
236
+ }
237
+ else {
238
+ throw new Error("ENV variable MAILOSAUR_SERVER_ID is not defined. Please add the Server ID to use this method. Please visit https://mailosaur.com/app/servers to find the Server ID.");
239
+ }
240
+ }
241
+ }
242
+
211
243
  const commands = {
212
244
  neetoPlaywrightUtilities: async ({ page, request }, use) => {
213
245
  const commands = new CustomCommands(page, request);
214
246
  await use(commands);
215
247
  },
248
+ mailosaur: async ({}, use) => {
249
+ skipTest.forAllExceptStagingEnv();
250
+ if (isNotNil(process.env.MAILOSAUR_API_KEY)) {
251
+ const mailosaur = new MailosaurClient(process.env.MAILOSAUR_API_KEY);
252
+ await use(mailosaur);
253
+ }
254
+ else {
255
+ throw new Error("ENV variable MAILOSAUR_API_KEY is not defined. Please add the API key to use this fixture. Please visit https://mailosaur.com/app/account/keys to find the API key.");
256
+ }
257
+ },
216
258
  page: async ({ page }, use) => {
217
259
  await page.goto("/");
218
260
  await page.waitForLoadState();
219
261
  await use(page);
220
262
  },
263
+ mailosaurUtils: async ({ mailosaur }, use) => {
264
+ skipTest.forAllExceptStagingEnv();
265
+ const mailosaurUtils = new MailosaurUtils(mailosaur);
266
+ await use(mailosaurUtils);
267
+ },
221
268
  };
222
269
 
223
270
  const generateStagingData = (product = "invoice") => {
@@ -1427,7 +1474,7 @@ const append = (queue = '', stash = '', enclose = false) => {
1427
1474
  return utils$g.flatten(result);
1428
1475
  };
1429
1476
 
1430
- const expand$1 = (ast, options = {}) => {
1477
+ const expand$2 = (ast, options = {}) => {
1431
1478
  let rangeLimit = options.rangeLimit === void 0 ? 1000 : options.rangeLimit;
1432
1479
 
1433
1480
  let walk = (node, parent = {}) => {
@@ -1507,7 +1554,7 @@ const expand$1 = (ast, options = {}) => {
1507
1554
  return utils$g.flatten(walk(ast));
1508
1555
  };
1509
1556
 
1510
- var expand_1 = expand$1;
1557
+ var expand_1 = expand$2;
1511
1558
 
1512
1559
  var constants$4 = {
1513
1560
  MAX_LENGTH: 1024 * 64,
@@ -1896,7 +1943,7 @@ var parse_1$1 = parse$4;
1896
1943
 
1897
1944
  const stringify = stringify$4;
1898
1945
  const compile = compile_1;
1899
- const expand = expand_1;
1946
+ const expand$1 = expand_1;
1900
1947
  const parse$3 = parse_1$1;
1901
1948
 
1902
1949
  /**
@@ -2016,7 +2063,7 @@ braces$1.expand = (input, options = {}) => {
2016
2063
  input = braces$1.parse(input, options);
2017
2064
  }
2018
2065
 
2019
- let result = expand(input, options);
2066
+ let result = expand$1(input, options);
2020
2067
 
2021
2068
  // filter out empty strings if specified
2022
2069
  if (options.noempty === true) {
@@ -7407,12 +7454,12 @@ const loginWithoutSSO = async ({ page, neetoPlaywrightUtilities, loginPath = "/"
7407
7454
  const login = async ({ page, neetoPlaywrightUtilities, loginPath, }) => !IS_STAGING_ENV &&
7408
7455
  (await loginWithoutSSO({ page, neetoPlaywrightUtilities, loginPath }));
7409
7456
 
7410
- var main$1 = {exports: {}};
7457
+ var main$2 = {exports: {}};
7411
7458
 
7412
7459
  var name = "dotenv";
7413
7460
  var version$1 = "16.3.1";
7414
7461
  var description = "Loads environment variables from .env file";
7415
- var main = "lib/main.js";
7462
+ var main$1 = "lib/main.js";
7416
7463
  var types = "lib/main.d.ts";
7417
7464
  var exports = {
7418
7465
  ".": {
@@ -7475,7 +7522,7 @@ var require$$4 = {
7475
7522
  name: name,
7476
7523
  version: version$1,
7477
7524
  description: description,
7478
- main: main,
7525
+ main: main$1,
7479
7526
  types: types,
7480
7527
  exports: exports,
7481
7528
  scripts: scripts,
@@ -7794,21 +7841,108 @@ const DotenvModule = {
7794
7841
  populate
7795
7842
  };
7796
7843
 
7797
- main$1.exports.configDotenv = DotenvModule.configDotenv;
7798
- main$1.exports._configVault = DotenvModule._configVault;
7799
- main$1.exports._parseVault = DotenvModule._parseVault;
7800
- main$1.exports.config = DotenvModule.config;
7801
- main$1.exports.decrypt = DotenvModule.decrypt;
7802
- main$1.exports.parse = DotenvModule.parse;
7803
- main$1.exports.populate = DotenvModule.populate;
7844
+ main$2.exports.configDotenv = DotenvModule.configDotenv;
7845
+ main$2.exports._configVault = DotenvModule._configVault;
7846
+ main$2.exports._parseVault = DotenvModule._parseVault;
7847
+ main$2.exports.config = DotenvModule.config;
7848
+ main$2.exports.decrypt = DotenvModule.decrypt;
7849
+ main$2.exports.parse = DotenvModule.parse;
7850
+ main$2.exports.populate = DotenvModule.populate;
7851
+
7852
+ main$2.exports = DotenvModule;
7853
+
7854
+ var main = {};
7855
+
7856
+ // like String.prototype.search but returns the last index
7857
+ function _searchLast (str, rgx) {
7858
+ const matches = Array.from(str.matchAll(rgx));
7859
+ return matches.length > 0 ? matches.slice(-1)[0].index : -1
7860
+ }
7861
+
7862
+ function _interpolate (envValue, environment, config) {
7863
+ // find the last unescaped dollar sign in the
7864
+ // value so that we can evaluate it
7865
+ const lastUnescapedDollarSignIndex = _searchLast(envValue, /(?!(?<=\\))\$/g);
7866
+
7867
+ // If we couldn't match any unescaped dollar sign
7868
+ // let's return the string as is
7869
+ if (lastUnescapedDollarSignIndex === -1) return envValue
7804
7870
 
7805
- main$1.exports = DotenvModule;
7871
+ // This is the right-most group of variables in the string
7872
+ const rightMostGroup = envValue.slice(lastUnescapedDollarSignIndex);
7873
+
7874
+ /**
7875
+ * This finds the inner most variable/group divided
7876
+ * by variable name and default value (if present)
7877
+ * (
7878
+ * (?!(?<=\\))\$ // only match dollar signs that are not escaped
7879
+ * {? // optional opening curly brace
7880
+ * ([\w]+) // match the variable name
7881
+ * (?::-([^}\\]*))? // match an optional default value
7882
+ * }? // optional closing curly brace
7883
+ * )
7884
+ */
7885
+ const matchGroup = /((?!(?<=\\))\${?([\w]+)(?::-([^}\\]*))?}?)/;
7886
+ const match = rightMostGroup.match(matchGroup);
7887
+
7888
+ if (match != null) {
7889
+ const [, group, variableName, defaultValue] = match;
7890
+
7891
+ return _interpolate(
7892
+ envValue.replace(
7893
+ group,
7894
+ environment[variableName] ||
7895
+ defaultValue ||
7896
+ config.parsed[variableName] ||
7897
+ ''
7898
+ ),
7899
+ environment,
7900
+ config
7901
+ )
7902
+ }
7903
+
7904
+ return envValue
7905
+ }
7906
+
7907
+ function _resolveEscapeSequences (value) {
7908
+ return value.replace(/\\\$/g, '$')
7909
+ }
7910
+
7911
+ function expand (config) {
7912
+ // if ignoring process.env, use a blank object
7913
+ const environment = config.ignoreProcessEnv ? {} : process.env;
7914
+
7915
+ for (const configKey in config.parsed) {
7916
+ const value = Object.prototype.hasOwnProperty.call(environment, configKey)
7917
+ ? environment[configKey]
7918
+ : config.parsed[configKey];
7919
+
7920
+ config.parsed[configKey] = _resolveEscapeSequences(
7921
+ _interpolate(value, environment, config)
7922
+ );
7923
+ }
7924
+
7925
+ for (const processKey in config.parsed) {
7926
+ environment[processKey] = config.parsed[processKey];
7927
+ }
7928
+
7929
+ return config
7930
+ }
7931
+
7932
+ main.expand = expand;
7806
7933
 
7807
7934
  // @ts-check
7808
7935
  var _a, _b;
7809
- main$1.exports.config({
7936
+ const env = main$2.exports.config({
7810
7937
  path: `./e2e/config/.env.${(_a = process.env.TEST_ENV) !== null && _a !== void 0 ? _a : "development"}`,
7811
7938
  });
7939
+ main.expand(env);
7940
+ if (require$$0.existsSync("./e2e/config/.env.local")) {
7941
+ const localEnv = main$2.exports.config({
7942
+ path: "./e2e/config/.env.local",
7943
+ });
7944
+ main.expand(localEnv);
7945
+ }
7812
7946
  const currentsConfig = {
7813
7947
  ciBuildId: process.env.NEETO_CI_JOB_ID,
7814
7948
  recordKey: "PVHNwxEOySsdAeTc",
@@ -7822,7 +7956,7 @@ const definePlaywrightConfig = (overrides) => {
7822
7956
  fullyParallel: true,
7823
7957
  forbidOnly: isCI,
7824
7958
  retries: isCI ? 1 : 0,
7825
- timeout: 0,
7959
+ timeout: 5 * 60 * 1000,
7826
7960
  reporter: isCI
7827
7961
  ? [["@currents/playwright", { ...currentsConfig, ...currentsOverrides }]]
7828
7962
  : [["line"]],
@@ -7854,5 +7988,5 @@ const definePlaywrightConfig = (overrides) => {
7854
7988
  });
7855
7989
  };
7856
7990
 
7857
- export { BASE_URL, CHAT_WIDGET_SELECTORS, COMMON_SELECTORS, CREDENTIALS, CustomCommands, ENVIRONMENT, GLOBAL_TRANSLATIONS_PATTERN, HELP_CENTER_SELECTORS, IS_STAGING_ENV, LOGIN_SELECTORS, MEMBER_FORM_SELECTORS, MEMBER_SELECTORS, MERGE_TAGS_SELECTORS, NEETO_EDITOR_SELECTORS, NEETO_FILTERS_SELECTORS, OrganizationPage, PROJECT_TRANSLATIONS_PATH, ROLES_SELECTORS, ROUTES, SIGNUP_SELECTORS, STORAGE_STATE, TAGS_SELECTORS, clearCredentials, commands, definePlaywrightConfig, extractSubdomainFromError, generateStagingData, hyphenize, i18nFixture, initializeCredentials, joinHyphenCase, joinString, login, loginWithoutSSO, readFileSyncIfExists, updateCredentials, writeDataToFile };
7991
+ export { BASE_URL, CHAT_WIDGET_SELECTORS, COMMON_SELECTORS, CREDENTIALS, CustomCommands, ENVIRONMENT, GLOBAL_TRANSLATIONS_PATTERN, HELP_CENTER_SELECTORS, IS_STAGING_ENV, LOGIN_SELECTORS, MEMBER_FORM_SELECTORS, MEMBER_SELECTORS, MERGE_TAGS_SELECTORS, MailosaurUtils, NEETO_EDITOR_SELECTORS, NEETO_FILTERS_SELECTORS, OTP_EMAIL_PATTERN, OrganizationPage, PROJECT_TRANSLATIONS_PATH, ROLES_SELECTORS, ROUTES, SIGNUP_SELECTORS, STORAGE_STATE, TAGS_SELECTORS, clearCredentials, commands, definePlaywrightConfig, extractSubdomainFromError, generateStagingData, hyphenize, i18nFixture, initializeCredentials, joinHyphenCase, joinString, login, loginWithoutSSO, readFileSyncIfExists, skipTest, updateCredentials, writeDataToFile };
7858
7992
  //# sourceMappingURL=index.js.map