AdBanner.test.jsx (5790B)
1 import { mount } from "enzyme"; 2 import { INITIAL_STATE, reducers } from "common/Reducers.sys.mjs"; 3 import { AdBanner } from "content-src/components/DiscoveryStreamComponents/AdBanner/AdBanner"; 4 import { combineReducers, createStore } from "redux"; 5 import { Provider } from "react-redux"; 6 import { actionCreators as ac } from "common/Actions.mjs"; 7 import React from "react"; 8 9 const DEFAULT_PROPS = { 10 prefs: { 11 "discoverystream.sections.enabled": false, 12 }, 13 type: "foo", 14 firstVisibleTimestamp: new Date("March 21, 2024 10:11:12").getTime(), 15 row: 3, 16 spoc: { 17 format: "billboard", 18 id: "12345", 19 raw_image_src: "https://picsum.photos/200", 20 alt_text: "alt-text", 21 url: "https://example.com", 22 shim: { 23 url: "https://fallback.example.com", 24 }, 25 }, 26 }; 27 28 // Wrap this around any component that uses useSelector, 29 // or any mount that uses a child that uses redux. 30 function WrapWithProvider({ children, state = INITIAL_STATE }) { 31 let store = createStore(combineReducers(reducers), state); 32 return <Provider store={store}>{children}</Provider>; 33 } 34 35 describe("Discovery Stream <AdBanner>", () => { 36 let wrapper; 37 let sandbox; 38 let dispatch; 39 40 beforeEach(() => { 41 sandbox = sinon.createSandbox(); 42 dispatch = sandbox.stub(); 43 44 wrapper = mount( 45 <WrapWithProvider> 46 <AdBanner dispatch={dispatch} {...DEFAULT_PROPS} /> 47 </WrapWithProvider> 48 ); 49 }); 50 51 afterEach(() => { 52 sandbox.restore(); 53 }); 54 55 it("should render", () => { 56 assert.ok(wrapper.exists()); 57 assert.ok(wrapper.find(".ad-banner-wrapper").exists()); 58 }); 59 60 it("should have 'sponsored' text visible", () => { 61 assert.ok(wrapper.find(".ad-banner-sponsored").exists()); 62 assert.ok( 63 wrapper.find("[data-l10n-id='newtab-label-sponsored-fixed']").exists() 64 ); 65 }); 66 67 it("should load API image for the billboard banner with correct dimensions", () => { 68 const image = wrapper.find(".ad-banner-content img"); 69 assert.ok(image.exists()); 70 assert.equal(image.prop("src"), DEFAULT_PROPS.spoc.raw_image_src); 71 assert.equal(image.prop("width"), "970"); 72 assert.equal(image.prop("height"), "250"); 73 }); 74 75 it("should add alt text from spoc.alt_text property", () => { 76 const image = wrapper.find(".ad-banner-content img"); 77 assert.equal(image.prop("alt"), DEFAULT_PROPS.spoc.alt_text); 78 }); 79 80 it("should load API image for the leaderboard banner with correct dimensions", () => { 81 wrapper.setProps({ 82 children: ( 83 <AdBanner 84 dispatch={dispatch} 85 {...DEFAULT_PROPS} 86 spoc={{ ...DEFAULT_PROPS.spoc, format: "leaderboard" }} 87 /> 88 ), 89 }); 90 const image = wrapper.find(".ad-banner-content img"); 91 assert.ok(image.exists()); 92 assert.equal(image.prop("src"), DEFAULT_PROPS.spoc.raw_image_src); 93 assert.equal(image.prop("width"), "728"); 94 assert.equal(image.prop("height"), "90"); 95 }); 96 97 it("should set image dimensions to undefined if format is not specified", () => { 98 wrapper.setProps({ 99 children: ( 100 <AdBanner 101 dispatch={dispatch} 102 {...DEFAULT_PROPS} 103 spoc={{ ...DEFAULT_PROPS.spoc, format: undefined }} 104 /> 105 ), 106 }); 107 108 const image = wrapper.find(".ad-banner-content img"); 109 assert.ok(image.exists()); 110 assert.equal(image.prop("width"), undefined); 111 assert.equal(image.prop("height"), undefined); 112 }); 113 114 it("should pass row prop as `gridRow` to aside element", () => { 115 const aside = wrapper.find(".ad-banner-wrapper"); 116 const clampedRow = Math.max(1, Math.min(9, DEFAULT_PROPS.row)); 117 assert.deepEqual(aside.prop("style"), { gridRow: clampedRow }); 118 }); 119 120 it("should have the context menu button be visible", () => { 121 const dismiss = wrapper.find("moz-button"); 122 assert.ok(dismiss.exists()); 123 124 // The rest of the context menu functionality is now tested in 125 // AdBannerContextMenu.test.jsx 126 }); 127 128 it("should render data-is-sponsored-link='true' on banner link", () => { 129 const link = wrapper.find(".ad-banner-link a"); 130 assert.equal(link.prop("data-is-sponsored-link"), true); 131 }); 132 133 it("should call onLinkClick when banner is clicked", () => { 134 const link = wrapper.find(".ad-banner-link a"); 135 link.simulate("click"); 136 assert.calledThrice(dispatch); 137 const secondCall = dispatch.getCall(2); 138 assert.deepEqual( 139 secondCall.args[0], 140 ac.DiscoveryStreamUserEvent({ 141 event: "CLICK", 142 source: "FOO", 143 // Banner ads don't have a position, but a row number 144 action_position: DEFAULT_PROPS.row, 145 value: { 146 card_type: "spoc", 147 tile_id: DEFAULT_PROPS.spoc.id, 148 149 fetchTimestamp: DEFAULT_PROPS.spoc.fetchTimestamp, 150 firstVisibleTimestamp: DEFAULT_PROPS.firstVisibleTimestamp, 151 format: DEFAULT_PROPS.spoc.format, 152 }, 153 }) 154 ); 155 }); 156 157 it("should set proper ohttp src if ohttp, contextual, inferred, and sections are true", () => { 158 wrapper.setProps({ 159 children: ( 160 <AdBanner 161 dispatch={dispatch} 162 {...DEFAULT_PROPS} 163 prefs={{ 164 ...DEFAULT_PROPS.prefs, 165 "discoverystream.sections.enabled": true, 166 "unifiedAds.ohttp.enabled": true, 167 ohttpImagesConfig: { enabled: true }, 168 "discoverystream.sections.contextualAds.enabled": true, 169 "discoverystream.sections.personalization.inferred.user.enabled": true, 170 "discoverystream.sections.personalization.inferred.enabled": true, 171 }} 172 /> 173 ), 174 }); 175 176 const image = wrapper.find(".ad-banner-content img"); 177 assert.equal( 178 image.prop("src"), 179 `moz-cached-ohttp://newtab-image/?url=${encodeURIComponent(DEFAULT_PROPS.spoc.raw_image_src)}` 180 ); 181 }); 182 });