简体   繁体   中英

How to jest test lightning-pills in LWC

It's the first time I'm using jest tests and I'm trying to test a method that generates lightning pills from a query of groups with access permissions (array). The lightning pills get updated whenever a new group is either added or removed from an array.

I need to test the following scenarios, but I'm not sure if I created the tests correctly:

(these are already properly functioning in actual code).

Test#1: The returned array from query should be displayed as lightning pills

Test#2: Clicking the X icon in a pill should remove the selected pill from array

enter image description here

For Test#1, the jest test fails for a mock array of multiple or single elements. I'm not sure where is the problem, but debugging shows this line is undefined:

 const detailEls = element.shadowRoot.querySelectorAll('lightning-pill');

I'm using return method GroupController.getSpecificGroups:

public with sharing class GroupController {

/* Description: Gets the groups where the contact is being shared to
*
*/
@AuraEnabled
public static List<sObject> getSpecificGroups(String recordId){
    List<GroupShare> groupShareList = new List<GroupShare>();
    List<sObject> returnShareList = new List<sObject>();

    try{
        groupShareList = [SELECT Id, UserOrGroupId, UserOrGroup.Name, ContactId, Contact.Name,
                            FROM GroupShare 
                            WHERE ContactId =: recordId];

        if(groupShareList != NULL && !groupShareList.isEmpty()){
            for(GroupShare csBuff : groupShareList){
                returnShareList.add(csBuff);
            }
        }
    }
    catch(queryException qExcp){
    }
    return returnShareList;
}

}

