@commercetools-frontend/cypress 24.3.0 → 24.4.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/add-commands/dist/commercetools-frontend-cypress-add-commands.cjs.dev.js +229 -148
- package/add-commands/dist/commercetools-frontend-cypress-add-commands.cjs.prod.js +229 -148
- package/add-commands/dist/commercetools-frontend-cypress-add-commands.esm.js +226 -144
- package/dist/commercetools-frontend-cypress.cjs.dev.js +1 -1
- package/dist/commercetools-frontend-cypress.cjs.prod.js +1 -1
- package/dist/commercetools-frontend-cypress.esm.js +1 -1
- package/dist/declarations/src/add-commands/login.d.ts +1 -3
- package/package.json +4 -4
|
@@ -10,13 +10,10 @@ var _Object$defineProperties = require('@babel/runtime-corejs3/core-js-stable/ob
|
|
|
10
10
|
var _Object$defineProperty = require('@babel/runtime-corejs3/core-js-stable/object/define-property');
|
|
11
11
|
var _defineProperty = require('@babel/runtime-corejs3/helpers/defineProperty');
|
|
12
12
|
var _findInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/find');
|
|
13
|
-
var constants
|
|
14
|
-
var _JSON$stringify = require('@babel/runtime-corejs3/core-js-stable/json/stringify');
|
|
13
|
+
var constants = require('@commercetools-frontend/constants');
|
|
15
14
|
var _URL = require('@babel/runtime-corejs3/core-js-stable/url');
|
|
16
15
|
var semver = require('semver');
|
|
17
|
-
var
|
|
18
|
-
var ssr = require('@commercetools-frontend/application-shell/ssr');
|
|
19
|
-
var constants = require('../../dist/constants-009cb682.cjs.dev.js');
|
|
16
|
+
var constants$1 = require('../../dist/constants-009cb682.cjs.dev.js');
|
|
20
17
|
var _slicedToArray = require('@babel/runtime-corejs3/helpers/slicedToArray');
|
|
21
18
|
var _mapInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/map');
|
|
22
19
|
var _Array$from = require('@babel/runtime-corejs3/core-js-stable/array/from');
|
|
@@ -34,7 +31,6 @@ var _Object$getOwnPropertyDescriptors__default = /*#__PURE__*/_interopDefault(_O
|
|
|
34
31
|
var _Object$defineProperties__default = /*#__PURE__*/_interopDefault(_Object$defineProperties);
|
|
35
32
|
var _Object$defineProperty__default = /*#__PURE__*/_interopDefault(_Object$defineProperty);
|
|
36
33
|
var _findInstanceProperty__default = /*#__PURE__*/_interopDefault(_findInstanceProperty);
|
|
37
|
-
var _JSON$stringify__default = /*#__PURE__*/_interopDefault(_JSON$stringify);
|
|
38
34
|
var _URL__default = /*#__PURE__*/_interopDefault(_URL);
|
|
39
35
|
var semver__default = /*#__PURE__*/_interopDefault(semver);
|
|
40
36
|
var _mapInstanceProperty__default = /*#__PURE__*/_interopDefault(_mapInstanceProperty);
|
|
@@ -43,7 +39,7 @@ var _entriesInstanceProperty__default = /*#__PURE__*/_interopDefault(_entriesIns
|
|
|
43
39
|
var _reduceRightInstanceProperty__default = /*#__PURE__*/_interopDefault(_reduceRightInstanceProperty);
|
|
44
40
|
|
|
45
41
|
function ownKeys$1(e, r) { var t = _Object$keys__default["default"](e); if (_Object$getOwnPropertySymbols__default["default"]) { var o = _Object$getOwnPropertySymbols__default["default"](e); r && (o = _filterInstanceProperty__default["default"](o).call(o, function (r) { return _Object$getOwnPropertyDescriptor__default["default"](e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
46
|
-
function _objectSpread$1(e) { for (var r = 1; r < arguments.length; r++) { var
|
|
42
|
+
function _objectSpread$1(e) { for (var r = 1; r < arguments.length; r++) { var _context2, _context3; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty__default["default"](_context2 = ownKeys$1(Object(t), !0)).call(_context2, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors__default["default"] ? _Object$defineProperties__default["default"](e, _Object$getOwnPropertyDescriptors__default["default"](t)) : _forEachInstanceProperty__default["default"](_context3 = ownKeys$1(Object(t))).call(_context3, function (r) { _Object$defineProperty__default["default"](e, r, _Object$getOwnPropertyDescriptor__default["default"](t, r)); }); } return e; }
|
|
47
43
|
|
|
48
44
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
49
45
|
|
|
@@ -54,15 +50,27 @@ function _objectSpread$1(e) { for (var r = 1; r < arguments.length; r++) { var _
|
|
|
54
50
|
function isFeatureSupported(expectedVersion) {
|
|
55
51
|
return semver__default["default"].gte(Cypress.version, expectedVersion);
|
|
56
52
|
}
|
|
53
|
+
function isRunningOnLocalhost() {
|
|
54
|
+
const baseUrl = new _URL__default["default"](Cypress.config('baseUrl'));
|
|
55
|
+
return baseUrl.hostname === 'localhost';
|
|
56
|
+
}
|
|
57
|
+
const isCustomView = commandOptions => commandOptions.entryPointUriPath === constants.CUSTOM_VIEW_HOST_ENTRY_POINT_URI_PATH;
|
|
57
58
|
function loginByForm(commandOptions) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
const isLocalhost = isRunningOnLocalhost();
|
|
60
|
+
Cypress.log({
|
|
61
|
+
name: 'isLocalhost',
|
|
62
|
+
message: isLocalhost
|
|
63
|
+
});
|
|
61
64
|
const projectKey = commandOptions.projectKey ?? Cypress.env('PROJECT_KEY');
|
|
62
|
-
|
|
65
|
+
const isCustomViewConfigCommand = isCustomView(commandOptions);
|
|
66
|
+
const customEntityConfigCommand = isCustomViewConfigCommand ? 'customViewConfig' : 'customApplicationConfig';
|
|
67
|
+
const packageName = commandOptions.packageName ?? Cypress.env('PACKAGE_NAME');
|
|
68
|
+
cy.task(customEntityConfigCommand, _objectSpread$1({
|
|
63
69
|
entryPointUriPath: commandOptions.entryPointUriPath,
|
|
64
70
|
dotfiles: commandOptions.dotfiles
|
|
65
|
-
},
|
|
71
|
+
}, isCustomViewConfigCommand ? {
|
|
72
|
+
packageName
|
|
73
|
+
} : {}),
|
|
66
74
|
// Do not show log, as it may contain sensible information.
|
|
67
75
|
{
|
|
68
76
|
log: false
|
|
@@ -75,7 +83,7 @@ function loginByForm(commandOptions) {
|
|
|
75
83
|
// Log loaded application config for debugging purposes.
|
|
76
84
|
Cypress.log({
|
|
77
85
|
displayName: 'task',
|
|
78
|
-
name:
|
|
86
|
+
name: customEntityConfigCommand,
|
|
79
87
|
message: appConfig
|
|
80
88
|
});
|
|
81
89
|
const userCredentials = commandOptions.login ?? {
|
|
@@ -83,28 +91,197 @@ function loginByForm(commandOptions) {
|
|
|
83
91
|
password: Cypress.env('LOGIN_PASSWORD')
|
|
84
92
|
};
|
|
85
93
|
const sessionKey = ['loginByForm', userCredentials.email, commandOptions.entryPointUriPath];
|
|
86
|
-
// const mcUrl = new URL(appConfig.mcApiUrl);
|
|
87
|
-
// const mcFrontendHostname = mcUrl.hostname.replace('mc-api', 'mc');
|
|
88
94
|
|
|
95
|
+
/**
|
|
96
|
+
* The function is used by Cypress `session` command to store the
|
|
97
|
+
* browser state after executing the authentication flow.
|
|
98
|
+
*/
|
|
89
99
|
function authCallback() {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
100
|
+
// Get the feature flags from the Merchant Center API so we can
|
|
101
|
+
// check whether Identity is enabled
|
|
102
|
+
cy.request({
|
|
103
|
+
method: 'POST',
|
|
104
|
+
url: `${appConfig.mcApiUrl}/graphql`,
|
|
105
|
+
body: {
|
|
106
|
+
operationName: 'AllFeatures',
|
|
107
|
+
query: `query AllFeatures { allFeatures { name value reason } }`
|
|
108
|
+
},
|
|
109
|
+
headers: {
|
|
110
|
+
'content-type': 'application/json',
|
|
111
|
+
'x-graphql-target': constants.GRAPHQL_TARGETS.MERCHANT_CENTER_BACKEND,
|
|
112
|
+
'x-graphql-operation-name': 'AllFeatures',
|
|
113
|
+
'x-project-key': projectKey
|
|
114
|
+
}
|
|
115
|
+
}).then(res => {
|
|
116
|
+
var _context;
|
|
117
|
+
const enableIdentity = _findInstanceProperty__default["default"](_context = res.body.data.allFeatures).call(_context, feature => feature.name === 'enableGlobalIdentity');
|
|
118
|
+
const isGlobalIdentityEnabled = Boolean(enableIdentity?.value);
|
|
119
|
+
Cypress.log({
|
|
120
|
+
name: 'isGlobalIdentityEnabled',
|
|
121
|
+
message: isGlobalIdentityEnabled
|
|
122
|
+
});
|
|
123
|
+
const identityUrl = Cypress.env('IDENTITY_URL') || 'https://identity.commercetools.com';
|
|
124
|
+
|
|
125
|
+
// Visit the application URL, which triggers then the login flow.
|
|
126
|
+
cy.visit(url, {
|
|
127
|
+
onBeforeLoad: commandOptions.onBeforeLoad
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* There are different scenarios and variations on the flow depending
|
|
132
|
+
* on the environment (localhost, production) and if Identity is enabled.
|
|
133
|
+
*
|
|
134
|
+
* # When the application runs on localhost:3001.
|
|
135
|
+
*
|
|
136
|
+
* ## When Identity is enabled
|
|
137
|
+
* - The test visits the application at localhost:3001.
|
|
138
|
+
* - Cypress registers the default origin being localhost:3001.
|
|
139
|
+
* - The application is redirected to the Identity URL.
|
|
140
|
+
* - Cypress interacts with the Identity URL via `cy.origin`.
|
|
141
|
+
* - At the end of the flow, the test interacts with the application at localhost:3001.
|
|
142
|
+
* ## When Identity is disabled
|
|
143
|
+
* - The test visits the application at localhost:3001.
|
|
144
|
+
* - Cypress registers the default origin being localhost:3001.
|
|
145
|
+
* - The application is redirected to the Merchant Center login page.
|
|
146
|
+
* - Cypress interacts with the Merchant Center login page via `cy.origin`.
|
|
147
|
+
* - At the end of the flow, the test interacts with the application at localhost:3001.
|
|
148
|
+
*
|
|
149
|
+
* # When the application runs on a production URL.
|
|
150
|
+
*
|
|
151
|
+
* ## When Identity is enabled
|
|
152
|
+
* - The test visits the application at the production URL.
|
|
153
|
+
* - The MC Proxy performs a server-side redirect to the Identity URL.
|
|
154
|
+
* - Cypress registers the default origin being the Identity URL.
|
|
155
|
+
* - Cypress interacts with the Identity URL.
|
|
156
|
+
* - At the end of the flow, the test interacts with the application at the production URL via `cy.origin`.
|
|
157
|
+
*
|
|
158
|
+
* ## When Identity is disabled
|
|
159
|
+
* - The test visits the application at the production URL.
|
|
160
|
+
* - The MC Proxy renders the Merchant Center login page.
|
|
161
|
+
* - Cypress registers the default origin being the Merchant Center URL.
|
|
162
|
+
* - Cypress interacts with the Merchant Center login page.
|
|
163
|
+
* - At the end of the flow, the test interacts with the application at the production URL.
|
|
164
|
+
*/
|
|
93
165
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
166
|
+
if (isLocalhost) {
|
|
167
|
+
if (isGlobalIdentityEnabled) {
|
|
168
|
+
// Cypress gets confused when switching between origins, likely because
|
|
169
|
+
// the redirect to Identity doesn't happen immediately.
|
|
170
|
+
// If we don't wait, Cypress fails as it tries to interact with `cy.origin`
|
|
171
|
+
// but the test is still in the initial origin URL.
|
|
172
|
+
// This is a bit unexpected and to be considered a workaround.
|
|
173
|
+
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
174
|
+
cy.wait(1000);
|
|
97
175
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
176
|
+
// Use cy.origin to handle the identity domain
|
|
177
|
+
cy.origin(identityUrl, {
|
|
178
|
+
args: {
|
|
179
|
+
userCredentials,
|
|
180
|
+
identityUrl
|
|
181
|
+
}
|
|
182
|
+
}, _ref => {
|
|
183
|
+
let userCredentials = _ref.userCredentials,
|
|
184
|
+
identityUrl = _ref.identityUrl;
|
|
185
|
+
cy.url().should('include', `${identityUrl}/login`);
|
|
186
|
+
// Fill in the email and click Next
|
|
187
|
+
cy.get('input[name="identifier"]').type(userCredentials.email);
|
|
188
|
+
cy.get('button').contains('Next').click();
|
|
105
189
|
|
|
106
|
-
|
|
107
|
-
|
|
190
|
+
// Wait for the password form to appear
|
|
191
|
+
cy.get('input[name="password"]').should('be.visible');
|
|
192
|
+
// Fill in the password and submit
|
|
193
|
+
cy.get('input[name="password"]').type(userCredentials.password, {
|
|
194
|
+
log: false
|
|
195
|
+
});
|
|
196
|
+
cy.get('button').contains('Submit').click();
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
// Wait for the flow to redirect back to the application.
|
|
200
|
+
cy.get('[role="main"]').should('exist');
|
|
201
|
+
cy.url().should('include', url);
|
|
202
|
+
} else {
|
|
203
|
+
const mcUrl = appConfig.mcApiUrl.replace('mc-api', 'mc');
|
|
204
|
+
// See similar comment above regarding the usage of `cy.wait`.
|
|
205
|
+
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
206
|
+
cy.wait(1000);
|
|
207
|
+
cy.origin(mcUrl, {
|
|
208
|
+
args: {
|
|
209
|
+
userCredentials,
|
|
210
|
+
mcUrl
|
|
211
|
+
}
|
|
212
|
+
}, _ref2 => {
|
|
213
|
+
let userCredentials = _ref2.userCredentials,
|
|
214
|
+
mcUrl = _ref2.mcUrl;
|
|
215
|
+
cy.url().should('include', `${mcUrl}/login`);
|
|
216
|
+
|
|
217
|
+
// Same as `fillLegacyLoginFormWithRetry`.
|
|
218
|
+
// eslint-disable-next-line cypress/unsafe-to-chain-command
|
|
219
|
+
cy.get('input[name=email]')
|
|
220
|
+
// We use `force` as the MC login UI (production) in tests renders the
|
|
221
|
+
// cookie banner overlapping the input fields.
|
|
222
|
+
// To allow Cypress to interact with the input fields, we use `force`.
|
|
223
|
+
.clear({
|
|
224
|
+
force: true
|
|
225
|
+
}).type(userCredentials.email, {
|
|
226
|
+
force: true
|
|
227
|
+
});
|
|
228
|
+
// eslint-disable-next-line cypress/unsafe-to-chain-command
|
|
229
|
+
cy.get('input[name=password]')
|
|
230
|
+
// We use `force` as the MC login UI (production) in tests renders the
|
|
231
|
+
// cookie banner overlapping the input fields.
|
|
232
|
+
// To allow Cypress to interact with the input fields, we use `force`.
|
|
233
|
+
.clear({
|
|
234
|
+
force: true
|
|
235
|
+
}).type(userCredentials.password, {
|
|
236
|
+
log: false,
|
|
237
|
+
force: true
|
|
238
|
+
});
|
|
239
|
+
cy.get('button').contains('Sign in').click({
|
|
240
|
+
force: true
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
244
|
+
cy.wait(1000);
|
|
245
|
+
|
|
246
|
+
// Wait for the flow to redirect back to the application.
|
|
247
|
+
cy.get('[role="main"]').should('exist');
|
|
248
|
+
cy.url().should('include', url);
|
|
249
|
+
}
|
|
250
|
+
} else {
|
|
251
|
+
if (isGlobalIdentityEnabled) {
|
|
252
|
+
cy.url().should('include', `${identityUrl}/login`);
|
|
253
|
+
// Fill in the email and click Next
|
|
254
|
+
cy.get('input[name="identifier"]').type(userCredentials.email);
|
|
255
|
+
cy.get('button').contains('Next').click();
|
|
256
|
+
|
|
257
|
+
// Wait for the password form to appear
|
|
258
|
+
cy.get('input[name="password"]').should('be.visible');
|
|
259
|
+
// Fill in the password and submit
|
|
260
|
+
cy.get('input[name="password"]').type(userCredentials.password, {
|
|
261
|
+
log: false
|
|
262
|
+
});
|
|
263
|
+
cy.get('button').contains('Submit').click();
|
|
264
|
+
|
|
265
|
+
// Wait for the flow to redirect back to the application.
|
|
266
|
+
cy.origin(Cypress.config('baseUrl'), {
|
|
267
|
+
args: {
|
|
268
|
+
url
|
|
269
|
+
}
|
|
270
|
+
}, _ref3 => {
|
|
271
|
+
let url = _ref3.url;
|
|
272
|
+
cy.get('[role="main"]').should('exist');
|
|
273
|
+
cy.url().should('include', url);
|
|
274
|
+
});
|
|
275
|
+
} else {
|
|
276
|
+
// Legacy login flow.
|
|
277
|
+
fillLegacyLoginFormWithRetry(userCredentials);
|
|
278
|
+
|
|
279
|
+
// Wait for the flow to redirect back to the application.
|
|
280
|
+
cy.get('[role="main"]').should('exist');
|
|
281
|
+
cy.url().should('include', url);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
});
|
|
108
285
|
}
|
|
109
286
|
|
|
110
287
|
// For backwards compatibility.
|
|
@@ -123,108 +300,11 @@ function loginByForm(commandOptions) {
|
|
|
123
300
|
}
|
|
124
301
|
});
|
|
125
302
|
}
|
|
126
|
-
const isCustomView = commandOptions => commandOptions.entryPointUriPath === constants$1.CUSTOM_VIEW_HOST_ENTRY_POINT_URI_PATH;
|
|
127
|
-
function loginByOidc(commandOptions) {
|
|
128
|
-
const isCustomViewConfigCommand = isCustomView(commandOptions);
|
|
129
|
-
if (!isLocalhost()) {
|
|
130
|
-
throw new Error(`The "loginByOidc" command only works when testing a Custom ${isCustomViewConfigCommand ? 'View' : 'Application'} running on localhost.`);
|
|
131
|
-
}
|
|
132
|
-
const sessionNonce = uuid.v4();
|
|
133
|
-
let projectKey = undefined;
|
|
134
|
-
if (commandOptions.entryPointUriPath !== 'account') {
|
|
135
|
-
projectKey = commandOptions.projectKey ?? Cypress.env('PROJECT_KEY');
|
|
136
|
-
}
|
|
137
|
-
const customEntityConfigCommand = isCustomViewConfigCommand ? 'customViewConfig' : 'customApplicationConfig';
|
|
138
|
-
const packageName = commandOptions.packageName ?? Cypress.env('PACKAGE_NAME');
|
|
139
|
-
if (isCustomViewConfigCommand && !packageName) {
|
|
140
|
-
throw new Error(`Missing required option "packageName" when using the "loginToMerchantCenterForCustomView" command.`);
|
|
141
|
-
}
|
|
142
|
-
cy.task(customEntityConfigCommand, _objectSpread$1({
|
|
143
|
-
entryPointUriPath: commandOptions.entryPointUriPath,
|
|
144
|
-
dotfiles: commandOptions.dotfiles
|
|
145
|
-
}, isCustomViewConfigCommand ? {
|
|
146
|
-
packageName
|
|
147
|
-
} : {}),
|
|
148
|
-
// Do not show log, as it may contain sensible information.
|
|
149
|
-
{
|
|
150
|
-
log: false
|
|
151
|
-
}).then(appConfig => {
|
|
152
|
-
// Log loaded application config for debugging purposes.
|
|
153
|
-
Cypress.log({
|
|
154
|
-
displayName: 'task',
|
|
155
|
-
name: customEntityConfigCommand,
|
|
156
|
-
message: appConfig
|
|
157
|
-
});
|
|
158
|
-
const applicationId = appConfig.applicationId;
|
|
159
|
-
const sessionScope = ssr.buildOidcScope({
|
|
160
|
-
projectKey,
|
|
161
|
-
oAuthScopes: appConfig.__DEVELOPMENT__?.oidc?.oAuthScopes,
|
|
162
|
-
additionalOAuthScopes: appConfig.__DEVELOPMENT__?.oidc?.additionalOAuthScopes,
|
|
163
|
-
teamId: appConfig.__DEVELOPMENT__?.oidc?.teamId,
|
|
164
|
-
applicationId: appConfig.__DEVELOPMENT__?.oidc?.applicationId
|
|
165
|
-
});
|
|
166
|
-
const userCredentials = commandOptions.login ?? {
|
|
167
|
-
email: Cypress.env('LOGIN_EMAIL') || Cypress.env('LOGIN_USER'),
|
|
168
|
-
password: Cypress.env('LOGIN_PASSWORD')
|
|
169
|
-
};
|
|
170
|
-
// Perform the login using the API, then store some required values into the browser storage
|
|
171
|
-
// and redirect to the auth callback route.
|
|
172
|
-
const requestOptions = {
|
|
173
|
-
method: 'POST',
|
|
174
|
-
url: `${appConfig.mcApiUrl}/tokens`,
|
|
175
|
-
body: _objectSpread$1(_objectSpread$1({}, userCredentials), {}, {
|
|
176
|
-
client_id: applicationId,
|
|
177
|
-
response_type: constants.OIDC_RESPONSE_TYPES.ID_TOKEN,
|
|
178
|
-
scope: sessionScope,
|
|
179
|
-
state: sessionNonce,
|
|
180
|
-
nonce: sessionNonce
|
|
181
|
-
}),
|
|
182
|
-
followRedirect: false
|
|
183
|
-
};
|
|
184
|
-
cy.request(requestOptions).then(res => {
|
|
185
|
-
const sessionKey = ['loginByOidc', userCredentials.email, commandOptions.entryPointUriPath];
|
|
186
|
-
function authCallback() {
|
|
187
|
-
cy.visit(res.body.redirectTo, {
|
|
188
|
-
onBeforeLoad(win) {
|
|
189
|
-
if (projectKey) {
|
|
190
|
-
win.localStorage.setItem(constants.STORAGE_KEYS.ACTIVE_PROJECT_KEY, projectKey);
|
|
191
|
-
}
|
|
192
|
-
win.sessionStorage.setItem(`${constants.STORAGE_KEYS.NONCE}_${sessionNonce}`, _JSON$stringify__default["default"]({
|
|
193
|
-
applicationId,
|
|
194
|
-
query: {}
|
|
195
|
-
}));
|
|
196
|
-
win.sessionStorage.setItem(constants.STORAGE_KEYS.SESSION_SCOPE, sessionScope);
|
|
197
|
-
if (commandOptions.onBeforeLoad) {
|
|
198
|
-
commandOptions.onBeforeLoad(win);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
});
|
|
202
|
-
// Wait for the application to be loaded so that the session can be saved.
|
|
203
|
-
cy.get('#app-loader').should('not.exist');
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// For backwards compatibility.
|
|
207
|
-
if (isFeatureSupported('12.0.0') || Cypress.config('experimentalSessionAndOrigin')) {
|
|
208
|
-
// https://www.cypress.io/blog/2021/08/04/authenticate-faster-in-tests-cy-session-command/
|
|
209
|
-
cy.session(sessionKey, authCallback, isFeatureSupported('10.9.0') ? {
|
|
210
|
-
cacheAcrossSpecs: typeof commandOptions.disableCacheAcrossSpecs === 'boolean' ? !commandOptions.disableCacheAcrossSpecs : true
|
|
211
|
-
} : undefined);
|
|
212
|
-
} else {
|
|
213
|
-
cy.log(`We recommend to use "cy.session" to reduce the time to log in between tests. Make sure to have at least Cypress v12 or enable it via "experimentalSessionAndOrigin" for older Cypress versions.`);
|
|
214
|
-
authCallback();
|
|
215
|
-
}
|
|
216
|
-
if (commandOptions.initialRoute) {
|
|
217
|
-
cy.visit(`${Cypress.config('baseUrl')}${commandOptions.initialRoute}`);
|
|
218
|
-
cy.url().should('include', commandOptions.initialRoute);
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
303
|
|
|
224
304
|
/* Utilities */
|
|
225
305
|
|
|
226
|
-
const
|
|
227
|
-
function
|
|
306
|
+
const legacyMaxLoginAttempts = Cypress.config('maxLoginAttempts') ?? 3;
|
|
307
|
+
function fillLegacyLoginFormWithRetry(userCredentials) {
|
|
228
308
|
// Intercept the login request so we can retry it if we receive a TOO_MANY_REQUESTS status code
|
|
229
309
|
cy.intercept('POST', '**/tokens').as('loginRequest');
|
|
230
310
|
function getRandomDelayInSeconds() {
|
|
@@ -239,18 +319,27 @@ function fillLoginForm(userCredentials) {
|
|
|
239
319
|
cy.log(`Attempts left: ${attemptsLeft}`);
|
|
240
320
|
|
|
241
321
|
// eslint-disable-next-line cypress/unsafe-to-chain-command
|
|
242
|
-
cy.get('input[name=email]').clear(
|
|
322
|
+
cy.get('input[name=email]').clear({
|
|
323
|
+
force: true
|
|
324
|
+
}).type(userCredentials.email, {
|
|
325
|
+
force: true
|
|
326
|
+
});
|
|
243
327
|
// eslint-disable-next-line cypress/unsafe-to-chain-command
|
|
244
|
-
cy.get('input[name=password]').clear(
|
|
245
|
-
|
|
328
|
+
cy.get('input[name=password]').clear({
|
|
329
|
+
force: true
|
|
330
|
+
}).type(userCredentials.password, {
|
|
331
|
+
log: false,
|
|
332
|
+
force: true
|
|
333
|
+
});
|
|
334
|
+
cy.get('button').contains('Sign in').click({
|
|
335
|
+
force: true
|
|
246
336
|
});
|
|
247
|
-
cy.get('button').contains('Sign in').click();
|
|
248
337
|
|
|
249
338
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
250
339
|
cy.wait('@loginRequest').then(interception => {
|
|
251
340
|
const statusCode = interception.response.statusCode;
|
|
252
341
|
cy.log('Login request status code:', statusCode);
|
|
253
|
-
if (statusCode === constants.HTTP_STATUS_CODES.TOO_MANY_REQUESTS) {
|
|
342
|
+
if (statusCode === constants$1.HTTP_STATUS_CODES.TOO_MANY_REQUESTS) {
|
|
254
343
|
// We wait for something between 0.5 and 1.5 seconds before retrying
|
|
255
344
|
cy.wait(getRandomDelayInSeconds());
|
|
256
345
|
attemptLogin(attemptsLeft - 1);
|
|
@@ -259,11 +348,7 @@ function fillLoginForm(userCredentials) {
|
|
|
259
348
|
}
|
|
260
349
|
});
|
|
261
350
|
}
|
|
262
|
-
attemptLogin(
|
|
263
|
-
}
|
|
264
|
-
function isLocalhost() {
|
|
265
|
-
const baseUrl = new _URL__default["default"](Cypress.config('baseUrl'));
|
|
266
|
-
return baseUrl.hostname === 'localhost';
|
|
351
|
+
attemptLogin(legacyMaxLoginAttempts);
|
|
267
352
|
}
|
|
268
353
|
|
|
269
354
|
/**
|
|
@@ -490,20 +575,16 @@ Cypress.Commands.add('loginToMerchantCenter', commandOptions => {
|
|
|
490
575
|
Cypress.log({
|
|
491
576
|
name: 'loginToMerchantCenter'
|
|
492
577
|
});
|
|
493
|
-
|
|
494
|
-
loginByOidc(commandOptions);
|
|
495
|
-
} else {
|
|
496
|
-
loginByForm(commandOptions);
|
|
497
|
-
}
|
|
578
|
+
loginByForm(commandOptions);
|
|
498
579
|
});
|
|
499
580
|
Cypress.Commands.add('loginToMerchantCenterForCustomView', commandOptions => {
|
|
500
581
|
Cypress.log({
|
|
501
582
|
name: 'loginToMerchantCenterForCustomView'
|
|
502
583
|
});
|
|
503
584
|
const projectKey = Cypress.env('PROJECT_KEY');
|
|
504
|
-
|
|
505
|
-
entryPointUriPath: constants
|
|
506
|
-
initialRoute: `/${projectKey}/${constants
|
|
585
|
+
loginByForm(_objectSpread(_objectSpread({}, commandOptions), {}, {
|
|
586
|
+
entryPointUriPath: constants.CUSTOM_VIEW_HOST_ENTRY_POINT_URI_PATH,
|
|
587
|
+
initialRoute: `/${projectKey}/${constants.CUSTOM_VIEW_HOST_ENTRY_POINT_URI_PATH}`
|
|
507
588
|
}));
|
|
508
589
|
});
|
|
509
590
|
Cypress.Commands.add('loginByOidc', commandOptions => {
|
|
@@ -511,7 +592,7 @@ Cypress.Commands.add('loginByOidc', commandOptions => {
|
|
|
511
592
|
name: 'loginByOidc'
|
|
512
593
|
});
|
|
513
594
|
cy.log('We recommend not to use the command "cy.loginByOidc" directly. Instead, use the more generic "cy.loginToMerchantCenter" command as it automatically detects which login mechanism to use.');
|
|
514
|
-
|
|
595
|
+
loginByForm(commandOptions);
|
|
515
596
|
});
|
|
516
597
|
Cypress.Commands.add('hover', {
|
|
517
598
|
prevSubject: true
|