tor-browser

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

test_tabs_to_process.js (6400B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 * http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 const { SmartTabGroupingManager } = ChromeUtils.importESModule(
      5  "moz-src:///browser/components/tabbrowser/SmartTabGrouping.sys.mjs"
      6 );
      7 
      8 // Simple helper to construct tab-like objects for tests.
      9 function makeTab(id, { pinned = false, hasURL = true } = {}) {
     10  return {
     11    id,
     12    label: `Tab ${id}`,
     13    pinned,
     14    linkedBrowser: hasURL
     15      ? { currentURI: { spec: `https://example.com/${id}` } }
     16      : null,
     17  };
     18 }
     19 
     20 add_task(
     21  function test_tabs_to_process_includes_group_first_and_respects_limit() {
     22    const manager = new SmartTabGroupingManager();
     23 
     24    const groupTab1 = makeTab("group-1");
     25    const groupTab2 = makeTab("group-2");
     26    const other1 = makeTab("other-1");
     27    const other2 = makeTab("other-2");
     28    const other3 = makeTab("other-3");
     29 
     30    const tabsInGroup = [groupTab1, groupTab2];
     31    const allTabs = [groupTab1, other1, groupTab2, other2, other3];
     32 
     33    // Limit 4: should be [group tabs] first, then fill with window tabs.
     34    let resultIds = manager
     35      .getTabsToProcess(tabsInGroup, allTabs, 4)
     36      .map(t => t.id);
     37 
     38    Assert.deepEqual(
     39      resultIds,
     40      ["group-1", "group-2", "other-1", "other-2"],
     41      "Group tabs should come first, then window tabs, up to the limit"
     42    );
     43 
     44    // Limit 2: should only include the group tabs.
     45    resultIds = manager
     46      .getTabsToProcess(tabsInGroup, allTabs, 2)
     47      .map(t => t.id);
     48 
     49    Assert.deepEqual(
     50      resultIds,
     51      ["group-1", "group-2"],
     52      "When limit equals number of group tabs, only group tabs are returned"
     53    );
     54  }
     55 );
     56 
     57 add_task(
     58  function test_tabs_to_process_limits_anchor_tabs_to_max_nn_grouped_tabs() {
     59    const manager = new SmartTabGroupingManager();
     60 
     61    // More than MAX_NN_GROUPED_TABS (4) tabs in the group.
     62    const groupTabs = [];
     63    for (let i = 0; i < 6; i++) {
     64      groupTabs.push(makeTab(`group-${i}`));
     65    }
     66    const extraTab = makeTab("other");
     67    const allTabs = [...groupTabs, extraTab];
     68 
     69    const resultIds = manager
     70      .getTabsToProcess(groupTabs, allTabs, 10)
     71      .map(t => t.id);
     72 
     73    Assert.deepEqual(
     74      resultIds,
     75      ["group-0", "group-1", "group-2", "other"],
     76      "Only the first MAX_NN_GROUPED_TABS group tabs should be kept, then window tabs"
     77    );
     78  }
     79 );
     80 
     81 add_task(function test_tabs_to_process_deduplicates_group_tabs_in_all_tabs() {
     82  const manager = new SmartTabGroupingManager();
     83 
     84  const groupTab1 = makeTab("group-1");
     85  const groupTab2 = makeTab("group-2");
     86  const other1 = makeTab("other-1");
     87 
     88  // group tabs also appear in allTabs
     89  const tabsInGroup = [groupTab1, groupTab2];
     90  const allTabs = [groupTab1, groupTab2, other1];
     91 
     92  const resultIds = manager
     93    .getTabsToProcess(tabsInGroup, allTabs, 10)
     94    .map(t => t.id);
     95 
     96  Assert.deepEqual(
     97    resultIds,
     98    ["group-1", "group-2", "other-1"],
     99    "Tabs already in the group should not be duplicated when iterating allTabs"
    100  );
    101 });
    102 
    103 add_task(function test_tabs_to_process_more_non_group_tabs_than_limit() {
    104  const manager = new SmartTabGroupingManager();
    105 
    106  const groupTab1 = makeTab("group-1");
    107  const groupTab2 = makeTab("group-2");
    108 
    109  const tabsInGroup = [groupTab1, groupTab2];
    110 
    111  // 10 non-group tabs
    112  const nonGroupTabs = [];
    113  for (let i = 0; i < 10; i++) {
    114    nonGroupTabs.push(makeTab(`other-${i}`));
    115  }
    116 
    117  const allTabs = [groupTab1, ...nonGroupTabs, groupTab2];
    118 
    119  // Limit 6 => 2 group tabs + first 4 non-group tabs (in allTabs order)
    120  const resultIds = manager
    121    .getTabsToProcess(tabsInGroup, allTabs, 6)
    122    .map(t => t.id);
    123 
    124  Assert.deepEqual(
    125    resultIds,
    126    ["group-1", "group-2", "other-0", "other-1", "other-2", "other-3"],
    127    "When there are more non-group tabs than the limit, only the first ones (by window order) are included after the group tabs"
    128  );
    129 });
    130 
    131 add_task(function test_tabs_to_process_with_no_group_tabs() {
    132  const manager = new SmartTabGroupingManager();
    133 
    134  const allTabs = [];
    135  for (let i = 0; i < 8; i++) {
    136    allTabs.push(makeTab(`tab-${i}`));
    137  }
    138 
    139  const tabsInGroup = [];
    140 
    141  const resultIds = manager
    142    .getTabsToProcess(tabsInGroup, allTabs, 5)
    143    .map(t => t.id);
    144 
    145  Assert.deepEqual(
    146    resultIds,
    147    ["tab-0", "tab-1", "tab-2", "tab-3", "tab-4"],
    148    "When there are no group tabs, we should just take up to the limit from window tabs"
    149  );
    150 });
    151 
    152 add_task(function test_tabs_to_process_uses_default_max_limit() {
    153  const manager = new SmartTabGroupingManager();
    154 
    155  // 350 non-group tabs, all valid
    156  const allTabs = [];
    157  for (let i = 0; i < 350; i++) {
    158    allTabs.push(makeTab(`tab-${i}`));
    159  }
    160 
    161  const tabsInGroup = [];
    162 
    163  // Use default max_limit_to_process (should be 100)
    164  const result = manager.getTabsToProcess(tabsInGroup, allTabs);
    165  const resultIds = result.map(t => t.id);
    166 
    167  Assert.equal(
    168    resultIds.length,
    169    300,
    170    "Default max limit should cap the number of processed tabs to 300"
    171  );
    172 
    173  Assert.deepEqual(
    174    resultIds.slice(0, 5),
    175    ["tab-0", "tab-1", "tab-2", "tab-3", "tab-4"],
    176    "Default behavior should preserve window order for the first tabs"
    177  );
    178 });
    179 
    180 add_task(function test_tabs_to_process_all_tabs_filtered_out() {
    181  const manager = new SmartTabGroupingManager();
    182 
    183  // All pinned
    184  const pinned1 = makeTab("pinned-1", { pinned: true });
    185  const pinned2 = makeTab("pinned-2", { pinned: true });
    186 
    187  // All missing URL
    188  const noUrl1 = makeTab("no-url-1", { hasURL: false });
    189  const noUrl2 = makeTab("no-url-2", { hasURL: false });
    190 
    191  const tabsInGroup = [pinned1];
    192  const allTabs = [pinned1, pinned2, noUrl1, noUrl2];
    193 
    194  const result = manager.getTabsToProcess(tabsInGroup, allTabs, 10);
    195 
    196  Assert.deepEqual(
    197    result,
    198    [],
    199    "If all tabs are filtered out (pinned or no URL), we should return an empty list"
    200  );
    201 });
    202 
    203 add_task(function test_tabs_to_process_group_tabs_not_in_allTabs() {
    204  const manager = new SmartTabGroupingManager();
    205 
    206  const externalGroupTab = makeTab("external-group"); // not in allTabs
    207  const other1 = makeTab("other-1");
    208  const other2 = makeTab("other-2");
    209 
    210  const tabsInGroup = [externalGroupTab];
    211  const allTabs = [other1, other2];
    212 
    213  const resultIds = manager
    214    .getTabsToProcess(tabsInGroup, allTabs, 3)
    215    .map(t => t.id);
    216 
    217  Assert.deepEqual(
    218    resultIds,
    219    ["external-group", "other-1", "other-2"],
    220    "Tabs in the group should still be included even if they don't appear in allTabs"
    221  );
    222 });