DiscoveryStreamBase.test.jsx (7994B)
1 import { 2 _DiscoveryStreamBase as DiscoveryStreamBase, 3 isAllowedCSS, 4 } from "content-src/components/DiscoveryStreamBase/DiscoveryStreamBase"; 5 import { GlobalOverrider } from "test/unit/utils"; 6 import { CardGrid } from "content-src/components/DiscoveryStreamComponents/CardGrid/CardGrid"; 7 import { CollapsibleSection } from "content-src/components/CollapsibleSection/CollapsibleSection"; 8 import { DSMessage } from "content-src/components/DiscoveryStreamComponents/DSMessage/DSMessage"; 9 import { HorizontalRule } from "content-src/components/DiscoveryStreamComponents/HorizontalRule/HorizontalRule"; 10 import { Navigation } from "content-src/components/DiscoveryStreamComponents/Navigation/Navigation"; 11 import React from "react"; 12 import { shallow } from "enzyme"; 13 import { SectionTitle } from "content-src/components/DiscoveryStreamComponents/SectionTitle/SectionTitle"; 14 import { TopSites } from "content-src/components/TopSites/TopSites"; 15 16 describe("<isAllowedCSS>", () => { 17 it("should allow colors", () => { 18 assert.isTrue(isAllowedCSS("color", "red")); 19 }); 20 21 it("should allow chrome urls", () => { 22 assert.isTrue( 23 isAllowedCSS( 24 "background-image", 25 `url("chrome://global/skin/icons/info.svg")` 26 ) 27 ); 28 }); 29 30 it("should allow chrome urls", () => { 31 assert.isTrue( 32 isAllowedCSS( 33 "background-image", 34 `url("chrome://browser/skin/history.svg")` 35 ) 36 ); 37 }); 38 39 it("should allow allowed https urls", () => { 40 assert.isTrue( 41 isAllowedCSS( 42 "background-image", 43 `url("https://img-getpocket.cdn.mozilla.net/media/image.png")` 44 ) 45 ); 46 }); 47 48 it("should disallow other https urls", () => { 49 assert.isFalse( 50 isAllowedCSS( 51 "background-image", 52 `url("https://mozilla.org/media/image.png")` 53 ) 54 ); 55 }); 56 57 it("should disallow other protocols", () => { 58 assert.isFalse( 59 isAllowedCSS( 60 "background-image", 61 `url("ftp://mozilla.org/media/image.png")` 62 ) 63 ); 64 }); 65 66 it("should allow allowed multiple valid urls", () => { 67 assert.isTrue( 68 isAllowedCSS( 69 "background-image", 70 `url("https://img-getpocket.cdn.mozilla.net/media/image.png"), url("chrome://browser/skin/history.svg")` 71 ) 72 ); 73 }); 74 75 it("should disallow if any invaild", () => { 76 assert.isFalse( 77 isAllowedCSS( 78 "background-image", 79 `url("chrome://browser/skin/history.svg"), url("ftp://mozilla.org/media/image.png")` 80 ) 81 ); 82 }); 83 }); 84 85 describe("<DiscoveryStreamBase>", () => { 86 let wrapper; 87 let globals; 88 let sandbox; 89 90 function mountComponent(props = {}) { 91 const defaultProps = { 92 config: { collapsible: true }, 93 layout: [], 94 feeds: { loaded: true }, 95 spocs: { 96 loaded: true, 97 data: { spocs: null }, 98 }, 99 ...props, 100 }; 101 return shallow( 102 <DiscoveryStreamBase 103 locale="en-US" 104 DiscoveryStream={defaultProps} 105 Prefs={{ 106 values: { 107 "feeds.section.topstories": true, 108 "feeds.system.topstories": true, 109 "feeds.topsites": true, 110 }, 111 }} 112 App={{ 113 locale: "en-US", 114 }} 115 document={{ 116 documentElement: { lang: "en-US" }, 117 }} 118 Sections={[ 119 { 120 id: "topstories", 121 learnMore: { link: {} }, 122 pref: {}, 123 }, 124 ]} 125 /> 126 ); 127 } 128 129 beforeEach(() => { 130 globals = new GlobalOverrider(); 131 sandbox = sinon.createSandbox(); 132 wrapper = mountComponent(); 133 }); 134 135 afterEach(() => { 136 sandbox.restore(); 137 globals.restore(); 138 }); 139 140 it("should render something if spocs are not loaded", () => { 141 wrapper = mountComponent({ 142 spocs: { loaded: false, data: { spocs: null } }, 143 }); 144 145 assert.notEqual(wrapper.type(), null); 146 }); 147 148 it("should render something if feeds are not loaded", () => { 149 wrapper = mountComponent({ feeds: { loaded: false } }); 150 151 assert.notEqual(wrapper.type(), null); 152 }); 153 154 it("should render nothing with no layout", () => { 155 assert.ok(wrapper.exists()); 156 assert.isEmpty(wrapper.children()); 157 }); 158 159 it("should render a HorizontalRule component", () => { 160 wrapper = mountComponent({ 161 layout: [{ components: [{ type: "HorizontalRule" }] }], 162 }); 163 164 assert.equal( 165 wrapper.find(".ds-column-grid div").children().at(0).type(), 166 HorizontalRule 167 ); 168 }); 169 170 it("should render a CardGrid component", () => { 171 wrapper = mountComponent({ 172 layout: [{ components: [{ properties: {}, type: "CardGrid" }] }], 173 }); 174 175 assert.equal( 176 wrapper.find(".ds-column-grid div").children().at(0).type(), 177 CardGrid 178 ); 179 }); 180 181 it("should render a Navigation component", () => { 182 wrapper = mountComponent({ 183 layout: [{ components: [{ properties: {}, type: "Navigation" }] }], 184 }); 185 186 assert.equal( 187 wrapper.find(".ds-column-grid div").children().at(0).type(), 188 Navigation 189 ); 190 }); 191 192 it("should render nothing if there was only a Message", () => { 193 wrapper = mountComponent({ 194 layout: [ 195 { components: [{ header: {}, properties: {}, type: "Message" }] }, 196 ], 197 }); 198 199 assert.isEmpty(wrapper.children()); 200 }); 201 202 it("should render a regular Message when not collapsible", () => { 203 wrapper = mountComponent({ 204 config: { collapsible: false }, 205 layout: [ 206 { components: [{ header: {}, properties: {}, type: "Message" }] }, 207 ], 208 }); 209 210 assert.equal( 211 wrapper.find(".ds-column-grid div").children().at(0).type(), 212 DSMessage 213 ); 214 }); 215 216 it("should convert first Message component to CollapsibleSection", () => { 217 wrapper = mountComponent({ 218 layout: [ 219 { 220 components: [ 221 { header: {}, properties: {}, type: "Message" }, 222 { type: "HorizontalRule" }, 223 ], 224 }, 225 ], 226 }); 227 228 assert.equal(wrapper.children().at(0).type(), CollapsibleSection); 229 assert.equal(wrapper.children().at(0).props().eventSource, "CARDGRID"); 230 }); 231 232 it("should render a Message component", () => { 233 wrapper = mountComponent({ 234 layout: [ 235 { 236 components: [ 237 { header: {}, type: "Message" }, 238 { properties: {}, type: "Message" }, 239 ], 240 }, 241 ], 242 }); 243 244 assert.equal( 245 wrapper.find(".ds-column-grid div").children().at(0).type(), 246 DSMessage 247 ); 248 }); 249 250 it("should render a SectionTitle component", () => { 251 wrapper = mountComponent({ 252 layout: [{ components: [{ properties: {}, type: "SectionTitle" }] }], 253 }); 254 255 assert.equal( 256 wrapper.find(".ds-column-grid div").children().at(0).type(), 257 SectionTitle 258 ); 259 }); 260 261 it("should render TopSites", () => { 262 wrapper = mountComponent({ 263 layout: [{ components: [{ properties: {}, type: "TopSites" }] }], 264 }); 265 266 assert.equal( 267 wrapper 268 .find(".ds-column-grid div") 269 .find(".ds-top-sites") 270 .children() 271 .at(0) 272 .type(), 273 TopSites 274 ); 275 }); 276 277 describe("#onStyleMount", () => { 278 let parseStub; 279 280 beforeEach(() => { 281 parseStub = sandbox.stub(); 282 globals.set("JSON", { parse: parseStub }); 283 }); 284 285 afterEach(() => { 286 sandbox.restore(); 287 globals.restore(); 288 }); 289 290 it("should return if no style", () => { 291 assert.isUndefined(wrapper.instance().onStyleMount()); 292 assert.notCalled(parseStub); 293 }); 294 295 it("should insert rules", () => { 296 const sheetStub = { insertRule: sandbox.stub(), cssRules: [{}] }; 297 parseStub.returns([ 298 [ 299 null, 300 { 301 ".ds-message": "margin-bottom: -20px", 302 }, 303 null, 304 null, 305 ], 306 ]); 307 wrapper.instance().onStyleMount({ sheet: sheetStub, dataset: {} }); 308 309 assert.calledOnce(sheetStub.insertRule); 310 assert.calledWithExactly(sheetStub.insertRule, "DUMMY#CSS.SELECTOR {}"); 311 }); 312 }); 313 });