1

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

1 Answer 1

1

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')...
4
  • Umm that doesn't solve the issue at all. Maybe the core problem is something else.
    – dzh
    Sep 7, 2020 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, 2020 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, 2020 at 7:22
  • Ok. Managed to solve the problem. createElement needs to be in beforeEach or it for some reason :)
    – dzh
    Sep 7, 2020 at 7:38

You must log in to answer this question.

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