6

I am trying to write some Jest test for my LWC and is encountering issue evaluating the if:true attribute. Below is a sample of my code:

import { LightningElement, track } from 'lwc';

export default class EinsteinModelMetrics extends LightningElement {

    @track metrics;

    constructor(){
        super();

        let self = this;
        window.addEventListener('message', (event, data) => {
            if (event.data.name === 'metrics') { 
                self.metrics = event.data.payload;
            }
        });
    }
}

HTML template

<template>
<lightning-card if:true={metrics}>
    <div class="app slds-p-around_x-small">
        <h1 class="slds-text-heading_medium">
            Model Id {metrics.id}
        </h1>
</lightning-card>
</template>

Test script

import { createElement } from 'lwc';
import EinsteinModelMetrics from 'c/einsteinModelMetrics';

describe('c-einstein-model-metrics', () => {

    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);
        }
    });

    it('displays Model id', () => {
        const element = createElement('c-einstein-model-metrics', {
            is: EinsteinModelMetrics,
        });
        document.body.appendChild(element);

        element.metrics = {
            "id": "LIUVBSMXR6OJKHYUDCERBKKKKK",
            "object": "metrics",
            "createdAt": "2019-05-14T13:34:52.000+0000",
        };


        return Promise.resolve().then(()=>{
            const h1Tag = element.shadowRoot.querySelector('h1');
            expect(h1Tag.textContent).toBe('Model Id LIUVBSMXR6OJKHYUDCERBKKKKK');
        });        
    });

});

If I had a h1 tag with a text without any condition, the test work.

Any help around this issue?

Thanks

6

Only properties decorated with @api are public and accessible from outside the component. Tracked variables are component internals and the test cannot set them - which is the reason why your rendering condition will never be fulfilled. You have also some other small issues in your shared code.

  1. you miss a closing tag from the inner div
  2. directives are only allowed on a template element

First Option is to change the @track decorator to @api (keep in mind that you are then not able to mutate the property inside this component which means you have to consume it by a different component and bubble up the message event)

Or alternatively you have to trigger the message event in order to mutate the data: Changes to your testcase:

    it('displays Model id', () => {
        const element = createElement('c-einstein-model-metrics', {
            is: EinsteinModelMetrics,
        });
        document.body.appendChild(element);

        window.postMessage({
            name: 'metrics', payload: {
                "id": "LIUVBSMXR6OJKHYUDCERBKKKKK",
                "object": "metrics",
                "createdAt": "2019-05-14T13:34:52.000+0000",
            }
        }, '*');

        return new Promise(resolve => { setImmediate(resolve) }).then(() => {
            return new Promise(resolve => { setImmediate(resolve) })
        }).then(() => {
            const h1Tag = element.shadowRoot.querySelector('h1');
            expect(h1Tag.textContent).toBe('Model Id LIUVBSMXR6OJKHYUDCERBKKKKK');
        })
    });
  • Thanks @Renji-xD, it solved my issue. – Kevan Jun 13 at 6:55

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.