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 uselightning/datatable
in your case.