0

I have an LWC app that has a lightning-input and a lighning-button. It fetches data from the server for a record whose ID is specified. I have successfully mocked the server calls. I am trying to select a div that is inside a template which is rendered only after the data is fetched from the server (which is mocked successfully, the variable required for the template to display indeed becomes true). However, when I run the test, it says 'Cannot read properties of null (reading 'textContent')' as for some reason, the querySelection fails to select the div 'nameField'. What am I doing wrong here? I select the input field, set its value, dispatch the onchange event, and when the value updates, select the button and click it (manually on Jest). Value is fetched from the DB (mock result) successfully and the isDataFetched variable becomes true. However, I still can't select the div inside the template tag. What exactly am I doing wrong here? I have been trying to debug for quite some time now with no luck.

<template>
        <lightning-input type="text" onchange={handleInputChange} value={inputText} placeholder="Enter record id.." variant="label-hidden" class="slds-m-around_small"></lightning-input>


    <lightning-button variant="brand" label="Submit" title="Primary action" onclick={onSubmitClick} class="slds-m-around_small"></lightning-button>
   
 

    <template if:true={isDataFetched}>

        <div class="recordResultOuterWrapper">
            
            <div class="currentRecordCard">
                
                <div class="nameField">
                    {currentRecordDetails.NameField}
                </div>
                
            </div>
        </div>

       
    </template>


</template>
describe('Unit tests for recordResult.js', () => {

  afterEach(() => {
    while(document.body.firstChild) {
      document.body.removeChild(document.body.firstChild);
    }
  });
    
  it('Test to ensure current record is displayed correctly', () => 
  {
    getChildEntityDetails.mockResolvedValue(APEX_RECORDLIST_SUCCESS);
    getRecordById.mockResolvedValue(APEX_CURRENTRECORD_SUCCESS);
    getParentEntityDetails.mockResolvedValue(APEX_RECORDLIST_SUCCESS);

    const element = createElement('c-record-result', {
        is: recordResult
      });
     
  
      document.body.appendChild(element);

      const recordIdInput = element.shadowRoot.querySelector('lightning-input'); 
      recordIdInput.value='001Iw000002MIZ4IAO';
      recordIdInput.dispatchEvent(new CustomEvent('change')); //Update input with record id


      return Promise.resolve().then(()=> {
          const submitButton = element.shadowRoot.querySelector('lightning-button');
          submitButton.dispatchEvent(new CustomEvent("click")); //Click submit button after input is successfully updated
          return Promise.resolve().then(()=> {
            const nameFieldDiv = element.shadowRoot.querySelector('.nameField'); //Select nameField after submit button fetches data. This fails (it is null for some reason)
            expect(nameFieldDiv.textContent).toBe(APEX_CURRENTRECORD_SUCCESS.Name);
          });
      });
      
  });

  
});

1 Answer 1

1
// Helper function to wait until the microtask queue is empty. This is needed for promise
// timing when calling imperative Apex.
async function flushPromises() {
    return Promise.resolve();
}

Try to add following line after submitButton.dispatchEvent(new CustomEvent("click"));:

// Wait for any asynchronous DOM updates
await flushPromises();
2
  • While this did not exactly solve my problem, installing flush-promises from NPM and then adding the line of code you suggested did. Simply adding the function definition did not suffice. However, your comment helped me solve an issue that I had been stuck with for the longest time, so thank you! Please edit your comment so I may mark it correct. If you think it is indeed enough to simply add the function definition and then call it like you suggested, please tell me why it didn't work for me. Jun 13 at 11:49
  • 1
    Glad to hear that, I was using above code copied from some other place in my jest test. I didn't install flush-promise from NPM. As long as you wait for asyn DOM update then should be fine.
    – Felix
    Jun 14 at 9:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.