8

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

1 Answer 1

8

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');
        })
    });
1
  • Thanks @Renji-xD, it solved my issue.
    – Kevan
    Jun 13, 2019 at 6:55

You must log in to answer this question.

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