From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../TopSites/TopSiteImpressionWrapper.test.jsx | 150 +++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 browser/components/newtab/test/unit/content-src/components/TopSites/TopSiteImpressionWrapper.test.jsx (limited to 'browser/components/newtab/test/unit/content-src/components/TopSites/TopSiteImpressionWrapper.test.jsx') diff --git a/browser/components/newtab/test/unit/content-src/components/TopSites/TopSiteImpressionWrapper.test.jsx b/browser/components/newtab/test/unit/content-src/components/TopSites/TopSiteImpressionWrapper.test.jsx new file mode 100644 index 0000000000..79cb6ec7c5 --- /dev/null +++ b/browser/components/newtab/test/unit/content-src/components/TopSites/TopSiteImpressionWrapper.test.jsx @@ -0,0 +1,150 @@ +"use strict"; + +import { + TopSiteImpressionWrapper, + INTERSECTION_RATIO, +} from "content-src/components/TopSites/TopSiteImpressionWrapper"; +import { actionTypes as at } from "common/Actions.sys.mjs"; +import React from "react"; +import { shallow } from "enzyme"; + +describe("", () => { + const FullIntersectEntries = [ + { isIntersecting: true, intersectionRatio: INTERSECTION_RATIO }, + ]; + const ZeroIntersectEntries = [ + { isIntersecting: false, intersectionRatio: 0 }, + ]; + const PartialIntersectEntries = [ + { isIntersecting: true, intersectionRatio: INTERSECTION_RATIO / 2 }, + ]; + + // Build IntersectionObserver class with the arg `entries` for the intersect callback. + function buildIntersectionObserver(entries) { + return class { + constructor(callback) { + this.callback = callback; + } + + observe() { + this.callback(entries); + } + + unobserve() {} + }; + } + + const DEFAULT_PROPS = { + actionType: at.TOP_SITES_SPONSORED_IMPRESSION_STATS, + tile: { + tile_id: 1, + position: 1, + reporting_url: "https://test.reporting.com", + advertiser: "test_advertiser", + }, + IntersectionObserver: buildIntersectionObserver(FullIntersectEntries), + document: { + visibilityState: "visible", + addEventListener: sinon.stub(), + removeEventListener: sinon.stub(), + }, + }; + + const InnerEl = () =>
Inner Element
; + + function renderTopSiteImpressionWrapper(props = {}) { + return shallow( + + + + ); + } + + it("should render props.children", () => { + const wrapper = renderTopSiteImpressionWrapper(); + assert.ok(wrapper.contains()); + }); + it("should not send impression when the wrapped item is visbible but below the ratio", () => { + const dispatch = sinon.spy(); + const props = { + dispatch, + IntersectionObserver: buildIntersectionObserver(PartialIntersectEntries), + }; + renderTopSiteImpressionWrapper(props); + + assert.notCalled(dispatch); + }); + it("should send an impression when the page is visible and the wrapped item meets the visibility ratio", () => { + const dispatch = sinon.spy(); + const props = { + dispatch, + IntersectionObserver: buildIntersectionObserver(FullIntersectEntries), + }; + renderTopSiteImpressionWrapper(props); + + assert.calledOnce(dispatch); + + let [action] = dispatch.firstCall.args; + assert.equal(action.type, at.TOP_SITES_SPONSORED_IMPRESSION_STATS); + assert.deepEqual(action.data, { + type: "impression", + ...DEFAULT_PROPS.tile, + }); + }); + it("should send an impression when the wrapped item transiting from invisible to visible", () => { + const dispatch = sinon.spy(); + const props = { + dispatch, + IntersectionObserver: buildIntersectionObserver(ZeroIntersectEntries), + }; + const wrapper = renderTopSiteImpressionWrapper(props); + + assert.notCalled(dispatch); + + dispatch.resetHistory(); + wrapper.instance().impressionObserver.callback(FullIntersectEntries); + + // For the impression + assert.calledOnce(dispatch); + + const [action] = dispatch.firstCall.args; + assert.equal(action.type, at.TOP_SITES_SPONSORED_IMPRESSION_STATS); + assert.deepEqual(action.data, { + type: "impression", + ...DEFAULT_PROPS.tile, + }); + }); + it("should remove visibility change listener when the wrapper is removed", () => { + const props = { + dispatch: sinon.spy(), + document: { + visibilityState: "hidden", + addEventListener: sinon.spy(), + removeEventListener: sinon.spy(), + }, + IntersectionObserver, + }; + + const wrapper = renderTopSiteImpressionWrapper(props); + assert.calledWith(props.document.addEventListener, "visibilitychange"); + const [, listener] = props.document.addEventListener.firstCall.args; + + wrapper.unmount(); + assert.calledWith( + props.document.removeEventListener, + "visibilitychange", + listener + ); + }); + it("should unobserve the intersection observer when the wrapper is removed", () => { + const IntersectionObserver = + buildIntersectionObserver(ZeroIntersectEntries); + const spy = sinon.spy(IntersectionObserver.prototype, "unobserve"); + const props = { dispatch: sinon.spy(), IntersectionObserver }; + + const wrapper = renderTopSiteImpressionWrapper(props); + wrapper.unmount(); + + assert.calledOnce(spy); + }); +}); -- cgit v1.2.3