Jest test is passed when testing if the method successfully passes recordId to the apex method call so I'm thinking there's no problem with method calls.

 it('passes the recordId to the Apex method correctly', () => { const RECORD_ID = '00AAABBBCCCDDD12345'; const APEX_PARAMETERS = { recordId: RECORD_ID }; // Assign mock value for resolved Apex promise getSpecificGroups.mockResolvedValue(APEX_GROUPS_SUCCESS); // Create initial element const element = createElement('c-cmm-specific-group-sharing', { is: Cmm_specificGroupSharing }); element.recordId = RECORD_ID; document.body.appendChild(element); // Select button for executing Apex call const buttonEl = element.shadowRoot.querySelector('lightning-button'); buttonEl.click(); return flushPromises().then(() => { // Validate parameters of mocked Apex call expect(getSpecificGroups.mock.calls[0][0]).toEqual(APEX_PARAMETERS); }); });

For Test#2, jest test for removing pills fail. The pill is not removed from array using dispatchEvent:

 it('handleRemoveSelectedItem works', () => { // Create element const element = createElement('c-cmm-specific-group-sharing', { is: Cmm_specificGroupSharing }); element.availableGroups = APEX_GROUPS_SUCCESS; document.body.appendChild(element); // Remove a selected item const selPills = element.shadowRoot.querySelectorAll('lightning-pill'); selPills[0].dispatchEvent(new CustomEvent('remove')); // Check selection expect(element.availableGroups.length).toBe(0); });

Jest Test

 import { createElement } from 'lwc'; import Cmm_specificGroupSharing from 'c/c-cmm-specific-group-sharing'; import getSpecificGroups from '@salesforce/apex/GroupController.getSpecificGroups'; import delete from "@salesforce/apex/GroupController.delete"; // Mocking Apex method call jest.mock( '@salesforce/apex/GroupController.getSpecificGroups', () => { return { default: jest.fn() }; }, { virtual: true } ); // Sample data for Apex call const APEX_GROUPS_SUCCESS = [ { "Id": "000001112222DDDD001", "UserOrGroupId": "00AAABBBCCCDDD12345", "Name": "Asia Pacific" } ]; describe('c-cmm-specific-group-sharing', () => { 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(); }); // Helper function to wait until the microtask queue is empty. This is needed for promise // timing when calling imperative Apex. function flushPromises() { // eslint-disable-next-line no-undef return new Promise(resolve => setImmediate(resolve)); } it('passes the recordId to the Apex method correctly', () => { const RECORD_ID = '00AAABBBCCCDDD12345'; const APEX_PARAMETERS = { recordId: RECORD_ID }; // Assign mock value for resolved Apex promise getSpecificGroups.mockResolvedValue(APEX_GROUPS_SUCCESS); // Create initial element const element = createElement('c-cmm-specific-group-sharing', { is: Cmm_specificGroupSharing }); element.recordId = RECORD_ID; document.body.appendChild(element); // Select button for executing Apex call const buttonEl = element.shadowRoot.querySelector('lightning-button'); buttonEl.click(); return flushPromises().then(() => { // Validate parameters of mocked Apex call expect(getSpecificGroups.mock.calls[0][0]).toEqual(APEX_PARAMETERS); }); }); it('renders one sharing group', () => { // Assign mock value for resolved Apex promise getSpecificGroups.mockResolvedValue(APEX_GROUPS_SUCCESS); // Create initial element const element = createElement('c-cmm-specific-group-sharing', { is: Cmm_specificGroupSharing }); document.body.appendChild(element); // Select button for executing Apex call const buttonEl = element.shadowRoot.querySelector('lightning-button'); buttonEl.click(); return flushPromises().then(() => { const detailEls = element.shadowRoot.querySelectorAll('lightning-pill'); expect(detailEls.length).toBe(APEX_GROUPS_SUCCESS.length); expect(detailEls[0].label).toBe( APEX_GROUPS_SUCCESS[0].Name ); }); }); it('handleRemoveSelectedItem works', () => { // Create element const element = createElement('c-cmm-specific-group-sharing', { is: Cmm_specificGroupSharing }); element.availableGroups = APEX_GROUPS_SUCCESS; document.body.appendChild(element); // Remove a selected item const selPills = element.shadowRoot.querySelectorAll('lightning-pill'); selPills[0].dispatchEvent(new CustomEvent('remove')); // Check selection expect(element.availableGroups.length).toBe(0); }); });

JS and HTML

 import { LightningElement api } from 'lwc'; import getSpecificGroups from '@salesforce/apex/GroupController.getSpecificGroups'; import deleteGroup from "@salesforce/apex/GroupController.deleteGroup"; export default class Cmm_specificGroupSharing extends LightningElement { @api availableGroups; @api get recordId() { return this._recordId; } set recordId(value) { this._recordId = value; } connectedCallback() { this.getSpecificGroups(); } getSpecificGroups() { this.availableGroups =[]; getSpecificGroups({ recordId: this._recordId, }) .then(result => { result.map(gShare => { let obj = { 'Id': gShare.Id, 'UserOrGroupId': gShare.UserOrGroupId, 'Name': gShare.UserOrGroup.Name }; this.availableGroups.push(obj); return null; }) console.log('result' + JSON.stringify(result)); }) .catch((err) => { }); } handleRemoveSelectedItem(event) { const recordId = event.currentTarget.dataset.id; this.availableGroups = this. availableGroups.filter(item => item.id !== recordId); deleteGroup ({ recordId: recordId }) .then(() => { this.notifyUser('', this.deleteSuccessMsg, 'success'); }) .catch((err) => { this.error = err; }); } }
 <template> <template for:each={availableGroups} for:item="groupShare"> <lightning-pill data-id={groupShare.Id} key={groupShare.Id} label={groupShare.Name} onremove={handleRemoveSelectedItem}> </lightning-pill> </template> </template>

I appreciate any help. Thanks!

Please, could you please try in this way?:

it('handleRemoveSelectedItem works', () => {
    // Create element
    const element = createElement('c-cmm-specific-group-sharing', {
        is: Cmm_specificGroupSharing
    });
    element.availableGroups = APEX_GROUPS_SUCCESS;
    document.body.appendChild(element);

    return Promise.resolve()
    .then(() => {
         // Remove a selected item
        let selPills = element.shadowRoot.querySelectorAll('lightning-pill');
        selPills[0].dispatchEvent(new CustomEvent('remove'));
    }) // Move foward
    .then(() => {
        selPills = element.shadowRoot.querySelectorAll('lightning-pill');
        expect(selPills.length).toBe(0);
    });
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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