4

I'm trying to implement Jest tests for a module(to reorder data table rows). However, I'm unable to mimic the dragstart event. Can anyone help me to achieve the same behavior -

Here is the function which is getting called on the dragstart -

onDragStart(evt) {
    evt.dataTransfer.setData("dragId", evt.currentTarget.dataset.dragId);
    evt.dataTransfer.setData("sy", evt.pageY );
    evt.dataTransfer.effectAllowed = "move";
    evt.currentTarget.classList.add("grabbed");
}

Here I'm getting error -
TypeError: Cannot read property 'setData' of undefined at first line.

Here is the jest method -

it("should check a mouse drag event", () => {
    const element = createElement("c-data-table-draggable", {
      is: DataTableDragable
    });
    document.body.appendChild(element);

    getRecordWireAdapter.emit(mockGetRecord);
    //element.users = mockGetRecord;

    return Promise.resolve().then(() => {
      expect(element).toBeAccessible();
      
      const trEls = element.shadowRoot.querySelectorAll('tr');
      expect(trEls.length).toBeGreaterThan(mockGetRecord.length);
 
      trEls[1].dispatchEvent(new CustomEvent("dragstart", { clientX: 0, clientY: 0, pageY : 20 }));      
    });
  });

Component HTML for reference -

<template>
  <table
    class="table-dragable slds-table slds-table_cell-buffer slds-table_bordered"
    aria-describedby="User Details"
  >
    <thead>
      <tr>
        <th scope="col">Index</th>
        <th scope="col">Salesforce ID</th>
        <th scope="col">User Name</th>
        <th scope="col">Email ID</th>
      </tr>
    </thead>
    <tbody>
      <template if:true={users.data}>
        <template for:each={users.data} for:item="user" for:index="index">
          <tr
            class="grabable"
            key={user.Id}
            id={user.Id}
            draggable="true"
            data-drag-id={index}
            ondragstart={onDragStart}
            ondragover={onDragOver}
            ondrop={onDrop}
          >
            <th scope="col" class="myIndex">{index}</th>
            <th scope="col" class="myId">{user.Id}</th>
            <th scope="col">{user.Username}</th>
            <th scope="col">{user.Email}</th>
          </tr>
        </template>
      </template>
      <template if:true={users.error}> No rows found. </template>
    </tbody>
  </table>

  <div>
    <lightning-button
      variant="brand"
      label="Submit"
      title="Submit"
      onclick={handleSubmit}
      class="slds-m-around_x-large"
    ></lightning-button>
  </div>
</template>

1 Answer 1

3

Jest ships with the jsdom and you can see that the dataTransfer is not yet implemented and hence you are receiving the error below

TypeError: Cannot read property 'setData' of undefined

The undefined here is the dataTransfer object.

You can use the jest manual mocks to mock the implementation of dataTransfer as shown below. Note how I have used the object.assign() to override the custom event so it has the dataTransfer function and the properties.

The HTML template code is as below

<template>
<table
    class="table-dragable slds-table slds-table_cell-buffer slds-table_bordered"
    aria-describedby="User Details"
>
    <thead>
        <tr>
            <th scope="col">Index</th>
            <th scope="col">Salesforce ID</th>
            <th scope="col">User Name</th>
            <th scope="col">Email ID</th>
        </tr>
    </thead>
    <tbody>
        <template if:true={users}>
            <template
                for:each={users}
                for:item="user"
                for:index="index"
            >
                <tr
                    class="grabable"
                    key={user.Id}
                    id={user.Id}
                    draggable="true"
                    data-drag-id={index}
                    ondragstart={onDragStart}
                >
                    <th scope="col" class="myIndex">{index}</th>
                    <th scope="col" class="myId">{user.Id}</th>
                    <th scope="col">{user.Username}</th>
                    <th scope="col">{user.Email}</th>
                </tr>
            </template>
        </template>
        <template if:true={error}> No rows found. </template>
    </tbody>
</table>

<div>
    <lightning-button
        variant="brand"
        label="Submit"
        title="Submit"
        onclick={handleSubmit}
        class="slds-var-m-around_x-large"
    ></lightning-button>
</div>
__________________________________________________________________________________

The JavaScript code that i have written test is below

import { LightningElement, track, wire } from 'lwc';
import getUserList from '@salesforce/apex/UserController.getUserList';

export default class LwcTest extends LightningElement {

@track
users
@track
error;

@wire(getUserList)
wiredUsers({ error, data }) {
    if (data) {
        this.users = data;
        this.error = undefined;
    } else if (error) {
        this.error = error;
        this.users = undefined;
    }
}

onDragStart(evt) {
    evt.dataTransfer.setData("dragId", evt.currentTarget.dataset.dragId);
    evt.dataTransfer.setData("sy", evt.pageY );
    evt.dataTransfer.effectAllowed = "move";
    evt.currentTarget.classList.add("grabbed");
   }
}

Here is how the jest code for the above code

import { createElement } from 'lwc';
import { registerLdsTestWireAdapter } from '@salesforce/sfdx-lwc-jest';
import LwcTest from 'c/lwcTest';
import getUserList from '@salesforce/apex/UserController.getUserList';

const users = [
 {
    Id: '0050U000004YzSVQA0',
    Username: 'autoproc@00d0u000000gvvruac',
    Email: 'autoproc@00d0u000000gvvruac',
    index: 0
},
{
    Id: '0050U000004YzSaQAK',
    Username: 'automatedclean@00d0u000000gvvruac',
    Email: 'automatedclean@00d0u000000gvvruac',
    index: 1
},
{
    Id: '0050U000004YzSPQA0',
    Username: '[email protected]',
    Email: '[email protected]',
    index: 2
},
{
    Id: '0050U000004YzSUQA0',
    Username: '[email protected]',
    Email: '[email protected]',
    index: 3
},
{
    Id: '0050U000004YzSYQA0',
    Username: '[email protected]',
    Email: '[email protected]',
    index: 4
},
   {
    Id: '0050U000004YzSZQA0',
    Username:
        '[email protected]',
    Email: '[email protected]',
    index: 5
    }
 ];

  const getRecordWireAdapter = registerLdsTestWireAdapter(getUserList);

  describe('c-lwc-test', () => {
    afterEach(() => {
    // The jsdom instance is shared across test cases in a single file so reset the DOM
    while (document.body.firstChild) {
        document.body.removeChild(document.body.firstChild);
        // Prevent data saved on mocks from leaking between tests
        jest.clearAllMocks();
    }
});

 it('should check a mouse drag event', () => {
     const element = createElement('c-lwc-test', {
        is: LwcTest
    });
    document.body.appendChild(element);

    getRecordWireAdapter.emit(users);

    return Promise.resolve().then(() => {
        expect(element).toBeAccessible();

        const trEls = element.shadowRoot.querySelectorAll('tr');
        expect(trEls.length).toBeGreaterThan(users.length);
        const dragStartEvt = new CustomEvent('dragstart');
        dragStartEvt.pageY = '1';
        const setData = jest.fn();
        Object.assign(dragStartEvt, {
            dataTransfer: { setData: setData, effectAllowed: 'move' }
        });
        trEls[1].dispatchEvent(dragStartEvt);
        expect(setData).toHaveBeenCalledTimes(2);
        expect(setData).toHaveBeenNthCalledWith(1,'dragId', '0');
        expect(setData).toHaveBeenNthCalledWith(2,'sy', '1');
      });
   });
});
1
  • 1
    Thank you so much, it worked smooth! :)
    – Ysr Shk
    Nov 22, 2020 at 6:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .