Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions extension/src/rules/__tests__/disguised-ad-flag.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,3 +294,53 @@ describe("disguisedAdFlagRule false-positive guards", () => {
expect(document.querySelector(`.${PLACEHOLDER_CLASS}`)).toBeNull();
});
});

describe("disguisedAdFlagRule reveal flow", () => {
it("does not re-hide an article the user revealed via click", () => {
document.body.innerHTML = articleCard({ label: "Sponsored" });
disguisedAdFlagRule.apply(document.body);

const placeholder = document.querySelector<HTMLElement>(
`.${PLACEHOLDER_CLASS}`,
);
expect(placeholder).not.toBeNull();

// attachReveal in lib/placeholder restores the original element with
// REVEALED_ATTR stamped on it. A subsequent scan (the second apply
// call here stands in for the mutation burst the subtree-watcher
// fans out when the original re-attaches) must not re-wrap the
// same article — otherwise the placeholder comes back the moment
// the user clicks reveal.
placeholder?.click();
expect(document.querySelector('[data-fixture="card"]')).not.toBeNull();

disguisedAdFlagRule.apply(document.body);

expect(document.querySelectorAll(`.${PLACEHOLDER_CLASS}`)).toHaveLength(0);
expect(document.querySelector('[data-fixture="card"]')).not.toBeNull();
});

it("re-hides a freshly-inserted advertorial card after a reveal elsewhere", () => {
// A reveal on one card must not desensitize the rule for unrelated
// siblings — only the revealed ancestor (and its descendants) are
// exempt.
document.body.innerHTML = `
${articleCard({ label: "Sponsored", heading: "First card" })}
${articleCard({ label: "Sponsored", heading: "Second card" })}
`;
disguisedAdFlagRule.apply(document.body);
expect(document.querySelectorAll(`.${PLACEHOLDER_CLASS}`)).toHaveLength(2);

const [first] = document.querySelectorAll<HTMLElement>(
`.${PLACEHOLDER_CLASS}`,
);
first?.click();

disguisedAdFlagRule.apply(document.body);

// First card is revealed and stays revealed; second card stays hidden.
expect(document.querySelectorAll(`.${PLACEHOLDER_CLASS}`)).toHaveLength(1);
const revealedCards = document.querySelectorAll('[data-fixture="card"]');
expect(revealedCards).toHaveLength(1);
});
});
7 changes: 6 additions & 1 deletion extension/src/rules/disguised-ad-flag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,12 @@ function isCandidateSkipped(element: HTMLElement): boolean {
if (element.hasAttribute(CONSIDERED_ATTR)) {
return true;
}
if (element.hasAttribute(REVEALED_ATTR)) {
// Skip if the label sits inside (or is) an element this rule already
// hid and the user then revealed. The reveal stamp lives on the article
// ancestor — not on the label — so checking only `element.hasAttribute`
// missed the common case and let a post-reveal mutation burst re-wrap
// the same article into an unrevealable loop.
if (element.closest(`[${REVEALED_ATTR}="${RULE_ID}"]`)) {
return true;
}
if (isInsidePlaceholder(element)) {
Expand Down
Loading