简体   繁体   English

赛普拉斯按偏移量拖放

[英]Cypress drag and drop by offset

I am trying to make DnD work in Cypress and React app.我正在尝试让 DnD 在 Cypress 和 React 应用程序中工作。

At first I was trying all examples around those with simulating by mouse events but it is not working in general in my environment.起初,我尝试了所有通过鼠标事件进行模拟的示例,但它在我的环境中通常不起作用。 :( :(

I was able to write a test where I know the drag element and drop element using this code.我能够使用此代码编写一个测试,其中我知道拖动元素和放置元素。

const dataTransfer = new DataTransfer();


   cy.get(dragSelector).trigger("dragstart", {
       dataTransfer,
       force: true,
   });


   cy.get(dropSelector).trigger("drop", {
       dataTransfer,
       force: true,
   });

And it's working well.而且效果很好。 Similar sample code I have found in Cypress cookbook.我在赛普拉斯食谱中找到了类似的示例代码。

But now I need to do DnD where I don't know the drop zone / elem.但是现在我需要在不知道拖放区/元素的地方进行 DnD。 Its resizer and I need dnd by offset for example 20px on Y axis.它的调整器和我需要 dnd by offset 例如 Y 轴上的 20px。 (Resize element height by 20px) (将元素高度调整 20px)

So is it possible to do it somehow like this?那么有可能像这样以某种方式做到这一点吗?

const dataTransfer = new DataTransfer();

   // drag selector is element with draggable attribute and I need move it by 20px from top to down  
   cy.get(dragSelector).trigger("dragstart", {
       dataTransfer,
       force: true,
   }).trigger("drop",{...how to set drop offset if is possible...})

trigger drop event as some parameters like offsetX and offsetY or x or y and pageX or pageY... but I was not successful.触发 drop 事件作为一些参数,如 offsetX 和 offsetY 或 x 或 y 和 pageX 或 pageY ...但我没有成功。

Like I sad I am not able use it by simulating mouse events in my app from unknow reason its not working.就像我很难过一样,我无法通过在我的应用程序中模拟鼠标事件来使用它,原因是它不起作用。

This is how I'm testing a divider (resizer) using mouse events.这就是我使用鼠标事件测试分隔线(调整大小)的方式。

I did add cypress-real-events for mousedown and mouseup, but it may be ok to use .trigger('mousedown') instead.我确实为 mousedown 和 mouseup 添加了cypress-real-events ,但使用.trigger('mousedown')可能没问题。

My app is React hooks, and I found it needed a small wait before checking.我的应用程序是 React hooks,我发现它需要稍等片刻才能检查。 I think that can be optimized with a .should() , but for my tests now this is working.我认为可以使用.should()对其进行优化,但对于我的测试来说,现在这是可行的。

Cypress.Commands.add('checkPosition', 
  {prevSubject: true}, 
  (subject, start, delta = {dx:0}) => {

    cy.wait(75, {log:false}).then(function () {
      
      const deltaValue = delta.dx || delta.dy
      const measurePoint = measurePoint || (delta.dx ? 'pageX' : 'pageY')
      const current = getClientRect(subject[0])[measurePoint]
      const expected = start[measurePoint] + deltaValue 
      expect(current).to.be.closeTo(expected, variance)
    })
  }
)

let start;
cy.get(divider)
  .then(subject => start = getClientRect(subject[0]))
  .realMouseDown({position:'center'})
  .then($el => {
    cy.wrap($el, {log:false})
      .trigger('mousemove', { pageX: start.pageX +20 })
      .checkPosition(start, {dx:20})
      .trigger('mousemove', { pageX: start.pageX +40 })
      .checkPosition(start, {dx:40})
      // more steps as required
      .realMouseUp()
      .checkPosition(start, {dx:100})
  })

You can do x or y movements in the test, my divider is either horizontal or vertical (can it be anything else?)你可以在测试中做 x 或 y 运动,我的分隔线是水平的或垂直的(可以是其他任何东西吗?)

The calculation on position isn't exact, so I've added close.to assertion in /cypress/support/e2e.js . position 的计算并不准确,因此我在/cypress/support/e2e.js中添加了close.to断言。

const closeTo = (_chai, utils) => {
  function assertIscloseTo(expected, delta, msg) {
    msg = msg || utils.flag(this, 'message')
    msg = msg ? `${msg}: ` : ''
    _chai.assert(
      Math.abs(this._obj - expected) <= delta
        , msg + 'expected ' + this._obj + ' to be close to ' + expected + ' +/- ' + delta
        , msg + 'expected ' + this._obj + ' not to be close to ' + expected + ' +/- ' + delta
    )
  }
  _chai.Assertion.addMethod('closeTo', assertIscloseTo)
}
chai.use(closeTo)

getClientRect() getClientRect()

This is just to provide some rounding on the native getBoundingClientRect() function.这只是为了对本机getBoundingClientRect() function 进行一些舍入。

I also added centerX and centerY calc as it is sometimes useful to vary the mousedown location, if the React app records it's start position from the mousedown event.我还添加了centerXcenterY calc,因为有时改变 mousedown 位置很有用,如果 React 应用程序记录它是从 mousedown 事件开始的 position。

function getClientRect(el) {
  const bb = el.getBoundingClientRect()
  return {
    top: Math.round(bb.top),
    bottom: Math.round(bb.bottom),
    left: Math.round(bb.left),
    right: Math.round(bb.right),
    height: Math.round(bb.height),
    width: Math.round(bb.width),
    x: Math.round(bb.x),
    y: Math.round(bb.y),
    centerX: Math.round(bb.left + (bb.width/2)),
    centerY: Math.round(bb.top + (bb.height/2)),
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM