@bigbinary/neeto-playwright-commons 1.1.3 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -19,13 +19,13 @@ interface VerifySuccessToastParams {
19
19
  closeAfterVerification: boolean;
20
20
  }
21
21
  type VerifySuccessToast = (params: VerifySuccessToastParams) => Promise<void>;
22
- declare const HTTP_METHODS: readonly ["get", "post", "put", "delete", "GET", "POST", "PUT", "DELETE"];
23
22
  type BasicTypesInterface = Record<string, number | string | boolean>;
23
+ type HttpMethods = "get" | "post" | "put" | "delete";
24
24
  interface ApiRequestProps {
25
25
  url: string;
26
26
  headers?: BasicTypesInterface;
27
27
  data?: Record<string, unknown>;
28
- method?: typeof HTTP_METHODS[number];
28
+ method?: HttpMethods;
29
29
  params?: BasicTypesInterface;
30
30
  }
31
31
  type ApiRequest = (props: ApiRequestProps & Record<string, unknown>) => Promise<APIResponse | undefined>;
@@ -55,7 +55,7 @@ interface CustomFixture {
55
55
  type Commands = Fixtures<CustomFixture, PlaywrightWorkerArgs & PlaywrightWorkerOptions, PlaywrightTestArgs & PlaywrightTestOptions, PlaywrightWorkerArgs & PlaywrightWorkerOptions>;
56
56
  declare const commands: Commands;
57
57
 
58
- declare const stagingData: {
58
+ declare const generateStagingData: (product?: string) => {
59
59
  firstName: string;
60
60
  lastName: string;
61
61
  otp: number;
@@ -93,7 +93,7 @@ declare class OrganizationPage {
93
93
  neetoPlaywrightUtilities: CustomCommands;
94
94
  constructor(page: Page, neetoPlaywrightUtilities: CustomCommands);
95
95
  createOrganization: ({ email, businessName, subdomainName, firstName, lastName, appName, }: CreateOrganizationProps) => Promise<void>;
96
- setupOrganization: () => Promise<void>;
96
+ setupOrganization: (product: string) => Promise<void>;
97
97
  updateSubdomainIfExists: (appName: string) => Promise<void>;
98
98
  }
99
99
 
@@ -107,6 +107,7 @@ declare const STORAGE_STATE = "./e2e/auth/user.json";
107
107
  declare const GLOBAL_TRANSLATIONS_PATTERN = "../node_modules/@bigbinary/**/translations/en.json";
108
108
  declare const PROJECT_TRANSLATIONS_PATH = "../app/javascript/src/translations/en.json";
109
109
  declare const CREDENTIALS: {
110
+ name: string;
110
111
  email: string;
111
112
  password: string;
112
113
  };
@@ -166,7 +167,7 @@ declare const COMMON_TEXTS: {
166
167
  edit: string;
167
168
  };
168
169
 
169
- declare const initializeCredentials: () => void;
170
+ declare const initializeCredentials: (product: string) => void;
170
171
 
171
172
  interface KeyValue {
172
173
  key: string;
@@ -191,9 +192,10 @@ declare const readTranslations: () => Record<string, unknown>;
191
192
  interface LoginProps {
192
193
  page: Page;
193
194
  neetoPlaywrightUtilities: CustomCommands;
195
+ loginPath: string;
194
196
  }
195
- declare const loginWithoutSSO: ({ page, neetoPlaywrightUtilities, }: LoginProps) => Promise<void>;
196
- declare const login: ({ page, neetoPlaywrightUtilities }: LoginProps) => Promise<false | void>;
197
+ declare const loginWithoutSSO: ({ page, neetoPlaywrightUtilities, loginPath, }: LoginProps) => Promise<void>;
198
+ declare const login: ({ page, neetoPlaywrightUtilities, loginPath, }: LoginProps) => Promise<false | void>;
197
199
 
198
200
  interface CurrentsOverrides {
199
201
  projectId: string;
@@ -206,4 +208,4 @@ interface Overrides {
206
208
  }
207
209
  declare const definePlaywrightConfig: (overrides: Overrides) => _playwright_test.PlaywrightTestConfig<{}, {}>;
208
210
 
209
- export { BASE_URL, COMMON_SELECTORS, COMMON_TEXTS, CREDENTIALS, CustomCommands, type CustomFixture, ENVIRONMENT, GLOBAL_TRANSLATIONS_PATTERN, IS_STAGING_ENV, LOGIN_SELECTORS, OrganizationPage, PROJECT_TRANSLATIONS_PATH, ROUTES, SIGNUP_SELECTORS, STORAGE_STATE, clearCredentials, commands, definePlaywrightConfig, i18n, initializeCredentials, joinString, login, loginWithoutSSO, readFileSyncIfExists, readTranslations, stagingData, updateCredentials, writeDataToFile };
211
+ export { BASE_URL, COMMON_SELECTORS, COMMON_TEXTS, CREDENTIALS, CustomCommands, type CustomFixture, ENVIRONMENT, GLOBAL_TRANSLATIONS_PATTERN, IS_STAGING_ENV, LOGIN_SELECTORS, OrganizationPage, PROJECT_TRANSLATIONS_PATH, ROUTES, SIGNUP_SELECTORS, STORAGE_STATE, clearCredentials, commands, definePlaywrightConfig, generateStagingData, i18n, initializeCredentials, joinString, login, loginWithoutSSO, readFileSyncIfExists, readTranslations, updateCredentials, writeDataToFile };
package/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { expect, defineConfig, devices } from '@playwright/test';
2
+ import dayjs from 'dayjs';
2
3
  import * as require$$0 from 'fs';
3
4
  import require$$0__default from 'fs';
4
5
  import require$$2 from 'os';
@@ -6,8 +7,7 @@ import require$$0$1 from 'path';
6
7
  import require$$0$2 from 'util';
7
8
  import require$$0$3 from 'stream';
8
9
  import require$$0$4 from 'events';
9
- import { mergeDeepLeft } from 'ramda';
10
- import dayjs from 'dayjs';
10
+ import { mergeDeepLeft, mergeAll } from 'ramda';
11
11
  import require$$3 from 'crypto';
12
12
 
13
13
  const COMMON_SELECTORS = {
@@ -23,6 +23,115 @@ const COMMON_SELECTORS = {
23
23
  subheaderText: "subheader-left",
24
24
  };
25
25
 
26
+ class CustomCommands {
27
+ constructor(page, request) {
28
+ this.interceptMultipleResponses = ({ responseUrl = "", times = 1, baseUrl, }) => Promise.all([...new Array(times)].map(() => this.page.waitForResponse((response) => {
29
+ var _a, _b, _c;
30
+ if (response.request().resourceType() === "xhr" &&
31
+ response.status() === 200 &&
32
+ response.url().includes(responseUrl) &&
33
+ response
34
+ .url()
35
+ .startsWith((_a = baseUrl !== null && baseUrl !== void 0 ? baseUrl : process.env.BASE_URL) !== null && _a !== void 0 ? _a : "") &&
36
+ !this.responses.includes((_b = response.headers()) === null || _b === void 0 ? void 0 : _b["x-request-id"])) {
37
+ this.responses.push((_c = response.headers()) === null || _c === void 0 ? void 0 : _c["x-request-id"]);
38
+ return true;
39
+ }
40
+ return false;
41
+ }, { timeout: 10000 })));
42
+ this.recursiveMethod = async (callback, condition, timeout, startTime) => {
43
+ if (Date.now() - timeout >= startTime) {
44
+ return false;
45
+ }
46
+ else if (await condition()) {
47
+ return await callback();
48
+ }
49
+ return await this.recursiveMethod(callback, condition, timeout, startTime);
50
+ };
51
+ this.executeRecursively = async ({ callback, condition, timeout = 5000, }) => {
52
+ const startTime = Date.now();
53
+ await this.recursiveMethod(callback, condition, timeout, startTime);
54
+ };
55
+ this.verifySuccessToast = async ({ message, closeAfterVerification = true, }) => {
56
+ if (message) {
57
+ await expect(this.page.getByTestId(COMMON_SELECTORS.toastMessage)).toHaveValue(message);
58
+ }
59
+ else {
60
+ await expect(this.page.locator(COMMON_SELECTORS.toastIcon)).toHaveValue("👍");
61
+ closeAfterVerification &&
62
+ (await this.page
63
+ .getByTestId(COMMON_SELECTORS.toastCloseButton)
64
+ .click());
65
+ }
66
+ };
67
+ this.reloadAndWait = async (requestCount) => {
68
+ const reloadRequests = this.interceptMultipleResponses({
69
+ times: requestCount,
70
+ });
71
+ await this.page.reload();
72
+ await reloadRequests;
73
+ };
74
+ this.apiRequest = async ({ url, headers: additionalHeaders, body: data, method = "get", params = {}, ...otherOptions }) => {
75
+ const csrfToken = await this.page
76
+ .locator("[name='csrf-token']")
77
+ .getAttribute("content");
78
+ const requestOptions = {
79
+ headers: {
80
+ ...additionalHeaders,
81
+ "accept-encoding": "gzip",
82
+ "x-csrf-token": csrfToken !== null && csrfToken !== void 0 ? csrfToken : "",
83
+ },
84
+ data,
85
+ params,
86
+ ...otherOptions,
87
+ };
88
+ const httpMethodsHandlers = {
89
+ get: () => this.request.get(url, requestOptions),
90
+ post: () => this.request.post(url, requestOptions),
91
+ put: () => this.request.put(url, requestOptions),
92
+ delete: () => this.request.delete(url, requestOptions),
93
+ };
94
+ return await httpMethodsHandlers[method]();
95
+ };
96
+ this.verifyFieldValue = values => {
97
+ const verifyEachFieldValue = ({ field, value, }) => expect(this.page.getByTestId(field)).toHaveValue(value);
98
+ return Array.isArray(values)
99
+ ? Promise.all(values.map(value => verifyEachFieldValue(value)))
100
+ : verifyEachFieldValue(values);
101
+ };
102
+ this.page = page;
103
+ this.responses = [];
104
+ this.request = request;
105
+ }
106
+ }
107
+
108
+ const commands = {
109
+ neetoPlaywrightUtilities: async ({ page, request }, use) => {
110
+ const commands = new CustomCommands(page, request);
111
+ await use(commands);
112
+ },
113
+ page: async ({ page }, use) => {
114
+ await page.goto("/");
115
+ await page.waitForLoadState();
116
+ await use(page);
117
+ },
118
+ };
119
+
120
+ const ENVIRONMENT = {
121
+ development: "development",
122
+ staging: "staging",
123
+ review: "review",
124
+ };
125
+ const IS_STAGING_ENV = process.env.TEST_ENV === "staging";
126
+ const STORAGE_STATE = "./e2e/auth/user.json";
127
+ const GLOBAL_TRANSLATIONS_PATTERN = "../node_modules/@bigbinary/**/translations/en.json";
128
+ const PROJECT_TRANSLATIONS_PATH = "../app/javascript/src/translations/en.json";
129
+ const CREDENTIALS = {
130
+ name: "Oliver Smith",
131
+ email: "oliver@example.com",
132
+ password: "welcome",
133
+ };
134
+
26
135
  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
27
136
 
28
137
  var tasks = {};
@@ -6721,17 +6830,6 @@ function assertPatternsInput(input) {
6721
6830
  }
6722
6831
  var out = FastGlob;
6723
6832
 
6724
- const ENVIRONMENT = {
6725
- development: "development",
6726
- staging: "staging",
6727
- review: "review",
6728
- };
6729
- const IS_STAGING_ENV = process.env.TEST_ENV === "staging";
6730
- const STORAGE_STATE = "./e2e/auth/user.json";
6731
- const GLOBAL_TRANSLATIONS_PATTERN = "../node_modules/@bigbinary/**/translations/en.json";
6732
- const PROJECT_TRANSLATIONS_PATH = "../app/javascript/src/translations/en.json";
6733
- const CREDENTIALS = { email: "oliver@example.com", password: "welcome" };
6734
-
6735
6833
  const joinString = (string1, string2, string3 = "", separator = " ") => {
6736
6834
  if (string3 === "") {
6737
6835
  return string1 + separator + string2;
@@ -6777,112 +6875,26 @@ const readTranslations = () => {
6777
6875
  return translations;
6778
6876
  };
6779
6877
 
6780
- class CustomCommands {
6781
- constructor(page, request) {
6782
- this.interceptMultipleResponses = ({ responseUrl = "", times = 1, baseUrl, }) => Promise.all([...new Array(times)].map(() => this.page.waitForResponse(response => {
6783
- var _a, _b, _c;
6784
- if (response.request().resourceType() === "xhr" &&
6785
- response.status() === 200 &&
6786
- response.url().includes(responseUrl) &&
6787
- response
6788
- .url()
6789
- .startsWith((_a = baseUrl !== null && baseUrl !== void 0 ? baseUrl : process.env.BASE_URL) !== null && _a !== void 0 ? _a : "") &&
6790
- !this.responses.includes((_b = response.headers()) === null || _b === void 0 ? void 0 : _b["x-request-id"])) {
6791
- this.responses.push((_c = response.headers()) === null || _c === void 0 ? void 0 : _c["x-request-id"]);
6792
- return true;
6793
- }
6794
- return false;
6795
- }, { timeout: 10000 })));
6796
- this.recursiveMethod = async (callback, condition, timeout, startTime) => {
6797
- if (Date.now() - timeout >= startTime) {
6798
- return false;
6799
- }
6800
- else if (await condition()) {
6801
- return await callback();
6802
- }
6803
- return await this.recursiveMethod(callback, condition, timeout, startTime);
6804
- };
6805
- this.executeRecursively = async ({ callback, condition, timeout = 5000, }) => {
6806
- const startTime = Date.now();
6807
- await this.recursiveMethod(callback, condition, timeout, startTime);
6808
- };
6809
- this.verifySuccessToast = async ({ message, closeAfterVerification = true, }) => {
6810
- if (message) {
6811
- await expect(this.page.getByTestId(COMMON_SELECTORS.toastMessage)).toHaveValue(message);
6812
- }
6813
- else {
6814
- await expect(this.page.locator(COMMON_SELECTORS.toastIcon)).toHaveValue("👍");
6815
- closeAfterVerification &&
6816
- (await this.page
6817
- .getByTestId(COMMON_SELECTORS.toastCloseButton)
6818
- .click());
6819
- }
6820
- };
6821
- this.reloadAndWait = async (requestCount) => {
6822
- const reloadRequests = this.interceptMultipleResponses({
6823
- times: requestCount,
6824
- });
6825
- await this.page.reload();
6826
- await reloadRequests;
6827
- };
6828
- this.apiRequest = async ({ url, headers: additionalHeaders, body: data, method = "get", params = {}, ...otherOptions }) => {
6829
- const { headers } = readFileSyncIfExists();
6830
- const requestOptions = {
6831
- headers: { ...headers, ...additionalHeaders, "accept-encoding": "gzip" },
6832
- data,
6833
- params,
6834
- ...otherOptions,
6835
- };
6836
- const httpMethodsHandlers = {
6837
- get: () => this.request.get(url, requestOptions),
6838
- post: () => this.request.post(url, requestOptions),
6839
- put: () => this.request.put(url, requestOptions),
6840
- delete: () => this.request.delete(url, requestOptions),
6841
- };
6842
- return await httpMethodsHandlers[method.toLowerCase()]();
6843
- };
6844
- this.verifyFieldValue = values => {
6845
- const verifyEachFieldValue = ({ field, value, }) => expect(this.page.getByTestId(field)).toHaveValue(value);
6846
- return Array.isArray(values)
6847
- ? Promise.all(values.map(value => verifyEachFieldValue(value)))
6848
- : verifyEachFieldValue(values);
6849
- };
6850
- this.page = page;
6851
- this.responses = [];
6852
- this.request = request;
6853
- }
6854
- }
6855
-
6856
- const commands = {
6857
- neetoPlaywrightUtilities: async ({ page, request }, use) => {
6858
- const commands = new CustomCommands(page, request);
6859
- await use(commands);
6860
- },
6861
- page: async ({ page }, use) => {
6862
- await page.goto("/");
6863
- await page.waitForLoadState();
6864
- await use(page);
6865
- },
6866
- };
6867
-
6868
- const timestamp = dayjs().format("YYYYMMDDHH");
6869
- const firstName = "André";
6870
- const lastName = "O'Reilly";
6871
- const stagingOrganization = `cypresstest-invoice-${timestamp}`;
6872
- const otpBypassKey = process.env.OTP_BYPASS_KEY;
6873
- const stagingData = {
6874
- firstName,
6875
- lastName,
6876
- otp: 111111,
6877
- domain: "neetoinvoice.net",
6878
- currentUserName: IS_STAGING_ENV
6879
- ? joinString(firstName, lastName)
6880
- : "Oliver Smith",
6881
- businessName: stagingOrganization,
6882
- subdomainName: IS_STAGING_ENV ? stagingOrganization : "spinkart",
6883
- email: IS_STAGING_ENV
6884
- ? `cypresstest${otpBypassKey}+invoice+${timestamp}-playwright@bigbinary.com`
6885
- : "oliver@example.com",
6878
+ const generateStagingData = (product = "invoice") => {
6879
+ const timestamp = dayjs().format("YYYYMMDDHH");
6880
+ const firstName = "André";
6881
+ const lastName = "O'Reilly";
6882
+ const otpBypassKey = process.env.OTP_BYPASS_KEY;
6883
+ const stagingOrganization = `cypresstest-${product}-${timestamp}`;
6884
+ return {
6885
+ firstName,
6886
+ lastName,
6887
+ otp: 111111,
6888
+ domain: `neeto${product}.net`,
6889
+ currentUserName: IS_STAGING_ENV
6890
+ ? joinString(firstName, lastName)
6891
+ : CREDENTIALS.name,
6892
+ businessName: stagingOrganization,
6893
+ subdomainName: IS_STAGING_ENV ? stagingOrganization : "spinkart",
6894
+ email: IS_STAGING_ENV
6895
+ ? `cypresstest${otpBypassKey}+${product}+${timestamp}-playwright@bigbinary.com`
6896
+ : "oliver@example.com",
6897
+ };
6886
6898
  };
6887
6899
 
6888
6900
  const i18n = {
@@ -6987,10 +6999,9 @@ class OrganizationPage {
6987
6999
  await this.page.getByTestId(SIGNUP_SELECTORS.profileSubmitButton).click();
6988
7000
  await submitProfile;
6989
7001
  };
6990
- this.setupOrganization = async () => {
7002
+ this.setupOrganization = async (product) => {
6991
7003
  if (!IS_STAGING_ENV)
6992
7004
  return;
6993
- let headers = {};
6994
7005
  const { user } = readFileSyncIfExists();
6995
7006
  await this.createOrganization({
6996
7007
  businessName: user.businessName,
@@ -6998,20 +7009,15 @@ class OrganizationPage {
6998
7009
  firstName: user.firstName,
6999
7010
  lastName: user.lastName,
7000
7011
  subdomainName: user.subdomainName,
7001
- appName: "neetoInvoice",
7002
- });
7003
- await this.page.route(`**${ROUTES.neetoApps}`, async (route) => {
7004
- headers = await route.request().allHeaders();
7005
- await route.continue();
7012
+ appName: `neeto${product}`,
7006
7013
  });
7007
7014
  await expect(this.page.locator(COMMON_SELECTORS.spinner)).toBeHidden();
7008
7015
  const userCredentials = readFileSyncIfExists();
7009
7016
  await this.page.context().storageState({ path: STORAGE_STATE });
7010
- const mergedCredentials = {
7011
- ...readFileSyncIfExists(),
7012
- ...userCredentials,
7013
- headers,
7014
- };
7017
+ const mergedCredentials = mergeAll([
7018
+ readFileSyncIfExists(),
7019
+ userCredentials,
7020
+ ]);
7015
7021
  writeDataToFile(JSON.stringify(mergedCredentials, null, 2));
7016
7022
  };
7017
7023
  this.updateSubdomainIfExists = async (appName) => {
@@ -7065,8 +7071,9 @@ const LOGIN_SELECTORS = {
7065
7071
 
7066
7072
  const COMMON_TEXTS = { edit: "Edit" };
7067
7073
 
7068
- const initializeCredentials = () => {
7074
+ const initializeCredentials = (product) => {
7069
7075
  const { user } = readFileSyncIfExists();
7076
+ const stagingData = generateStagingData(product);
7070
7077
  const newState = {
7071
7078
  ...user,
7072
7079
  businessName: (user === null || user === void 0 ? void 0 : user.businessName) || stagingData.businessName,
@@ -7084,10 +7091,9 @@ const initializeCredentials = () => {
7084
7091
  }
7085
7092
  };
7086
7093
 
7087
- const loginWithoutSSO = async ({ page, neetoPlaywrightUtilities, }) => {
7094
+ const loginWithoutSSO = async ({ page, neetoPlaywrightUtilities, loginPath = "/", }) => {
7088
7095
  var _a;
7089
- await page.goto((_a = process.env.BASE_URL) !== null && _a !== void 0 ? _a : "");
7090
- let headers = {};
7096
+ await page.goto((_a = `${process.env.BASE_URL}${loginPath}`) !== null && _a !== void 0 ? _a : "");
7091
7097
  await page.getByTestId("login-email-text-field").fill(CREDENTIALS.email);
7092
7098
  await page
7093
7099
  .getByTestId("login-password-text-field")
@@ -7097,23 +7103,16 @@ const loginWithoutSSO = async ({ page, neetoPlaywrightUtilities, }) => {
7097
7103
  });
7098
7104
  await page.getByTestId(LOGIN_SELECTORS.submitButton).click();
7099
7105
  await login;
7100
- await page.route(`**${BASE_URL}/**`, async (route) => {
7101
- headers = await route.request().allHeaders();
7102
- await route.continue();
7103
- });
7104
7106
  const userCredentials = readFileSyncIfExists();
7105
7107
  await page.context().storageState({ path: STORAGE_STATE });
7106
- //eslint-disable-next-line
7107
- await page.waitForTimeout(5000); // There is a delay in headers being set from the route.
7108
- const mergedCredentials = {
7109
- ...readFileSyncIfExists(),
7110
- ...userCredentials,
7111
- headers,
7112
- };
7108
+ const mergedCredentials = mergeAll([
7109
+ readFileSyncIfExists(),
7110
+ userCredentials,
7111
+ ]);
7113
7112
  writeDataToFile(JSON.stringify(mergedCredentials, null, 2));
7114
7113
  };
7115
- const login = async ({ page, neetoPlaywrightUtilities }) => !IS_STAGING_ENV &&
7116
- (await loginWithoutSSO({ page, neetoPlaywrightUtilities }));
7114
+ const login = async ({ page, neetoPlaywrightUtilities, loginPath, }) => !IS_STAGING_ENV &&
7115
+ (await loginWithoutSSO({ page, neetoPlaywrightUtilities, loginPath }));
7117
7116
 
7118
7117
  var main$1 = {exports: {}};
7119
7118
 
@@ -7563,5 +7562,5 @@ const definePlaywrightConfig = (overrides) => {
7563
7562
  });
7564
7563
  };
7565
7564
 
7566
- export { BASE_URL, COMMON_SELECTORS, COMMON_TEXTS, CREDENTIALS, CustomCommands, ENVIRONMENT, GLOBAL_TRANSLATIONS_PATTERN, IS_STAGING_ENV, LOGIN_SELECTORS, OrganizationPage, PROJECT_TRANSLATIONS_PATH, ROUTES, SIGNUP_SELECTORS, STORAGE_STATE, clearCredentials, commands, definePlaywrightConfig, i18n, initializeCredentials, joinString, login, loginWithoutSSO, readFileSyncIfExists, readTranslations, stagingData, updateCredentials, writeDataToFile };
7565
+ export { BASE_URL, COMMON_SELECTORS, COMMON_TEXTS, CREDENTIALS, CustomCommands, ENVIRONMENT, GLOBAL_TRANSLATIONS_PATTERN, IS_STAGING_ENV, LOGIN_SELECTORS, OrganizationPage, PROJECT_TRANSLATIONS_PATH, ROUTES, SIGNUP_SELECTORS, STORAGE_STATE, clearCredentials, commands, definePlaywrightConfig, generateStagingData, i18n, initializeCredentials, joinString, login, loginWithoutSSO, readFileSyncIfExists, readTranslations, updateCredentials, writeDataToFile };
7567
7566
  //# sourceMappingURL=index.js.map