0

How to write a jest test on conditional rendering? so I have a page in that page few input and combobox and when the combobox selected to a particular type which is accepted then I display the input field called amount. my question how would you write a jest test to a conditional rendering, please see for detail below.

<lightning-combobox
   name="pType"  
   value={pType}
   options={options}
   onchange={handleChange}>
</lightning-combobox>

<lightning-input ....</lightning-input>
<lightning-input ....</lightning-input>
<lightning-input ....</lightning-input>

<div if:true={isSelected} >
         <lightning-input type="number" onchange={handleChange} label="amount" name="amount"></lightning-input>
</div> 

.JS:

isSelected = false; //hide amount field by default

handleChange(event) { 
 const {name} = event.target 
 const {value} = event.detail;

 ......
 if (name === 'pType') {
    if (value) {
       this.isSelected = value.toLowerCase() === 'accepted'
    } 
 }  
 ......
}

JEST test class:

import { createElement } from 'lwc';
import MyConditionalRendering from 'c/myConditionalRendering';

describe('c-my-conditional-rendering suite', ()=>{

    beforeEach(() => {
        const element = createElement('c-my-conditional-rendering', {
            is: MyConditionalRendering
        })
        document.body.appendChild(element)
    })
     
    it("show amount input field when combobox is accepted", ()=>{
        const element = document.querySelector('c-my-conditional-rendering')
        const inputElement = element.shadowRoot.querySelector('lightning-input');

        //lets select the type from the combobox:
        const comboBox = element.shadowRoot.querySelector("lightning-combobox"); 
        comboBox.dispatchEvent(new CustomEvent("change", {detail: {value: 'accepted'}}));

        //not sure how should I grab the input amount text field from here.
         
    }) 
    
}) 

1 Answer 1

1

On inital load, the input field won't display as the combobox doesn't have any value. As such, you need to do the following to replicate the scenario you care about:

  1. Set the value of the combobox to what you expect
  2. Fire the event that a change has occurred
  3. Wait for DOM updates
  4. Assert the amount input is now visible

I'll also add, with many different lightning-input elements in one LWC (and maybe always in general), you could consider leveraging the data attribute to have an easy way to query exactly what you want. As an example, below, you could add an attribute called data-test-id with some sort of descriptive name that makes sense to utilize in your jest test

<lightning-combobox
    name="pType"  
    value={pType}
    options={options}
    onchange={handleChange}>
    data-testid="combobox_pType_field"
>
</lightning-combobox>


<div if:true={isSelected} >
     <lightning-input 
         type="number" 
         onchange={handleChange} 
         label="amount" 
         name="amount"
         data-testid="amount_input_field" 
     >
     </lightning-input>
</div> 

In your jest test, you can use that data-attribute to query your specific input(s). As I said above, if you query for it on the initial load - your conditional will mean that the input for amount is not shown (as expected). You can assert that and then, once you set the right value and dispatch the event, wait for the DOM update (async, use a promise) to see that the input element now exists

const hiddenAmountInputElement = element.shadowRoot.querySelector('[data-test-id="amount_input_field"]');
expect(hiddenAmountInputElement).toBeNull();

//lets select the type from the combobox:
const comboBox = element.shadowRoot.querySelector('[data-test-id="comboBox_pType_field"]'); 
comboBox.dispatchEvent(new CustomEvent("change", {detail: {value: 'accepted'}}));

//Return a promise to wait for any asynchronous DOM updates
return Promise.resolve()
    .then(() => {
        const inputAmountElement = element.shadowRoot.querySelector('[data-test-id="amount_input_field"]');
        expect(amountInputElement).not.toBeNull();
    });
});

If you needed the value or anything, you can just access it like so

const inputAmountElement = element.shadowRoot.querySelector('[data-test-id="amount_input_field"]');
expect(amountInputElement.value).toBe('whatever amount');

3
  • thank you so much and appreciate your time! when I try to do expect(amountInputElement.value).toBe(100) I get the error it says expect(received).toBe(expected) // Object.is equality Expected: 100 Received: undefined` any idea why it would throw this error? but it passed if I use not.toBeNull
    – Nick
    Sep 9, 2021 at 20:24
  • how are you expecting 100 to be set as the value for amount? I presume the only thing that happens is the input is visible (unless you have other automation that fills out amount). I showed the value use case as a fyi - but, it'll be empty unless you set it within your test. The not.toBeNull was for the input element (which exists/is visible, even if there's no value for the input). Sep 9, 2021 at 20:33
  • 1
    never mind, I was not setting the value before I call the expect.
    – Nick
    Sep 9, 2021 at 20:43

You must log in to answer this question.

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