From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001
From: Daniel Baumann <daniel.baumann@progress-linux.org>
Date: Sun, 7 Apr 2024 19:32:43 +0200
Subject: Adding upstream version 1:115.7.0.

Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
---
 .../DiscoveryStreamComponents/CardGrid.test.jsx    | 354 +++++++++++++++++++++
 1 file changed, 354 insertions(+)
 create mode 100644 browser/components/newtab/test/unit/content-src/components/DiscoveryStreamComponents/CardGrid.test.jsx

(limited to 'browser/components/newtab/test/unit/content-src/components/DiscoveryStreamComponents/CardGrid.test.jsx')

diff --git a/browser/components/newtab/test/unit/content-src/components/DiscoveryStreamComponents/CardGrid.test.jsx b/browser/components/newtab/test/unit/content-src/components/DiscoveryStreamComponents/CardGrid.test.jsx
new file mode 100644
index 0000000000..418a731ba1
--- /dev/null
+++ b/browser/components/newtab/test/unit/content-src/components/DiscoveryStreamComponents/CardGrid.test.jsx
@@ -0,0 +1,354 @@
+import {
+  _CardGrid as CardGrid,
+  IntersectionObserver,
+  RecentSavesContainer,
+  OnboardingExperience,
+  DSSubHeader,
+} from "content-src/components/DiscoveryStreamComponents/CardGrid/CardGrid";
+import { combineReducers, createStore } from "redux";
+import { INITIAL_STATE, reducers } from "common/Reducers.sys.mjs";
+import { Provider } from "react-redux";
+import {
+  DSCard,
+  PlaceholderDSCard,
+} from "content-src/components/DiscoveryStreamComponents/DSCard/DSCard";
+import { TopicsWidget } from "content-src/components/DiscoveryStreamComponents/TopicsWidget/TopicsWidget";
+import {
+  actionCreators as ac,
+  actionTypes as at,
+} from "common/Actions.sys.mjs";
+import React from "react";
+import { shallow, mount } from "enzyme";
+
+// Wrap this around any component that uses useSelector,
+// or any mount that uses a child that uses redux.
+function WrapWithProvider({ children, state = INITIAL_STATE }) {
+  let store = createStore(combineReducers(reducers), state);
+  return <Provider store={store}>{children}</Provider>;
+}
+
+describe("<CardGrid>", () => {
+  let wrapper;
+
+  beforeEach(() => {
+    wrapper = shallow(
+      <CardGrid
+        Prefs={INITIAL_STATE.Prefs}
+        DiscoveryStream={INITIAL_STATE.DiscoveryStream}
+      />
+    );
+  });
+
+  it("should render an empty div", () => {
+    assert.ok(wrapper.exists());
+    assert.lengthOf(wrapper.children(), 0);
+  });
+
+  it("should render DSCards", () => {
+    wrapper.setProps({ items: 2, data: { recommendations: [{}, {}] } });
+
+    assert.lengthOf(wrapper.find(".ds-card-grid").children(), 2);
+    assert.equal(wrapper.find(".ds-card-grid").children().at(0).type(), DSCard);
+  });
+
+  it("should add 4 card classname to card grid", () => {
+    wrapper.setProps({
+      fourCardLayout: true,
+      data: { recommendations: [{}, {}] },
+    });
+
+    assert.ok(wrapper.find(".ds-card-grid-four-card-variant").exists());
+  });
+
+  it("should add no description classname to card grid", () => {
+    wrapper.setProps({
+      hideCardBackground: true,
+      data: { recommendations: [{}, {}] },
+    });
+
+    assert.ok(wrapper.find(".ds-card-grid-hide-background").exists());
+  });
+
+  it("should render sub header in the middle of the card grid for both regular and compact", () => {
+    const commonProps = {
+      essentialReadsHeader: true,
+      editorsPicksHeader: true,
+      items: 12,
+      data: {
+        recommendations: [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}],
+      },
+      Prefs: INITIAL_STATE.Prefs,
+      DiscoveryStream: INITIAL_STATE.DiscoveryStream,
+    };
+    wrapper = mount(
+      <WrapWithProvider>
+        <CardGrid {...commonProps} />
+      </WrapWithProvider>
+    );
+
+    assert.ok(wrapper.find(DSSubHeader).exists());
+
+    wrapper.setProps({
+      compact: true,
+    });
+    wrapper = mount(
+      <WrapWithProvider>
+        <CardGrid {...commonProps} compact={true} />
+      </WrapWithProvider>
+    );
+
+    assert.ok(wrapper.find(DSSubHeader).exists());
+  });
+
+  it("should add/hide description classname to card grid", () => {
+    wrapper.setProps({
+      data: { recommendations: [{}, {}] },
+    });
+
+    assert.ok(wrapper.find(".ds-card-grid-include-descriptions").exists());
+
+    wrapper.setProps({
+      hideDescriptions: true,
+      data: { recommendations: [{}, {}] },
+    });
+
+    assert.ok(!wrapper.find(".ds-card-grid-include-descriptions").exists());
+  });
+
+  it("should create a widget card", () => {
+    wrapper.setProps({
+      widgets: {
+        positions: [{ index: 1 }],
+        data: [{ type: "TopicsWidget" }],
+      },
+      data: {
+        recommendations: [{}, {}, {}],
+      },
+    });
+
+    assert.ok(wrapper.find(TopicsWidget).exists());
+  });
+});
+
+// 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() {}
+
+    disconnect() {}
+  };
+}
+
+describe("<IntersectionObserver>", () => {
+  let wrapper;
+  let fakeWindow;
+  let intersectEntries;
+
+  beforeEach(() => {
+    intersectEntries = [{ isIntersecting: true }];
+    fakeWindow = {
+      IntersectionObserver: buildIntersectionObserver(intersectEntries),
+    };
+    wrapper = mount(<IntersectionObserver windowObj={fakeWindow} />);
+  });
+
+  it("should render an empty div", () => {
+    assert.ok(wrapper.exists());
+    assert.equal(wrapper.children().at(0).type(), "div");
+  });
+
+  it("should fire onIntersecting", () => {
+    const onIntersecting = sinon.stub();
+    wrapper = mount(
+      <IntersectionObserver
+        windowObj={fakeWindow}
+        onIntersecting={onIntersecting}
+      />
+    );
+    assert.calledOnce(onIntersecting);
+  });
+});
+
+describe("<RecentSavesContainer>", () => {
+  let wrapper;
+  let fakeWindow;
+  let intersectEntries;
+  let dispatch;
+
+  beforeEach(() => {
+    dispatch = sinon.stub();
+    intersectEntries = [{ isIntersecting: true }];
+    fakeWindow = {
+      IntersectionObserver: buildIntersectionObserver(intersectEntries),
+    };
+    wrapper = mount(
+      <WrapWithProvider
+        state={{
+          DiscoveryStream: {
+            isUserLoggedIn: true,
+            recentSavesData: [
+              {
+                resolved_id: "resolved_id",
+                top_image_url: "top_image_url",
+                title: "title",
+                resolved_url: "https://resolved_url",
+                domain: "domain",
+                excerpt: "excerpt",
+              },
+            ],
+            experimentData: {
+              utmSource: "utmSource",
+              utmContent: "utmContent",
+              utmCampaign: "utmCampaign",
+            },
+          },
+        }}
+      >
+        <RecentSavesContainer
+          gridClassName="ds-card-grid"
+          windowObj={fakeWindow}
+          dispatch={dispatch}
+        />
+      </WrapWithProvider>
+    ).find(RecentSavesContainer);
+  });
+
+  it("should render an IntersectionObserver when not visible", () => {
+    intersectEntries = [{ isIntersecting: false }];
+    fakeWindow = {
+      IntersectionObserver: buildIntersectionObserver(intersectEntries),
+    };
+    wrapper = mount(
+      <WrapWithProvider>
+        <RecentSavesContainer windowObj={fakeWindow} dispatch={dispatch} />
+      </WrapWithProvider>
+    ).find(RecentSavesContainer);
+
+    assert.ok(wrapper.exists());
+    assert.ok(wrapper.find(IntersectionObserver).exists());
+  });
+
+  it("should render nothing if visible until we log in", () => {
+    assert.ok(!wrapper.find(IntersectionObserver).exists());
+    assert.calledOnce(dispatch);
+    assert.calledWith(
+      dispatch,
+      ac.AlsoToMain({
+        type: at.DISCOVERY_STREAM_POCKET_STATE_INIT,
+      })
+    );
+  });
+
+  it("should render a grid if visible and logged in", () => {
+    assert.lengthOf(wrapper.find(".ds-card-grid"), 1);
+    assert.lengthOf(wrapper.find(DSSubHeader), 1);
+    assert.lengthOf(wrapper.find(PlaceholderDSCard), 2);
+    assert.lengthOf(wrapper.find(DSCard), 3);
+  });
+
+  it("should render a my list link with proper utm params", () => {
+    assert.equal(
+      wrapper.find(".section-sub-link").at(0).prop("url"),
+      "https://getpocket.com/a?utm_source=utmSource&utm_content=utmContent&utm_campaign=utmCampaign"
+    );
+  });
+
+  it("should fire a UserEvent for my list clicks", () => {
+    wrapper.find(".section-sub-link").at(0).simulate("click");
+    assert.calledWith(
+      dispatch,
+      ac.DiscoveryStreamUserEvent({
+        event: "CLICK",
+        source: `CARDGRID_RECENT_SAVES_VIEW_LIST`,
+      })
+    );
+  });
+});
+
+describe("<OnboardingExperience>", () => {
+  let wrapper;
+  let fakeWindow;
+  let intersectEntries;
+  let dispatch;
+  let resizeCallback;
+
+  let fakeResizeObserver = class {
+    constructor(callback) {
+      resizeCallback = callback;
+    }
+
+    observe() {}
+
+    unobserve() {}
+
+    disconnect() {}
+  };
+
+  beforeEach(() => {
+    dispatch = sinon.stub();
+    intersectEntries = [{ isIntersecting: true, intersectionRatio: 1 }];
+    fakeWindow = {
+      ResizeObserver: fakeResizeObserver,
+      IntersectionObserver: buildIntersectionObserver(intersectEntries),
+      document: {
+        visibilityState: "visible",
+        addEventListener: () => {},
+        removeEventListener: () => {},
+      },
+    };
+    wrapper = mount(
+      <WrapWithProvider state={{}}>
+        <OnboardingExperience windowObj={fakeWindow} dispatch={dispatch} />
+      </WrapWithProvider>
+    ).find(OnboardingExperience);
+  });
+
+  it("should render a ds-onboarding", () => {
+    assert.ok(wrapper.exists());
+    assert.lengthOf(wrapper.find(".ds-onboarding"), 1);
+  });
+
+  it("should dismiss on dismiss click", () => {
+    wrapper.find(".ds-dismiss-button").simulate("click");
+
+    assert.calledWith(
+      dispatch,
+      ac.DiscoveryStreamUserEvent({
+        event: "BLOCK",
+        source: "POCKET_ONBOARDING",
+      })
+    );
+    assert.calledWith(
+      dispatch,
+      ac.SetPref("discoverystream.onboardingExperience.dismissed", true)
+    );
+    assert.equal(wrapper.getDOMNode().style["max-height"], "0px");
+    assert.equal(wrapper.getDOMNode().style.opacity, "0");
+  });
+
+  it("should update max-height on resize", () => {
+    sinon
+      .stub(wrapper.find(".ds-onboarding-ref").getDOMNode(), "offsetHeight")
+      .get(() => 123);
+    resizeCallback();
+    assert.equal(wrapper.getDOMNode().style["max-height"], "123px");
+  });
+
+  it("should fire intersection events", () => {
+    assert.calledWith(
+      dispatch,
+      ac.DiscoveryStreamUserEvent({
+        event: "IMPRESSION",
+        source: "POCKET_ONBOARDING",
+      })
+    );
+  });
+});
-- 
cgit v1.2.3

