tor-browser

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

test_Tools_GetOpenTabs.js (8399B)


      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 const { getOpenTabs } = ChromeUtils.importESModule(
      6  "moz-src:///browser/components/aiwindow/models/Tools.sys.mjs"
      7 );
      8 
      9 const { sinon } = ChromeUtils.importESModule(
     10  "resource://testing-common/Sinon.sys.mjs"
     11 );
     12 
     13 function createFakeTab(url, title, lastAccessed) {
     14  return {
     15    linkedBrowser: {
     16      currentURI: {
     17        spec: url,
     18      },
     19    },
     20    label: title,
     21    lastAccessed,
     22  };
     23 }
     24 
     25 function createFakeWindow(tabs, closed = false, isAIWindow = true) {
     26  return {
     27    closed,
     28    gBrowser: {
     29      tabs,
     30    },
     31    document: {
     32      documentElement: {
     33        hasAttribute: attr => attr === "ai-window" && isAIWindow,
     34      },
     35    },
     36  };
     37 }
     38 
     39 function setupPageDataServiceMock(sandbox, descriptionMap = {}) {
     40  const PageDataService = ChromeUtils.importESModule(
     41    "moz-src:///browser/components/pagedata/PageDataService.sys.mjs"
     42  ).PageDataService;
     43 
     44  sandbox.stub(PageDataService, "getCached").callsFake(url => {
     45    if (url in descriptionMap) {
     46      return { description: descriptionMap[url] };
     47    }
     48    return null;
     49  });
     50 
     51  sandbox.stub(PageDataService, "fetchPageData").callsFake(async url => {
     52    if (url in descriptionMap) {
     53      return { description: descriptionMap[url] };
     54    }
     55    return null;
     56  });
     57 }
     58 
     59 add_task(async function test_getOpenTabs_basic() {
     60  const BrowserWindowTracker = ChromeUtils.importESModule(
     61    "resource:///modules/BrowserWindowTracker.sys.mjs"
     62  ).BrowserWindowTracker;
     63 
     64  const sb = sinon.createSandbox();
     65 
     66  try {
     67    const fakeWindow = createFakeWindow([
     68      createFakeTab("https://example.com", "Example", 1000),
     69      createFakeTab("https://mozilla.org", "Mozilla", 2000),
     70      createFakeTab("https://firefox.com", "Firefox", 3000),
     71    ]);
     72 
     73    sb.stub(BrowserWindowTracker, "orderedWindows").get(() => [fakeWindow]);
     74    setupPageDataServiceMock(sb, {
     75      "https://firefox.com": "Firefox browser homepage",
     76      "https://mozilla.org": "Mozilla organization site",
     77    });
     78 
     79    const tabs = await getOpenTabs();
     80 
     81    Assert.equal(tabs.length, 3, "Should return all 3 tabs");
     82    Assert.equal(tabs[0].url, "https://firefox.com", "Most recent tab first");
     83    Assert.equal(tabs[0].title, "Firefox", "Title should match");
     84    // @todo Bug2009194
     85    // Assert.equal(
     86    //   tabs[0].description,
     87    //   "Firefox browser homepage",
     88    //   "Description should be fetched"
     89    // );
     90    Assert.equal(tabs[1].url, "https://mozilla.org", "Second most recent tab");
     91    // @todo Bug2009194
     92    // Assert.equal(
     93    //   tabs[1].description,
     94    //   "Mozilla organization site",
     95    //   "Description should be fetched"
     96    // );
     97    Assert.equal(tabs[2].url, "https://example.com", "Least recent tab");
     98    Assert.equal(
     99      tabs[2].description,
    100      "",
    101      "Description should be empty when not available"
    102    );
    103  } finally {
    104    sb.restore();
    105  }
    106 });
    107 
    108 add_task(async function test_getOpenTabs_filters_about_urls() {
    109  const BrowserWindowTracker = ChromeUtils.importESModule(
    110    "resource:///modules/BrowserWindowTracker.sys.mjs"
    111  ).BrowserWindowTracker;
    112 
    113  const sb = sinon.createSandbox();
    114 
    115  try {
    116    const fakeWindow = createFakeWindow([
    117      createFakeTab("https://example.com", "Example", 1000),
    118      createFakeTab("about:preferences", "Preferences", 2000),
    119      createFakeTab("about:config", "Config", 3000),
    120      createFakeTab("https://mozilla.org", "Mozilla", 4000),
    121      createFakeTab("about:blank", "Blank", 5000),
    122    ]);
    123 
    124    sb.stub(BrowserWindowTracker, "orderedWindows").get(() => [fakeWindow]);
    125    setupPageDataServiceMock(sb);
    126 
    127    const tabs = await getOpenTabs();
    128 
    129    Assert.equal(
    130      tabs.length,
    131      2,
    132      "Should only return non-about: tabs (filtered 3)"
    133    );
    134    Assert.equal(
    135      tabs[0].url,
    136      "https://mozilla.org",
    137      "Should return mozilla.org"
    138    );
    139    Assert.equal(tabs[1].url, "https://example.com", "Should return example");
    140    Assert.ok(
    141      !tabs.some(t => t.url.startsWith("about:")),
    142      "No about: URLs in results"
    143    );
    144  } finally {
    145    sb.restore();
    146  }
    147 });
    148 
    149 add_task(async function test_getOpenTabs_pagination() {
    150  const BrowserWindowTracker = ChromeUtils.importESModule(
    151    "resource:///modules/BrowserWindowTracker.sys.mjs"
    152  ).BrowserWindowTracker;
    153 
    154  const sb = sinon.createSandbox();
    155 
    156  try {
    157    const tabs = [];
    158    for (let i = 0; i < 20; i++) {
    159      tabs.push(
    160        createFakeTab(`https://example${i}.com`, `Example ${i}`, i * 1000)
    161      );
    162    }
    163    const fakeWindow = createFakeWindow(tabs);
    164 
    165    sb.stub(BrowserWindowTracker, "orderedWindows").get(() => [fakeWindow]);
    166    setupPageDataServiceMock(sb);
    167 
    168    // Test default limit
    169    const defaultResult = await getOpenTabs();
    170    Assert.equal(defaultResult.length, 15, "Should default to 15 tabs");
    171    Assert.equal(
    172      defaultResult[0].url,
    173      "https://example19.com",
    174      "First tab should be most recent"
    175    );
    176 
    177    // Test custom limit
    178    const customResult = await getOpenTabs(10);
    179    Assert.equal(customResult.length, 10, "Should return at most 10 tabs");
    180    Assert.equal(
    181      customResult[9].url,
    182      "https://example10.com",
    183      "Last tab should be 10th most recent"
    184    );
    185  } finally {
    186    sb.restore();
    187  }
    188 });
    189 
    190 add_task(async function test_getOpenTabs_filters_non_ai_windows() {
    191  const BrowserWindowTracker = ChromeUtils.importESModule(
    192    "resource:///modules/BrowserWindowTracker.sys.mjs"
    193  ).BrowserWindowTracker;
    194 
    195  const sb = sinon.createSandbox();
    196 
    197  try {
    198    const aiWindow = createFakeWindow(
    199      [
    200        createFakeTab("https://ai1.com", "AI Tab 1", 1000),
    201        createFakeTab("https://ai2.com", "AI Tab 2", 2000),
    202      ],
    203      false,
    204      true
    205    );
    206 
    207    const classicWindow = createFakeWindow(
    208      [
    209        createFakeTab("https://classic1.com", "Classic Tab 1", 3000),
    210        createFakeTab("https://classic2.com", "Classic Tab 2", 4000),
    211      ],
    212      false,
    213      false
    214    );
    215 
    216    sb.stub(BrowserWindowTracker, "orderedWindows").get(() => [
    217      classicWindow,
    218      aiWindow,
    219    ]);
    220    setupPageDataServiceMock(sb);
    221 
    222    const tabs = await getOpenTabs();
    223 
    224    Assert.equal(
    225      tabs.length,
    226      2,
    227      "Should only return tabs from AI Windows (filtered 2 classic tabs)"
    228    );
    229    Assert.equal(tabs[0].url, "https://ai2.com", "Most recent AI tab");
    230    Assert.equal(tabs[1].url, "https://ai1.com", "Second AI tab");
    231    Assert.ok(
    232      !tabs.some(t => t.url.includes("classic")),
    233      "No classic window tabs in results"
    234    );
    235  } finally {
    236    sb.restore();
    237  }
    238 });
    239 
    240 add_task(async function test_getOpenTabs_return_structure() {
    241  const BrowserWindowTracker = ChromeUtils.importESModule(
    242    "resource:///modules/BrowserWindowTracker.sys.mjs"
    243  ).BrowserWindowTracker;
    244 
    245  const sb = sinon.createSandbox();
    246 
    247  try {
    248    const fakeWindow = createFakeWindow([
    249      createFakeTab("https://test.com", "Test Page", 1000),
    250    ]);
    251 
    252    sb.stub(BrowserWindowTracker, "orderedWindows").get(() => [fakeWindow]);
    253    setupPageDataServiceMock(sb, {
    254      "https://test.com": "A test page description",
    255    });
    256 
    257    const tabs = await getOpenTabs();
    258 
    259    Assert.equal(tabs.length, 1, "Should return one tab");
    260 
    261    const tab = tabs[0];
    262    Assert.ok("url" in tab, "Tab should have url property");
    263    Assert.ok("title" in tab, "Tab should have title property");
    264    Assert.ok("description" in tab, "Tab should have description property");
    265    Assert.ok("lastAccessed" in tab, "Tab should have lastAccessed property");
    266 
    267    Assert.equal(typeof tab.url, "string", "url should be a string");
    268    Assert.equal(typeof tab.title, "string", "title should be a string");
    269    Assert.equal(
    270      typeof tab.description,
    271      "string",
    272      "description should be a string"
    273    );
    274    Assert.equal(
    275      typeof tab.lastAccessed,
    276      "number",
    277      "lastAccessed should be a number"
    278    );
    279 
    280    Assert.equal(tab.url, "https://test.com", "url value correct");
    281    Assert.equal(tab.title, "Test Page", "title value correct");
    282    // @todo Bug2009194
    283    // Assert.equal(
    284    //   tab.description,
    285    //   "A test page description",
    286    //   "description should be fetched from PageDataService"
    287    // );
    288    Assert.equal(tab.lastAccessed, 1000, "lastAccessed value correct");
    289  } finally {
    290    sb.restore();
    291  }
    292 });