如何使用 CodeceptJs 实现拖放(拖动重新排序)
How to implement drag and drop (drag to reorder) with CodeceptJs
我有这个请求在两张卡片之间实现拖放,以便它们交换位置,更具体地说是“拖动以重新排序”。考虑到当我将新物品放入其中时容器不会为空,不确定如何解决这种情况?我看到了 Selenium 和 Protractor 的示例,但找不到 CodeceptJs 的示例。
我在这里试过了
await I.dragAndDrop('//*[@id="myAssessments"]/main/div/div[7]/div[2]/div[1]/li', '//*[@id="myAssessments"]/main/div/div[7]/div[2]',);
我认为相当于
I.dragAndDrop('#dragHandle', '#container');
从 https://codecept.io/helpers/WebDriver/#draganddrop 使用容器的 xpath 和第一个列表项的 xpath 但是元素没有拖动,我得到了错误 Element "{null: undefined}" was not found by text|CSS|XPath
我们现在开始工作了。我们需要使用 自定义函数。
似乎是因为我们的元素有圆角,0,0位置没有到达,所以我们需要尝试得到中间元素。
因此,这就是我们需要做的。
await I.dragDown(
{
css:
'#myAssessments > main > div > * > div:nth-child(2) > div:nth-child(1)',
},
200,
);
async dragDown(locator, pixels) {
await this.dragInDirection('down', locator, pixels);
}
async dragInDirection(direction, locator, pixels) {
const queryString = resolveLocator(locator);
const location = await this.getElementLocation(queryString);
const x = parseInt(location.x + location.width / 2, 10);
const y = parseInt(location.y + location.height / 2, 10);
await this.performBrowserActions([
createActionSet({ x, y }, direction, pixels),
]);
}
function resolveLocator(locator) {
let queryString;
if (locator.dataTestId) {
queryString = `[data-testid=${locator.dataTestId}]`;
} else if (locator.test) {
queryString = `[data-test-id=${locator.test}]`;
} else if (locator.css) {
queryString = locator.css;
} else {
queryString = locator;
}
return queryString;
}
function createActionSet(origin, direction, length) {
const { x, y } = origin;
let xMoveTo = 0;
let yMoveTo = 0;
switch (direction) {
case 'up':
yMoveTo = -length;
break;
case 'down':
yMoveTo = length;
break;
case 'right':
xMoveTo = length;
break;
case 'left':
xMoveTo = -length;
break;
default:
return new Error('Direction passed was wrong or no direction passed');
}
return {
type: 'pointer',
id: 'finger1',
parameters: { pointerType: 'touch' },
actions: [
{ type: 'pointerMove', duration: 0, x, y },
{ type: 'pointerDown', button: 0 },
{ type: 'pause', duration: 500 },
{
type: 'pointerMove',
duration: 1000,
origin: 'pointer',
x: xMoveTo,
y: yMoveTo,
},
{ type: 'pointerUp', button: 0 },
],
};
}
如果不使用自定义定位器,您或许可以简化并这样做:
async dragInDirection(direction, locator, pixels) {
const location = await this.getElementLocation(locator);
const x = parseInt(location.x + location.width / 2, 10);
const y = parseInt(location.y + location.height / 2, 10);
await this.performBrowserActions([
createActionSet({ x, y }, direction, pixels),
]);
}
这里是带键盘选项卡的版本:
await I.pressKey('Tab');
await I.pressKey('Tab'); // Tabbing to focus the card
await I.pressKey('Space'); // "Jump" item
await I.pressKey('ArrowDown'); // Move item
await I.pressKey('Space'); // Drop item
我有这个请求在两张卡片之间实现拖放,以便它们交换位置,更具体地说是“拖动以重新排序”。考虑到当我将新物品放入其中时容器不会为空,不确定如何解决这种情况?我看到了 Selenium 和 Protractor 的示例,但找不到 CodeceptJs 的示例。
我在这里试过了
await I.dragAndDrop('//*[@id="myAssessments"]/main/div/div[7]/div[2]/div[1]/li', '//*[@id="myAssessments"]/main/div/div[7]/div[2]',);
我认为相当于
I.dragAndDrop('#dragHandle', '#container');
从 https://codecept.io/helpers/WebDriver/#draganddrop 使用容器的 xpath 和第一个列表项的 xpath 但是元素没有拖动,我得到了错误 Element "{null: undefined}" was not found by text|CSS|XPath
我们现在开始工作了。我们需要使用 自定义函数。
似乎是因为我们的元素有圆角,0,0位置没有到达,所以我们需要尝试得到中间元素。
因此,这就是我们需要做的。
await I.dragDown(
{
css:
'#myAssessments > main > div > * > div:nth-child(2) > div:nth-child(1)',
},
200,
);
async dragDown(locator, pixels) {
await this.dragInDirection('down', locator, pixels);
}
async dragInDirection(direction, locator, pixels) {
const queryString = resolveLocator(locator);
const location = await this.getElementLocation(queryString);
const x = parseInt(location.x + location.width / 2, 10);
const y = parseInt(location.y + location.height / 2, 10);
await this.performBrowserActions([
createActionSet({ x, y }, direction, pixels),
]);
}
function resolveLocator(locator) {
let queryString;
if (locator.dataTestId) {
queryString = `[data-testid=${locator.dataTestId}]`;
} else if (locator.test) {
queryString = `[data-test-id=${locator.test}]`;
} else if (locator.css) {
queryString = locator.css;
} else {
queryString = locator;
}
return queryString;
}
function createActionSet(origin, direction, length) {
const { x, y } = origin;
let xMoveTo = 0;
let yMoveTo = 0;
switch (direction) {
case 'up':
yMoveTo = -length;
break;
case 'down':
yMoveTo = length;
break;
case 'right':
xMoveTo = length;
break;
case 'left':
xMoveTo = -length;
break;
default:
return new Error('Direction passed was wrong or no direction passed');
}
return {
type: 'pointer',
id: 'finger1',
parameters: { pointerType: 'touch' },
actions: [
{ type: 'pointerMove', duration: 0, x, y },
{ type: 'pointerDown', button: 0 },
{ type: 'pause', duration: 500 },
{
type: 'pointerMove',
duration: 1000,
origin: 'pointer',
x: xMoveTo,
y: yMoveTo,
},
{ type: 'pointerUp', button: 0 },
],
};
}
如果不使用自定义定位器,您或许可以简化并这样做:
async dragInDirection(direction, locator, pixels) {
const location = await this.getElementLocation(locator);
const x = parseInt(location.x + location.width / 2, 10);
const y = parseInt(location.y + location.height / 2, 10);
await this.performBrowserActions([
createActionSet({ x, y }, direction, pixels),
]);
}
这里是带键盘选项卡的版本:
await I.pressKey('Tab');
await I.pressKey('Tab'); // Tabbing to focus the card
await I.pressKey('Space'); // "Jump" item
await I.pressKey('ArrowDown'); // Move item
await I.pressKey('Space'); // Drop item