[SalesForce] mocking getSelectedRows() method from standard lightning-datatable component’s JS class in jest test not working

my LWC component under test have lightning-datatable with onrowselection event, that I want to test in jest. Here is
code snippet for component:

HTML:

<lightning-datatable
                key-field="Id"
                data={assetDetails}
                columns={assetColumns}
                onrowselection={handleAssetSelection}
                data-my-id="assetTable">
</lightning-datatable>

JS:

handleAssetSelection(event){
        this.load =false;
        if(event.target.getSelectedRows().length){
            this.retrieveSOL(event.target.getSelectedRows(),this.solines );
        }
        else
            this.load =true;
}

I am mocking the getSelectedRows method in my test file like below:

jest.mock('datatable.js',()=>{
  return {
    getSelectedRows: ()=>{
                      return [{"Id" : "02i0e00000Ye3jzAAB",
                               "Name" :  "NX-1365-G5, 3 Node, CPU E5-2620v4, CM",
                               "Order__c" :  "aBQ0q000000HI52GAG",
                               "Product2" : {
                                              "Id" :  "01t32000005eoMyAAI",
                                              "Name" :  "NX-1365-G5, 3 Nodes"
                                             },
                               "SerialNumber" : "17SM6G480179"
                               }];
                     }
  };
});

Error on run

TypeError: Cannot read property 'length' of undefined

  172 |         this.load =false;
> 173 |         if(event.target.getSelectedRows().length){
      |            ^
  174 |             this.retrieveSOL(event.target.getSelectedRows(),this.solines );

It appears code is calling standard getSelectedRows() from sfdx-lwc-jest instead of my declared mock.

What's wrong in mocking here? What is the correct way of mocking so it call my mocked definition?

UPDATE: adding jest asked in comment

import {createElement} from 'lwc';
import NtnxRetrunForCredit from 'c/ntnxRetrunForCredit';
import { registerApexTestWireAdapter } from '@salesforce/sfdx-lwc-jest';
import getAssetDetails from '@salesforce/apex/NtnxReturnForCreditComponentController.getAssetDetails';
import getSalesOrderLineDetails from '@salesforce/apex/NtnxReturnForCreditComponentController.getSalesOrderLineDetails';
import getSelectedSOL from '@salesforce/apex/NtnxReturnForCreditComponentController.onAssetselection';

const mockGetAssetDetails = require('./data/getAssetDetails.json');
const mockGetSalesOrderLineDetails = require('./data/getSalesOrderLineDetails.json');

const getAssetDetailsAdapter = registerApexTestWireAdapter(getAssetDetails);
const getSalesOrderLineDetailsAdapter = registerApexTestWireAdapter(getSalesOrderLineDetails);

const SALES_ORDER_ID = 'aBQ0q000000HI52GAG';
const CONTAINER = 'Visualforce';

jest.mock(
    '@salesforce/apex/NtnxReturnForCreditComponentController.onAssetselection',
    () => {
        return {
            default: jest.fn()
        };
    },
    { virtual: true }
);

const SELECTED_SOLS = [{"Id":"aBP0q0000006KFSGA2"},{"Id":"aBP0q0000006KFTGA2"},{"Id":"aBP0q0000006KFYGA2"}];

jest.mock('datatable.js',()=>{
    return {
        getSelectedRows:()=>{return [{  "Id" : "02i0e00000Ye3jzAAB",
                                        "Name" :  "NX-1365-G5, 3 Node, CPU E5-2620v4, CM",
                                        "Order__c" : "aBQ0q000000HI52GAG",
                                        "Product2" : {
                                                        "Id" :  "01t32000005eoMyAAI",
                                                        "Name" :  "NX-1365-G5, 3 Nodes"
                                         },
                                         "SerialNumber" : "17SM6G480179"
                                     }
                                    ];
                            }
    };
},

{virtual:true});

describe('c-ntnx-retrun-for-credit',()=>{
    afterEach(()=>{
        while(document.body.firstChild){
            document.body.removeChild(document.body.firstChild);
        }
        jest.clearAllMocks();
    });

    function flushPromises() {
        // eslint-disable-next-line no-undef
        return new Promise((resolve) => setImmediate(resolve));
    }


    describe('Throw hardware contained error',()=>{
        it('Throw error',()=>{
            getSelectedSOL.mockResolvedValue(SELECTED_SOLS);

            const element = createElement('c-ntnx-retrun-for-credit',{
                is: NtnxRetrunForCredit
            });
            element.recordId = SALES_ORDER_ID;
            element.container= CONTAINER;
            document.body.appendChild(element);
            getAssetDetailsAdapter.emit(mockGetAssetDetails);
            getSalesOrderLineDetailsAdapter.emit(mockGetSalesOrderLineDetails);

            const datatableAsset = element.shadowRoot.querySelector('lightning-datatable[data-my-id="assetTable"]');

            
            datatableAsset.dispatchEvent(new CustomEvent('rowselection',{});
            return flushPromises().then(()=>{
                
                const datatableSOL = element.shadowRoot.querySelector('lightning-datatable[data-my-id="solTable"]');
                
                expect(datatableSOL.selectedRows.length).toBe(SELECTED_SOLS.length);
                
            });
        });
    });
});

Best Answer

You're not using the correct syntax in your jest.mock() call. The first parameter needs to be a qualified module name, not a JavaScript file. You need to use lightning/datatable in your case.

jest.mock('lightning/datatable',()=>{
  ...
});
Related Topic