@commercetools-frontend/cypress 24.3.0 → 24.5.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.
@@ -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$1 = require('@commercetools-frontend/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 uuid = require('uuid');
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 _context, _context2; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty__default["default"](_context = ownKeys$1(Object(t), !0)).call(_context, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors__default["default"] ? _Object$defineProperties__default["default"](e, _Object$getOwnPropertyDescriptors__default["default"](t)) : _forEachInstanceProperty__default["default"](_context2 = ownKeys$1(Object(t))).call(_context2, function (r) { _Object$defineProperty__default["default"](e, r, _Object$getOwnPropertyDescriptor__default["default"](t, r)); }); } return e; }
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
 
@@ -51,18 +47,34 @@ function _objectSpread$1(e) { for (var r = 1; r < arguments.length; r++) { var _
51
47
 
52
48
  // Alias for backwards compatibility
53
49
 
50
+ const defaultTimeouts = {
51
+ waitForEmailInput: 4000,
52
+ waitForPasswordInput: 8000
53
+ };
54
54
  function isFeatureSupported(expectedVersion) {
55
55
  return semver__default["default"].gte(Cypress.version, expectedVersion);
56
56
  }
57
+ function isRunningOnLocalhost() {
58
+ const baseUrl = new _URL__default["default"](Cypress.config('baseUrl'));
59
+ return baseUrl.hostname === 'localhost';
60
+ }
61
+ const isCustomView = commandOptions => commandOptions.entryPointUriPath === constants.CUSTOM_VIEW_HOST_ENTRY_POINT_URI_PATH;
57
62
  function loginByForm(commandOptions) {
58
- if (isLocalhost()) {
59
- throw new Error(`At the moment, the "loginByForm" command only works when testing a Merchant Center production URL. Using form login in an application running on localhost is not supported due to issues with "cy.origin".`);
60
- }
63
+ const isLocalhost = isRunningOnLocalhost();
64
+ Cypress.log({
65
+ name: 'isLocalhost',
66
+ message: isLocalhost
67
+ });
61
68
  const projectKey = commandOptions.projectKey ?? Cypress.env('PROJECT_KEY');
62
- cy.task('customApplicationConfig', {
69
+ const isCustomViewConfigCommand = isCustomView(commandOptions);
70
+ const customEntityConfigCommand = isCustomViewConfigCommand ? 'customViewConfig' : 'customApplicationConfig';
71
+ const packageName = commandOptions.packageName ?? Cypress.env('PACKAGE_NAME');
72
+ cy.task(customEntityConfigCommand, _objectSpread$1({
63
73
  entryPointUriPath: commandOptions.entryPointUriPath,
64
74
  dotfiles: commandOptions.dotfiles
65
- },
75
+ }, isCustomViewConfigCommand ? {
76
+ packageName
77
+ } : {}),
66
78
  // Do not show log, as it may contain sensible information.
67
79
  {
68
80
  log: false
@@ -75,7 +87,7 @@ function loginByForm(commandOptions) {
75
87
  // Log loaded application config for debugging purposes.
76
88
  Cypress.log({
77
89
  displayName: 'task',
78
- name: 'customApplicationConfig',
90
+ name: customEntityConfigCommand,
79
91
  message: appConfig
80
92
  });
81
93
  const userCredentials = commandOptions.login ?? {
@@ -83,28 +95,217 @@ function loginByForm(commandOptions) {
83
95
  password: Cypress.env('LOGIN_PASSWORD')
84
96
  };
85
97
  const sessionKey = ['loginByForm', userCredentials.email, commandOptions.entryPointUriPath];
86
- // const mcUrl = new URL(appConfig.mcApiUrl);
87
- // const mcFrontendHostname = mcUrl.hostname.replace('mc-api', 'mc');
88
98
 
99
+ /**
100
+ * The function is used by Cypress `session` command to store the
101
+ * browser state after executing the authentication flow.
102
+ */
89
103
  function authCallback() {
90
- cy.visit(url, {
91
- onBeforeLoad: commandOptions.onBeforeLoad
92
- });
104
+ // Get the feature flags from the Merchant Center API so we can
105
+ // check whether Identity is enabled
106
+ cy.request({
107
+ method: 'POST',
108
+ url: `${appConfig.mcApiUrl}/graphql`,
109
+ body: {
110
+ operationName: 'AllFeatures',
111
+ query: `query AllFeatures { allFeatures { name value reason } }`
112
+ },
113
+ headers: {
114
+ 'content-type': 'application/json',
115
+ 'x-graphql-target': constants.GRAPHQL_TARGETS.MERCHANT_CENTER_BACKEND,
116
+ 'x-graphql-operation-name': 'AllFeatures',
117
+ 'x-project-key': projectKey
118
+ }
119
+ }).then(res => {
120
+ var _context;
121
+ const enableIdentity = _findInstanceProperty__default["default"](_context = res.body.data.allFeatures).call(_context, feature => feature.name === 'enableGlobalIdentity');
122
+ const isGlobalIdentityEnabled = Boolean(enableIdentity?.value);
123
+ Cypress.log({
124
+ name: 'isGlobalIdentityEnabled',
125
+ message: isGlobalIdentityEnabled
126
+ });
127
+ const identityUrl = Cypress.env('IDENTITY_URL') || 'https://identity.commercetools.com';
128
+
129
+ // Visit the application URL, which triggers then the login flow.
130
+ cy.visit(url, {
131
+ onBeforeLoad: commandOptions.onBeforeLoad
132
+ });
93
133
 
94
- // NOTE: using `cy.origin` is currently disabled as it does not seem to properly work.
95
- // Interestingly, starting an application locally using Vite works, however not when using Webpack.
96
- // For now we keep it disabled until we find a solution.
134
+ /**
135
+ * There are different scenarios and variations on the flow depending
136
+ * on the environment (localhost, production) and if Identity is enabled.
137
+ *
138
+ * # When the application runs on localhost:3001.
139
+ *
140
+ * ## When Identity is enabled
141
+ * - The test visits the application at localhost:3001.
142
+ * - Cypress registers the default origin being localhost:3001.
143
+ * - The application is redirected to the Identity URL.
144
+ * - Cypress interacts with the Identity URL via `cy.origin`.
145
+ * - At the end of the flow, the test interacts with the application at localhost:3001.
146
+ * ## When Identity is disabled
147
+ * - The test visits the application at localhost:3001.
148
+ * - Cypress registers the default origin being localhost:3001.
149
+ * - The application is redirected to the Merchant Center login page.
150
+ * - Cypress interacts with the Merchant Center login page via `cy.origin`.
151
+ * - At the end of the flow, the test interacts with the application at localhost:3001.
152
+ *
153
+ * # When the application runs on a production URL.
154
+ *
155
+ * ## When Identity is enabled
156
+ * - The test visits the application at the production URL.
157
+ * - The MC Proxy performs a server-side redirect to the Identity URL.
158
+ * - Cypress registers the default origin being the Identity URL.
159
+ * - Cypress interacts with the Identity URL.
160
+ * - At the end of the flow, the test interacts with the application at the production URL via `cy.origin`.
161
+ *
162
+ * ## When Identity is disabled
163
+ * - The test visits the application at the production URL.
164
+ * - The MC Proxy renders the Merchant Center login page.
165
+ * - Cypress registers the default origin being the Merchant Center URL.
166
+ * - Cypress interacts with the Merchant Center login page.
167
+ * - At the end of the flow, the test interacts with the application at the production URL.
168
+ */
97
169
 
98
- // // https://cypress.io/blog/2022/04/25/cypress-9-6-0-easily-test-multi-domain-workflows-with-cy-origin/
99
- // cy.origin(
100
- // mcFrontendHostname,
101
- // { args: userCredentials },
102
- // fillLoginForm
103
- // );
104
- fillLoginForm(userCredentials);
170
+ if (isLocalhost) {
171
+ if (isGlobalIdentityEnabled) {
172
+ // Cypress gets confused when switching between origins, likely because
173
+ // the redirect to Identity doesn't happen immediately.
174
+ // If we don't wait, Cypress fails as it tries to interact with `cy.origin`
175
+ // but the test is still in the initial origin URL.
176
+ // This is a bit unexpected and to be considered a workaround.
177
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
178
+ cy.wait(1000);
105
179
 
106
- // Wait for the route to be loaded so that the session can be saved.
107
- cy.url().should('include', url);
180
+ // Use cy.origin to handle the identity domain
181
+ cy.origin(identityUrl, {
182
+ args: {
183
+ userCredentials,
184
+ identityUrl,
185
+ timeouts: commandOptions.timeouts,
186
+ defaultTimeouts
187
+ }
188
+ }, _ref => {
189
+ let userCredentials = _ref.userCredentials,
190
+ identityUrl = _ref.identityUrl,
191
+ timeouts = _ref.timeouts,
192
+ defaultTimeouts = _ref.defaultTimeouts;
193
+ cy.url().should('include', `${identityUrl}/login`);
194
+ // Fill in the email and click Next
195
+ cy.get('input[name="identifier"]', {
196
+ timeout: timeouts?.waitForEmailInput ?? defaultTimeouts.waitForEmailInput
197
+ }).type(userCredentials.email);
198
+ cy.get('button').contains('Next').click();
199
+
200
+ // Wait for the password form to appear
201
+ cy.get('input[name="password"]', {
202
+ timeout: timeouts?.waitForPasswordInput ?? defaultTimeouts.waitForPasswordInput
203
+ }).should('be.visible');
204
+ // Fill in the password and submit
205
+ cy.get('input[name="password"]').type(userCredentials.password, {
206
+ log: false
207
+ });
208
+ cy.get('button').contains('Submit').click();
209
+ });
210
+
211
+ // Wait for the flow to redirect back to the application.
212
+ cy.get('[role="main"]').should('exist');
213
+ cy.url().should('include', url);
214
+ } else {
215
+ const mcUrl = appConfig.mcApiUrl.replace('mc-api', 'mc');
216
+ // See similar comment above regarding the usage of `cy.wait`.
217
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
218
+ cy.wait(1000);
219
+ cy.origin(mcUrl, {
220
+ args: {
221
+ userCredentials,
222
+ mcUrl,
223
+ timeouts: commandOptions.timeouts,
224
+ defaultTimeouts
225
+ }
226
+ }, _ref2 => {
227
+ let userCredentials = _ref2.userCredentials,
228
+ mcUrl = _ref2.mcUrl,
229
+ timeouts = _ref2.timeouts,
230
+ defaultTimeouts = _ref2.defaultTimeouts;
231
+ cy.url().should('include', `${mcUrl}/login`);
232
+
233
+ // Same as `fillLegacyLoginFormWithRetry`.
234
+ // eslint-disable-next-line cypress/unsafe-to-chain-command
235
+ cy.get('input[name=email]', {
236
+ timeout: timeouts?.waitForEmailInput ?? defaultTimeouts.waitForEmailInput
237
+ })
238
+ // We use `force` as the MC login UI (production) in tests renders the
239
+ // cookie banner overlapping the input fields.
240
+ // To allow Cypress to interact with the input fields, we use `force`.
241
+ .clear({
242
+ force: true
243
+ }).type(userCredentials.email, {
244
+ force: true
245
+ });
246
+ // eslint-disable-next-line cypress/unsafe-to-chain-command
247
+ cy.get('input[name=password]', {
248
+ timeout: timeouts?.waitForPasswordInput ?? defaultTimeouts.waitForPasswordInput
249
+ })
250
+ // We use `force` as the MC login UI (production) in tests renders the
251
+ // cookie banner overlapping the input fields.
252
+ // To allow Cypress to interact with the input fields, we use `force`.
253
+ .clear({
254
+ force: true
255
+ }).type(userCredentials.password, {
256
+ log: false,
257
+ force: true
258
+ });
259
+ cy.get('button').contains('Sign in').click({
260
+ force: true
261
+ });
262
+ });
263
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
264
+ cy.wait(1000);
265
+
266
+ // Wait for the flow to redirect back to the application.
267
+ cy.get('[role="main"]').should('exist');
268
+ cy.url().should('include', url);
269
+ }
270
+ } else {
271
+ if (isGlobalIdentityEnabled) {
272
+ cy.url().should('include', `${identityUrl}/login`);
273
+ // Fill in the email and click Next
274
+ cy.get('input[name="identifier"]', {
275
+ timeout: commandOptions.timeouts?.waitForEmailInput ?? defaultTimeouts.waitForEmailInput
276
+ }).type(userCredentials.email);
277
+ cy.get('button').contains('Next').click();
278
+
279
+ // Wait for the password form to appear
280
+ cy.get('input[name="password"]', {
281
+ timeout: commandOptions.timeouts?.waitForPasswordInput ?? defaultTimeouts.waitForPasswordInput
282
+ }).should('be.visible');
283
+ // Fill in the password and submit
284
+ cy.get('input[name="password"]').type(userCredentials.password, {
285
+ log: false
286
+ });
287
+ cy.get('button').contains('Submit').click();
288
+
289
+ // Wait for the flow to redirect back to the application.
290
+ cy.origin(Cypress.config('baseUrl'), {
291
+ args: {
292
+ url
293
+ }
294
+ }, _ref3 => {
295
+ let url = _ref3.url;
296
+ cy.get('[role="main"]').should('exist');
297
+ cy.url().should('include', url);
298
+ });
299
+ } else {
300
+ // Legacy login flow.
301
+ fillLegacyLoginFormWithRetry(userCredentials, commandOptions.timeouts);
302
+
303
+ // Wait for the flow to redirect back to the application.
304
+ cy.get('[role="main"]').should('exist');
305
+ cy.url().should('include', url);
306
+ }
307
+ }
308
+ });
108
309
  }
109
310
 
110
311
  // For backwards compatibility.
@@ -123,108 +324,11 @@ function loginByForm(commandOptions) {
123
324
  }
124
325
  });
125
326
  }
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
327
 
224
328
  /* Utilities */
225
329
 
226
- const maxLoginAttempts = Cypress.config('maxLoginAttempts') ?? 3;
227
- function fillLoginForm(userCredentials) {
330
+ const legacyMaxLoginAttempts = Cypress.config('maxLoginAttempts') ?? 3;
331
+ function fillLegacyLoginFormWithRetry(userCredentials, timeouts) {
228
332
  // Intercept the login request so we can retry it if we receive a TOO_MANY_REQUESTS status code
229
333
  cy.intercept('POST', '**/tokens').as('loginRequest');
230
334
  function getRandomDelayInSeconds() {
@@ -239,18 +343,31 @@ function fillLoginForm(userCredentials) {
239
343
  cy.log(`Attempts left: ${attemptsLeft}`);
240
344
 
241
345
  // eslint-disable-next-line cypress/unsafe-to-chain-command
242
- cy.get('input[name=email]').clear().type(userCredentials.email);
346
+ cy.get('input[name=email]', {
347
+ timeout: timeouts?.waitForEmailInput ?? defaultTimeouts.waitForEmailInput
348
+ }).clear({
349
+ force: true
350
+ }).type(userCredentials.email, {
351
+ force: true
352
+ });
243
353
  // eslint-disable-next-line cypress/unsafe-to-chain-command
244
- cy.get('input[name=password]').clear().type(userCredentials.password, {
245
- log: false
354
+ cy.get('input[name=password]', {
355
+ timeout: timeouts?.waitForPasswordInput ?? defaultTimeouts.waitForPasswordInput
356
+ }).clear({
357
+ force: true
358
+ }).type(userCredentials.password, {
359
+ log: false,
360
+ force: true
361
+ });
362
+ cy.get('button').contains('Sign in').click({
363
+ force: true
246
364
  });
247
- cy.get('button').contains('Sign in').click();
248
365
 
249
366
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
250
367
  cy.wait('@loginRequest').then(interception => {
251
368
  const statusCode = interception.response.statusCode;
252
369
  cy.log('Login request status code:', statusCode);
253
- if (statusCode === constants.HTTP_STATUS_CODES.TOO_MANY_REQUESTS) {
370
+ if (statusCode === constants$1.HTTP_STATUS_CODES.TOO_MANY_REQUESTS) {
254
371
  // We wait for something between 0.5 and 1.5 seconds before retrying
255
372
  cy.wait(getRandomDelayInSeconds());
256
373
  attemptLogin(attemptsLeft - 1);
@@ -259,11 +376,7 @@ function fillLoginForm(userCredentials) {
259
376
  }
260
377
  });
261
378
  }
262
- attemptLogin(maxLoginAttempts);
263
- }
264
- function isLocalhost() {
265
- const baseUrl = new _URL__default["default"](Cypress.config('baseUrl'));
266
- return baseUrl.hostname === 'localhost';
379
+ attemptLogin(legacyMaxLoginAttempts);
267
380
  }
268
381
 
269
382
  /**
@@ -490,20 +603,16 @@ Cypress.Commands.add('loginToMerchantCenter', commandOptions => {
490
603
  Cypress.log({
491
604
  name: 'loginToMerchantCenter'
492
605
  });
493
- if (isLocalhost()) {
494
- loginByOidc(commandOptions);
495
- } else {
496
- loginByForm(commandOptions);
497
- }
606
+ loginByForm(commandOptions);
498
607
  });
499
608
  Cypress.Commands.add('loginToMerchantCenterForCustomView', commandOptions => {
500
609
  Cypress.log({
501
610
  name: 'loginToMerchantCenterForCustomView'
502
611
  });
503
612
  const projectKey = Cypress.env('PROJECT_KEY');
504
- loginByOidc(_objectSpread(_objectSpread({}, commandOptions), {}, {
505
- entryPointUriPath: constants$1.CUSTOM_VIEW_HOST_ENTRY_POINT_URI_PATH,
506
- initialRoute: `/${projectKey}/${constants$1.CUSTOM_VIEW_HOST_ENTRY_POINT_URI_PATH}`
613
+ loginByForm(_objectSpread(_objectSpread({}, commandOptions), {}, {
614
+ entryPointUriPath: constants.CUSTOM_VIEW_HOST_ENTRY_POINT_URI_PATH,
615
+ initialRoute: `/${projectKey}/${constants.CUSTOM_VIEW_HOST_ENTRY_POINT_URI_PATH}`
507
616
  }));
508
617
  });
509
618
  Cypress.Commands.add('loginByOidc', commandOptions => {
@@ -511,7 +620,7 @@ Cypress.Commands.add('loginByOidc', commandOptions => {
511
620
  name: 'loginByOidc'
512
621
  });
513
622
  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
- loginByOidc(commandOptions);
623
+ loginByForm(commandOptions);
515
624
  });
516
625
  Cypress.Commands.add('hover', {
517
626
  prevSubject: true