test_MemoriesHistoryScheduler.js (4778B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 do_get_profile(); 6 ("use strict"); 7 8 const { sinon } = ChromeUtils.importESModule( 9 "resource://testing-common/Sinon.sys.mjs" 10 ); 11 const { MemoriesHistoryScheduler } = ChromeUtils.importESModule( 12 "moz-src:///browser/components/aiwindow/models/memories/MemoriesHistoryScheduler.sys.mjs" 13 ); 14 const { MemoriesDriftDetector } = ChromeUtils.importESModule( 15 "moz-src:///browser/components/aiwindow/models/memories/MemoriesDriftDetector.sys.mjs" 16 ); 17 const { MemoriesManager } = ChromeUtils.importESModule( 18 "moz-src:///browser/components/aiwindow/models/memories/MemoriesManager.sys.mjs" 19 ); 20 21 const { PREF_GENERATE_MEMORIES } = ChromeUtils.importESModule( 22 "moz-src:///browser/components/aiwindow/models/memories/MemoriesConstants.sys.mjs" 23 ); 24 25 // insert N visits so the scheduler crosses its page threshold. 26 async function addTestVisits(count) { 27 let seeded = []; 28 let base = Date.now(); 29 for (let i = 0; i < count; i++) { 30 seeded.push({ 31 url: `https://example${i}.com/`, 32 title: `Example ${i}`, 33 visits: [{ date: new Date(base - i * 1000) }], 34 }); 35 } 36 await PlacesUtils.history.insertMany(seeded); 37 } 38 39 registerCleanupFunction(async () => { 40 Services.prefs.clearUserPref(PREF_GENERATE_MEMORIES); 41 await PlacesUtils.history.clear(); 42 }); 43 44 // Drift triggers => memories run 45 add_task(async function test_scheduler_runs_when_drift_triggers() { 46 Services.prefs.setBoolPref(PREF_GENERATE_MEMORIES, true); 47 48 const generateStub = sinon 49 .stub(MemoriesManager, "generateMemoriesFromBrowsingHistory") 50 .resolves(); 51 52 const driftStub = sinon 53 .stub(MemoriesDriftDetector, "computeHistoryDriftAndTrigger") 54 .resolves({ 55 baselineMetrics: [{ sessionId: 1, jsScore: 0.1, avgSurprisal: 1.0 }], 56 deltaMetrics: [{ sessionId: 2, jsScore: 0.9, avgSurprisal: 3.0 }], 57 trigger: { 58 jsThreshold: 0.5, 59 surpriseThreshold: 2.0, 60 triggered: true, 61 triggeredSessionIds: [2], 62 }, 63 }); 64 65 try { 66 let scheduler = MemoriesHistoryScheduler.maybeInit(); 67 68 // Force pagesVisited above threshold for the test. 69 scheduler.setPagesVisitedForTesting(100); 70 71 // Run the interval logic once. 72 await scheduler.runNowForTesting(); 73 74 sinon.assert.calledOnce(generateStub); 75 } finally { 76 generateStub.restore(); 77 driftStub.restore(); 78 } 79 }); 80 81 // Drift does NOT trigger => memories skipped 82 add_task(async function test_scheduler_skips_when_drift_not_triggered() { 83 Services.prefs.setBoolPref(PREF_GENERATE_MEMORIES, true); 84 85 const generateStub = sinon 86 .stub(MemoriesManager, "generateMemoriesFromBrowsingHistory") 87 .resolves(); 88 89 const driftStub = sinon 90 .stub(MemoriesDriftDetector, "computeHistoryDriftAndTrigger") 91 .resolves({ 92 baselineMetrics: [{ sessionId: 1, jsScore: 0.1, avgSurprisal: 1.0 }], 93 deltaMetrics: [{ sessionId: 2, jsScore: 0.2, avgSurprisal: 1.2 }], 94 trigger: { 95 jsThreshold: 0.5, 96 surpriseThreshold: 2.0, 97 triggered: false, 98 triggeredSessionIds: [], 99 }, 100 }); 101 102 try { 103 let scheduler = MemoriesHistoryScheduler.maybeInit(); 104 await addTestVisits(60); 105 await scheduler.runNowForTesting(); 106 sinon.assert.notCalled(generateStub); 107 } finally { 108 generateStub.restore(); 109 driftStub.restore(); 110 } 111 }); 112 113 // First run (no previous memories) => memories run even with small history. 114 add_task(async function test_scheduler_runs_on_first_run_with_small_history() { 115 Services.prefs.setBoolPref(PREF_GENERATE_MEMORIES, true); 116 117 const generateStub = sinon 118 .stub(MemoriesManager, "generateMemoriesFromBrowsingHistory") 119 .resolves(); 120 121 const driftStub = sinon 122 .stub(MemoriesDriftDetector, "computeHistoryDriftAndTrigger") 123 .resolves({ 124 baselineMetrics: [], 125 deltaMetrics: [], 126 trigger: { 127 jsThreshold: 0, 128 surpriseThreshold: 0, 129 triggered: false, 130 triggeredSessionIds: [], 131 }, 132 }); 133 134 const lastTsStub = sinon 135 .stub(MemoriesManager, "getLastHistoryMemoryTimestamp") 136 .resolves(0); 137 138 try { 139 let scheduler = MemoriesHistoryScheduler.maybeInit(); 140 Assert.ok(scheduler, "Scheduler should be initialized when pref is true"); 141 142 // Set a number of pages that is: 143 // - below the normal threshold (25), but 144 // - high enough for the special first-run threshold (e.g. 15). 145 scheduler.setPagesVisitedForTesting(20); 146 147 // Run the interval logic once. 148 await scheduler.runNowForTesting(); 149 sinon.assert.calledOnce(generateStub); 150 } finally { 151 generateStub.restore(); 152 driftStub.restore(); 153 lastTsStub.restore(); 154 } 155 });