Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drag and Drop Not Functioning Properly #6161

Closed
davidschwarb opened this issue Jan 14, 2020 · 17 comments
Closed

Drag and Drop Not Functioning Properly #6161

davidschwarb opened this issue Jan 14, 2020 · 17 comments
Labels
stage: needs investigating Someone from Cypress needs to look at this stale no activity on this issue for a long period

Comments

@davidschwarb
Copy link

davidschwarb commented Jan 14, 2020

Issue:

Attempting to use cypress to test a drag and drop event. HTML element is selected, however mousemove does not move the selected element.

Important to note:
Element uses interactjs for drag events.

image

Desired behavior:

The pointerdown, pointermove, and pointerup commands should drag the element to a new position.

cy.get('.grid .col.column.cell.droppable')
            .first()
            .then(element => {
                cy.get('esynch-patient-card.draggable').first()
                    .trigger('pointerdown', { which: 1})
                    .trigger('pointermove', {clientX: element.position().left, clientY: element.position().top})
                    .trigger('pointerup', { force: true});
            });

Versions

Cypress 0.4.1
MacOS
Chrome Browser

@jennifer-shehane
Copy link
Member

@davidschwarb We will need the HTML to run the test code provided against in order to recreate this issue.

Unfortunately we have to close this issue if a fully reproducible example is not provided. Please comment with test code we can run on our machine to see the issue.

@jennifer-shehane jennifer-shehane added the stage: needs information Not enough info to reproduce the issue label Jan 15, 2020
@joaobarcia
Copy link

joaobarcia commented Jan 16, 2020

We are having the same issue. I believe it might be related to #311

I've tried following your comment at #669 (comment) and some other implementations (like https://gist.github.com/superMDguy/f10d29b17ef0a473fb2700f3c72661cd) but none seemed to work.

Test code wise, I believe if you run a cypress test on the drag examples at https://interactjs.io/ it will give you the same result. I can't test at the moment now, but would assume so.

@joaobarcia
Copy link

joaobarcia commented Jan 17, 2020

I just refactored one of the examples into a single HTML file in case it is more straightforward for you guys to test.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Highlight dropzones with interact.js</title>
    <script src="https://cdn.jsdelivr.net/npm/interactjs/dist/interact.min.js"></script>
    <script>
      let transformProp;
      const dragPositions = [1, 2, 3, 4].reduce((acc, n) => {
        acc[`drag${n}`] = { x: 0, y: 0 };
        return acc;
      }, {});

      interact.maxInteractions(Infinity);

      // setup draggable elements.
      interact(".js-drag").draggable({
        listeners: {
          start(event) {
            const position = dragPositions[event.target.id];
            position.x = parseInt(event.target.getAttribute("data-x"), 10) || 0;
            position.y = parseInt(event.target.getAttribute("data-y"), 10) || 0;
          },
          move(event) {
            const position = dragPositions[event.target.id];
            position.x += event.dx;
            position.y += event.dy;

            if (transformProp) {
              event.target.style[transformProp] =
                "translate(" + position.x + "px, " + position.y + "px)";
            } else {
              event.target.style.left = position.x + "px";
              event.target.style.top = position.y + "px";
            }
          },
          end(event) {
            const position = dragPositions[event.target.id];
            event.target.setAttribute("data-x", position.x);
            event.target.setAttribute("data-y", position.y);
          }
        }
      });

      // setup drop areas.
      // dropzone #1 accepts draggable #1
      setupDropzone("#drop1", "#drag1");
      // dropzone #2 accepts draggable #1 and #2
      setupDropzone("#drop2", "#drag1, #drag2");
      // every dropzone accepts draggable #3
      setupDropzone(".js-drop", "#drag3");

      /**
       * Setup a given element as a dropzone.
       *
       * @param {HTMLElement|String} target
       * @param {String} accept
       */
      function setupDropzone(target, accept) {
        interact(target)
          .dropzone({
            accept: accept,
            ondropactivate: function(event) {
              addClass(event.relatedTarget, "-drop-possible");
            },
            ondropdeactivate: function(event) {
              removeClass(event.relatedTarget, "-drop-possible");
            }
          })
          .on("dropactivate", function(event) {
            const active = event.target.getAttribute("active") | 0;

            // change style if it was previously not active
            if (active === 0) {
              addClass(event.target, "-drop-possible");
              event.target.textContent = "Drop me here!";
            }

            event.target.setAttribute("active", active + 1);
          })
          .on("dropdeactivate", function(event) {
            const active = event.target.getAttribute("active") | 0;

            // change style if it was previously active
            // but will no longer be active
            if (active === 1) {
              removeClass(event.target, "-drop-possible");
              event.target.textContent = "Dropzone";
            }

            event.target.setAttribute("active", active - 1);
          })
          .on("dragenter", function(event) {
            addClass(event.target, "-drop-over");
            event.relatedTarget.textContent = "I'm in";
          })
          .on("dragleave", function(event) {
            removeClass(event.target, "-drop-over");
            event.relatedTarget.textContent = "Drag me…";
          })
          .on("drop", function(event) {
            removeClass(event.target, "-drop-over");
            event.relatedTarget.textContent = "Dropped";
          });
      }

      function addClass(element, className) {
        if (element.classList) {
          return element.classList.add(className);
        } else {
          element.className += " " + className;
        }
      }

      function removeClass(element, className) {
        if (element.classList) {
          return element.classList.remove(className);
        } else {
          element.className = element.className.replace(
            new RegExp(className + " *", "g"),
            ""
          );
        }
      }

      interact(document).on("ready", function() {
        transformProp =
          "transform" in document.body.style
            ? "transform"
            : "webkitTransform" in document.body.style
            ? "webkitTransform"
            : "mozTransform" in document.body.style
            ? "mozTransform"
            : "oTransform" in document.body.style
            ? "oTransform"
            : "msTransform" in document.body.style
            ? "msTransform"
            : null;
      });
    </script>
    <style>
      body {
        font-family: Helvetica, Arial, sans-serif;
      }

      .dropzone-wrapper {
        position: absolute;
        bottom: 0;
        left: 0;
        right: 0;
      }

      .dropzone {
        overflow: hidden;
        margin: 0.5em;
        padding: 1em;
        color: #666;
        text-align: center;
        background: #ccc;
        line-height: 4em;
        border: 4px dashed transparent;
        transition: background 0.15s linear, border-color 0.15s linear;
      }

      .dropzone.-drop-possible {
        border-color: #666;
      }

      .dropzone.-drop-over {
        background: #666;
        color: #fff;
      }

      .draggable {
        position: relative;
        z-index: 10;
        width: 200px;
        margin: 0.25em;
        padding: 1em 2em;
        background-color: #29e;
        color: #fff;
        text-align: center;

        -ms-touch-action: none;
        touch-action: none;
      }

      .draggable.-drop-possible {
        background-color: #42bd41;
      }
    </style>
  </head>
  <body>
    <div id="drag1" class="draggable js-drag">Drag me…</div>
    <div id="drag2" class="draggable js-drag">Drag me…</div>
    <div id="drag3" class="draggable js-drag">Drag me…</div>
    <div id="drag4" class="draggable js-drag">Drag me…</div>

    <div class="dropzone-wrapper">
      <div id="drop1" class="dropzone js-drop">Dropzone</div>
      <div id="drop2" class="dropzone js-drop">Dropzone</div>
      <div id="drop3" class="dropzone js-drop">Dropzone</div>
    </div>
  </body>
