test_TopSitesFeed_frecencyRanking.js (8037B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 ChromeUtils.defineESModuleGetters(this, { 7 actionCreators: "resource://newtab/common/Actions.mjs", 8 actionTypes: "resource://newtab/common/Actions.mjs", 9 sinon: "resource://testing-common/Sinon.sys.mjs", 10 TopSitesFeed: "resource://newtab/lib/TopSitesFeed.sys.mjs", 11 }); 12 13 const PREF_SOV_ENABLED = "sov.enabled"; 14 const SHOW_SPONSORED_PREF = "showSponsoredTopSites"; 15 const ROWS_PREF = "topSitesRows"; 16 17 async function getTopSitesFeedForTest(sandbox, { frecent = [] } = {}) { 18 let feed = new TopSitesFeed(); 19 20 feed.store = { 21 getState() { 22 return this.state; 23 }, 24 state: { 25 Prefs: { 26 values: { 27 [PREF_SOV_ENABLED]: true, 28 [SHOW_SPONSORED_PREF]: true, 29 [ROWS_PREF]: 1, 30 }, 31 }, 32 }, 33 }; 34 35 feed.frecentCache = { 36 request() { 37 return this.cache; 38 }, 39 cache: frecent, 40 }; 41 feed.frecencyBoostProvider.frecentCache = feed.frecentCache; 42 43 const frecencyBoostedSponsors = new Map([ 44 [ 45 "domain1", 46 { 47 domain: "https://domain1.com", 48 faviconDataURI: "faviconDataURI1", 49 hostname: "domain1", 50 redirectURL: "https://redirectURL1.com", 51 title: "title1", 52 }, 53 ], 54 [ 55 "domain2", 56 { 57 domain: "https://domain2.com", 58 faviconDataURI: "faviconDataURI2", 59 hostname: "domain2", 60 redirectURL: "https://redirectURL2.com", 61 title: "title2", 62 }, 63 ], 64 [ 65 "domain3", 66 { 67 domain: "https://domain3.com", 68 faviconDataURI: "faviconDataURI3", 69 hostname: "domain3", 70 redirectURL: "https://redirectURL3.com", 71 title: "title3", 72 }, 73 ], 74 [ 75 "domain4", 76 { 77 domain: "https://domain4.com", 78 faviconDataURI: "faviconDataURI4", 79 hostname: "domain4", 80 redirectURL: "https://redirectURL4.com", 81 title: "title4", 82 }, 83 ], 84 [ 85 "sub.domain1", 86 { 87 domain: "https://sub.domain1.com", 88 faviconDataURI: "faviconDataURI1", 89 hostname: "sub.domain1", 90 redirectURL: "https://redirectURL1.com", 91 title: "title1", 92 }, 93 ], 94 ]); 95 96 sandbox 97 .stub(feed.frecencyBoostProvider, "_frecencyBoostedSponsors") 98 .value(frecencyBoostedSponsors); 99 100 // Kick off an update so the cache is populated. 101 await feed.frecencyBoostProvider.update(); 102 103 return feed; 104 } 105 106 // eslint-disable-next-line max-statements 107 add_task(async function test_frecency_sponsored_topsites() { 108 let sandbox = sinon.createSandbox(); 109 { 110 info( 111 "TopSitesFeed.fetchFrecencyBoostedSpocs - " + 112 "Should return random fallback tile with no history" 113 ); 114 const feed = await getTopSitesFeedForTest(sandbox); 115 116 const frecencyBoostedSpocs = await feed.fetchFrecencyBoostedSpocs(); 117 Assert.equal(frecencyBoostedSpocs.length, 1); 118 Assert.equal(frecencyBoostedSpocs[0].type, "frecency-boost-random"); 119 120 sandbox.restore(); 121 } 122 { 123 info( 124 "TopSitesFeed.fetchFrecencyBoostedSpocs - " + 125 "Should return a single match with the right format" 126 ); 127 const feed = await getTopSitesFeedForTest(sandbox, { 128 frecent: [ 129 { 130 url: "https://domain1.com", 131 frecency: 1234, 132 }, 133 ], 134 }); 135 136 const frecencyBoostedSpocs = await feed.fetchFrecencyBoostedSpocs(); 137 Assert.equal(frecencyBoostedSpocs.length, 1); 138 Assert.deepEqual(frecencyBoostedSpocs[0], { 139 hostname: "domain1", 140 url: "https://redirectURL1.com", 141 label: "title1", 142 partner: "frec-boost", 143 type: "frecency-boost", 144 frecency: 1234, 145 show_sponsored_label: true, 146 favicon: "faviconDataURI1", 147 faviconSize: 96, 148 }); 149 150 sandbox.restore(); 151 } 152 { 153 info( 154 "TopSitesFeed.fetchFrecencyBoostedSpocs - " + 155 "Should return multiple matches" 156 ); 157 const feed = await getTopSitesFeedForTest(sandbox, { 158 frecent: [ 159 { 160 url: "https://domain1.com", 161 frecency: 1234, 162 }, 163 { 164 url: "https://domain3.com", 165 frecency: 1234, 166 }, 167 ], 168 }); 169 170 const frecencyBoostedSpocs = await feed.fetchFrecencyBoostedSpocs(); 171 Assert.equal(frecencyBoostedSpocs.length, 2); 172 Assert.equal(frecencyBoostedSpocs[0].hostname, "domain1"); 173 Assert.equal(frecencyBoostedSpocs[1].hostname, "domain3"); 174 175 sandbox.restore(); 176 } 177 { 178 info( 179 "TopSitesFeed.fetchFrecencyBoostedSpocs - " + 180 "Should return a single match with partial url" 181 ); 182 const feed = await getTopSitesFeedForTest(sandbox, { 183 frecent: [ 184 { 185 url: "https://domain1.com/path", 186 frecency: 1234, 187 }, 188 ], 189 }); 190 191 const frecencyBoostedSpocs = await feed.fetchFrecencyBoostedSpocs(); 192 Assert.equal(frecencyBoostedSpocs.length, 1); 193 Assert.equal(frecencyBoostedSpocs[0].hostname, "domain1"); 194 Assert.equal(frecencyBoostedSpocs[0].type, "frecency-boost"); 195 196 sandbox.restore(); 197 } 198 { 199 info( 200 "TopSitesFeed.fetchFrecencyBoostedSpocs - " + 201 "Should return a single match with a subdomain" 202 ); 203 const feed = await getTopSitesFeedForTest(sandbox, { 204 frecent: [ 205 { 206 url: "https://www.domain1.com", 207 frecency: 1234, 208 }, 209 ], 210 }); 211 212 const frecencyBoostedSpocs = await feed.fetchFrecencyBoostedSpocs(); 213 Assert.equal(frecencyBoostedSpocs.length, 1); 214 Assert.equal(frecencyBoostedSpocs[0].hostname, "domain1"); 215 Assert.equal(frecencyBoostedSpocs[0].type, "frecency-boost"); 216 217 sandbox.restore(); 218 } 219 { 220 info( 221 "TopSitesFeed.fetchFrecencyBoostedSpocs - " + 222 "Should not return a match with a different subdomain (returns random fallback)" 223 ); 224 const feed = await getTopSitesFeedForTest(sandbox, { 225 frecent: [ 226 { 227 url: "https://bus.domain1.com", 228 frecency: 1234, 229 }, 230 ], 231 }); 232 233 const frecencyBoostedSpocs = await feed.fetchFrecencyBoostedSpocs(); 234 Assert.equal(frecencyBoostedSpocs.length, 1); 235 Assert.equal(frecencyBoostedSpocs[0].type, "frecency-boost-random"); 236 237 sandbox.restore(); 238 } 239 { 240 info( 241 "TopSitesFeed.fetchFrecencyBoostedSpocs - " + 242 "Should return a match with the same subdomain" 243 ); 244 const feed = await getTopSitesFeedForTest(sandbox, { 245 frecent: [ 246 { 247 url: "https://sub.domain1.com", 248 frecency: 1234, 249 }, 250 ], 251 }); 252 253 const frecencyBoostedSpocs = await feed.fetchFrecencyBoostedSpocs(); 254 Assert.equal(frecencyBoostedSpocs.length, 1); 255 Assert.equal(frecencyBoostedSpocs[0].hostname, "sub.domain1"); 256 Assert.equal(frecencyBoostedSpocs[0].type, "frecency-boost"); 257 258 sandbox.restore(); 259 } 260 { 261 info( 262 "TopSitesFeed.fetchFrecencyBoostedSpocs - " + 263 "Should not match a partial domain (returns random fallback)" 264 ); 265 const feed = await getTopSitesFeedForTest(sandbox, { 266 frecent: [ 267 { 268 url: "https://domain12.com", 269 frecency: 1234, 270 }, 271 ], 272 }); 273 274 const frecencyBoostedSpocs = await feed.fetchFrecencyBoostedSpocs(); 275 Assert.equal(frecencyBoostedSpocs.length, 1); 276 Assert.equal(frecencyBoostedSpocs[0].type, "frecency-boost-random"); 277 278 sandbox.restore(); 279 } 280 { 281 info( 282 "TopSitesFeed.fetchFrecencyBoostedSpocs - " + 283 "Control group always returns random tile (ignores frecency matches)" 284 ); 285 const feed = await getTopSitesFeedForTest(sandbox, { 286 frecent: [ 287 { 288 url: "https://domain1.com", 289 frecency: 1234, 290 }, 291 ], 292 }); 293 294 feed.store.state.Prefs.values.trainhopConfig = { 295 sov: { 296 random_sponsor: true, 297 }, 298 }; 299 300 const frecencyBoostedSpocs = await feed.fetchFrecencyBoostedSpocs(); 301 Assert.equal(frecencyBoostedSpocs.length, 1); 302 Assert.equal(frecencyBoostedSpocs[0].type, "frecency-boost-random"); 303 304 sandbox.restore(); 305 } 306 });