tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_AboutNewTabComponentRegistry.js (8563B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 * http://creativecommons.org/publicdomain/zero/1.0/
      3 */
      4 
      5 "use strict";
      6 
      7 const { TestUtils } = ChromeUtils.importESModule(
      8  "resource://testing-common/TestUtils.sys.mjs"
      9 );
     10 
     11 const { AboutNewTabComponentRegistry } = ChromeUtils.importESModule(
     12  "moz-src:///browser/components/newtab/AboutNewTabComponents.sys.mjs"
     13 );
     14 
     15 const CATEGORY_NAME = "browser-newtab-external-component";
     16 
     17 const originalCategoryEntries = [];
     18 
     19 add_setup(() => {
     20  for (let { entry, value } of Services.catMan.enumerateCategory(
     21    CATEGORY_NAME
     22  )) {
     23    originalCategoryEntries.push({ entry, value });
     24  }
     25  Services.catMan.deleteCategory(CATEGORY_NAME);
     26 
     27  registerCleanupFunction(() => {
     28    Services.catMan.deleteCategory(CATEGORY_NAME);
     29 
     30    for (let { entry, value } of originalCategoryEntries) {
     31      Services.catMan.addCategoryEntry(
     32        CATEGORY_NAME,
     33        entry,
     34        value,
     35        false,
     36        true
     37      );
     38    }
     39  });
     40 });
     41 
     42 /**
     43 * Tests that the AboutNewTabComponentRegistry can be instantiated.
     44 */
     45 add_task(async function test_registry_initializes() {
     46  let registry = new AboutNewTabComponentRegistry();
     47  Assert.ok(registry, "Registry should instantiate");
     48  registry.destroy();
     49 });
     50 
     51 /**
     52 * Tests that the registry loads component configurations from category entries
     53 * and fires an UPDATED_EVENT when components are registered.
     54 */
     55 add_task(async function test_registry_loads_valid_configuration() {
     56  let updateEventFired = false;
     57  let registry = new AboutNewTabComponentRegistry();
     58 
     59  registry.on(AboutNewTabComponentRegistry.UPDATED_EVENT, () => {
     60    updateEventFired = true;
     61  });
     62 
     63  const testModuleURI = "resource://testing-common/TestRegistrant1.sys.mjs";
     64 
     65  Services.catMan.addCategoryEntry(
     66    CATEGORY_NAME,
     67    testModuleURI,
     68    "TestRegistrant1",
     69    false,
     70    true
     71  );
     72 
     73  await TestUtils.waitForCondition(
     74    () => updateEventFired,
     75    "Should fire updated event"
     76  );
     77 
     78  let components = Array.from(registry.values);
     79  Assert.equal(components.length, 1, "Should have one component registered");
     80  Assert.equal(components[0].type, "SEARCH", "Component type should be SEARCH");
     81 
     82  Services.catMan.deleteCategoryEntry(CATEGORY_NAME, testModuleURI, false);
     83  registry.destroy();
     84 });
     85 
     86 /**
     87 * Tests that the registry rejects duplicate component types and only
     88 * registers the first component when multiple registrants provide
     89 * components with the same type.
     90 */
     91 add_task(async function test_registry_rejects_duplicate_types() {
     92  let registry = new AboutNewTabComponentRegistry();
     93 
     94  const testModuleURI =
     95    "resource://testing-common/TestRegistrantDuplicateTypes.sys.mjs";
     96 
     97  Services.catMan.addCategoryEntry(
     98    CATEGORY_NAME,
     99    testModuleURI,
    100    "TestRegistrantDuplicateTypes",
    101    false,
    102    true
    103  );
    104 
    105  await TestUtils.waitForTick();
    106 
    107  let components = Array.from(registry.values);
    108  Assert.equal(
    109    components.length,
    110    1,
    111    "Should only register one component when types conflict"
    112  );
    113 
    114  Services.catMan.deleteCategoryEntry(CATEGORY_NAME, testModuleURI, false);
    115  registry.destroy();
    116 });
    117 
    118 /**
    119 * Tests that the registry rejects component configurations that are missing
    120 * required fields like the type property.
    121 */
    122 add_task(async function test_registry_rejects_invalid_configurations() {
    123  let registry = new AboutNewTabComponentRegistry();
    124 
    125  const testModuleURI =
    126    "resource://testing-common/TestRegistrantInvalidConfigs.sys.mjs";
    127 
    128  Services.catMan.addCategoryEntry(
    129    CATEGORY_NAME,
    130    testModuleURI,
    131    "TestRegistrantInvalidConfigs",
    132    false,
    133    true
    134  );
    135 
    136  await TestUtils.waitForTick();
    137 
    138  let components = Array.from(registry.values);
    139  Assert.equal(
    140    components.length,
    141    0,
    142    "Should reject configurations without valid type"
    143  );
    144 
    145  Services.catMan.deleteCategoryEntry(CATEGORY_NAME, testModuleURI, false);
    146  registry.destroy();
    147 });
    148 
    149 /**
    150 * Tests that the registry properly handles category entry removal by
    151 * unregistering components and firing an UPDATED_EVENT.
    152 */
    153 add_task(async function test_registry_handles_category_removal() {
    154  let updateCount = 0;
    155  let registry = new AboutNewTabComponentRegistry();
    156 
    157  registry.on(AboutNewTabComponentRegistry.UPDATED_EVENT, () => {
    158    updateCount++;
    159  });
    160 
    161  const testModuleURI = "resource://testing-common/TestRegistrant1.sys.mjs";
    162 
    163  Services.catMan.addCategoryEntry(
    164    CATEGORY_NAME,
    165    testModuleURI,
    166    "TestRegistrant1",
    167    false,
    168    true
    169  );
    170 
    171  await TestUtils.waitForCondition(() => updateCount >= 1);
    172 
    173  const initialUpdateCount = updateCount;
    174  let components = Array.from(registry.values);
    175  Assert.equal(components.length, 1, "Should have component registered");
    176 
    177  Services.catMan.deleteCategoryEntry(CATEGORY_NAME, testModuleURI, false);
    178 
    179  await TestUtils.waitForCondition(() => updateCount > initialUpdateCount);
    180 
    181  components = Array.from(registry.values);
    182  Assert.equal(components.length, 0, "Should have no components after removal");
    183 
    184  registry.destroy();
    185 });
    186 
    187 /**
    188 * Tests that the registry responds to registrant updates by refreshing
    189 * its component list and firing update events.
    190 */
    191 add_task(async function test_registry_handles_registrant_updates() {
    192  let registry = new AboutNewTabComponentRegistry();
    193  let updateCount = 0;
    194 
    195  registry.on(AboutNewTabComponentRegistry.UPDATED_EVENT, () => {
    196    updateCount++;
    197  });
    198 
    199  const testModuleURI = "resource://testing-common/TestRegistrant1.sys.mjs";
    200 
    201  Services.catMan.addCategoryEntry(
    202    CATEGORY_NAME,
    203    testModuleURI,
    204    "TestRegistrant1",
    205    false,
    206    true
    207  );
    208 
    209  await TestUtils.waitForCondition(() => updateCount >= 1);
    210 
    211  let components = Array.from(registry.values);
    212  Assert.equal(components.length, 1, "Should have initial component");
    213  Assert.equal(components[0].type, "SEARCH", "Initial type should be SEARCH");
    214 
    215  Services.catMan.deleteCategoryEntry(CATEGORY_NAME, testModuleURI, false);
    216  registry.destroy();
    217 });
    218 
    219 /**
    220 * Tests that calling destroy() on the registry properly cleans up all
    221 * registered components and internal state.
    222 */
    223 add_task(async function test_registry_cleanup_on_destroy() {
    224  let registry = new AboutNewTabComponentRegistry();
    225 
    226  const testModuleURI = "resource://testing-common/TestRegistrant1.sys.mjs";
    227 
    228  Services.catMan.addCategoryEntry(
    229    CATEGORY_NAME,
    230    testModuleURI,
    231    "TestRegistrant1",
    232    false,
    233    true
    234  );
    235 
    236  await TestUtils.waitForTick();
    237 
    238  registry.destroy();
    239 
    240  let components = Array.from(registry.values);
    241  Assert.equal(components.length, 0, "Should have no components after destroy");
    242 
    243  Services.catMan.deleteCategoryEntry(CATEGORY_NAME, testModuleURI, false);
    244 });
    245 
    246 /**
    247 * Tests that the registry validates registrants are instances of
    248 * BaseAboutNewTabComponentRegistrant and rejects invalid registrants.
    249 */
    250 add_task(async function test_registrant_subclass_validation() {
    251  let registry = new AboutNewTabComponentRegistry();
    252 
    253  const invalidModuleURI = "resource://testing-common/NotARegistrant.sys.mjs";
    254 
    255  Services.catMan.addCategoryEntry(
    256    CATEGORY_NAME,
    257    invalidModuleURI,
    258    "NotARegistrant",
    259    false,
    260    true
    261  );
    262 
    263  await TestUtils.waitForTick();
    264 
    265  let components = Array.from(registry.values);
    266  Assert.equal(
    267    components.length,
    268    0,
    269    "Should reject registrant that doesn't subclass BaseAboutNewTabComponentRegistrant"
    270  );
    271 
    272  Services.catMan.deleteCategoryEntry(CATEGORY_NAME, invalidModuleURI, false);
    273  registry.destroy();
    274 });
    275 
    276 /**
    277 * Tests that the registry can handle multiple registrants providing
    278 * different component types simultaneously.
    279 */
    280 add_task(async function test_multiple_registrants() {
    281  let registry = new AboutNewTabComponentRegistry();
    282 
    283  const testModule1URI = "resource://testing-common/TestRegistrant1.sys.mjs";
    284  const testModule2URI = "resource://testing-common/TestRegistrant2.sys.mjs";
    285 
    286  Services.catMan.addCategoryEntry(
    287    CATEGORY_NAME,
    288    testModule1URI,
    289    "TestRegistrant1",
    290    false,
    291    true
    292  );
    293 
    294  Services.catMan.addCategoryEntry(
    295    CATEGORY_NAME,
    296    testModule2URI,
    297    "TestRegistrant2",
    298    false,
    299    true
    300  );
    301 
    302  await TestUtils.waitForTick();
    303 
    304  let components = Array.from(registry.values);
    305  Assert.equal(
    306    components.length,
    307    2,
    308    "Should register components from multiple registrants"
    309  );
    310 
    311  let types = components.map(c => c.type).sort();
    312  Assert.deepEqual(
    313    types,
    314    ["OTHER", "SEARCH"],
    315    "Should have both component types"
    316  );
    317 
    318  Services.catMan.deleteCategoryEntry(CATEGORY_NAME, testModule1URI, false);
    319  Services.catMan.deleteCategoryEntry(CATEGORY_NAME, testModule2URI, false);
    320  registry.destroy();
    321 });