</html>

@joaobarcia
Copy link

@jennifer-shehane , is there any more data we could still provide related to this issue? I see you still have the label 'stage: needs information'. Thanks!

@osky9913

This comment has been minimized.

@brunobg
Copy link

brunobg commented May 26, 2020

Having the same issue here.

@davidschwarb
Copy link
Author

@jennifer-shehane is there any further information we can provide? @joaobarcia seems to have provided some reproduction steps. Thanks!

@alwill
Copy link

alwill commented May 29, 2020

Seeing the same issue here.

@jennifer-shehane
Copy link
Member

Yeah, I'm not sure exactly what events interact js is listening for here, so someone would need to play with that libary to ensure you're sending the exact events it expects on the elements.

@cypress-bot cypress-bot bot added stage: needs investigating Someone from Cypress needs to look at this and removed stage: needs information Not enough info to reproduce the issue labels Jul 15, 2020
@tktaofik
Copy link

I am having the same issue with interact js I can't seem to use cypress to test interact js.
I tried several examples online including drag and drop recommended by cypress testing-dom__drag-drop

@joaobarcia
Copy link

@jennifer-shehane

so someone would need to play with that libary to ensure you're sending the exact events it expects on the elements.

Could you give us some more info on what Cypress expects? Or where to learn about it? I'd be willing to try to discuss the issue with the people from https://github.com/taye/interact.js but would be good to know what to look for.

@TimVee
Copy link

TimVee commented Nov 18, 2020

I have the same problem. I've created a reproducible example to open taye/interact.js#871.

Now I'm looking at this I've noticed in the drag n drop example that Cypress by default creates an event of type Event, and not a more specific type like MouseEvent for example. Meaning that a library checking for type by using e instanceof MouseEvent it would not recognize the event as a mouse event. I don't know if that's the case with interact.js, but it is a difference between cy.trigger and what the browser fires.

@TimVee
Copy link

TimVee commented Nov 19, 2020

After some more testing it seems that interact.js does indeed work when specifying event type.

@superveetz
Copy link

anyone experiencing this problem, i took a different route which seems to work. When registering the draggables and droppables on the front end, if you pass the interact instance to the Cypress runtime (either by attaching it to the window or by some other way), then you can begin using the API provided by interactjs to perform testing,

interact(draggableElem as Interact.Target).fire({
      type: 'dragmove',
      target: draggableElem,
      dx: droppableCoords.x - draggableCoords.x + 20,
      dy: droppableCoords.y - draggableCoords.y + 20,
})

@sunpietro
Copy link

I've managed to fix that by wrapping an output of cy.get() with cy.wrap(). Then the trigger() command works as expected.

@cypress-app-bot
Copy link
Collaborator

This issue has not had any activity in 180 days. Cypress evolves quickly and the reported behavior should be tested on the latest version of Cypress to verify the behavior is still occurring. It will be closed in 14 days if no updates are provided.

@cypress-app-bot cypress-app-bot added the stale no activity on this issue for a long period label May 17, 2023
@cypress-app-bot
Copy link
Collaborator

This issue has been closed due to inactivity.

@cypress-app-bot cypress-app-bot closed this as not planned Won't fix, can't repro, duplicate, stale Jun 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stage: needs investigating Someone from Cypress needs to look at this stale no activity on this issue for a long period
Projects
None yet
Development

No branches or pull requests