gpt4 book ai didi

angular - 如何在 cypress 测试中实现拖放?

转载 作者:行者123 更新时间:2023-12-04 00:57:51 25 4
gpt4 key购买 nike

我正在努力使用 Cypress 测试拖放和 Angular Material Drag and Drop .因此,目标是将“开始工作”从待办事项转移到完成。
我创建了以下测试,应该可以让您轻松重现:
你可以玩 Stackblitz here .

describe('Trying to implement drag-n-drop', () => {

before(() => {
Cypress.config('baseUrl', null);

cy.viewport(1000, 600);
cy.visit('https://angular-oxkc7l-zirwfs.stackblitz.io')
.url().should('contain', 'angular')
.get('h2').should('contain', 'To do');
});

it('Should work, based on this https://stackoverflow.com/a/54119137/3694288', () => {

const dataTransfer = new DataTransfer;

cy.get('#cdk-drop-list-0 > :nth-child(1)')
.trigger('dragstart', { dataTransfer });

cy.get('#cdk-drop-list-1')
.trigger('drop', { dataTransfer });

cy.get('#cdk-drop-list-0 > :nth-child(1)')
.trigger('dragend');

cy.get('#cdk-drop-list-1').should('contain', 'Get to work');
});


it('Should work, with this library https://github.com/4teamwork/cypress-drag-drop', () => {
cy.get('#cdk-drop-list-0 > :nth-child(1)')
.drag('#cdk-drop-list-1');

cy.get('#cdk-drop-list-1').should('contain', 'Get to work');
});

});
运行上述测试的结果如下所示:
enter image description here
这里是 a repo制定解决方案。
谢谢您的帮助。
事件触发,使用 chrome 调试器找到:
元素
  • 指针悬停
  • 指针进入
  • 鼠标悬停
  • 鼠标按下
  • 指针移动
  • 鼠标移动
  • 指针指针
  • 指针离开
  • 鼠标悬停
  • mouseleave

  • 拖放区
  • 指针悬停
  • 指针进入
  • 鼠标悬停
  • 指针移动
  • 鼠标移动
  • 指针离开
  • 鼠标悬停
  • mouseleave

  • 解决方案
    在@Richard Matsen 的精彩回答之后,我最终添加了 his answer作为自定义命令。解决方案看起来像这样
    支持/拖动-support.ts
        export function drag(dragSelector: string, dropSelector: string) {
    // Based on this answer: https://stackoverflow.com/a/55436989/3694288
    cy.get(dragSelector).should('exist')
    .get(dropSelector).should('exist');

    const draggable = Cypress.$(dragSelector)[0]; // Pick up this
    const droppable = Cypress.$(dropSelector)[0]; // Drop over this

    const coords = droppable.getBoundingClientRect();
    draggable.dispatchEvent(<any>new MouseEvent('mousedown'));
    draggable.dispatchEvent(<any>new MouseEvent('mousemove', {clientX: 10, clientY: 0}));
    draggable.dispatchEvent(<any>new MouseEvent('mousemove', {
    // I had to add (as any here --> maybe this can help solve the issue??)
    clientX: coords.left + 10,
    clientY: coords.top + 10 // A few extra pixels to get the ordering right
    }));
    draggable.dispatchEvent(new MouseEvent('mouseup'));
    return cy.get(dropSelector);
    }
    支持/commands.ts
        // Add typings for the custom command
    declare global {
    namespace Cypress {
    interface Chainable {
    drag: (dragSelector: string, dropSelector: string) => Chainable;
    }
    }
    }
    // Finally add the custom command
    Cypress.Commands.add('drag', drag);
    在规范文件中
        it('🔥 Thx to Stackoverflow, drag and drop support now works 🔥', () => {
    cy.drag('#cdk-drop-list-0 > :nth-child(1)', '#cdk-drop-list-1')
    .should('contain', 'Get to work');
    });
    一个小 giph,因为我很高兴它终于可以工作了😲
    enter image description here
    CI
    现在它也适用于 CI 🔥(和本地电子)。使用 CircleCI 2.0 测试。

    最佳答案

    调度 MouseEvents 似乎是测试 Angular Material 拖放的唯一方法。

    您还应该注意以下问题,该问题在 Protractor 中进行测试,但也适用于此 Cypress 测试

    CDK DragDrop Regression between 7.0.0-beta.2 and 7.0.0-rc.2: Protractor tests stopped working #13642 ,

    似乎(为了更好的解释)鼠标移动需要额外的轻推。

    workaround 形式给出的步骤( Protractor 语法),

    private async dragAndDrop ( $element, $destination ) {
    await browser.actions().mouseMove( $element ).perform();
    await browser.actions().mouseDown( $element ).perform();
    await browser.actions().mouseMove( {x: 10, y: 0 } ).perform();
    await browser.actions().mouseMove( $destination ).perform();
    return browser.actions().mouseUp().perform();
    }

    可以翻译成 Cypress 测试,我找到的最简单的形式是

    it('works (simply)', () => {
    const draggable = Cypress.$('#cdk-drop-list-0 > :nth-child(1)')[0] // Pick up this
    const droppable = Cypress.$('#cdk-drop-list-1 > :nth-child(4)')[0] // Drop over this

    const coords = droppable.getBoundingClientRect()
    draggable.dispatchEvent(new MouseEvent('mousedown'));
    draggable.dispatchEvent(new MouseEvent('mousemove', {clientX: 10, clientY: 0}));
    draggable.dispatchEvent(new MouseEvent('mousemove', {
    clientX: coords.x+10,
    clientY: coords.y+10 // A few extra pixels to get the ordering right
    }));
    draggable.dispatchEvent(new MouseEvent('mouseup'));

    cy.get('#cdk-drop-list-1').should('contain', 'Get to work');
    cy.get('#cdk-drop-list-1 > .cdk-drag').eq(3).should('contain', 'Get to work');

    });

    备注
  • 引用问题中的问题不仅限于 Protractor 。如果删除第一个 mousemove在 Cypress 测试中,它也失败了。
  • cy.get(..).trigger()语法似乎不适用于 Angular,但原生 dispatchEvent()做。
  • 拖动目标列表中的特定元素(而不是仅仅拖放到列表上)在目标列表中提供精确定位。
  • dragstart, dragend可能不适合 Angular Material,因为代码显示接收到的事件类型为 CdkDragDrop而不是 DataTransfer 对象。
  • 如果内容是异步获取的,您可能必须从 Cypress.$(...) 切换至cy.get(...).then(el => {...}) , 以利用 cypress 在命令中的自动重试。
  • 我必须添加 10 秒超时才能访问 Stackblitz 网址。


  • 异步列表获取

    如果在组件构建期间由异步 Angular 服务 (httpClient) 获取列表,则在测试中使用它
    const draggable = Cypress.$('#cdk-drop-list-0 > :nth-child(1)')[0]

    不会工作,因为第 n 个 child 不会立即出现,只有在 fetch 完成后才会出现。

    相反,您可以使用 cy.get()提供超时重试(默认为 5 秒)。

    cy.get('#cdk-drop-list-0 > :nth-child(1)').then(el => {
    const draggable = el[0] // Pick up this
    cy.get('#cdk-drop-list-1 > :nth-child(4)').then(el => {
    const droppable = el[0] // Drop over this

    const coords = droppable.getBoundingClientRect()
    draggable.dispatchEvent(new MouseEvent('mousemove'));
    draggable.dispatchEvent(new MouseEvent('mousedown'));
    draggable.dispatchEvent(new MouseEvent('mousemove', {clientX: 10, clientY: 0}));
    draggable.dispatchEvent(new MouseEvent('mousemove', {clientX: coords.x+10, clientY: coords.y+10}));
    draggable.dispatchEvent(new MouseEvent('mouseup'));

    })

    cy.get('#cdk-drop-list-1').should('contain', 'Get to work');
    cy.get('#cdk-drop-list-1 > .cdk-drag').eq(3).should('contain', 'Get to work');
    })

    或者我的偏好是使用“金丝雀”测试来确保加载完成,例如

    before(() => {
    cy.get('#cdk-drop-list-0 > :nth-child(1)') // Canary - wait 5s for data
    })

    it('should...', () => {
    const draggable = Cypress.$('#cdk-drop-list-0 > :nth-child(1)')[0] // Pick up this
    const droppable = Cypress.$('#cdk-drop-list-1 > :nth-child(4)')[0] // Drop over this
    ...
    })

    typescript 支持

    警告 - 这是一个快速解决 Typescript 编译器问题的方法,可以改进。
  • Actor MouseEvent<any>根据 MouseEvent in TypeScript error not matching signature
  • 类型返回 getBoundingClientRect()ClientRect , 并使用属性 left 和 top 而不是 x 和 y。

  • const coords: ClientRect = droppable.getBoundingClientRect()
    draggable.dispatchEvent(new (<any>MouseEvent)('mousemove'));
    draggable.dispatchEvent(new (<any>MouseEvent)('mousedown'));
    draggable.dispatchEvent(new (<any>MouseEvent)('mousemove', {clientX: 10.0, clientY: 0.0}));
    draggable.dispatchEvent(new (<any>MouseEvent)('mousemove', {clientX: coords.left + 10.0, clientY: coords.top + 10.0}));
    draggable.dispatchEvent(new (<any>MouseEvent)('mouseup'));

    关于angular - 如何在 cypress 测试中实现拖放?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55361499/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com