Cypress Angular CDK DragAndDrop

JS
S
JavaScript

Drag and Drop solution to Angular CDK Drag&Drop. Based on: https://stackoverflow.com/questions/55361499/how-to-implement-drag-and-drop-in-cypress-test

1// support/index.js
2import './commands'
3
4const getCoords = ($el) => {
5  const domRect = $el[0].getBoundingClientRect()
6  const coords = { x: domRect.left + (domRect.width / 2 || 0), y: domRect.top + (domRect.height / 2 || 0) }
7
8  return coords
9}
10
11const dragTo = (subject, to, opts) => {
12
13  opts = Cypress._.defaults(opts, {
14    // delay inbetween steps
15    delay: 0,
16    // interpolation between coords
17    steps: 0,
18    // >=10 steps
19    smooth: false,
20  })
21
22  if (opts.smooth) {
23    opts.steps = Math.max(opts.steps, 10)
24  }
25
26  const win = subject[0].ownerDocument.defaultView
27
28  const elFromCoords = (coords) => win.document.elementFromPoint(coords.x, coords.y)
29  const winMouseEvent = win.MouseEvent
30
31  const send = (type, coords, el) => {
32
33    el = el || elFromCoords(coords)
34
35    el.dispatchEvent(
36      new winMouseEvent(type, Object.assign({}, { clientX: coords.x, clientY: coords.y }, { bubbles: true, cancelable: true }))
37    )
38  }
39
40  const toSel = to
41
42  function drag (from, to, steps = 1) {
43
44    const fromEl = elFromCoords(from)
45
46    const _log = Cypress.log({
47      $el: fromEl,
48      name: 'drag to',
49      message: toSel,
50    })
51
52    _log.snapshot('before', { next: 'after', at: 0 })
53
54    _log.set({ coords: to })
55
56    send('mouseover', from, fromEl)
57    send('mousedown', from, fromEl)
58
59    cy.then(() => {
60      return Cypress.Promise.try(() => {
61
62        if (steps > 0) {
63
64          const dx = (to.x - from.x) / steps
65          const dy = (to.y - from.y) / steps
66
67          return Cypress.Promise.map(Array(steps).fill(), (v, i) => {
68            i = steps - 1 - i
69
70            let _to = {
71              x: from.x + dx * (i),
72              y: from.y + dy * (i),
73            }
74
75            send('mousemove', _to, fromEl)
76
77            return Cypress.Promise.delay(opts.delay)
78
79          }, { concurrency: 1 })
80        }
81      })
82      .then(() => {
83
84        send('mousemove', to, fromEl)
85        send('mouseover', to)
86        send('mousemove', to)
87        send('mouseup', to)
88        _log.snapshot('after', { at: 1 }).end()
89
90      })
91
92    })
93
94  }
95
96  const $el = subject
97  const fromCoords = getCoords($el)
98  const toCoords = getCoords(cy.$$(to))
99
100  drag(fromCoords, toCoords, opts.steps)
101}
102
103Cypress.Commands.addAll(
104  { prevSubject: 'element' },
105  {
106    dragTo,
107  }
108)
109
110
111// cypress/integration/dd/test.ts
112import { Common } from '../common/common';
113
114/* tslint:disable */
115
116describe('Flight Test Suite', () => {
117  beforeEach( () => {
118    cy.viewport( 1200, 600 );
119  });
120
121  it('works (simply)', () => {
122    Common.doLogin();
123    const draggable: any = cy.get('.field:contains("Management Fee")');
124    draggable.dragTo('#groupBy')
125  });
126});
127

Created on 9/10/2019