Vue.js + Vue.Draggable + Cypress에서 Drag & Drop하는 테스트 작성

전치



Vue.js + Vue.Draggable에서 드래그 앤 드롭 기능을 구현하는 웹 페이지에 Cypress에서 테스트 코드를 작성했는데 드래그 앤 드롭이 좀처럼 작동하지 않고 빠졌기 때문에 해결 방법을 기록해 둡니다. 합니다.

환경


  • OS: Mac OS X 10.14.5 Mojave
  • Node.js: v12.6.0
  • npm: 6.10.0
  • yarn: 1.16.0
  • Vue CLI: v3.9.3
  • Vue: 2.6.10
  • Vue.Draggable: 2.23.0
  • Cypress: 3.4.0
  • Chrome: 75
  • Electron: 61
  • cypress-drag-drop: 1.1.1

  • 드래그 앤 드롭이 작동하는 테스트 코드



    test.js
    describe('Drag and Drop test', () => {
      it('Swap ITEM-1 and ITEM-2', () => {
        cy.visit('/')
    
        cy.get('.items').first().as('sourceItem')
        cy.get('.items').last().as('targetItem')
        cy.get('@sourceItem')
          .trigger('pointerdown', { which: 1, button: 0 })
          .trigger('dragstart')
        cy.get('@targetItem')
          .trigger('dragover')
          .trigger('drop')
    
        cy.get('.items').first().should('contain', 'ITEM-2')
        cy.get('.items').last().should('contain', 'ITEM-1')
      })
    })
    

    테스트 대상 vue 코드

    ※draggable 태그의 부분은, class 속성을 추가한 이외는 공식의 샘플 코드 를 그대로 유용하고 있습니다.

    App.vue
    <template>
      <div id="app">
        <draggable v-model="myArray" group="people" @start="drag=true" @end="drag=false">
           <div v-for="element in myArray" :key="element.id" class="items">{{element.name}}</div>
        </draggable>
      </div>
    </template>
    
    <script>
    import draggable from 'vuedraggable'
    
    export default {
      name: 'app',
      components: {
        draggable
      },
      data () {
        return {
          myArray: [
            { id: '1', name: 'ITEM-1' },
            { id: '2', name: 'ITEM-2' }
          ]
        }
      }
    }
    </script>
    
    <style>
    #app {
      font-family: 'Avenir', Helvetica, Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      text-align: center;
      color: #2c3e50;
      margin-top: 60px;
    }
    </style>
    



    테스트 실행 결과




    ※확인의 용이함 때문에 TRIGGER 전후의 애니메이션의 재생 속도가 느려지도록 편집하고 있습니다. 사실 Cypress 실행은 더 빠릅니다.

    드래그&드롭에 의해 ITEM-1과 ITEM-2의 상하가 바뀌어, ASSERT에 성공합니다.
    Chrome 75, Electron 61 모두 위의 테스트 코드에서 드래그 앤 드롭을 수행할 수 있었습니다.

    드래그 앤 드롭이 작동하지 않는 테스트 코드



    처음 작성한 테스트 코드입니다.
    Cypress 공식 사이트의 플러그인에서 소개된 cypress-drag-dropdrag()를 사용했지만 드래그 앤 드롭이 작동하지 않았습니다.

    test.js
    describe('Drag and Drop test', () => {
      it('Swap ITEM-1 and ITEM-2', () => {
        cy.visit('/')
    
        cy.get('.items').first().as('sourceItem')
        cy.get('.items').last().as('targetItem')
        cy.get('@sourceItem').drag('@targetItem', 'center')
    
        cy.get('.items').first().should('contain', 'ITEM-2')
        cy.get('.items').last().should('contain', 'ITEM-1')
      })
    })
    

    commands.js
    import 'cypress-drag-drop'
    

    테스트 실행 결과




    ※동작 성공 예와 마찬가지로 확인의 용이성을 위해 TRIGGER 전후의 애니메이션 재생 속도가 느려지도록 편집하고 있습니다.

    mousedown, dragstart 이벤트 후, dragover 이벤트가 반복되어 드래그 앤 드롭 처리가 완료되지 않습니다.

    요인



    디버그 해 보았을 때, Vue.Draggable의 대상이 되고 있는 HTML 요소에 대해서 pointerdown 이벤트가 발생하면 해당 요소에 draggable="true" 의 속성이 부여되어 그 후가 아니면 드래그&드롭을 실행할 수 없는 것 같습니다 .
    최초로 이용하려고 하고 있던 cypress-drag-drop 의 플러그인에서는 pointerdown 이벤트가 발생하지 않고, 그것이 예상대로 동작하지 않았던 원인이라고 생각됩니다.
    사전에 해당 HTML 요소에 대해 draggable="true"를 작성해도 작동하지 않았습니다.

    2019/3/1에 등록된 cypress-drag-drop 의 issue 에서는 vuedraggable 에 대해서도 동작하고 있다고의 코멘트가 있었습니다. 버렸을지도 모릅니다.

    또한 다음과 같이 pointerdown 이벤트와 결합하면 cypress-drag-drop 플러그인의 drag()도 예상대로 작동합니다.

    test.js
    describe('Drag and Drop test', () => {
      it('Swap ITEM-1 and ITEM-2', () => {
        cy.visit('/')
    
        cy.get('.items').first().as('sourceItem')
        cy.get('.items').last().as('targetItem')
        cy.get('@sourceItem')
          .trigger('pointerdown', { which: 1, button: 0 })
          .drag('@targetItem', 'center')
    
        cy.get('.items').first().should('contain', 'ITEM-2')
        cy.get('.items').last().should('contain', 'ITEM-1')
      })
    })
    


    참고 사이트


  • trigger | Cypress Documentation
  • vuedraggable - npm
  • 4teamwork/cypress-drag-drop: A cypress child command for drag'n'drop support.
  • 좋은 웹페이지 즐겨찾기