@commercetools-frontend/cypress 24.7.0 → 24.7.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/add-commands/dist/commercetools-frontend-cypress-add-commands.cjs.dev.js +86 -129
- package/add-commands/dist/commercetools-frontend-cypress-add-commands.cjs.prod.js +86 -129
- package/add-commands/dist/commercetools-frontend-cypress-add-commands.esm.js +86 -129
- 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 +2 -27
- package/package.json +4 -4
|
@@ -48,12 +48,7 @@ function _objectSpread$1(e) { for (var r = 1; r < arguments.length; r++) { var _
|
|
|
48
48
|
// Alias for backwards compatibility
|
|
49
49
|
|
|
50
50
|
const defaultTimeouts = {
|
|
51
|
-
|
|
52
|
-
waitForPasswordInput: 8000,
|
|
53
|
-
waitForElement: 15000,
|
|
54
|
-
waitForUrl: 15000,
|
|
55
|
-
waitForRedirect: 3000,
|
|
56
|
-
waitForIdentityRedirect: 8000
|
|
51
|
+
waitForRedirectToLogin: 1000
|
|
57
52
|
};
|
|
58
53
|
function isFeatureSupported(expectedVersion) {
|
|
59
54
|
return semver__default["default"].gte(Cypress.version, expectedVersion);
|
|
@@ -83,9 +78,9 @@ function loginByForm(commandOptions) {
|
|
|
83
78
|
{
|
|
84
79
|
log: false
|
|
85
80
|
}).then(appConfig => {
|
|
86
|
-
let
|
|
81
|
+
let initialUriPath = `/${projectKey}/${commandOptions.entryPointUriPath}`;
|
|
87
82
|
if (commandOptions.entryPointUriPath === 'account') {
|
|
88
|
-
|
|
83
|
+
initialUriPath = `/${commandOptions.entryPointUriPath}`;
|
|
89
84
|
}
|
|
90
85
|
|
|
91
86
|
// Log loaded application config for debugging purposes.
|
|
@@ -104,7 +99,7 @@ function loginByForm(commandOptions) {
|
|
|
104
99
|
* The function is used by Cypress `session` command to store the
|
|
105
100
|
* browser state after executing the authentication flow.
|
|
106
101
|
*/
|
|
107
|
-
function
|
|
102
|
+
function sessionAuthCallback() {
|
|
108
103
|
// Get the feature flags from the Merchant Center API so we can
|
|
109
104
|
// check whether Identity is enabled
|
|
110
105
|
cy.request({
|
|
@@ -112,7 +107,7 @@ function loginByForm(commandOptions) {
|
|
|
112
107
|
url: `${appConfig.mcApiUrl}/graphql`,
|
|
113
108
|
body: {
|
|
114
109
|
operationName: 'AllFeatures',
|
|
115
|
-
query: `query AllFeatures { allFeatures { name value
|
|
110
|
+
query: `query AllFeatures { allFeatures { name value } }`
|
|
116
111
|
},
|
|
117
112
|
headers: {
|
|
118
113
|
'content-type': 'application/json',
|
|
@@ -130,11 +125,6 @@ function loginByForm(commandOptions) {
|
|
|
130
125
|
});
|
|
131
126
|
const identityUrl = Cypress.env('IDENTITY_URL') || 'https://identity.commercetools.com';
|
|
132
127
|
|
|
133
|
-
// Visit the application URL, which triggers then the login flow.
|
|
134
|
-
cy.visit(url, {
|
|
135
|
-
onBeforeLoad: commandOptions.onBeforeLoad
|
|
136
|
-
});
|
|
137
|
-
|
|
138
128
|
/**
|
|
139
129
|
* There are different scenarios and variations on the flow depending
|
|
140
130
|
* on the environment (localhost, production) and if Identity is enabled.
|
|
@@ -172,79 +162,59 @@ function loginByForm(commandOptions) {
|
|
|
172
162
|
*/
|
|
173
163
|
|
|
174
164
|
if (isLocalhost) {
|
|
165
|
+
// Visit the special endpoint /api/health to ensure that the primary origin is set to localhost.
|
|
166
|
+
cy.visit('/api/health');
|
|
167
|
+
// Visit the application URL, which triggers then the login flow.
|
|
168
|
+
cy.visit(initialUriPath, {
|
|
169
|
+
onBeforeLoad: commandOptions.onBeforeLoad
|
|
170
|
+
});
|
|
171
|
+
// Cypress gets confused when switching between origins, likely because
|
|
172
|
+
// the redirect to Identity/MC doesn't happen immediately.
|
|
173
|
+
// If we don't wait, Cypress fails as it tries to interact with `cy.origin`
|
|
174
|
+
// but the test is still in the initial origin URL.
|
|
175
|
+
// This is a bit unexpected and to be considered a workaround.
|
|
176
|
+
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
177
|
+
cy.wait(commandOptions.timeouts?.waitForRedirectToLogin ?? defaultTimeouts.waitForRedirectToLogin);
|
|
175
178
|
if (isGlobalIdentityEnabled) {
|
|
176
|
-
// Cypress gets confused when switching between origins, likely because
|
|
177
|
-
// the redirect to Identity doesn't happen immediately.
|
|
178
|
-
// If we don't wait, Cypress fails as it tries to interact with `cy.origin`
|
|
179
|
-
// but the test is still in the initial origin URL.
|
|
180
|
-
// This is a bit unexpected and to be considered a workaround.
|
|
181
|
-
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
182
|
-
cy.wait(1000);
|
|
183
|
-
|
|
184
179
|
// Use cy.origin to handle the identity domain
|
|
185
180
|
cy.origin(identityUrl, {
|
|
186
181
|
args: {
|
|
187
182
|
userCredentials,
|
|
188
|
-
identityUrl
|
|
189
|
-
timeouts: commandOptions.timeouts,
|
|
190
|
-
defaultTimeouts
|
|
183
|
+
identityUrl
|
|
191
184
|
}
|
|
192
185
|
}, _ref => {
|
|
193
186
|
let userCredentials = _ref.userCredentials,
|
|
194
|
-
identityUrl = _ref.identityUrl
|
|
195
|
-
timeouts = _ref.timeouts,
|
|
196
|
-
defaultTimeouts = _ref.defaultTimeouts;
|
|
187
|
+
identityUrl = _ref.identityUrl;
|
|
197
188
|
cy.url().should('include', `${identityUrl}/login`);
|
|
198
189
|
// Fill in the email and click Next
|
|
199
|
-
cy.get('input[name="identifier"]'
|
|
200
|
-
timeout: timeouts?.waitForEmailInput ?? defaultTimeouts.waitForEmailInput
|
|
201
|
-
}).type(userCredentials.email);
|
|
190
|
+
cy.get('input[name="identifier"]').type(userCredentials.email);
|
|
202
191
|
cy.get('button').contains('Next').click();
|
|
203
192
|
|
|
204
193
|
// Wait for the password form to appear
|
|
205
|
-
cy.get('input[name="password"]'
|
|
206
|
-
timeout: timeouts?.waitForPasswordInput ?? defaultTimeouts.waitForPasswordInput
|
|
207
|
-
}).should('be.visible');
|
|
194
|
+
cy.get('input[name="password"]').should('be.visible');
|
|
208
195
|
// Fill in the password and submit
|
|
209
196
|
cy.get('input[name="password"]').type(userCredentials.password, {
|
|
210
197
|
log: false
|
|
211
198
|
});
|
|
212
|
-
cy.get('button').contains('Submit').click(
|
|
199
|
+
cy.get('button').contains('Submit').click({
|
|
200
|
+
force: true
|
|
201
|
+
});
|
|
213
202
|
});
|
|
214
|
-
|
|
215
|
-
// Wait for the flow to redirect back to the application.
|
|
216
|
-
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
217
|
-
cy.wait(commandOptions.timeouts?.waitForRedirect ?? defaultTimeouts.waitForRedirect);
|
|
218
|
-
cy.get('[role="main"]', {
|
|
219
|
-
timeout: commandOptions.timeouts?.waitForElement ?? defaultTimeouts.waitForElement
|
|
220
|
-
}).should('exist');
|
|
221
|
-
cy.url({
|
|
222
|
-
timeout: commandOptions.timeouts?.waitForUrl ?? defaultTimeouts.waitForUrl
|
|
223
|
-
}).should('include', url);
|
|
224
203
|
} else {
|
|
225
204
|
const mcUrl = appConfig.mcApiUrl.replace('mc-api', 'mc');
|
|
226
|
-
// See similar comment above regarding the usage of `cy.wait`.
|
|
227
|
-
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
228
|
-
cy.wait(1000);
|
|
229
205
|
cy.origin(mcUrl, {
|
|
230
206
|
args: {
|
|
231
207
|
userCredentials,
|
|
232
|
-
mcUrl
|
|
233
|
-
timeouts: commandOptions.timeouts,
|
|
234
|
-
defaultTimeouts
|
|
208
|
+
mcUrl
|
|
235
209
|
}
|
|
236
210
|
}, _ref2 => {
|
|
237
211
|
let userCredentials = _ref2.userCredentials,
|
|
238
|
-
mcUrl = _ref2.mcUrl
|
|
239
|
-
timeouts = _ref2.timeouts,
|
|
240
|
-
defaultTimeouts = _ref2.defaultTimeouts;
|
|
212
|
+
mcUrl = _ref2.mcUrl;
|
|
241
213
|
cy.url().should('include', `${mcUrl}/login`);
|
|
242
214
|
|
|
243
215
|
// Same as `fillLegacyLoginFormWithRetry`.
|
|
244
216
|
// eslint-disable-next-line cypress/unsafe-to-chain-command
|
|
245
|
-
cy.get('input[name=email]'
|
|
246
|
-
timeout: timeouts?.waitForEmailInput ?? defaultTimeouts.waitForEmailInput
|
|
247
|
-
})
|
|
217
|
+
cy.get('input[name=email]')
|
|
248
218
|
// We use `force` as the MC login UI (production) in tests renders the
|
|
249
219
|
// cookie banner overlapping the input fields.
|
|
250
220
|
// To allow Cypress to interact with the input fields, we use `force`.
|
|
@@ -254,9 +224,7 @@ function loginByForm(commandOptions) {
|
|
|
254
224
|
force: true
|
|
255
225
|
});
|
|
256
226
|
// eslint-disable-next-line cypress/unsafe-to-chain-command
|
|
257
|
-
cy.get('input[name=password]'
|
|
258
|
-
timeout: timeouts?.waitForPasswordInput ?? defaultTimeouts.waitForPasswordInput
|
|
259
|
-
})
|
|
227
|
+
cy.get('input[name=password]')
|
|
260
228
|
// We use `force` as the MC login UI (production) in tests renders the
|
|
261
229
|
// cookie banner overlapping the input fields.
|
|
262
230
|
// To allow Cypress to interact with the input fields, we use `force`.
|
|
@@ -270,70 +238,55 @@ function loginByForm(commandOptions) {
|
|
|
270
238
|
force: true
|
|
271
239
|
});
|
|
272
240
|
});
|
|
273
|
-
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
274
|
-
cy.wait(1000);
|
|
275
|
-
|
|
276
|
-
// Wait for the flow to redirect back to the application.
|
|
277
|
-
cy.get('[role="main"]').should('exist');
|
|
278
|
-
cy.url().should('include', url);
|
|
279
241
|
}
|
|
242
|
+
// Wait for the flow to redirect back to the application.
|
|
243
|
+
cy.get('[role="main"]').should('exist');
|
|
244
|
+
cy.url().should('include', initialUriPath);
|
|
280
245
|
} else {
|
|
246
|
+
// Ensure the primary origin is set to MC.
|
|
247
|
+
cy.visit(new _URL__default["default"]('/health', Cypress.config('baseUrl')).toString());
|
|
281
248
|
if (isGlobalIdentityEnabled) {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
//
|
|
289
|
-
cy.
|
|
290
|
-
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
});
|
|
302
|
-
cy.get('button').contains('Submit').click({
|
|
303
|
-
force: true
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
// Wait for redirect to start
|
|
307
|
-
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
308
|
-
cy.wait(commandOptions.timeouts?.waitForRedirect ?? defaultTimeouts.waitForRedirect);
|
|
249
|
+
const identityArgs = {
|
|
250
|
+
email: userCredentials.email,
|
|
251
|
+
password: userCredentials.password,
|
|
252
|
+
returnTo: new _URL__default["default"](initialUriPath, Cypress.config('baseUrl')).toString()
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
// Perform the login flow through Identity.
|
|
256
|
+
cy.origin('https://identity.commercetools.com', {
|
|
257
|
+
args: identityArgs
|
|
258
|
+
}, args => {
|
|
259
|
+
cy.visit({
|
|
260
|
+
url: `/login`,
|
|
261
|
+
qs: {
|
|
262
|
+
returnTo: args.returnTo
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
// Fill in the email and click Next
|
|
266
|
+
cy.get('input[name="identifier"]').type(args.email);
|
|
267
|
+
cy.get('button').contains('Next').click();
|
|
309
268
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
timeouts = _ref3.timeouts,
|
|
320
|
-
defaultTimeouts = _ref3.defaultTimeouts;
|
|
321
|
-
// Wait for application to fully load
|
|
322
|
-
cy.get('[role="main"]', {
|
|
323
|
-
timeout: timeouts?.waitForElement ?? defaultTimeouts.waitForElement
|
|
324
|
-
}).should('exist');
|
|
325
|
-
cy.url({
|
|
326
|
-
timeout: timeouts?.waitForUrl ?? defaultTimeouts.waitForUrl
|
|
327
|
-
}).should('include', url);
|
|
269
|
+
// Wait for the password form to appear
|
|
270
|
+
cy.get('input[name="password"]').should('be.visible');
|
|
271
|
+
// Fill in the password and submit
|
|
272
|
+
cy.get('input[name="password"]').type(args.password, {
|
|
273
|
+
log: false
|
|
274
|
+
});
|
|
275
|
+
cy.get('button').contains('Submit').click({
|
|
276
|
+
force: true
|
|
277
|
+
});
|
|
328
278
|
});
|
|
329
279
|
} else {
|
|
330
280
|
// Legacy login flow.
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
281
|
+
// Visit the application URL, which triggers then the login flow.
|
|
282
|
+
cy.visit(initialUriPath, {
|
|
283
|
+
onBeforeLoad: commandOptions.onBeforeLoad
|
|
284
|
+
});
|
|
285
|
+
fillLegacyLoginFormWithRetry(userCredentials);
|
|
336
286
|
}
|
|
287
|
+
// Wait for the flow to redirect back to the application.
|
|
288
|
+
cy.get('[role="main"]').should('exist');
|
|
289
|
+
cy.url().should('include', initialUriPath);
|
|
337
290
|
}
|
|
338
291
|
});
|
|
339
292
|
}
|
|
@@ -341,18 +294,26 @@ function loginByForm(commandOptions) {
|
|
|
341
294
|
// For backwards compatibility.
|
|
342
295
|
if (isFeatureSupported('12.0.0') || Cypress.config('experimentalSessionAndOrigin')) {
|
|
343
296
|
// https://www.cypress.io/blog/2021/08/04/authenticate-faster-in-tests-cy-session-command/
|
|
344
|
-
cy.session(sessionKey,
|
|
297
|
+
cy.session(sessionKey, sessionAuthCallback, isFeatureSupported('10.9.0') ? {
|
|
345
298
|
cacheAcrossSpecs: typeof commandOptions.disableCacheAcrossSpecs === 'boolean' ? !commandOptions.disableCacheAcrossSpecs : true
|
|
299
|
+
// TODO: enable it once Identity is enabled by default.
|
|
300
|
+
// validate() {
|
|
301
|
+
// if (isLocalhost) {
|
|
302
|
+
// return;
|
|
303
|
+
// }
|
|
304
|
+
// // Verify that the session is valid (session cookie is included in the request).
|
|
305
|
+
// cy.request(new URL('/whoami', appConfig.mcApiUrl).toString())
|
|
306
|
+
// .its('status')
|
|
307
|
+
// .should('eq', 200);
|
|
308
|
+
// },
|
|
346
309
|
} : undefined);
|
|
347
310
|
} else {
|
|
348
311
|
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.`);
|
|
349
|
-
|
|
312
|
+
sessionAuthCallback();
|
|
350
313
|
}
|
|
351
314
|
if (commandOptions.initialRoute) {
|
|
352
315
|
cy.visit(`${Cypress.config('baseUrl')}${commandOptions.initialRoute}`);
|
|
353
|
-
cy.url(
|
|
354
|
-
timeout: commandOptions.timeouts?.waitForUrl ?? defaultTimeouts.waitForUrl
|
|
355
|
-
}).should('include', commandOptions.initialRoute);
|
|
316
|
+
cy.url().should('include', commandOptions.initialRoute);
|
|
356
317
|
}
|
|
357
318
|
});
|
|
358
319
|
}
|
|
@@ -360,7 +321,7 @@ function loginByForm(commandOptions) {
|
|
|
360
321
|
/* Utilities */
|
|
361
322
|
|
|
362
323
|
const legacyMaxLoginAttempts = Cypress.config('maxLoginAttempts') ?? 3;
|
|
363
|
-
function fillLegacyLoginFormWithRetry(userCredentials
|
|
324
|
+
function fillLegacyLoginFormWithRetry(userCredentials) {
|
|
364
325
|
// Intercept the login request so we can retry it if we receive a TOO_MANY_REQUESTS status code
|
|
365
326
|
cy.intercept('POST', '**/tokens').as('loginRequest');
|
|
366
327
|
function getRandomDelayInSeconds() {
|
|
@@ -375,17 +336,13 @@ function fillLegacyLoginFormWithRetry(userCredentials, timeouts) {
|
|
|
375
336
|
cy.log(`Attempts left: ${attemptsLeft}`);
|
|
376
337
|
|
|
377
338
|
// eslint-disable-next-line cypress/unsafe-to-chain-command
|
|
378
|
-
cy.get('input[name=email]'
|
|
379
|
-
timeout: timeouts?.waitForEmailInput ?? defaultTimeouts.waitForEmailInput
|
|
380
|
-
}).clear({
|
|
339
|
+
cy.get('input[name=email]').clear({
|
|
381
340
|
force: true
|
|
382
341
|
}).type(userCredentials.email, {
|
|
383
342
|
force: true
|
|
384
343
|
});
|
|
385
344
|
// eslint-disable-next-line cypress/unsafe-to-chain-command
|
|
386
|
-
cy.get('input[name=password]'
|
|
387
|
-
timeout: timeouts?.waitForPasswordInput ?? defaultTimeouts.waitForPasswordInput
|
|
388
|
-
}).clear({
|
|
345
|
+
cy.get('input[name=password]').clear({
|
|
389
346
|
force: true
|
|
390
347
|
}).type(userCredentials.password, {
|
|
391
348
|
log: false,
|
|
@@ -48,12 +48,7 @@ function _objectSpread$1(e) { for (var r = 1; r < arguments.length; r++) { var _
|
|
|
48
48
|
// Alias for backwards compatibility
|
|
49
49
|
|
|
50
50
|
const defaultTimeouts = {
|
|
51
|
-
|
|
52
|
-
waitForPasswordInput: 8000,
|
|
53
|
-
waitForElement: 15000,
|
|
54
|
-
waitForUrl: 15000,
|
|
55
|
-
waitForRedirect: 3000,
|
|
56
|
-
waitForIdentityRedirect: 8000
|
|
51
|
+
waitForRedirectToLogin: 1000
|
|
57
52
|
};
|
|
58
53
|
function isFeatureSupported(expectedVersion) {
|
|
59
54
|
return semver__default["default"].gte(Cypress.version, expectedVersion);
|
|
@@ -83,9 +78,9 @@ function loginByForm(commandOptions) {
|
|
|
83
78
|
{
|
|
84
79
|
log: false
|
|
85
80
|
}).then(appConfig => {
|
|
86
|
-
let
|
|
81
|
+
let initialUriPath = `/${projectKey}/${commandOptions.entryPointUriPath}`;
|
|
87
82
|
if (commandOptions.entryPointUriPath === 'account') {
|
|
88
|
-
|
|
83
|
+
initialUriPath = `/${commandOptions.entryPointUriPath}`;
|
|
89
84
|
}
|
|
90
85
|
|
|
91
86
|
// Log loaded application config for debugging purposes.
|
|
@@ -104,7 +99,7 @@ function loginByForm(commandOptions) {
|
|
|
104
99
|
* The function is used by Cypress `session` command to store the
|
|
105
100
|
* browser state after executing the authentication flow.
|
|
106
101
|
*/
|
|
107
|
-
function
|
|
102
|
+
function sessionAuthCallback() {
|
|
108
103
|
// Get the feature flags from the Merchant Center API so we can
|
|
109
104
|
// check whether Identity is enabled
|
|
110
105
|
cy.request({
|
|
@@ -112,7 +107,7 @@ function loginByForm(commandOptions) {
|
|
|
112
107
|
url: `${appConfig.mcApiUrl}/graphql`,
|
|
113
108
|
body: {
|
|
114
109
|
operationName: 'AllFeatures',
|
|
115
|
-
query: `query AllFeatures { allFeatures { name value
|
|
110
|
+
query: `query AllFeatures { allFeatures { name value } }`
|
|
116
111
|
},
|
|
117
112
|
headers: {
|
|
118
113
|
'content-type': 'application/json',
|
|
@@ -130,11 +125,6 @@ function loginByForm(commandOptions) {
|
|
|
130
125
|
});
|
|
131
126
|
const identityUrl = Cypress.env('IDENTITY_URL') || 'https://identity.commercetools.com';
|
|
132
127
|
|
|
133
|
-
// Visit the application URL, which triggers then the login flow.
|
|
134
|
-
cy.visit(url, {
|
|
135
|
-
onBeforeLoad: commandOptions.onBeforeLoad
|
|
136
|
-
});
|
|
137
|
-
|
|
138
128
|
/**
|
|
139
129
|
* There are different scenarios and variations on the flow depending
|
|
140
130
|
* on the environment (localhost, production) and if Identity is enabled.
|
|
@@ -172,79 +162,59 @@ function loginByForm(commandOptions) {
|
|
|
172
162
|
*/
|
|
173
163
|
|
|
174
164
|
if (isLocalhost) {
|
|
165
|
+
// Visit the special endpoint /api/health to ensure that the primary origin is set to localhost.
|
|
166
|
+
cy.visit('/api/health');
|
|
167
|
+
// Visit the application URL, which triggers then the login flow.
|
|
168
|
+
cy.visit(initialUriPath, {
|
|
169
|
+
onBeforeLoad: commandOptions.onBeforeLoad
|
|
170
|
+
});
|
|
171
|
+
// Cypress gets confused when switching between origins, likely because
|
|
172
|
+
// the redirect to Identity/MC doesn't happen immediately.
|
|
173
|
+
// If we don't wait, Cypress fails as it tries to interact with `cy.origin`
|
|
174
|
+
// but the test is still in the initial origin URL.
|
|
175
|
+
// This is a bit unexpected and to be considered a workaround.
|
|
176
|
+
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
177
|
+
cy.wait(commandOptions.timeouts?.waitForRedirectToLogin ?? defaultTimeouts.waitForRedirectToLogin);
|
|
175
178
|
if (isGlobalIdentityEnabled) {
|
|
176
|
-
// Cypress gets confused when switching between origins, likely because
|
|
177
|
-
// the redirect to Identity doesn't happen immediately.
|
|
178
|
-
// If we don't wait, Cypress fails as it tries to interact with `cy.origin`
|
|
179
|
-
// but the test is still in the initial origin URL.
|
|
180
|
-
// This is a bit unexpected and to be considered a workaround.
|
|
181
|
-
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
182
|
-
cy.wait(1000);
|
|
183
|
-
|
|
184
179
|
// Use cy.origin to handle the identity domain
|
|
185
180
|
cy.origin(identityUrl, {
|
|
186
181
|
args: {
|
|
187
182
|
userCredentials,
|
|
188
|
-
identityUrl
|
|
189
|
-
timeouts: commandOptions.timeouts,
|
|
190
|
-
defaultTimeouts
|
|
183
|
+
identityUrl
|
|
191
184
|
}
|
|
192
185
|
}, _ref => {
|
|
193
186
|
let userCredentials = _ref.userCredentials,
|
|
194
|
-
identityUrl = _ref.identityUrl
|
|
195
|
-
timeouts = _ref.timeouts,
|
|
196
|
-
defaultTimeouts = _ref.defaultTimeouts;
|
|
187
|
+
identityUrl = _ref.identityUrl;
|
|
197
188
|
cy.url().should('include', `${identityUrl}/login`);
|
|
198
189
|
// Fill in the email and click Next
|
|
199
|
-
cy.get('input[name="identifier"]'
|
|
200
|
-
timeout: timeouts?.waitForEmailInput ?? defaultTimeouts.waitForEmailInput
|
|
201
|
-
}).type(userCredentials.email);
|
|
190
|
+
cy.get('input[name="identifier"]').type(userCredentials.email);
|
|
202
191
|
cy.get('button').contains('Next').click();
|
|
203
192
|
|
|
204
193
|
// Wait for the password form to appear
|
|
205
|
-
cy.get('input[name="password"]'
|
|
206
|
-
timeout: timeouts?.waitForPasswordInput ?? defaultTimeouts.waitForPasswordInput
|
|
207
|
-
}).should('be.visible');
|
|
194
|
+
cy.get('input[name="password"]').should('be.visible');
|
|
208
195
|
// Fill in the password and submit
|
|
209
196
|
cy.get('input[name="password"]').type(userCredentials.password, {
|
|
210
197
|
log: false
|
|
211
198
|
});
|
|
212
|
-
cy.get('button').contains('Submit').click(
|
|
199
|
+
cy.get('button').contains('Submit').click({
|
|
200
|
+
force: true
|
|
201
|
+
});
|
|
213
202
|
});
|
|
214
|
-
|
|
215
|
-
// Wait for the flow to redirect back to the application.
|
|
216
|
-
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
217
|
-
cy.wait(commandOptions.timeouts?.waitForRedirect ?? defaultTimeouts.waitForRedirect);
|
|
218
|
-
cy.get('[role="main"]', {
|
|
219
|
-
timeout: commandOptions.timeouts?.waitForElement ?? defaultTimeouts.waitForElement
|
|
220
|
-
}).should('exist');
|
|
221
|
-
cy.url({
|
|
222
|
-
timeout: commandOptions.timeouts?.waitForUrl ?? defaultTimeouts.waitForUrl
|
|
223
|
-
}).should('include', url);
|
|
224
203
|
} else {
|
|
225
204
|
const mcUrl = appConfig.mcApiUrl.replace('mc-api', 'mc');
|
|
226
|
-
// See similar comment above regarding the usage of `cy.wait`.
|
|
227
|
-
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
228
|
-
cy.wait(1000);
|
|
229
205
|
cy.origin(mcUrl, {
|
|
230
206
|
args: {
|
|
231
207
|
userCredentials,
|
|
232
|
-
mcUrl
|
|
233
|
-
timeouts: commandOptions.timeouts,
|
|
234
|
-
defaultTimeouts
|
|
208
|
+
mcUrl
|
|
235
209
|
}
|
|
236
210
|
}, _ref2 => {
|
|
237
211
|
let userCredentials = _ref2.userCredentials,
|
|
238
|
-
mcUrl = _ref2.mcUrl
|
|
239
|
-
timeouts = _ref2.timeouts,
|
|
240
|
-
defaultTimeouts = _ref2.defaultTimeouts;
|
|
212
|
+
mcUrl = _ref2.mcUrl;
|
|
241
213
|
cy.url().should('include', `${mcUrl}/login`);
|
|
242
214
|
|
|
243
215
|
// Same as `fillLegacyLoginFormWithRetry`.
|
|
244
216
|
// eslint-disable-next-line cypress/unsafe-to-chain-command
|
|
245
|
-
cy.get('input[name=email]'
|
|
246
|
-
timeout: timeouts?.waitForEmailInput ?? defaultTimeouts.waitForEmailInput
|
|
247
|
-
})
|
|
217
|
+
cy.get('input[name=email]')
|
|
248
218
|
// We use `force` as the MC login UI (production) in tests renders the
|
|
249
219
|
// cookie banner overlapping the input fields.
|
|
250
220
|
// To allow Cypress to interact with the input fields, we use `force`.
|
|
@@ -254,9 +224,7 @@ function loginByForm(commandOptions) {
|
|
|
254
224
|
force: true
|
|
255
225
|
});
|
|
256
226
|
// eslint-disable-next-line cypress/unsafe-to-chain-command
|
|
257
|
-
cy.get('input[name=password]'
|
|
258
|
-
timeout: timeouts?.waitForPasswordInput ?? defaultTimeouts.waitForPasswordInput
|
|
259
|
-
})
|
|
227
|
+
cy.get('input[name=password]')
|
|
260
228
|
// We use `force` as the MC login UI (production) in tests renders the
|
|
261
229
|
// cookie banner overlapping the input fields.
|
|
262
230
|
// To allow Cypress to interact with the input fields, we use `force`.
|
|
@@ -270,70 +238,55 @@ function loginByForm(commandOptions) {
|
|
|
270
238
|
force: true
|
|
271
239
|
});
|
|
272
240
|
});
|
|
273
|
-
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
274
|
-
cy.wait(1000);
|
|
275
|
-
|
|
276
|
-
// Wait for the flow to redirect back to the application.
|
|
277
|
-
cy.get('[role="main"]').should('exist');
|
|
278
|
-
cy.url().should('include', url);
|
|
279
241
|
}
|
|
242
|
+
// Wait for the flow to redirect back to the application.
|
|
243
|
+
cy.get('[role="main"]').should('exist');
|
|
244
|
+
cy.url().should('include', initialUriPath);
|
|
280
245
|
} else {
|
|
246
|
+
// Ensure the primary origin is set to MC.
|
|
247
|
+
cy.visit(new _URL__default["default"]('/health', Cypress.config('baseUrl')).toString());
|
|
281
248
|
if (isGlobalIdentityEnabled) {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
//
|
|
289
|
-
cy.
|
|
290
|
-
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
});
|
|
302
|
-
cy.get('button').contains('Submit').click({
|
|
303
|
-
force: true
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
// Wait for redirect to start
|
|
307
|
-
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
308
|
-
cy.wait(commandOptions.timeouts?.waitForRedirect ?? defaultTimeouts.waitForRedirect);
|
|
249
|
+
const identityArgs = {
|
|
250
|
+
email: userCredentials.email,
|
|
251
|
+
password: userCredentials.password,
|
|
252
|
+
returnTo: new _URL__default["default"](initialUriPath, Cypress.config('baseUrl')).toString()
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
// Perform the login flow through Identity.
|
|
256
|
+
cy.origin('https://identity.commercetools.com', {
|
|
257
|
+
args: identityArgs
|
|
258
|
+
}, args => {
|
|
259
|
+
cy.visit({
|
|
260
|
+
url: `/login`,
|
|
261
|
+
qs: {
|
|
262
|
+
returnTo: args.returnTo
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
// Fill in the email and click Next
|
|
266
|
+
cy.get('input[name="identifier"]').type(args.email);
|
|
267
|
+
cy.get('button').contains('Next').click();
|
|
309
268
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
timeouts = _ref3.timeouts,
|
|
320
|
-
defaultTimeouts = _ref3.defaultTimeouts;
|
|
321
|
-
// Wait for application to fully load
|
|
322
|
-
cy.get('[role="main"]', {
|
|
323
|
-
timeout: timeouts?.waitForElement ?? defaultTimeouts.waitForElement
|
|
324
|
-
}).should('exist');
|
|
325
|
-
cy.url({
|
|
326
|
-
timeout: timeouts?.waitForUrl ?? defaultTimeouts.waitForUrl
|
|
327
|
-
}).should('include', url);
|
|
269
|
+
// Wait for the password form to appear
|
|
270
|
+
cy.get('input[name="password"]').should('be.visible');
|
|
271
|
+
// Fill in the password and submit
|
|
272
|
+
cy.get('input[name="password"]').type(args.password, {
|
|
273
|
+
log: false
|
|
274
|
+
});
|
|
275
|
+
cy.get('button').contains('Submit').click({
|
|
276
|
+
force: true
|
|
277
|
+
});
|
|
328
278
|
});
|
|
329
279
|
} else {
|
|
330
280
|
// Legacy login flow.
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
281
|
+
// Visit the application URL, which triggers then the login flow.
|
|
282
|
+
cy.visit(initialUriPath, {
|
|
283
|
+
onBeforeLoad: commandOptions.onBeforeLoad
|
|
284
|
+
});
|
|
285
|
+
fillLegacyLoginFormWithRetry(userCredentials);
|
|
336
286
|
}
|
|
287
|
+
// Wait for the flow to redirect back to the application.
|
|
288
|
+
cy.get('[role="main"]').should('exist');
|
|
289
|
+
cy.url().should('include', initialUriPath);
|
|
337
290
|
}
|
|
338
291
|
});
|
|
339
292
|
}
|
|
@@ -341,18 +294,26 @@ function loginByForm(commandOptions) {
|
|
|
341
294
|
// For backwards compatibility.
|
|
342
295
|
if (isFeatureSupported('12.0.0') || Cypress.config('experimentalSessionAndOrigin')) {
|
|
343
296
|
// https://www.cypress.io/blog/2021/08/04/authenticate-faster-in-tests-cy-session-command/
|
|
344
|
-
cy.session(sessionKey,
|
|
297
|
+
cy.session(sessionKey, sessionAuthCallback, isFeatureSupported('10.9.0') ? {
|
|
345
298
|
cacheAcrossSpecs: typeof commandOptions.disableCacheAcrossSpecs === 'boolean' ? !commandOptions.disableCacheAcrossSpecs : true
|
|
299
|
+
// TODO: enable it once Identity is enabled by default.
|
|
300
|
+
// validate() {
|
|
301
|
+
// if (isLocalhost) {
|
|
302
|
+
// return;
|
|
303
|
+
// }
|
|
304
|
+
// // Verify that the session is valid (session cookie is included in the request).
|
|
305
|
+
// cy.request(new URL('/whoami', appConfig.mcApiUrl).toString())
|
|
306
|
+
// .its('status')
|
|
307
|
+
// .should('eq', 200);
|
|
308
|
+
// },
|
|
346
309
|
} : undefined);
|
|
347
310
|
} else {
|
|
348
311
|
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.`);
|
|
349
|
-
|
|
312
|
+
sessionAuthCallback();
|
|
350
313
|
}
|
|
351
314
|
if (commandOptions.initialRoute) {
|
|
352
315
|
cy.visit(`${Cypress.config('baseUrl')}${commandOptions.initialRoute}`);
|
|
353
|
-
cy.url(
|
|
354
|
-
timeout: commandOptions.timeouts?.waitForUrl ?? defaultTimeouts.waitForUrl
|
|
355
|
-
}).should('include', commandOptions.initialRoute);
|
|
316
|
+
cy.url().should('include', commandOptions.initialRoute);
|
|
356
317
|
}
|
|
357
318
|
});
|
|
358
319
|
}
|
|
@@ -360,7 +321,7 @@ function loginByForm(commandOptions) {
|
|
|
360
321
|
/* Utilities */
|
|
361
322
|
|
|
362
323
|
const legacyMaxLoginAttempts = Cypress.config('maxLoginAttempts') ?? 3;
|
|
363
|
-
function fillLegacyLoginFormWithRetry(userCredentials
|
|
324
|
+
function fillLegacyLoginFormWithRetry(userCredentials) {
|
|
364
325
|
// Intercept the login request so we can retry it if we receive a TOO_MANY_REQUESTS status code
|
|
365
326
|
cy.intercept('POST', '**/tokens').as('loginRequest');
|
|
366
327
|
function getRandomDelayInSeconds() {
|
|
@@ -375,17 +336,13 @@ function fillLegacyLoginFormWithRetry(userCredentials, timeouts) {
|
|
|
375
336
|
cy.log(`Attempts left: ${attemptsLeft}`);
|
|
376
337
|
|
|
377
338
|
// eslint-disable-next-line cypress/unsafe-to-chain-command
|
|
378
|
-
cy.get('input[name=email]'
|
|
379
|
-
timeout: timeouts?.waitForEmailInput ?? defaultTimeouts.waitForEmailInput
|
|
380
|
-
}).clear({
|
|
339
|
+
cy.get('input[name=email]').clear({
|
|
381
340
|
force: true
|
|
382
341
|
}).type(userCredentials.email, {
|
|
383
342
|
force: true
|
|
384
343
|
});
|
|
385
344
|
// eslint-disable-next-line cypress/unsafe-to-chain-command
|
|
386
|
-
cy.get('input[name=password]'
|
|
387
|
-
timeout: timeouts?.waitForPasswordInput ?? defaultTimeouts.waitForPasswordInput
|
|
388
|
-
}).clear({
|
|
345
|
+
cy.get('input[name=password]').clear({
|
|
389
346
|
force: true
|
|
390
347
|
}).type(userCredentials.password, {
|
|
391
348
|
log: false,
|
|
@@ -28,12 +28,7 @@ function _objectSpread$1(e) { for (var r = 1; r < arguments.length; r++) { var _
|
|
|
28
28
|
// Alias for backwards compatibility
|
|
29
29
|
|
|
30
30
|
const defaultTimeouts = {
|
|
31
|
-
|
|
32
|
-
waitForPasswordInput: 8000,
|
|
33
|
-
waitForElement: 15000,
|
|
34
|
-
waitForUrl: 15000,
|
|
35
|
-
waitForRedirect: 3000,
|
|
36
|
-
waitForIdentityRedirect: 8000
|
|
31
|
+
waitForRedirectToLogin: 1000
|
|
37
32
|
};
|
|
38
33
|
function isFeatureSupported(expectedVersion) {
|
|
39
34
|
return semver.gte(Cypress.version, expectedVersion);
|
|
@@ -63,9 +58,9 @@ function loginByForm(commandOptions) {
|
|
|
63
58
|
{
|
|
64
59
|
log: false
|
|
65
60
|
}).then(appConfig => {
|
|
66
|
-
let
|
|
61
|
+
let initialUriPath = `/${projectKey}/${commandOptions.entryPointUriPath}`;
|
|
67
62
|
if (commandOptions.entryPointUriPath === 'account') {
|
|
68
|
-
|
|
63
|
+
initialUriPath = `/${commandOptions.entryPointUriPath}`;
|
|
69
64
|
}
|
|
70
65
|
|
|
71
66
|
// Log loaded application config for debugging purposes.
|
|
@@ -84,7 +79,7 @@ function loginByForm(commandOptions) {
|
|
|
84
79
|
* The function is used by Cypress `session` command to store the
|
|
85
80
|
* browser state after executing the authentication flow.
|
|
86
81
|
*/
|
|
87
|
-
function
|
|
82
|
+
function sessionAuthCallback() {
|
|
88
83
|
// Get the feature flags from the Merchant Center API so we can
|
|
89
84
|
// check whether Identity is enabled
|
|
90
85
|
cy.request({
|
|
@@ -92,7 +87,7 @@ function loginByForm(commandOptions) {
|
|
|
92
87
|
url: `${appConfig.mcApiUrl}/graphql`,
|
|
93
88
|
body: {
|
|
94
89
|
operationName: 'AllFeatures',
|
|
95
|
-
query: `query AllFeatures { allFeatures { name value
|
|
90
|
+
query: `query AllFeatures { allFeatures { name value } }`
|
|
96
91
|
},
|
|
97
92
|
headers: {
|
|
98
93
|
'content-type': 'application/json',
|
|
@@ -110,11 +105,6 @@ function loginByForm(commandOptions) {
|
|
|
110
105
|
});
|
|
111
106
|
const identityUrl = Cypress.env('IDENTITY_URL') || 'https://identity.commercetools.com';
|
|
112
107
|
|
|
113
|
-
// Visit the application URL, which triggers then the login flow.
|
|
114
|
-
cy.visit(url, {
|
|
115
|
-
onBeforeLoad: commandOptions.onBeforeLoad
|
|
116
|
-
});
|
|
117
|
-
|
|
118
108
|
/**
|
|
119
109
|
* There are different scenarios and variations on the flow depending
|
|
120
110
|
* on the environment (localhost, production) and if Identity is enabled.
|
|
@@ -152,79 +142,59 @@ function loginByForm(commandOptions) {
|
|
|
152
142
|
*/
|
|
153
143
|
|
|
154
144
|
if (isLocalhost) {
|
|
145
|
+
// Visit the special endpoint /api/health to ensure that the primary origin is set to localhost.
|
|
146
|
+
cy.visit('/api/health');
|
|
147
|
+
// Visit the application URL, which triggers then the login flow.
|
|
148
|
+
cy.visit(initialUriPath, {
|
|
149
|
+
onBeforeLoad: commandOptions.onBeforeLoad
|
|
150
|
+
});
|
|
151
|
+
// Cypress gets confused when switching between origins, likely because
|
|
152
|
+
// the redirect to Identity/MC doesn't happen immediately.
|
|
153
|
+
// If we don't wait, Cypress fails as it tries to interact with `cy.origin`
|
|
154
|
+
// but the test is still in the initial origin URL.
|
|
155
|
+
// This is a bit unexpected and to be considered a workaround.
|
|
156
|
+
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
157
|
+
cy.wait(commandOptions.timeouts?.waitForRedirectToLogin ?? defaultTimeouts.waitForRedirectToLogin);
|
|
155
158
|
if (isGlobalIdentityEnabled) {
|
|
156
|
-
// Cypress gets confused when switching between origins, likely because
|
|
157
|
-
// the redirect to Identity doesn't happen immediately.
|
|
158
|
-
// If we don't wait, Cypress fails as it tries to interact with `cy.origin`
|
|
159
|
-
// but the test is still in the initial origin URL.
|
|
160
|
-
// This is a bit unexpected and to be considered a workaround.
|
|
161
|
-
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
162
|
-
cy.wait(1000);
|
|
163
|
-
|
|
164
159
|
// Use cy.origin to handle the identity domain
|
|
165
160
|
cy.origin(identityUrl, {
|
|
166
161
|
args: {
|
|
167
162
|
userCredentials,
|
|
168
|
-
identityUrl
|
|
169
|
-
timeouts: commandOptions.timeouts,
|
|
170
|
-
defaultTimeouts
|
|
163
|
+
identityUrl
|
|
171
164
|
}
|
|
172
165
|
}, _ref => {
|
|
173
166
|
let userCredentials = _ref.userCredentials,
|
|
174
|
-
identityUrl = _ref.identityUrl
|
|
175
|
-
timeouts = _ref.timeouts,
|
|
176
|
-
defaultTimeouts = _ref.defaultTimeouts;
|
|
167
|
+
identityUrl = _ref.identityUrl;
|
|
177
168
|
cy.url().should('include', `${identityUrl}/login`);
|
|
178
169
|
// Fill in the email and click Next
|
|
179
|
-
cy.get('input[name="identifier"]'
|
|
180
|
-
timeout: timeouts?.waitForEmailInput ?? defaultTimeouts.waitForEmailInput
|
|
181
|
-
}).type(userCredentials.email);
|
|
170
|
+
cy.get('input[name="identifier"]').type(userCredentials.email);
|
|
182
171
|
cy.get('button').contains('Next').click();
|
|
183
172
|
|
|
184
173
|
// Wait for the password form to appear
|
|
185
|
-
cy.get('input[name="password"]'
|
|
186
|
-
timeout: timeouts?.waitForPasswordInput ?? defaultTimeouts.waitForPasswordInput
|
|
187
|
-
}).should('be.visible');
|
|
174
|
+
cy.get('input[name="password"]').should('be.visible');
|
|
188
175
|
// Fill in the password and submit
|
|
189
176
|
cy.get('input[name="password"]').type(userCredentials.password, {
|
|
190
177
|
log: false
|
|
191
178
|
});
|
|
192
|
-
cy.get('button').contains('Submit').click(
|
|
179
|
+
cy.get('button').contains('Submit').click({
|
|
180
|
+
force: true
|
|
181
|
+
});
|
|
193
182
|
});
|
|
194
|
-
|
|
195
|
-
// Wait for the flow to redirect back to the application.
|
|
196
|
-
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
197
|
-
cy.wait(commandOptions.timeouts?.waitForRedirect ?? defaultTimeouts.waitForRedirect);
|
|
198
|
-
cy.get('[role="main"]', {
|
|
199
|
-
timeout: commandOptions.timeouts?.waitForElement ?? defaultTimeouts.waitForElement
|
|
200
|
-
}).should('exist');
|
|
201
|
-
cy.url({
|
|
202
|
-
timeout: commandOptions.timeouts?.waitForUrl ?? defaultTimeouts.waitForUrl
|
|
203
|
-
}).should('include', url);
|
|
204
183
|
} else {
|
|
205
184
|
const mcUrl = appConfig.mcApiUrl.replace('mc-api', 'mc');
|
|
206
|
-
// See similar comment above regarding the usage of `cy.wait`.
|
|
207
|
-
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
208
|
-
cy.wait(1000);
|
|
209
185
|
cy.origin(mcUrl, {
|
|
210
186
|
args: {
|
|
211
187
|
userCredentials,
|
|
212
|
-
mcUrl
|
|
213
|
-
timeouts: commandOptions.timeouts,
|
|
214
|
-
defaultTimeouts
|
|
188
|
+
mcUrl
|
|
215
189
|
}
|
|
216
190
|
}, _ref2 => {
|
|
217
191
|
let userCredentials = _ref2.userCredentials,
|
|
218
|
-
mcUrl = _ref2.mcUrl
|
|
219
|
-
timeouts = _ref2.timeouts,
|
|
220
|
-
defaultTimeouts = _ref2.defaultTimeouts;
|
|
192
|
+
mcUrl = _ref2.mcUrl;
|
|
221
193
|
cy.url().should('include', `${mcUrl}/login`);
|
|
222
194
|
|
|
223
195
|
// Same as `fillLegacyLoginFormWithRetry`.
|
|
224
196
|
// eslint-disable-next-line cypress/unsafe-to-chain-command
|
|
225
|
-
cy.get('input[name=email]'
|
|
226
|
-
timeout: timeouts?.waitForEmailInput ?? defaultTimeouts.waitForEmailInput
|
|
227
|
-
})
|
|
197
|
+
cy.get('input[name=email]')
|
|
228
198
|
// We use `force` as the MC login UI (production) in tests renders the
|
|
229
199
|
// cookie banner overlapping the input fields.
|
|
230
200
|
// To allow Cypress to interact with the input fields, we use `force`.
|
|
@@ -234,9 +204,7 @@ function loginByForm(commandOptions) {
|
|
|
234
204
|
force: true
|
|
235
205
|
});
|
|
236
206
|
// eslint-disable-next-line cypress/unsafe-to-chain-command
|
|
237
|
-
cy.get('input[name=password]'
|
|
238
|
-
timeout: timeouts?.waitForPasswordInput ?? defaultTimeouts.waitForPasswordInput
|
|
239
|
-
})
|
|
207
|
+
cy.get('input[name=password]')
|
|
240
208
|
// We use `force` as the MC login UI (production) in tests renders the
|
|
241
209
|
// cookie banner overlapping the input fields.
|
|
242
210
|
// To allow Cypress to interact with the input fields, we use `force`.
|
|
@@ -250,70 +218,55 @@ function loginByForm(commandOptions) {
|
|
|
250
218
|
force: true
|
|
251
219
|
});
|
|
252
220
|
});
|
|
253
|
-
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
254
|
-
cy.wait(1000);
|
|
255
|
-
|
|
256
|
-
// Wait for the flow to redirect back to the application.
|
|
257
|
-
cy.get('[role="main"]').should('exist');
|
|
258
|
-
cy.url().should('include', url);
|
|
259
221
|
}
|
|
222
|
+
// Wait for the flow to redirect back to the application.
|
|
223
|
+
cy.get('[role="main"]').should('exist');
|
|
224
|
+
cy.url().should('include', initialUriPath);
|
|
260
225
|
} else {
|
|
226
|
+
// Ensure the primary origin is set to MC.
|
|
227
|
+
cy.visit(new _URL('/health', Cypress.config('baseUrl')).toString());
|
|
261
228
|
if (isGlobalIdentityEnabled) {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
//
|
|
269
|
-
cy.
|
|
270
|
-
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
});
|
|
282
|
-
cy.get('button').contains('Submit').click({
|
|
283
|
-
force: true
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
// Wait for redirect to start
|
|
287
|
-
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
288
|
-
cy.wait(commandOptions.timeouts?.waitForRedirect ?? defaultTimeouts.waitForRedirect);
|
|
229
|
+
const identityArgs = {
|
|
230
|
+
email: userCredentials.email,
|
|
231
|
+
password: userCredentials.password,
|
|
232
|
+
returnTo: new _URL(initialUriPath, Cypress.config('baseUrl')).toString()
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
// Perform the login flow through Identity.
|
|
236
|
+
cy.origin('https://identity.commercetools.com', {
|
|
237
|
+
args: identityArgs
|
|
238
|
+
}, args => {
|
|
239
|
+
cy.visit({
|
|
240
|
+
url: `/login`,
|
|
241
|
+
qs: {
|
|
242
|
+
returnTo: args.returnTo
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
// Fill in the email and click Next
|
|
246
|
+
cy.get('input[name="identifier"]').type(args.email);
|
|
247
|
+
cy.get('button').contains('Next').click();
|
|
289
248
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
timeouts = _ref3.timeouts,
|
|
300
|
-
defaultTimeouts = _ref3.defaultTimeouts;
|
|
301
|
-
// Wait for application to fully load
|
|
302
|
-
cy.get('[role="main"]', {
|
|
303
|
-
timeout: timeouts?.waitForElement ?? defaultTimeouts.waitForElement
|
|
304
|
-
}).should('exist');
|
|
305
|
-
cy.url({
|
|
306
|
-
timeout: timeouts?.waitForUrl ?? defaultTimeouts.waitForUrl
|
|
307
|
-
}).should('include', url);
|
|
249
|
+
// Wait for the password form to appear
|
|
250
|
+
cy.get('input[name="password"]').should('be.visible');
|
|
251
|
+
// Fill in the password and submit
|
|
252
|
+
cy.get('input[name="password"]').type(args.password, {
|
|
253
|
+
log: false
|
|
254
|
+
});
|
|
255
|
+
cy.get('button').contains('Submit').click({
|
|
256
|
+
force: true
|
|
257
|
+
});
|
|
308
258
|
});
|
|
309
259
|
} else {
|
|
310
260
|
// Legacy login flow.
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
261
|
+
// Visit the application URL, which triggers then the login flow.
|
|
262
|
+
cy.visit(initialUriPath, {
|
|
263
|
+
onBeforeLoad: commandOptions.onBeforeLoad
|
|
264
|
+
});
|
|
265
|
+
fillLegacyLoginFormWithRetry(userCredentials);
|
|
316
266
|
}
|
|
267
|
+
// Wait for the flow to redirect back to the application.
|
|
268
|
+
cy.get('[role="main"]').should('exist');
|
|
269
|
+
cy.url().should('include', initialUriPath);
|
|
317
270
|
}
|
|
318
271
|
});
|
|
319
272
|
}
|
|
@@ -321,18 +274,26 @@ function loginByForm(commandOptions) {
|
|
|
321
274
|
// For backwards compatibility.
|
|
322
275
|
if (isFeatureSupported('12.0.0') || Cypress.config('experimentalSessionAndOrigin')) {
|
|
323
276
|
// https://www.cypress.io/blog/2021/08/04/authenticate-faster-in-tests-cy-session-command/
|
|
324
|
-
cy.session(sessionKey,
|
|
277
|
+
cy.session(sessionKey, sessionAuthCallback, isFeatureSupported('10.9.0') ? {
|
|
325
278
|
cacheAcrossSpecs: typeof commandOptions.disableCacheAcrossSpecs === 'boolean' ? !commandOptions.disableCacheAcrossSpecs : true
|
|
279
|
+
// TODO: enable it once Identity is enabled by default.
|
|
280
|
+
// validate() {
|
|
281
|
+
// if (isLocalhost) {
|
|
282
|
+
// return;
|
|
283
|
+
// }
|
|
284
|
+
// // Verify that the session is valid (session cookie is included in the request).
|
|
285
|
+
// cy.request(new URL('/whoami', appConfig.mcApiUrl).toString())
|
|
286
|
+
// .its('status')
|
|
287
|
+
// .should('eq', 200);
|
|
288
|
+
// },
|
|
326
289
|
} : undefined);
|
|
327
290
|
} else {
|
|
328
291
|
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.`);
|
|
329
|
-
|
|
292
|
+
sessionAuthCallback();
|
|
330
293
|
}
|
|
331
294
|
if (commandOptions.initialRoute) {
|
|
332
295
|
cy.visit(`${Cypress.config('baseUrl')}${commandOptions.initialRoute}`);
|
|
333
|
-
cy.url(
|
|
334
|
-
timeout: commandOptions.timeouts?.waitForUrl ?? defaultTimeouts.waitForUrl
|
|
335
|
-
}).should('include', commandOptions.initialRoute);
|
|
296
|
+
cy.url().should('include', commandOptions.initialRoute);
|
|
336
297
|
}
|
|
337
298
|
});
|
|
338
299
|
}
|
|
@@ -340,7 +301,7 @@ function loginByForm(commandOptions) {
|
|
|
340
301
|
/* Utilities */
|
|
341
302
|
|
|
342
303
|
const legacyMaxLoginAttempts = Cypress.config('maxLoginAttempts') ?? 3;
|
|
343
|
-
function fillLegacyLoginFormWithRetry(userCredentials
|
|
304
|
+
function fillLegacyLoginFormWithRetry(userCredentials) {
|
|
344
305
|
// Intercept the login request so we can retry it if we receive a TOO_MANY_REQUESTS status code
|
|
345
306
|
cy.intercept('POST', '**/tokens').as('loginRequest');
|
|
346
307
|
function getRandomDelayInSeconds() {
|
|
@@ -355,17 +316,13 @@ function fillLegacyLoginFormWithRetry(userCredentials, timeouts) {
|
|
|
355
316
|
cy.log(`Attempts left: ${attemptsLeft}`);
|
|
356
317
|
|
|
357
318
|
// eslint-disable-next-line cypress/unsafe-to-chain-command
|
|
358
|
-
cy.get('input[name=email]'
|
|
359
|
-
timeout: timeouts?.waitForEmailInput ?? defaultTimeouts.waitForEmailInput
|
|
360
|
-
}).clear({
|
|
319
|
+
cy.get('input[name=email]').clear({
|
|
361
320
|
force: true
|
|
362
321
|
}).type(userCredentials.email, {
|
|
363
322
|
force: true
|
|
364
323
|
});
|
|
365
324
|
// eslint-disable-next-line cypress/unsafe-to-chain-command
|
|
366
|
-
cy.get('input[name=password]'
|
|
367
|
-
timeout: timeouts?.waitForPasswordInput ?? defaultTimeouts.waitForPasswordInput
|
|
368
|
-
}).clear({
|
|
325
|
+
cy.get('input[name=password]').clear({
|
|
369
326
|
force: true
|
|
370
327
|
}).type(userCredentials.password, {
|
|
371
328
|
log: false,
|
|
@@ -5,7 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
5
5
|
var constants = require('./constants-009cb682.cjs.dev.js');
|
|
6
6
|
|
|
7
7
|
// NOTE: This string will be replaced on build time with the package version.
|
|
8
|
-
var version = "24.7.
|
|
8
|
+
var version = "24.7.2";
|
|
9
9
|
|
|
10
10
|
exports.HTTP_STATUS_CODES = constants.HTTP_STATUS_CODES;
|
|
11
11
|
exports.OIDC_RESPONSE_TYPES = constants.OIDC_RESPONSE_TYPES;
|
|
@@ -5,7 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
5
5
|
var constants = require('./constants-2f1475a6.cjs.prod.js');
|
|
6
6
|
|
|
7
7
|
// NOTE: This string will be replaced on build time with the package version.
|
|
8
|
-
var version = "24.7.
|
|
8
|
+
var version = "24.7.2";
|
|
9
9
|
|
|
10
10
|
exports.HTTP_STATUS_CODES = constants.HTTP_STATUS_CODES;
|
|
11
11
|
exports.OIDC_RESPONSE_TYPES = constants.OIDC_RESPONSE_TYPES;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { H as HTTP_STATUS_CODES, O as OIDC_RESPONSE_TYPES, S as STORAGE_KEYS } from './constants-13c76918.esm.js';
|
|
2
2
|
|
|
3
3
|
// NOTE: This string will be replaced on build time with the package version.
|
|
4
|
-
var version = "24.7.
|
|
4
|
+
var version = "24.7.2";
|
|
5
5
|
|
|
6
6
|
export { version };
|
|
@@ -11,36 +11,11 @@ export type LoginCredentials = {
|
|
|
11
11
|
password: string;
|
|
12
12
|
};
|
|
13
13
|
export type LoginCommandTimeouts = {
|
|
14
|
-
/**
|
|
15
|
-
* The number of milliseconds to wait for the email input to appear.
|
|
16
|
-
* Defaults to `4000` (4 seconds).
|
|
17
|
-
*/
|
|
18
|
-
waitForEmailInput?: number;
|
|
19
|
-
/**
|
|
20
|
-
* The number of milliseconds to wait for the password input to appear.
|
|
21
|
-
* Defaults to `8000` (8 seconds).
|
|
22
|
-
*/
|
|
23
|
-
waitForPasswordInput?: number;
|
|
24
|
-
/**
|
|
25
|
-
* The timeout in milliseconds for cy.get() operations on elements.
|
|
26
|
-
* Defaults to `15000` (15 seconds).
|
|
27
|
-
*/
|
|
28
|
-
waitForElement?: number;
|
|
29
|
-
/**
|
|
30
|
-
* The timeout in milliseconds for cy.url() operations.
|
|
31
|
-
* Defaults to `15000` (15 seconds).
|
|
32
|
-
*/
|
|
33
|
-
waitForUrl?: number;
|
|
34
|
-
/**
|
|
35
|
-
* The number of milliseconds to wait for redirects to complete.
|
|
36
|
-
* Defaults to `3000` (3 seconds).
|
|
37
|
-
*/
|
|
38
|
-
waitForRedirect?: number;
|
|
39
14
|
/**
|
|
40
15
|
* The number of milliseconds to wait for Identity redirect to complete.
|
|
41
|
-
* Defaults to `
|
|
16
|
+
* Defaults to `1000` (1 second).
|
|
42
17
|
*/
|
|
43
|
-
|
|
18
|
+
waitForRedirectToLogin?: number;
|
|
44
19
|
};
|
|
45
20
|
export type CommandLoginOptions = {
|
|
46
21
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@commercetools-frontend/cypress",
|
|
3
|
-
"version": "24.7.
|
|
3
|
+
"version": "24.7.2",
|
|
4
4
|
"description": "Cypress commands and utilities for Custom Applications",
|
|
5
5
|
"bugs": "https://github.com/commercetools/merchant-center-application-kit/issues",
|
|
6
6
|
"repository": {
|
|
@@ -41,9 +41,9 @@
|
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@babel/runtime": "^7.22.15",
|
|
43
43
|
"@babel/runtime-corejs3": "^7.22.15",
|
|
44
|
-
"@commercetools-frontend/application-config": "24.7.
|
|
45
|
-
"@commercetools-frontend/application-shell": "24.7.
|
|
46
|
-
"@commercetools-frontend/constants": "24.7.
|
|
44
|
+
"@commercetools-frontend/application-config": "24.7.2",
|
|
45
|
+
"@commercetools-frontend/application-shell": "24.7.2",
|
|
46
|
+
"@commercetools-frontend/constants": "24.7.2",
|
|
47
47
|
"@manypkg/get-packages": "1.1.3",
|
|
48
48
|
"@types/semver": "^7.5.1",
|
|
49
49
|
"semver": "7.6.2",
|