diff --git a/src/core/best-practices.js b/src/core/best-practices.js index ea48d5f2d1..b1877e6326 100644 --- a/src/core/best-practices.js +++ b/src/core/best-practices.js @@ -57,8 +57,13 @@ export function run() { }); if (bps.length) { if (bpSummary) { - bpSummary.appendChild(html`

Best Practices Summary

`); - if (summaryItems) bpSummary.appendChild(summaryItems); + const existingHeading = bpSummary.querySelector( + ":scope > :is(h1, h2, h3, h4, h5, h6)" + ); + if (!existingHeading) { + bpSummary.prepend(html`

Best Practices Summary

`); + } + if (summaryItems) bpSummary.append(summaryItems); } } else if (bpSummary) { const msg = `Using best practices summary (#bp-summary) but no best practices found.`; diff --git a/tests/spec/core/best-practices-spec.js b/tests/spec/core/best-practices-spec.js index 6d4a1fdd77..0f4cd6461c 100644 --- a/tests/spec/core/best-practices-spec.js +++ b/tests/spec/core/best-practices-spec.js @@ -81,4 +81,29 @@ describe("Core — Best Practices", () => { ); expect(bps.querySelectorAll("ul li")).toHaveSize(3); }); + + it("does not duplicate heading when bp-summary already has one", async () => { + const body = ` +
+

Section

+ BP1 +
+

Custom Heading

+
+
+ `; + const ops = { + config: makeBasicConfig(), + body, + }; + const doc = await makeRSDoc(ops); + const bpSummary = doc.getElementById("bp-summary"); + const headings = bpSummary.querySelectorAll("h1, h2, h3, h4, h5, h6"); + expect(headings).toHaveSize(1); + expect(headings[0].textContent).toContain("Custom Heading"); + + const listItems = bpSummary.querySelectorAll("ul li"); + expect(listItems).toHaveSize(1); + expect(listItems[0].textContent.trim()).toBe("Best Practice 1: BP1"); + }); });