0

For some reason DOM is not cleared between lwc jest tests (I think).

What I want to test that page renders with lightning-input disabled by default and after button click it's enabled.

Test pass perfect if they are ran individually, but not when in same file.

Template:

<template>
    <lightning-button onclick={enable} label="Enable"></lightning-button>
    <lightning-input label="foo" disabled={isDisabled}></lightning-input>
</template>

Controller: import {LightningElement} from 'lwc';

export default class ButtonPress extends LightningElement {
    isDisabled = true
    enable(){
        this.isDisabled = false
    }
}

Test:

import {createElement} from 'lwc';
import buttonPress from 'c/buttonPress';
const flushPromises = () => new Promise(resolve => setImmediate(resolve))

describe('c-button-press', () => {
    afterEach(() => {
        while (document.body.firstChild) {
            document.body.removeChild(document.body.firstChild);
        }
    });
    describe('when setup is complete', () => {
        const element = createElement('c-button-press', {
            is: buttonPress
        });
        document.body.appendChild(element);
        describe('when rendered', () => {
            let elements
            beforeEach(async () => {
                await flushPromises()
                elements = Array.from(element.shadowRoot.querySelectorAll('lightning-input'))
            })
            it('displays disabled input field', () => {
                expect(elements).toHaveLength(1)
                expect(elements.filter(i => i.disabled)).toHaveLength(1)
            })
        })
    })
});
describe('c-button-press', () => {
    afterEach(() => {
        while (document.body.firstChild) {
            document.body.removeChild(document.body.firstChild);
        }
    });
    describe('when setup is complete', () => {
        const element = createElement('c-button-press', {
            is: buttonPress
        });
        document.body.appendChild(element);
        describe('when clicking edit', () => {
            let elements
            beforeEach(async () => {
                await new Promise(r => setTimeout(r, 10));
                const buttons = element.shadowRoot.querySelectorAll('lightning-button');
                buttons[0].click();
                await flushPromises()
                elements = element.shadowRoot.querySelectorAll('lightning-input')
            })
            it('enables field editing', async () => {
                expect(Array.from(elements).filter(i => i.disabled)).toHaveLength(0)
            })
        })
    })
})
0

IMHO your test hierarchy is incorrect, and can also be much more simplified.

It should to be:

describe('c-button-press')...
   afterEach()...
   it('displays disabled input field')...
   it('enables field editing')...
| improve this answer | |
  • Umm that doesn't solve the issue at all. Maybe the core problem is something else. – dzh Sep 7 at 7:18
  • Also from my newbie understanding of RSpec is not what I want. You seem to refer to more of a JUnit style of testing where you basically call methods. – dzh Sep 7 at 7:19
  • Putting createElement in each test does solve the problem, but I'd like to get to the bottom of this. Interesting that afterEach DOM cleanup is unneeded when each test is in separate it – dzh Sep 7 at 7:22
  • Ok. Managed to solve the problem. createElement needs to be in beforeEach or it for some reason :) – dzh Sep 7 at 7:38

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.