@commercetools-frontend/cypress
Version:
Cypress commands and utilities for Custom Applications
678 lines (638 loc) • 31 kB
JavaScript
var _Object$keys = require('@babel/runtime-corejs3/core-js-stable/object/keys');
var _Object$getOwnPropertySymbols = require('@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols');
var _filterInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/filter');
var _Object$getOwnPropertyDescriptor = require('@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptor');
var _forEachInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/for-each');
var _Object$getOwnPropertyDescriptors = require('@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptors');
var _Object$defineProperties = require('@babel/runtime-corejs3/core-js-stable/object/define-properties');
var _Object$defineProperty = require('@babel/runtime-corejs3/core-js-stable/object/define-property');
var _defineProperty = require('@babel/runtime-corejs3/helpers/defineProperty');
var _findInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/find');
var constants = require('@commercetools-frontend/constants');
var _URL = require('@babel/runtime-corejs3/core-js-stable/url');
var semver = require('semver');
var constants$1 = require('../../dist/constants-009cb682.cjs.dev.js');
var _slicedToArray = require('@babel/runtime-corejs3/helpers/slicedToArray');
var _mapInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/map');
var _Array$from = require('@babel/runtime-corejs3/core-js-stable/array/from');
var _entriesInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/entries');
var _reduceRightInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/reduce-right');
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
var _Object$keys__default = /*#__PURE__*/_interopDefault(_Object$keys);
var _Object$getOwnPropertySymbols__default = /*#__PURE__*/_interopDefault(_Object$getOwnPropertySymbols);
var _filterInstanceProperty__default = /*#__PURE__*/_interopDefault(_filterInstanceProperty);
var _Object$getOwnPropertyDescriptor__default = /*#__PURE__*/_interopDefault(_Object$getOwnPropertyDescriptor);
var _forEachInstanceProperty__default = /*#__PURE__*/_interopDefault(_forEachInstanceProperty);
var _Object$getOwnPropertyDescriptors__default = /*#__PURE__*/_interopDefault(_Object$getOwnPropertyDescriptors);
var _Object$defineProperties__default = /*#__PURE__*/_interopDefault(_Object$defineProperties);
var _Object$defineProperty__default = /*#__PURE__*/_interopDefault(_Object$defineProperty);
var _findInstanceProperty__default = /*#__PURE__*/_interopDefault(_findInstanceProperty);
var _URL__default = /*#__PURE__*/_interopDefault(_URL);
var semver__default = /*#__PURE__*/_interopDefault(semver);
var _mapInstanceProperty__default = /*#__PURE__*/_interopDefault(_mapInstanceProperty);
var _Array$from__default = /*#__PURE__*/_interopDefault(_Array$from);
var _entriesInstanceProperty__default = /*#__PURE__*/_interopDefault(_entriesInstanceProperty);
var _reduceRightInstanceProperty__default = /*#__PURE__*/_interopDefault(_reduceRightInstanceProperty);
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; }
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; }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
// eslint-disable-next-line @typescript-eslint/no-explicit-any
// Alias for backwards compatibility
const defaultTimeouts = {
waitForEmailInput: 4000,
waitForPasswordInput: 8000,
waitForElement: 15000,
waitForUrl: 15000,
waitForRedirect: 3000,
waitForIdentityRedirect: 8000
};
function isFeatureSupported(expectedVersion) {
return semver__default["default"].gte(Cypress.version, expectedVersion);
}
function isRunningOnLocalhost() {
const baseUrl = new _URL__default["default"](Cypress.config('baseUrl'));
return baseUrl.hostname === 'localhost';
}
const isCustomView = commandOptions => commandOptions.entryPointUriPath === constants.CUSTOM_VIEW_HOST_ENTRY_POINT_URI_PATH;
function loginByForm(commandOptions) {
const isLocalhost = isRunningOnLocalhost();
Cypress.log({
name: 'isLocalhost',
message: isLocalhost
});
const projectKey = commandOptions.projectKey ?? Cypress.env('PROJECT_KEY');
const isCustomViewConfigCommand = isCustomView(commandOptions);
const customEntityConfigCommand = isCustomViewConfigCommand ? 'customViewConfig' : 'customApplicationConfig';
const packageName = commandOptions.packageName ?? Cypress.env('PACKAGE_NAME');
cy.task(customEntityConfigCommand, _objectSpread$1({
entryPointUriPath: commandOptions.entryPointUriPath,
dotfiles: commandOptions.dotfiles
}, isCustomViewConfigCommand ? {
packageName
} : {}),
// Do not show log, as it may contain sensible information.
{
log: false
}).then(appConfig => {
let url = `/${projectKey}/${commandOptions.entryPointUriPath}`;
if (commandOptions.entryPointUriPath === 'account') {
url = `/${commandOptions.entryPointUriPath}`;
}
// Log loaded application config for debugging purposes.
Cypress.log({
displayName: 'task',
name: customEntityConfigCommand,
message: appConfig
});
const userCredentials = commandOptions.login ?? {
email: Cypress.env('LOGIN_EMAIL') || Cypress.env('LOGIN_USER'),
password: Cypress.env('LOGIN_PASSWORD')
};
const sessionKey = ['loginByForm', userCredentials.email, commandOptions.entryPointUriPath];
/**
* The function is used by Cypress `session` command to store the
* browser state after executing the authentication flow.
*/
function authCallback() {
// Get the feature flags from the Merchant Center API so we can
// check whether Identity is enabled
cy.request({
method: 'POST',
url: `${appConfig.mcApiUrl}/graphql`,
body: {
operationName: 'AllFeatures',
query: `query AllFeatures { allFeatures { name value reason } }`
},
headers: {
'content-type': 'application/json',
'x-graphql-target': constants.GRAPHQL_TARGETS.MERCHANT_CENTER_BACKEND,
'x-graphql-operation-name': 'AllFeatures',
'x-project-key': projectKey
}
}).then(res => {
var _context;
const enableIdentity = _findInstanceProperty__default["default"](_context = res.body.data.allFeatures).call(_context, feature => feature.name === 'enableGlobalIdentity');
const isGlobalIdentityEnabled = Boolean(enableIdentity?.value);
Cypress.log({
name: 'isGlobalIdentityEnabled',
message: isGlobalIdentityEnabled
});
const identityUrl = Cypress.env('IDENTITY_URL') || 'https://identity.commercetools.com';
// Visit the application URL, which triggers then the login flow.
cy.visit(url, {
onBeforeLoad: commandOptions.onBeforeLoad
});
/**
* There are different scenarios and variations on the flow depending
* on the environment (localhost, production) and if Identity is enabled.
*
* # When the application runs on localhost:3001.
*
* ## When Identity is enabled
* - The test visits the application at localhost:3001.
* - Cypress registers the default origin being localhost:3001.
* - The application is redirected to the Identity URL.
* - Cypress interacts with the Identity URL via `cy.origin`.
* - At the end of the flow, the test interacts with the application at localhost:3001.
* ## When Identity is disabled
* - The test visits the application at localhost:3001.
* - Cypress registers the default origin being localhost:3001.
* - The application is redirected to the Merchant Center login page.
* - Cypress interacts with the Merchant Center login page via `cy.origin`.
* - At the end of the flow, the test interacts with the application at localhost:3001.
*
* # When the application runs on a production URL.
*
* ## When Identity is enabled
* - The test visits the application at the production URL.
* - The MC Proxy performs a server-side redirect to the Identity URL.
* - Cypress registers the default origin being the Identity URL.
* - Cypress interacts with the Identity URL.
* - At the end of the flow, the test interacts with the application at the production URL via `cy.origin`.
*
* ## When Identity is disabled
* - The test visits the application at the production URL.
* - The MC Proxy renders the Merchant Center login page.
* - Cypress registers the default origin being the Merchant Center URL.
* - Cypress interacts with the Merchant Center login page.
* - At the end of the flow, the test interacts with the application at the production URL.
*/
if (isLocalhost) {
if (isGlobalIdentityEnabled) {
// Cypress gets confused when switching between origins, likely because
// the redirect to Identity doesn't happen immediately.
// If we don't wait, Cypress fails as it tries to interact with `cy.origin`
// but the test is still in the initial origin URL.
// This is a bit unexpected and to be considered a workaround.
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(1000);
// Use cy.origin to handle the identity domain
cy.origin(identityUrl, {
args: {
userCredentials,
identityUrl,
timeouts: commandOptions.timeouts,
defaultTimeouts
}
}, _ref => {
let userCredentials = _ref.userCredentials,
identityUrl = _ref.identityUrl,
timeouts = _ref.timeouts,
defaultTimeouts = _ref.defaultTimeouts;
cy.url().should('include', `${identityUrl}/login`);
// Fill in the email and click Next
cy.get('input[name="identifier"]', {
timeout: timeouts?.waitForEmailInput ?? defaultTimeouts.waitForEmailInput
}).type(userCredentials.email);
cy.get('button').contains('Next').click();
// Wait for the password form to appear
cy.get('input[name="password"]', {
timeout: timeouts?.waitForPasswordInput ?? defaultTimeouts.waitForPasswordInput
}).should('be.visible');
// Fill in the password and submit
cy.get('input[name="password"]').type(userCredentials.password, {
log: false
});
cy.get('button').contains('Submit').click();
});
// Wait for the flow to redirect back to the application.
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(commandOptions.timeouts?.waitForRedirect ?? defaultTimeouts.waitForRedirect);
cy.get('[role="main"]', {
timeout: commandOptions.timeouts?.waitForElement ?? defaultTimeouts.waitForElement
}).should('exist');
cy.url({
timeout: commandOptions.timeouts?.waitForUrl ?? defaultTimeouts.waitForUrl
}).should('include', url);
} else {
const mcUrl = appConfig.mcApiUrl.replace('mc-api', 'mc');
// See similar comment above regarding the usage of `cy.wait`.
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(1000);
cy.origin(mcUrl, {
args: {
userCredentials,
mcUrl,
timeouts: commandOptions.timeouts,
defaultTimeouts
}
}, _ref2 => {
let userCredentials = _ref2.userCredentials,
mcUrl = _ref2.mcUrl,
timeouts = _ref2.timeouts,
defaultTimeouts = _ref2.defaultTimeouts;
cy.url().should('include', `${mcUrl}/login`);
// Same as `fillLegacyLoginFormWithRetry`.
// eslint-disable-next-line cypress/unsafe-to-chain-command
cy.get('input[name=email]', {
timeout: timeouts?.waitForEmailInput ?? defaultTimeouts.waitForEmailInput
})
// We use `force` as the MC login UI (production) in tests renders the
// cookie banner overlapping the input fields.
// To allow Cypress to interact with the input fields, we use `force`.
.clear({
force: true
}).type(userCredentials.email, {
force: true
});
// eslint-disable-next-line cypress/unsafe-to-chain-command
cy.get('input[name=password]', {
timeout: timeouts?.waitForPasswordInput ?? defaultTimeouts.waitForPasswordInput
})
// We use `force` as the MC login UI (production) in tests renders the
// cookie banner overlapping the input fields.
// To allow Cypress to interact with the input fields, we use `force`.
.clear({
force: true
}).type(userCredentials.password, {
log: false,
force: true
});
cy.get('button').contains('Sign in').click({
force: true
});
});
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(1000);
// Wait for the flow to redirect back to the application.
cy.get('[role="main"]').should('exist');
cy.url().should('include', url);
}
} else {
if (isGlobalIdentityEnabled) {
// Wait for redirect to Identity to complete
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(commandOptions.timeouts?.waitForIdentityRedirect ?? defaultTimeouts.waitForIdentityRedirect);
cy.url({
timeout: commandOptions.timeouts?.waitForUrl ?? defaultTimeouts.waitForUrl
}).should('include', `${identityUrl}/login`);
// Fill in the email and click Next
cy.get('input[name="identifier"]', {
timeout: commandOptions.timeouts?.waitForEmailInput ?? defaultTimeouts.waitForEmailInput
}).type(userCredentials.email);
cy.get('button').contains('Next').click();
// Wait for the password form to appear
cy.get('input[name="password"]', {
timeout: commandOptions.timeouts?.waitForPasswordInput ?? defaultTimeouts.waitForPasswordInput
}).should('be.visible');
// Fill in the password and submit
cy.get('input[name="password"]').type(userCredentials.password, {
log: false
});
cy.get('button').contains('Submit').click({
force: true
});
// Wait for redirect to start
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(commandOptions.timeouts?.waitForRedirect ?? defaultTimeouts.waitForRedirect);
// Wait for the flow to redirect back to the application.
cy.origin(Cypress.config('baseUrl'), {
args: {
url,
timeouts: commandOptions.timeouts,
defaultTimeouts
}
}, _ref3 => {
let url = _ref3.url,
timeouts = _ref3.timeouts,
defaultTimeouts = _ref3.defaultTimeouts;
// Wait for application to fully load
cy.get('[role="main"]', {
timeout: timeouts?.waitForElement ?? defaultTimeouts.waitForElement
}).should('exist');
cy.url({
timeout: timeouts?.waitForUrl ?? defaultTimeouts.waitForUrl
}).should('include', url);
});
} else {
// Legacy login flow.
fillLegacyLoginFormWithRetry(userCredentials, commandOptions.timeouts);
// Wait for the flow to redirect back to the application.
cy.get('[role="main"]').should('exist');
cy.url().should('include', url);
}
}
});
}
// For backwards compatibility.
if (isFeatureSupported('12.0.0') || Cypress.config('experimentalSessionAndOrigin')) {
// https://www.cypress.io/blog/2021/08/04/authenticate-faster-in-tests-cy-session-command/
cy.session(sessionKey, authCallback, isFeatureSupported('10.9.0') ? {
cacheAcrossSpecs: typeof commandOptions.disableCacheAcrossSpecs === 'boolean' ? !commandOptions.disableCacheAcrossSpecs : true
} : undefined);
} else {
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.`);
authCallback();
}
if (commandOptions.initialRoute) {
cy.visit(`${Cypress.config('baseUrl')}${commandOptions.initialRoute}`);
cy.url({
timeout: commandOptions.timeouts?.waitForUrl ?? defaultTimeouts.waitForUrl
}).should('include', commandOptions.initialRoute);
}
});
}
/* Utilities */
const legacyMaxLoginAttempts = Cypress.config('maxLoginAttempts') ?? 3;
function fillLegacyLoginFormWithRetry(userCredentials, timeouts) {
// Intercept the login request so we can retry it if we receive a TOO_MANY_REQUESTS status code
cy.intercept('POST', '**/tokens').as('loginRequest');
function getRandomDelayInSeconds() {
const minSeconds = 0.5;
const maxSeconds = 1.5;
return (Math.random() * (maxSeconds - minSeconds) + minSeconds) * 1000;
}
function attemptLogin(attemptsLeft) {
if (attemptsLeft <= 0) {
throw new Error(`All login attempts exhausted. Please check your credentials.`);
}
cy.log(`Attempts left: ${attemptsLeft}`);
// eslint-disable-next-line cypress/unsafe-to-chain-command
cy.get('input[name=email]', {
timeout: timeouts?.waitForEmailInput ?? defaultTimeouts.waitForEmailInput
}).clear({
force: true
}).type(userCredentials.email, {
force: true
});
// eslint-disable-next-line cypress/unsafe-to-chain-command
cy.get('input[name=password]', {
timeout: timeouts?.waitForPasswordInput ?? defaultTimeouts.waitForPasswordInput
}).clear({
force: true
}).type(userCredentials.password, {
log: false,
force: true
});
cy.get('button').contains('Sign in').click({
force: true
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
cy.wait('@loginRequest').then(interception => {
const statusCode = interception.response.statusCode;
cy.log('Login request status code:', statusCode);
if (statusCode === constants$1.HTTP_STATUS_CODES.TOO_MANY_REQUESTS) {
// We wait for something between 0.5 and 1.5 seconds before retrying
cy.wait(getRandomDelayInSeconds());
attemptLogin(attemptsLeft - 1);
} else {
cy.log('Login successful');
}
});
}
attemptLogin(legacyMaxLoginAttempts);
}
/**
* NOTE: the `realHover` command is originally being implemented in `cypress-real-events` package.
* https://github.com/dmtrKovalenko/cypress-real-events/blob/develop/src/commands/realHover.ts
*
* However, due to known issues with conflicting types between Cypress and Jest, importing the `cypress-real-events`
* package here will cause such issues with TypeScript as our `@commercetools-frontend/cypress` package
* is checked and built together with all other packages and not in isolation.
* See https://docs.cypress.io/guides/tooling/typescript-support#Clashing-types-with-Jest.
*
* Therefore, we are porting here the implementation of `realHover` to avoid importing it from the
* original package `cypress-real-events`.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async function fireCdpCommand(command, params) {
return Cypress.automation('remote:debugger:protocol', {
command,
params
}).catch(error => {
throw new Error(`Failed request to chrome devtools protocol. This can happen if cypress lost connection to the browser or the command itself is not valid. Original cypress error: ${error}`);
});
}
function getPositionedCoordinates(x0, y0, width, height, position, frameScale) {
if (typeof position === 'object' && position !== null) {
const x = position.x,
y = position.y;
// scale the position coordinates according to the viewport scale
return [x0 + x * frameScale, y0 + y * frameScale];
}
switch (position) {
case 'topLeft':
return [x0, y0];
case 'top':
return [x0 + width / 2, y0];
case 'topRight':
return [x0 + width - 1, y0];
case 'left':
return [x0, y0 + height / 2];
case 'right':
return [x0 + width - 1, y0 + height / 2];
case 'bottomLeft':
return [x0, y0 + height - 1];
case 'bottom':
return [x0 + width / 2, y0 + height - 1];
case 'bottomRight':
return [x0 + width - 1, y0 + height - 1];
// center by default
default:
return [x0 + width / 2, y0 + height / 2];
}
}
/**
* Scrolls the given htmlElement into view on the page.
* The position the element is scrolled to can be customized with scrollBehavior.
*/
function scrollIntoView(htmlElement) {
let scrollBehavior = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'center';
let block;
if (scrollBehavior === 'top') {
block = 'start';
} else if (scrollBehavior === 'bottom') {
block = 'end';
} else {
block = scrollBehavior;
}
htmlElement.scrollIntoView({
block
});
}
// for cross origin domains .frameElement returns null so query using parentWindow
// but when running using --disable-web-security it will return the frame element
function getFrameElement(currentWindow) {
var _context, _context2;
if (currentWindow.frameElement) {
// accessible for same-origin iframes
// or when running with --disable-web-security
return currentWindow.frameElement;
}
// fallback to querying using the parent window, mainly to grab the AUT iframe
const iframeElements = currentWindow.parent.document.querySelectorAll('iframe');
return _findInstanceProperty__default["default"](_context = _mapInstanceProperty__default["default"](_context2 = _Array$from__default["default"](_entriesInstanceProperty__default["default"](iframeElements).call(iframeElements))).call(_context2, _ref => {
let _ref2 = _slicedToArray(_ref, 2),
element = _ref2[1];
return element;
})).call(_context, element => element.contentWindow === currentWindow);
}
function getIframesPositionShift(element) {
let currentWindow = element.ownerDocument.defaultView;
const noPositionShift = {
frameScale: 1,
frameX: 0,
frameY: 0
};
if (!currentWindow) {
return noPositionShift;
}
// eslint-disable-next-line prefer-const
const iframes = [];
while (currentWindow !== window.top) {
const element = getFrameElement(currentWindow);
if (element) {
iframes.push(element);
}
currentWindow = currentWindow.parent;
}
return _reduceRightInstanceProperty__default["default"](iframes).call(iframes, (_ref3, frame) => {
let frameX = _ref3.frameX,
frameY = _ref3.frameY,
frameScale = _ref3.frameScale;
const _frame$getBoundingCli = frame.getBoundingClientRect(),
x = _frame$getBoundingCli.x,
y = _frame$getBoundingCli.y,
width = _frame$getBoundingCli.width;
return {
frameX: frameX + x * frameScale,
frameY: frameY + y * frameScale,
frameScale: frameScale * (width / frame.offsetWidth)
};
}, noPositionShift);
}
/**
* Returns the coordinates and size of a given Element, relative to the Cypress app <iframe>.
* Accounts for any scaling on the iframes.
*/
function getElementPositionXY(htmlElement) {
const _htmlElement$getBound = htmlElement.getBoundingClientRect(),
elementX = _htmlElement$getBound.x,
elementY = _htmlElement$getBound.y,
width = _htmlElement$getBound.width,
height = _htmlElement$getBound.height;
const _getIframesPositionSh = getIframesPositionShift(htmlElement),
frameScale = _getIframesPositionSh.frameScale,
frameX = _getIframesPositionSh.frameX,
frameY = _getIframesPositionSh.frameY;
return {
x: frameX + elementX * frameScale,
y: frameY + elementY * frameScale,
width: width * frameScale,
height: height * frameScale,
frameScale: frameScale
};
}
function getCypressElementCoordinates(
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-explicit-any
jqueryEl, position, scrollBehavior) {
const htmlElement = jqueryEl.get(0);
const cypressAppFrame = window.parent.document.querySelector('iframe');
if (!cypressAppFrame) {
throw new Error('Can not find cypress application iframe, it looks like critical issue. Please rise an issue on GitHub.');
}
const effectiveScrollBehavior = scrollBehavior ?? Cypress.config('scrollBehavior') ?? 'center';
if (effectiveScrollBehavior && typeof effectiveScrollBehavior !== 'object') {
scrollIntoView(htmlElement, effectiveScrollBehavior);
}
const _getElementPositionXY = getElementPositionXY(htmlElement),
x = _getElementPositionXY.x,
y = _getElementPositionXY.y,
width = _getElementPositionXY.width,
height = _getElementPositionXY.height,
frameScale = _getElementPositionXY.frameScale;
const _getPositionedCoordin = getPositionedCoordinates(x, y, width, height, position ?? 'center', frameScale),
_getPositionedCoordin2 = _slicedToArray(_getPositionedCoordin, 2),
posX = _getPositionedCoordin2[0],
posY = _getPositionedCoordin2[1];
return {
x: posX,
y: posY,
frameScale: frameScale
};
}
const keyToModifierBitMap = {
Alt: 1,
Control: 2,
Meta: 4,
Shift: 8
};
async function realHover(
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-explicit-any
subject) {
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
const _getCypressElementCoo = getCypressElementCoordinates(subject, options.position, options.scrollBehavior),
x = _getCypressElementCoo.x,
y = _getCypressElementCoo.y;
const log = Cypress.log({
$el: subject,
name: 'realHover',
consoleProps: () => ({
'Applied To': subject.get(0),
'Absolute Coordinates': {
x,
y
}
})
});
await fireCdpCommand('Input.dispatchMouseEvent', {
x,
y,
type: 'mouseMoved',
button: 'none',
pointerType: options.pointer ?? 'mouse',
modifiers: options.shiftKey ? keyToModifierBitMap.Shift : 0
});
log.snapshot().end();
return subject;
}
function ownKeys(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; }
function _objectSpread(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(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(Object(t))).call(_context3, function (r) { _Object$defineProperty__default["default"](e, r, _Object$getOwnPropertyDescriptor__default["default"](t, r)); }); } return e; }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Cypress.Commands.add('loginToMerchantCenter', commandOptions => {
Cypress.log({
name: 'loginToMerchantCenter'
});
loginByForm(commandOptions);
});
Cypress.Commands.add('loginToMerchantCenterForCustomView', commandOptions => {
Cypress.log({
name: 'loginToMerchantCenterForCustomView'
});
const projectKey = Cypress.env('PROJECT_KEY');
loginByForm(_objectSpread(_objectSpread({}, commandOptions), {}, {
entryPointUriPath: constants.CUSTOM_VIEW_HOST_ENTRY_POINT_URI_PATH,
initialRoute: `/${projectKey}/${constants.CUSTOM_VIEW_HOST_ENTRY_POINT_URI_PATH}`
}));
});
Cypress.Commands.add('loginByOidc', commandOptions => {
Cypress.log({
name: 'loginByOidc'
});
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.');
loginByForm(commandOptions);
});
Cypress.Commands.add('hover', {
prevSubject: true
}, realHover);
Cypress.Commands.add('showNavigationSubmenuItems', menuItemTextMatcher => {
cy.findByTestId('left-navigation').findByText(menuItemTextMatcher).parents('[role="menuitem"]').first()
// Refers to the custom command "hover"
.hover();
});
// https://github.com/cypress-io/cypress/issues/136#issuecomment-342391119
Cypress.Commands.add('getIframeBody', {
prevSubject: 'element'
},
// eslint-disable-next-line @typescript-eslint/no-explicit-any
$iframe => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return new Cypress.Promise(resolve => {
var _context;
resolve(_findInstanceProperty__default["default"](_context = $iframe.contents()).call(_context, 'body'));
});
});
;