How to implement drag and drop in Cypress test when using Angular Material Drag and Drop?

Discussão em 'Angular' iniciado por DauleDK, Outubro 14, 2024.

  1. DauleDK

    DauleDK Guest

    I am struggling to test drag and drop with Cypress and Angular Material Drag and Drop. So the goal is to move "Get to work" from Todo to Done. I have created the following test, that should make it easy for you to reproduce:

    You can play with the 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');
    });

    });


    The result from running the above test, looks like this:

    [​IMG]

    Here is a repo to develop a solution.

    Thanks for the help.

    Events fired, found using the chrome debugger:

    Item

    • pointerover
    • pointerenter
    • mouseover
    • mousedown
    • pointermove
    • mousemove
    • pointerout
    • pointerleave
    • mouseout
    • mouseleave

    Drop zone

    • pointerover
    • pointerenter
    • mouseover
    • pointermove
    • mousemove
    • pointerleave
    • mouseout
    • mouseleave

    Solution

    After @Richard Matsen's awesome answer I ended up with adding his answer as a custom command. The solution looks like this

    support/drag-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);
    }


    support/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);


    in the spec file

    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');
    });


    A small giph, because I'm just so happy it finally works

    [​IMG]

    CI

    Now it also works in CI (and electron locally). Tested with CircleCI 2.0.

    Continue reading...

Compartilhe esta Página