summaryrefslogtreecommitdiffstats
path: root/toolkit/components/contentrelevancy/tests/xpcshell/test_ContentRelevancyManager.js
blob: 633f9fc49b350b7418b7bc74c507e0eb014b819c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/* Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/ */

"use strict";

ChromeUtils.defineESModuleGetters(this, {
  ContentRelevancyManager:
    "resource://gre/modules/ContentRelevancyManager.sys.mjs",
  TestUtils: "resource://testing-common/TestUtils.sys.mjs",
  setTimeout: "resource://gre/modules/Timer.sys.mjs",
  sinon: "resource://testing-common/Sinon.sys.mjs",
});

const PREF_CONTENT_RELEVANCY_ENABLED = "toolkit.contentRelevancy.enabled";
const PREF_TIMER_INTERVAL = "toolkit.contentRelevancy.timerInterval";

// These consts are copied from the update timer manager test. See
// `initUpdateTimerManager()`.
const PREF_APP_UPDATE_TIMERMINIMUMDELAY = "app.update.timerMinimumDelay";
const PREF_APP_UPDATE_TIMERFIRSTINTERVAL = "app.update.timerFirstInterval";
const MAIN_TIMER_INTERVAL = 1000; // milliseconds
const CATEGORY_UPDATE_TIMER = "update-timer";

let gSandbox;

add_setup(async () => {
  gSandbox = sinon.createSandbox();
  initUpdateTimerManager();
  Services.prefs.setBoolPref(PREF_CONTENT_RELEVANCY_ENABLED, true);
  await ContentRelevancyManager.init();

  registerCleanupFunction(() => {
    Services.prefs.clearUserPref(PREF_CONTENT_RELEVANCY_ENABLED);
    gSandbox.restore();
  });
});

add_task(async function test_init() {
  Assert.ok(ContentRelevancyManager.initialized, "Init should succeed");
});

add_task(async function test_uninit() {
  ContentRelevancyManager.uninit();

  Assert.ok(!ContentRelevancyManager.initialized, "Uninit should succeed");
});

add_task(async function test_timer() {
  // Set the timer interval to 0 will trigger the timer right away.
  Services.prefs.setIntPref(PREF_TIMER_INTERVAL, 0);
  gSandbox.spy(ContentRelevancyManager, "notify");

  await ContentRelevancyManager.init();

  await TestUtils.waitForCondition(
    () => ContentRelevancyManager.notify.called,
    "The timer callback should be called"
  );

  Services.prefs.clearUserPref(PREF_TIMER_INTERVAL);
  gSandbox.restore();
});

add_task(async function test_feature_toggling() {
  Services.prefs.setBoolPref(PREF_CONTENT_RELEVANCY_ENABLED, false);
  // Set the timer interval to 0 will trigger the timer right away.
  Services.prefs.setIntPref(PREF_TIMER_INTERVAL, 0);
  gSandbox.spy(ContentRelevancyManager, "notify");

  // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
  await new Promise(resolve => setTimeout(resolve, 1100));
  Assert.ok(
    ContentRelevancyManager.notify.notCalled,
    "Timer should not be registered if disabled"
  );

  // Toggle the pref again should re-enable the feature.
  Services.prefs.setBoolPref(PREF_CONTENT_RELEVANCY_ENABLED, true);
  await TestUtils.waitForTick();

  await TestUtils.waitForCondition(
    () => ContentRelevancyManager.notify.called,
    "The timer callback should be called"
  );

  Services.prefs.clearUserPref(PREF_CONTENT_RELEVANCY_ENABLED);
  Services.prefs.clearUserPref(PREF_TIMER_INTERVAL);
  gSandbox.restore();
});

add_task(async function test_call_disable_twice() {
  Services.prefs.setBoolPref(PREF_CONTENT_RELEVANCY_ENABLED, false);
  await TestUtils.waitForTick();

  Services.prefs.setBoolPref(PREF_CONTENT_RELEVANCY_ENABLED, false);
  await TestUtils.waitForTick();

  Assert.ok(true, "`#disable` should be safe to call multiple times");

  Services.prefs.clearUserPref(PREF_CONTENT_RELEVANCY_ENABLED);
});

add_task(async function test_doClassification() {
  Services.prefs.setBoolPref(PREF_CONTENT_RELEVANCY_ENABLED, true);
  await TestUtils.waitForCondition(() => ContentRelevancyManager._isStoreReady);
  await ContentRelevancyManager._test_doClassification([]);

  // Disable it to reset the store.
  Services.prefs.setBoolPref(PREF_CONTENT_RELEVANCY_ENABLED, false);
  await TestUtils.waitForTick();

  await Assert.rejects(
    ContentRelevancyManager._test_doClassification([]),
    /Store is not available/,
    "Should throw with an unset store"
  );

  Services.prefs.clearUserPref(PREF_CONTENT_RELEVANCY_ENABLED);
});

/**
 * Sets up the update timer manager for testing: makes it fire more often,
 * removes all existing timers, and initializes it for testing. The body of this
 * function is copied from:
 * https://searchfox.org/mozilla-central/source/toolkit/components/timermanager/tests/unit/consumerNotifications.js
 */
function initUpdateTimerManager() {
  // Set the timer to fire every second
  Services.prefs.setIntPref(
    PREF_APP_UPDATE_TIMERMINIMUMDELAY,
    MAIN_TIMER_INTERVAL / 1000
  );
  Services.prefs.setIntPref(
    PREF_APP_UPDATE_TIMERFIRSTINTERVAL,
    MAIN_TIMER_INTERVAL
  );

  // Remove existing update timers to prevent them from being notified
  for (let { data: entry } of Services.catMan.enumerateCategory(
    CATEGORY_UPDATE_TIMER
  )) {
    Services.catMan.deleteCategoryEntry(CATEGORY_UPDATE_TIMER, entry, false);
  }

  Cc["@mozilla.org/updates/timer-manager;1"]
    .getService(Ci.nsIUpdateTimerManager)
    .QueryInterface(Ci.nsIObserver)
    .observe(null, "utm-test-init", "");
}