diff --git a/src/oc-client.js b/src/oc-client.js index cc95a5f..1c78ef1 100644 --- a/src/oc-client.js +++ b/src/oc-client.js @@ -518,41 +518,48 @@ export function createOc(oc) { let isRendering = dataRendering == "true"; let isRendered = dataRendered == "true"; - if (!isRendering && !isRendered) { - logInfo(MESSAGES_RETRIEVING); - setAttribute(dataRenderingAttribute, true); - if (!DISABLE_LOADER) { - component.innerHTML = - '
' + MESSAGES_LOADING_COMPONENT + "
"; - } + if (isRendered) { + callback(); + return; + } + if (isRendering) { + timeout(() => { + oc.renderNestedComponent(component, callback); + }, POLLING_INTERVAL); + return; + } - oc.renderByHref( - { - href: getAttribute("href"), - id: getAttribute("id"), - element: component, - }, - (err, data) => { - if (err || !data) { - setAttribute(dataRenderingAttribute, false); - setAttribute(dataRenderedAttribute, false); - setAttribute("data-failed", true); - component.innerHTML = ""; - oc.events.fire("oc:failed", { - originalError: err, - data: data, - component, - }); - logError(err); - callback(); - } else { - processHtml(component, data, callback); - } - }, - ); - } else { - timeout(callback, POLLING_INTERVAL); + logInfo(MESSAGES_RETRIEVING); + setAttribute(dataRenderingAttribute, true); + if (!DISABLE_LOADER) { + component.innerHTML = + '
' + MESSAGES_LOADING_COMPONENT + "
"; } + + oc.renderByHref( + { + href: getAttribute("href"), + id: getAttribute("id"), + element: component, + }, + (err, data) => { + if (err || !data) { + setAttribute(dataRenderingAttribute, false); + setAttribute(dataRenderedAttribute, false); + setAttribute("data-failed", true); + component.innerHTML = ""; + oc.events.fire("oc:failed", { + originalError: err, + data: data, + component, + }); + logError(err); + callback(); + } else { + processHtml(component, data, callback); + } + }, + ); }); }; diff --git a/tests/edgeCases.spec.js b/tests/edgeCases.spec.js index 3830d62..f99477a 100644 --- a/tests/edgeCases.spec.js +++ b/tests/edgeCases.spec.js @@ -169,7 +169,7 @@ test.describe("oc-client : edge cases", () => { }); expect(result.callbackCalled).toBe(true); - expect(result.wasDelayed).toBe(true); + expect(result.wasDelayed).toBe(false); }); test("should handle renderNestedComponent with currently rendering component", async ({ @@ -195,6 +195,11 @@ test.describe("oc-client : edge cases", () => { wasDelayed: endTime - startTime >= 400, }); }); + + setTimeout(() => { + element.setAttribute("data-rendering", "false"); + element.setAttribute("data-rendered", "true"); + }, 200); }); }); diff --git a/tests/renderNestedComponent.spec.js b/tests/renderNestedComponent.spec.js index 23e70e0..4605d9c 100644 --- a/tests/renderNestedComponent.spec.js +++ b/tests/renderNestedComponent.spec.js @@ -177,4 +177,86 @@ test.describe("oc-client : renderNestedComponent", () => { expect(failureResult.failedEvent).toBeDefined(); expect(failureResult.failedEvent.component).toBeDefined(); }); + + test("should not re-render a component that has already been rendered", async ({ + page, + }) => { + const result = await page.evaluate( + (config) => { + return new Promise((resolve) => { + // Create a DOM element + const component = document.createElement("oc-component"); + component.setAttribute("href", config.componentHref); + component.setAttribute("data-rendered", "true"); + component.innerHTML = "
previously rendered content
"; + let renderByHrefCalls = 0; + // Mock renderByHref + oc.renderByHref = (href, cb) => { + renderByHrefCalls++; + }; + + // Call the function being tested + oc.renderNestedComponent(component, () => { + resolve({ + innerHTML: component.innerHTML, + renderByHrefCalls: renderByHrefCalls, + }); + }); + }); + }, + { componentHref }, + ); + + // Verify the result + expect(result.innerHTML).toContain("previously rendered content"); + expect(result.renderByHrefCalls).toBe(0); + }); + + test("should wait for a component that is already rendering", async ({ + page, + }) => { + const result = await page.evaluate( + (config) => { + return new Promise((resolve) => { + const component = document.createElement("oc-component"); + component.setAttribute("href", config.componentHref); + component.setAttribute("data-rendering", "true"); + document.body.appendChild(component); + + let renderByHrefCalls = 0; + oc.renderByHref = (href, cb) => { + renderByHrefCalls++; + cb(null, { + html: "
this is the component content
", + version: "1.0.0", + name: "my-component", + key: "12345678901234567890", + }); + }; + + // Call the function being tested + oc.renderNestedComponent(component, () => { + const data = { + finalHtml: component.innerHTML, + renderByHrefCalls: renderByHrefCalls, + }; + component.remove(); + resolve(data); + }); + + // a bit later, we simulate the end of the rendering + setTimeout(() => { + component.setAttribute("data-rendering", "false"); + component.setAttribute("data-rendered", "true"); + component.innerHTML = "
newly rendered content
"; + }, 200); + }); + }, + { componentHref }, + ); + + // Verify the results + expect(result.finalHtml).toContain("newly rendered content"); + expect(result.renderByHrefCalls).toBe(0); + }); });