diff --git a/packages/@lwc/integration-not-karma/test/component/dynamic-imports/index.spec.js b/packages/@lwc/integration-not-karma/test/component/dynamic-imports/index.spec.js index 8176b9b48c..640bd51eea 100644 --- a/packages/@lwc/integration-not-karma/test/component/dynamic-imports/index.spec.js +++ b/packages/@lwc/integration-not-karma/test/component/dynamic-imports/index.spec.js @@ -17,18 +17,19 @@ beforeEach(() => { clearRegister(); }); -function waitForMacroTask(fn) { - // waiting for the macro-task first, then micro-task - return new Promise((resolve) => { - setTimeout(() => { - resolve(); - }); - }).then(() => fn()); +async function microTask() { + await Promise.resolve(); +} + +/** Actually waits a macro-task and then a micro-task, for reasons unspecified. */ +async function macroTask() { + await new Promise((resolve) => setTimeout(resolve, 0)); + await microTask(); } // TODO [#3331]: remove lwc:dynamic portion of these tests in 246 -it('should call the loader using lwc:dynamic', () => { +it('should call the loader using lwc:dynamic', async () => { // note, using `x-` prefix instead of `x/` because these are // handled by `registerForLoad` registerForLoad('x-ctor', DynamicCtor); @@ -37,38 +38,38 @@ it('should call the loader using lwc:dynamic', () => { const elm = createElement('x-dynamic', { is: LwcDynamicContainer }); document.body.appendChild(elm); - return Promise.resolve().then(() => { - const child = elm.shadowRoot.querySelector('x-ctor'); - expect(child).toBeNull(); - // first rendered with ctor set to undefined (nothing) - elm.enableCtor(); - return waitForMacroTask(() => { - // second rendered with ctor set to x-ctor - const ctorElm = elm.shadowRoot.querySelector('x-ctor'); - expect(ctorElm).not.toBeNull(); - const span = ctorElm.shadowRoot.querySelector('span'); - expect(span).not.toBeNull(); - expect(span.textContent).toBe('ctor_html'); - elm.enableAlter(); - return waitForMacroTask(() => { - // third rendered with ctor set to x-alter - const alterElm = elm.shadowRoot.querySelector('x-ctor'); - expect(alterElm).not.toBeNull(); - const span = alterElm.shadowRoot.querySelector('span'); - expect(span).not.toBeNull(); - expect(span.textContent).toBe('alter_html'); - elm.disableAll(); - return waitForMacroTask(() => { - // third rendered with ctor set to null (nothing) - const child = elm.shadowRoot.querySelector('x-ctor'); - expect(child).toBeNull(); - }); - }); - }); - }); + const child = elm.shadowRoot.querySelector('x-ctor'); + expect(child).toBeNull(); + // first rendered with ctor set to undefined (nothing) + elm.enableCtor(); + + await macroTask(); + + // second rendered with ctor set to x-ctor + const ctorElm = elm.shadowRoot.querySelector('x-ctor'); + expect(ctorElm).not.toBeNull(); + const ctorElmSpan = ctorElm.shadowRoot.querySelector('span'); + expect(ctorElmSpan).not.toBeNull(); + expect(ctorElmSpan.textContent).toBe('ctor_html'); + elm.enableAlter(); + + await macroTask(); + + // third rendered with ctor set to x-alter + const alterElm = elm.shadowRoot.querySelector('x-ctor'); + expect(alterElm).not.toBeNull(); + const afterElmSpan = alterElm.shadowRoot.querySelector('span'); + expect(afterElmSpan).not.toBeNull(); + expect(afterElmSpan.textContent).toBe('alter_html'); + elm.disableAll(); + + await macroTask(); + + // third rendered with ctor set to null (nothing) + expect(elm.shadowRoot.querySelector('x-ctor')).toBeNull(); }); -it('should not reuse DOM elements using lwc:dynamic', () => { +it('should not reuse DOM elements using lwc:dynamic', async () => { registerForLoad('x-ctor', DynamicCtor); registerForLoad('x-alter', AlterCtor); @@ -76,18 +77,19 @@ it('should not reuse DOM elements using lwc:dynamic', () => { elm.enableCtor(); document.body.appendChild(elm); - return waitForMacroTask(() => { - const childElm = elm.shadowRoot.querySelector('x-ctor'); - expect(childElm).not.toBeNull(); - elm.enableAlter(); - return waitForMacroTask(() => { - const alterElm = elm.shadowRoot.querySelector('x-ctor'); - expect(alterElm).not.toBe(childElm); - }); - }); + await macroTask(); + + const childElm = elm.shadowRoot.querySelector('x-ctor'); + expect(childElm).not.toBeNull(); + elm.enableAlter(); + + await macroTask(); + + const alterElm = elm.shadowRoot.querySelector('x-ctor'); + expect(alterElm).not.toBe(childElm); }); -it('should not cache DOM elements using lwc:dynamic', () => { +it('should not cache DOM elements using lwc:dynamic', async () => { registerForLoad('x-ctor', DynamicCtor); registerForLoad('x-alter', AlterCtor); @@ -96,18 +98,20 @@ it('should not cache DOM elements using lwc:dynamic', () => { document.body.appendChild(elm); // from ctor to alter back to ctor, new elements should be created - return waitForMacroTask(() => { - const childElm = elm.shadowRoot.querySelector('x-ctor'); - expect(childElm).not.toBeNull(); - elm.enableAlter(); - return waitForMacroTask(() => { - elm.enableCtor(); - return waitForMacroTask(() => { - const secondCtorElm = elm.shadowRoot.querySelector('x-ctor'); - expect(secondCtorElm).not.toBe(childElm); - }); - }); - }); + await macroTask(); + + const childElm = elm.shadowRoot.querySelector('x-ctor'); + expect(childElm).not.toBeNull(); + elm.enableAlter(); + + await macroTask(); + + elm.enableCtor(); + + await macroTask(); + + const secondCtorElm = elm.shadowRoot.querySelector('x-ctor'); + expect(secondCtorElm).not.toBe(childElm); }); describe('slotted content using lwc:dynamic', () => { @@ -119,7 +123,7 @@ describe('slotted content using lwc:dynamic', () => { consoleSpy.reset(); }); - it('reallocate slotted content after changing constructor', () => { + it('reallocate slotted content after changing constructor', async () => { const elm = createElement('x-dynamic-slotted', { is: LwcDynamicSlotted }); elm.ctor = ContainerFoo; @@ -137,26 +141,22 @@ describe('slotted content using lwc:dynamic', () => { // Swap construstor and check if nodes have been reallocated. elm.ctor = ContainerBar; - return Promise.resolve().then(() => { - expect( - elm.shadowRoot.querySelector('[data-id="slot-default"]').assignedSlot - ).toBeDefined(); - expect(elm.shadowRoot.querySelector('[data-id="slot-bar"]').assignedSlot).toBeDefined(); - - if (process.env.NATIVE_SHADOW) { - // `slot-foo` is not rendered in synthetic shadow - expect(elm.shadowRoot.querySelector('[data-id="slot-foo"]').assignedSlot).toBe( - null - ); - } - expect(consoleSpy.calls.error.length).toEqual(0); - }); + await microTask(); + + expect(elm.shadowRoot.querySelector('[data-id="slot-default"]').assignedSlot).toBeDefined(); + expect(elm.shadowRoot.querySelector('[data-id="slot-bar"]').assignedSlot).toBeDefined(); + + if (process.env.NATIVE_SHADOW) { + // `slot-foo` is not rendered in synthetic shadow + expect(elm.shadowRoot.querySelector('[data-id="slot-foo"]').assignedSlot).toBe(null); + } + expect(consoleSpy.calls.error.length).toEqual(0); }); }); // Using -it('should call the loader', () => { +it('should call the loader', async () => { // note, using `x-` prefix instead of `x/` because these are // handled by `registerForLoad` registerForLoad('x-ctor', DynamicCtor); @@ -165,38 +165,40 @@ it('should call the loader', () => { const elm = createElement('x-dynamic', { is: DynamicContainer }); document.body.appendChild(elm); - return Promise.resolve().then(() => { - const child = elm.shadowRoot.querySelector('x-ctor'); - expect(child).toBeNull(); - // first rendered with ctor set to undefined (nothing) - elm.enableCtor(); - return waitForMacroTask(() => { - // second rendered with ctor set to x-ctor - const ctorElm = elm.shadowRoot.querySelector('x-ctor'); - expect(ctorElm).not.toBeNull(); - const span = ctorElm.shadowRoot.querySelector('span'); - expect(span).not.toBeNull(); - expect(span.textContent).toBe('ctor_html'); - elm.enableAlter(); - return waitForMacroTask(() => { - // third rendered with ctor set to x-alter - const alterElm = elm.shadowRoot.querySelector('x-alter'); - expect(alterElm).not.toBeNull(); - const span = alterElm.shadowRoot.querySelector('span'); - expect(span).not.toBeNull(); - expect(span.textContent).toBe('alter_html'); - elm.disableAll(); - return waitForMacroTask(() => { - // third rendered with ctor set to null (nothing) - const child = elm.shadowRoot.querySelector('x-ctor'); - expect(child).toBeNull(); - }); - }); - }); - }); + await microTask(); + + const child = elm.shadowRoot.querySelector('x-ctor'); + expect(child).toBeNull(); + // first rendered with ctor set to undefined (nothing) + elm.enableCtor(); + + await macroTask(); + + // second rendered with ctor set to x-ctor + const ctorElm = elm.shadowRoot.querySelector('x-ctor'); + expect(ctorElm).not.toBeNull(); + const ctorElmSpan = ctorElm.shadowRoot.querySelector('span'); + expect(ctorElmSpan).not.toBeNull(); + expect(ctorElmSpan.textContent).toBe('ctor_html'); + elm.enableAlter(); + + await macroTask(); + + // third rendered with ctor set to x-alter + const alterElm = elm.shadowRoot.querySelector('x-alter'); + expect(alterElm).not.toBeNull(); + const afterElmSpan = alterElm.shadowRoot.querySelector('span'); + expect(afterElmSpan).not.toBeNull(); + expect(afterElmSpan.textContent).toBe('alter_html'); + elm.disableAll(); + + await macroTask(); + + // third rendered with ctor set to null (nothing) + expect(elm.shadowRoot.querySelector('x-ctor')).toBeNull(); }); -it('should not reuse DOM elements', () => { +it('should not reuse DOM elements', async () => { registerForLoad('x-ctor', DynamicCtor); registerForLoad('x-alter', AlterCtor); @@ -204,38 +206,38 @@ it('should not reuse DOM elements', () => { elm.enableCtor(); document.body.appendChild(elm); - return waitForMacroTask(() => { - const childElm = elm.shadowRoot.querySelector('x-ctor'); - expect(childElm).not.toBeNull(); - elm.enableAlter(); - return waitForMacroTask(() => { - const alterElm = elm.shadowRoot.querySelector('x-alter'); - expect(alterElm).not.toBe(childElm); - }); - }); + await macroTask(); + const childElm = elm.shadowRoot.querySelector('x-ctor'); + expect(childElm).not.toBeNull(); + elm.enableAlter(); + await macroTask(); + const alterElm = elm.shadowRoot.querySelector('x-alter'); + expect(alterElm).not.toBe(childElm); }); -it('should not cache DOM elements', () => { +it('should not cache DOM elements', async () => { registerForLoad('x-ctor', DynamicCtor); registerForLoad('x-alter', AlterCtor); const elm = createElement('x-dynamic', { is: DynamicContainer }); elm.enableCtor(); document.body.appendChild(elm); - // from ctor to alter back to ctor, new elements should be created - return waitForMacroTask(() => { - const childElm = elm.shadowRoot.querySelector('x-ctor'); - expect(childElm).not.toBeNull(); - elm.enableAlter(); - return waitForMacroTask(() => { - elm.enableCtor(); - return waitForMacroTask(() => { - const secondCtorElm = elm.shadowRoot.querySelector('x-ctor'); - expect(secondCtorElm).not.toBe(childElm); - }); - }); - }); + + await macroTask(); + + const childElm = elm.shadowRoot.querySelector('x-ctor'); + expect(childElm).not.toBeNull(); + elm.enableAlter(); + + await macroTask(); + + elm.enableCtor(); + + await macroTask(); + + const secondCtorElm = elm.shadowRoot.querySelector('x-ctor'); + expect(secondCtorElm).not.toBe(childElm); }); describe('slotted content', () => { @@ -247,7 +249,7 @@ describe('slotted content', () => { consoleSpy.reset(); }); - it('reallocate slotted content after changing constructor', () => { + it('reallocate slotted content after changing constructor', async () => { const elm = createElement('x-dynamic-slotted', { is: DynamicSlotted }); elm.ctor = ContainerFoo; @@ -265,19 +267,15 @@ describe('slotted content', () => { // Swap constructor and check if nodes have been reallocated. elm.ctor = ContainerBar; - return Promise.resolve().then(() => { - expect( - elm.shadowRoot.querySelector('[data-id="slot-default"]').assignedSlot - ).toBeDefined(); - expect(elm.shadowRoot.querySelector('[data-id="slot-bar"]').assignedSlot).toBeDefined(); - - if (process.env.NATIVE_SHADOW) { - // `slot-foo` is not rendered in synthetic shadow - expect(elm.shadowRoot.querySelector('[data-id="slot-foo"]').assignedSlot).toBe( - null - ); - } - expect(consoleSpy.calls.error.length).toEqual(0); - }); + await microTask(); + + expect(elm.shadowRoot.querySelector('[data-id="slot-default"]').assignedSlot).toBeDefined(); + expect(elm.shadowRoot.querySelector('[data-id="slot-bar"]').assignedSlot).toBeDefined(); + + if (process.env.NATIVE_SHADOW) { + // `slot-foo` is not rendered in synthetic shadow + expect(elm.shadowRoot.querySelector('[data-id="slot-foo"]').assignedSlot).toBe(null); + } + expect(consoleSpy.calls.error.length).toEqual(0); }); });