tor-browser

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

test_suggestedIndex.js (19057B)


      1 /* Any copyright is dedicated to the Public Domain.
      2   http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 // Tests results with suggestedIndex and resultSpan.
      5 
      6 "use strict";
      7 
      8 const MAX_RESULTS = 10;
      9 
     10 add_task(async function suggestedIndex() {
     11  let tests = [
     12    // no result spans > 1
     13    {
     14      desc: "{ suggestedIndex: 0 }",
     15      suggestedIndexes: [0],
     16      expected: indexes([10, 1], [0, 9]),
     17    },
     18    {
     19      desc: "{ suggestedIndex: 1 }",
     20      suggestedIndexes: [1],
     21      expected: indexes([0, 1], [10, 1], [1, 8]),
     22    },
     23    {
     24      desc: "{ suggestedIndex: -1 }",
     25      suggestedIndexes: [-1],
     26      expected: indexes([0, 9], [10, 1]),
     27    },
     28    {
     29      desc: "{ suggestedIndex: -2 }",
     30      suggestedIndexes: [-2],
     31      expected: indexes([0, 8], [10, 1], [8, 1]),
     32    },
     33    {
     34      desc: "{ suggestedIndex: 0 }, { suggestedIndex: -1 }",
     35      suggestedIndexes: [0, -1],
     36      expected: indexes([10, 1], [0, 8], [11, 1]),
     37    },
     38    {
     39      desc: "{ suggestedIndex: 1 }, { suggestedIndex: -1 }",
     40      suggestedIndexes: [1, -1],
     41      expected: indexes([0, 1], [10, 1], [1, 7], [11, 1]),
     42    },
     43    {
     44      desc: "{ suggestedIndex: 1 }, { suggestedIndex: -2 }",
     45      suggestedIndexes: [1, -2],
     46      expected: indexes([0, 1], [10, 1], [1, 6], [11, 1], [7, 1]),
     47    },
     48    {
     49      desc: "{ suggestedIndex: 0 }, resultCount < max",
     50      suggestedIndexes: [0],
     51      resultCount: 5,
     52      expected: indexes([5, 1], [0, 5]),
     53    },
     54    {
     55      desc: "{ suggestedIndex: 1 }, resultCount < max",
     56      suggestedIndexes: [1],
     57      resultCount: 5,
     58      expected: indexes([0, 1], [5, 1], [1, 4]),
     59    },
     60    {
     61      desc: "{ suggestedIndex: -1 }, resultCount < max",
     62      suggestedIndexes: [-1],
     63      resultCount: 5,
     64      expected: indexes([0, 5], [5, 1]),
     65    },
     66    {
     67      desc: "{ suggestedIndex: -2 }, resultCount < max",
     68      suggestedIndexes: [-2],
     69      resultCount: 5,
     70      expected: indexes([0, 4], [5, 1], [4, 1]),
     71    },
     72    {
     73      desc: "{ suggestedIndex: 0 }, { suggestedIndex: -1 }, resultCount < max",
     74      suggestedIndexes: [0, -1],
     75      resultCount: 5,
     76      expected: indexes([5, 1], [0, 5], [6, 1]),
     77    },
     78    {
     79      desc: "{ suggestedIndex: 1 }, { suggestedIndex: -1 }, resultCount < max",
     80      suggestedIndexes: [1, -1],
     81      resultCount: 5,
     82      expected: indexes([0, 1], [5, 1], [1, 4], [6, 1]),
     83    },
     84    {
     85      desc: "{ suggestedIndex: 0 }, { suggestedIndex: -2 }, resultCount < max",
     86      suggestedIndexes: [0, -2],
     87      resultCount: 5,
     88      expected: indexes([5, 1], [0, 4], [6, 1], [4, 1]),
     89    },
     90    {
     91      desc: "{ suggestedIndex: 1 }, { suggestedIndex: -2 }, resultCount < max",
     92      suggestedIndexes: [1, -2],
     93      resultCount: 5,
     94      expected: indexes([0, 1], [5, 1], [1, 3], [6, 1], [4, 1]),
     95    },
     96 
     97    // one suggestedIndex with result span > 1
     98    {
     99      desc: "{ suggestedIndex: 0, resultSpan: 2 }",
    100      suggestedIndexes: [0],
    101      spansByIndex: { 10: 2 },
    102      expected: indexes([10, 1], [0, 8]),
    103    },
    104    {
    105      desc: "{ suggestedIndex: 0, resultSpan: 3 }",
    106      suggestedIndexes: [0],
    107      spansByIndex: { 10: 3 },
    108      expected: indexes([10, 1], [0, 7]),
    109    },
    110    {
    111      desc: "{ suggestedIndex: 1, resultSpan: 2 }",
    112      suggestedIndexes: [1],
    113      spansByIndex: { 10: 2 },
    114      expected: indexes([0, 1], [10, 1], [1, 7]),
    115    },
    116    {
    117      desc: "suggestedIndex: 1, resultSpan:: 3 }",
    118      suggestedIndexes: [1],
    119      spansByIndex: { 10: 3 },
    120      expected: indexes([0, 1], [10, 1], [1, 6]),
    121    },
    122    {
    123      desc: "{ suggestedIndex: -1, resultSpan 2 }",
    124      suggestedIndexes: [-1],
    125      spansByIndex: { 10: 2 },
    126      expected: indexes([0, 8], [10, 1]),
    127    },
    128    {
    129      desc: "{ suggestedIndex: -1, resultSpan: 3 }",
    130      suggestedIndexes: [-1],
    131      spansByIndex: { 10: 3 },
    132      expected: indexes([0, 7], [10, 1]),
    133    },
    134    {
    135      desc: "{ suggestedIndex: 0, resultSpan: 2 }, { suggestedIndex: -1 }",
    136      suggestedIndexes: [0, -1],
    137      spansByIndex: { 10: 2 },
    138      expected: indexes([10, 1], [0, 7], [11, 1]),
    139    },
    140    {
    141      desc: "{ suggestedIndex: 0, resultSpan: 3 }, { suggestedIndex: -1 }",
    142      suggestedIndexes: [0, -1],
    143      spansByIndex: { 10: 3 },
    144      expected: indexes([10, 1], [0, 6], [11, 1]),
    145    },
    146    {
    147      desc: "{ suggestedIndex: 0 }, { suggestedIndex: -1, resultSpan: 2 }",
    148      suggestedIndexes: [0, -1],
    149      spansByIndex: { 11: 2 },
    150      expected: indexes([10, 1], [0, 7], [11, 1]),
    151    },
    152    {
    153      desc: "{ suggestedIndex: 0 }, { suggestedIndex: -1, resultSpan: 3 }",
    154      suggestedIndexes: [0, -1],
    155      spansByIndex: { 11: 3 },
    156      expected: indexes([10, 1], [0, 6], [11, 1]),
    157    },
    158    {
    159      desc: "{ suggestedIndex: 1, resultSpan: 2 }, { suggestedIndex: -1 }",
    160      suggestedIndexes: [1, -1],
    161      spansByIndex: { 10: 2 },
    162      expected: indexes([0, 1], [10, 1], [1, 6], [11, 1]),
    163    },
    164    {
    165      desc: "{ suggestedIndex: 1, resultSpan: 3 }, { suggestedIndex: -1 }",
    166      suggestedIndexes: [1, -1],
    167      spansByIndex: { 10: 3 },
    168      expected: indexes([0, 1], [10, 1], [1, 5], [11, 1]),
    169    },
    170    {
    171      desc: "{ suggestedIndex: 1 }, { suggestedIndex: -1, resultSpan: 2 }",
    172      suggestedIndexes: [1, -1],
    173      spansByIndex: { 11: 2 },
    174      expected: indexes([0, 1], [10, 1], [1, 6], [11, 1]),
    175    },
    176    {
    177      desc: "{ suggestedIndex: 1 }, { suggestedIndex: -1, resultSpan: 3 }",
    178      suggestedIndexes: [1, -1],
    179      spansByIndex: { 11: 3 },
    180      expected: indexes([0, 1], [10, 1], [1, 5], [11, 1]),
    181    },
    182    {
    183      desc: "{ suggestedIndex: 0, resultSpan: 2 }, { suggestedIndex: -2 }",
    184      suggestedIndexes: [0, -2],
    185      spansByIndex: { 10: 2 },
    186      expected: indexes([10, 1], [0, 6], [11, 1], [6, 1]),
    187    },
    188    {
    189      desc: "{ suggestedIndex: 0, resultSpan: 3 }, { suggestedIndex: -2 }",
    190      suggestedIndexes: [0, -2],
    191      spansByIndex: { 10: 3 },
    192      expected: indexes([10, 1], [0, 5], [11, 1], [5, 1]),
    193    },
    194    {
    195      desc: "{ suggestedIndex: 1, resultSpan: 2 }, { suggestedIndex: -2 }",
    196      suggestedIndexes: [1, -2],
    197      spansByIndex: { 10: 2 },
    198      expected: indexes([0, 1], [10, 1], [1, 5], [11, 1], [6, 1]),
    199    },
    200    {
    201      desc: "{ suggestedIndex: 1, resultSpan: 3 }, { suggestedIndex: -2 }",
    202      suggestedIndexes: [1, -2],
    203      spansByIndex: { 10: 3 },
    204      expected: indexes([0, 1], [10, 1], [1, 4], [11, 1], [5, 1]),
    205    },
    206    {
    207      desc: "{ suggestedIndex: 0 }, { suggestedIndex: -2, resultSpan: 2 }",
    208      suggestedIndexes: [0, -2],
    209      spansByIndex: { 11: 2 },
    210      expected: indexes([10, 1], [0, 6], [11, 1], [6, 1]),
    211    },
    212    {
    213      desc: "{ suggestedIndex: 0 }, { suggestedIndex: -2, resultSpan: 3 }",
    214      suggestedIndexes: [0, -2],
    215      spansByIndex: { 11: 3 },
    216      expected: indexes([10, 1], [0, 5], [11, 1], [5, 1]),
    217    },
    218    {
    219      desc: "{ suggestedIndex: 1 }, { suggestedIndex: -2, resultSpan: 2 }",
    220      suggestedIndexes: [1, -2],
    221      spansByIndex: { 11: 2 },
    222      expected: indexes([0, 1], [10, 1], [1, 5], [11, 1], [6, 1]),
    223    },
    224    {
    225      desc: "{ suggestedIndex: 1 }, { suggestedIndex: -2, resultSpan: 3 }",
    226      suggestedIndexes: [1, -2],
    227      spansByIndex: { 11: 3 },
    228      expected: indexes([0, 1], [10, 1], [1, 4], [11, 1], [5, 1]),
    229    },
    230    {
    231      desc: "{ suggestedIndex: 0, resultSpan: 2 }, resultCount < max",
    232      suggestedIndexes: [0],
    233      spansByIndex: { 5: 2 },
    234      resultCount: 5,
    235      expected: indexes([5, 1], [0, 5]),
    236    },
    237    {
    238      desc: "{ suggestedIndex: 1, resultSpan: 2 }, resultCount < max",
    239      suggestedIndexes: [1],
    240      spansByIndex: { 5: 2 },
    241      resultCount: 5,
    242      expected: indexes([0, 1], [5, 1], [1, 4]),
    243    },
    244    {
    245      desc: "{ suggestedIndex: -1, resultSpan: 2 }, resultCount < max",
    246      suggestedIndexes: [-1],
    247      spansByIndex: { 5: 2 },
    248      resultCount: 5,
    249      expected: indexes([0, 5], [5, 1]),
    250    },
    251    {
    252      desc: "{ suggestedIndex: -2, resultSpan: 2 }, resultCount < max",
    253      suggestedIndexes: [-2],
    254      spansByIndex: { 5: 2 },
    255      resultCount: 5,
    256      expected: indexes([0, 4], [5, 1], [4, 1]),
    257    },
    258    {
    259      desc: "{ suggestedIndex: 0, resultSpan: 2 }, { suggestedIndex: -1 }, resultCount < max",
    260      suggestedIndexes: [0, -1],
    261      spansByIndex: { 5: 2 },
    262      resultCount: 5,
    263      expected: indexes([5, 1], [0, 5], [6, 1]),
    264    },
    265    {
    266      desc: "{ suggestedIndex: 1, resultSpan: 2 }, { suggestedIndex: -1 }, resultCount < max",
    267      suggestedIndexes: [1, -1],
    268      spansByIndex: { 5: 2 },
    269      resultCount: 5,
    270      expected: indexes([0, 1], [5, 1], [1, 4], [6, 1]),
    271    },
    272    {
    273      desc: "{ suggestedIndex: 0, resultSpan: 2 }, { suggestedIndex: -2 }, resultCount < max",
    274      suggestedIndexes: [0, -2],
    275      spansByIndex: { 5: 2 },
    276      resultCount: 5,
    277      expected: indexes([5, 1], [0, 4], [6, 1], [4, 1]),
    278    },
    279    {
    280      desc: "{ suggestedIndex: 0 }, { suggestedIndex: -1, resultSpan: 2 }, resultCount < max",
    281      suggestedIndexes: [0, -1],
    282      spansByIndex: { 6: 2 },
    283      resultCount: 5,
    284      expected: indexes([5, 1], [0, 5], [6, 1]),
    285    },
    286    {
    287      desc: "{ suggestedIndex: 0 }, { suggestedIndex: -2, resultSpan: 2 }, resultCount < max",
    288      suggestedIndexes: [0, -2],
    289      spansByIndex: { 6: 2 },
    290      resultCount: 5,
    291      expected: indexes([5, 1], [0, 4], [6, 1], [4, 1]),
    292    },
    293 
    294    // two suggestedIndexes with result span > 1
    295    {
    296      desc: "{ suggestedIndex: 0, resultSpan: 2 }, { suggestedIndex: -1, resultSpan: 2 }",
    297      suggestedIndexes: [0, -1],
    298      spansByIndex: { 10: 2, 11: 2 },
    299      expected: indexes([10, 1], [0, 6], [11, 1]),
    300    },
    301    {
    302      desc: "{ suggestedIndex: 0, resultSpan: 3 }, { suggestedIndex: -1, resultSpan: 2 }",
    303      suggestedIndexes: [0, -1],
    304      spansByIndex: { 10: 3, 11: 2 },
    305      expected: indexes([10, 1], [0, 5], [11, 1]),
    306    },
    307    {
    308      desc: "{ suggestedIndex: 0, resultSpan: 2 }, { suggestedIndex: -1, resultSpan: 3 }",
    309      suggestedIndexes: [0, -1],
    310      spansByIndex: { 10: 2, 11: 3 },
    311      expected: indexes([10, 1], [0, 5], [11, 1]),
    312    },
    313    {
    314      desc: "{ suggestedIndex: 1, resultSpan: 2 }, { suggestedIndex: -1, resultSpan: 2 }",
    315      suggestedIndexes: [1, -1],
    316      spansByIndex: { 10: 2, 11: 2 },
    317      expected: indexes([0, 1], [10, 1], [1, 5], [11, 1]),
    318    },
    319    {
    320      desc: "{ suggestedIndex: 1, resultSpan: 3 }, { suggestedIndex: -1, resultSpan: 2 }",
    321      suggestedIndexes: [1, -1],
    322      spansByIndex: { 10: 3, 11: 2 },
    323      expected: indexes([0, 1], [10, 1], [1, 4], [11, 1]),
    324    },
    325    {
    326      desc: "{ suggestedIndex: 1, resultSpan: 2 }, { suggestedIndex: -1, resultSpan: 3 }",
    327      suggestedIndexes: [1, -1],
    328      spansByIndex: { 10: 2, 11: 3 },
    329      expected: indexes([0, 1], [10, 1], [1, 4], [11, 1]),
    330    },
    331    {
    332      desc: "{ suggestedIndex: 0, resultSpan: 2 }, { suggestedIndex: -2, resultSpan: 2 }",
    333      suggestedIndexes: [0, -2],
    334      spansByIndex: { 10: 2, 11: 2 },
    335      expected: indexes([10, 1], [0, 5], [11, 1], [5, 1]),
    336    },
    337    {
    338      desc: "{ suggestedIndex: 0, resultSpan: 3 }, { suggestedIndex: -2, resultSpan: 2 }",
    339      suggestedIndexes: [0, -2],
    340      spansByIndex: { 10: 3, 11: 2 },
    341      expected: indexes([10, 1], [0, 4], [11, 1], [4, 1]),
    342    },
    343    {
    344      desc: "{ suggestedIndex: 0, resultSpan: 2 }, { suggestedIndex: -2, resultSpan: 3 }",
    345      suggestedIndexes: [0, -2],
    346      spansByIndex: { 10: 2, 11: 3 },
    347      expected: indexes([10, 1], [0, 4], [11, 1], [4, 1]),
    348    },
    349    {
    350      desc: "{ suggestedIndex: 1, resultSpan: 2 }, { suggestedIndex: -2, resultSpan: 2 }",
    351      suggestedIndexes: [1, -2],
    352      spansByIndex: { 10: 2, 11: 2 },
    353      expected: indexes([0, 1], [10, 1], [1, 4], [11, 1], [5, 1]),
    354    },
    355    {
    356      desc: "{ suggestedIndex: 1, resultSpan: 3 }, { suggestedIndex: -2, resultSpan: 2 }",
    357      suggestedIndexes: [1, -2],
    358      spansByIndex: { 10: 3, 11: 2 },
    359      expected: indexes([0, 1], [10, 1], [1, 3], [11, 1], [4, 1]),
    360    },
    361    {
    362      desc: "{ suggestedIndex: 1, resultSpan: 2 }, { suggestedIndex: -2, resultSpan: 3 }",
    363      suggestedIndexes: [1, -2],
    364      spansByIndex: { 10: 2, 11: 3 },
    365      expected: indexes([0, 1], [10, 1], [1, 3], [11, 1], [4, 1]),
    366    },
    367    {
    368      desc: "{ suggestedIndex: 0, resultSpan: 2 }, { suggestedIndex: -1, resultSpan: 2 }, resultCount < max",
    369      suggestedIndexes: [0, -1],
    370      spansByIndex: { 5: 2, 6: 2 },
    371      resultCount: 5,
    372      expected: indexes([5, 1], [0, 5], [6, 1]),
    373    },
    374    {
    375      desc: "{ suggestedIndex: 1, resultSpan: 2 }, { suggestedIndex: -1, resultSpan: 2 }, resultCount < max",
    376      suggestedIndexes: [1, -1],
    377      spansByIndex: { 5: 2, 6: 2 },
    378      resultCount: 5,
    379      expected: indexes([0, 1], [5, 1], [1, 4], [6, 1]),
    380    },
    381    {
    382      desc: "{ suggestedIndex: 0, resultSpan: 2 }, { suggestedIndex: -2, resultSpan: 2 }, resultCount < max",
    383      suggestedIndexes: [0, -2],
    384      spansByIndex: { 5: 2, 6: 2 },
    385      resultCount: 5,
    386      expected: indexes([5, 1], [0, 4], [6, 1], [4, 1]),
    387    },
    388 
    389    // one suggestedIndex plus other result with resultSpan > 1
    390    {
    391      desc: "{ suggestedIndex: 0 }, { resultSpan: 2 } A",
    392      suggestedIndexes: [0],
    393      spansByIndex: { 0: 2 },
    394      expected: indexes([10, 1], [0, 8]),
    395    },
    396    {
    397      desc: "{ suggestedIndex: 0 }, { resultSpan: 2 } B",
    398      suggestedIndexes: [0],
    399      spansByIndex: { 8: 2 },
    400      expected: indexes([10, 1], [0, 8]),
    401    },
    402    {
    403      desc: "{ suggestedIndex: 0 }, { resultSpan: 2 } C",
    404      suggestedIndexes: [0],
    405      spansByIndex: { 9: 2 },
    406      expected: indexes([10, 1], [0, 9]),
    407    },
    408    {
    409      desc: "{ suggestedIndex: 1 }, { resultSpan: 2 } A",
    410      suggestedIndexes: [1],
    411      spansByIndex: { 0: 2 },
    412      expected: indexes([0, 1], [10, 1], [1, 7]),
    413    },
    414    {
    415      desc: "{ suggestedIndex: 1 }, { resultSpan: 2 } B",
    416      suggestedIndexes: [1],
    417      spansByIndex: { 8: 2 },
    418      expected: indexes([0, 1], [10, 1], [1, 7]),
    419    },
    420    {
    421      desc: "{ suggestedIndex: -1 }, { resultSpan: 2 }",
    422      suggestedIndexes: [-1],
    423      spansByIndex: { 0: 2 },
    424      expected: indexes([0, 8], [10, 1]),
    425    },
    426    {
    427      desc: "{ suggestedIndex: -2 }, { resultSpan: 2 }",
    428      suggestedIndexes: [-2],
    429      spansByIndex: { 0: 2 },
    430      expected: indexes([0, 7], [10, 1], [7, 1]),
    431    },
    432 
    433    // miscellaneous
    434    {
    435      desc: "no suggestedIndex, last result has resultSpan = 2",
    436      suggestedIndexes: [],
    437      spansByIndex: { 9: 2 },
    438      expected: indexes([0, 9]),
    439    },
    440    {
    441      desc: "{ suggestedIndex: -1 }, last result has resultSpan = 2",
    442      suggestedIndexes: [-1],
    443      spansByIndex: { 9: 2 },
    444      expected: indexes([0, 9], [10, 1]),
    445    },
    446    {
    447      desc: "no suggestedIndex, index 8 result has resultSpan = 2",
    448      suggestedIndexes: [],
    449      spansByIndex: { 8: 2 },
    450      expected: indexes([0, 9]),
    451    },
    452    {
    453      desc: "{ suggestedIndex: -1 }, index 8 result has resultSpan = 2",
    454      suggestedIndexes: [-1],
    455      spansByIndex: { 8: 2 },
    456      expected: indexes([0, 8], [10, 1]),
    457    },
    458    {
    459      desc: "{ suggestedIndex: 0, maxRichResults: 0 }",
    460      maxRichResults: 0,
    461      suggestedIndexes: [0],
    462      expected: [],
    463    },
    464    {
    465      desc: "{ suggestedIndex: 1, maxRichResults: 0 }",
    466      maxRichResults: 0,
    467      suggestedIndexes: [1],
    468      expected: [],
    469    },
    470    {
    471      desc: "{ suggestedIndex: -1, maxRichResults: 0 }",
    472      maxRichResults: 0,
    473      suggestedIndexes: [-1],
    474      expected: [],
    475    },
    476    {
    477      desc: "{ suggestedIndex: 0, maxRichResults: 1 }",
    478      maxRichResults: 1,
    479      suggestedIndexes: [0],
    480      expected: indexes([10, 1]),
    481    },
    482    {
    483      desc: "{ suggestedIndex: 1, maxRichResults: 1 }",
    484      maxRichResults: 1,
    485      suggestedIndexes: [1],
    486      expected: indexes([10, 1]),
    487    },
    488    {
    489      desc: "{ suggestedIndex: -1, maxRichResults: 1 }",
    490      maxRichResults: 1,
    491      suggestedIndexes: [-1],
    492      expected: indexes([10, 1]),
    493    },
    494  ];
    495 
    496  for (let test of tests) {
    497    info("Running test: " + JSON.stringify(test));
    498    await doSuggestedIndexTest(test);
    499  }
    500 });
    501 
    502 /**
    503 * Sets up a provider with some results with suggested indexes and result spans,
    504 * performs a search, and then checks the results.
    505 *
    506 * @param {object} options
    507 *   Options for the test.
    508 * @param {Array} options.suggestedIndexes
    509 *   For each of the indexes in this array, a new result with the given
    510 *   suggestedIndex will be returned by the provider.
    511 * @param {Array} options.expected
    512 *   The indexes of the expected results within the array of results returned by
    513 *   the provider.
    514 * @param {object} [options.spansByIndex]
    515 *   Maps indexes within the array of results returned by the provider to result
    516 *   spans to set on those results.
    517 * @param {number} [options.resultCount]
    518 *   Aside from the results with suggested indexes, this is the number of
    519 *   results that the provider will return.
    520 * @param {number} [options.maxRichResults]
    521 *   The `maxRichResults` pref will be set to this value.
    522 */
    523 async function doSuggestedIndexTest({
    524  suggestedIndexes,
    525  expected,
    526  spansByIndex = {},
    527  resultCount = MAX_RESULTS,
    528  maxRichResults = MAX_RESULTS,
    529 }) {
    530  // Make resultCount history results.
    531  let results = [];
    532  for (let i = 0; i < resultCount; i++) {
    533    results.push(
    534      new UrlbarResult({
    535        type: UrlbarUtils.RESULT_TYPE.URL,
    536        source: UrlbarUtils.RESULT_SOURCE.HISTORY,
    537        resultSpan: spansByIndex[results.length],
    538        payload: {
    539          url: "http://example.com/" + i,
    540        },
    541      })
    542    );
    543  }
    544 
    545  // Make the suggested-index results.
    546  for (let suggestedIndex of suggestedIndexes) {
    547    results.push(
    548      new UrlbarResult({
    549        type: UrlbarUtils.RESULT_TYPE.URL,
    550        source: UrlbarUtils.RESULT_SOURCE.HISTORY,
    551        suggestedIndex,
    552        resultSpan: spansByIndex[results.length],
    553        payload: {
    554          url: "http://example.com/si " + suggestedIndex,
    555        },
    556      })
    557    );
    558  }
    559 
    560  // Set up the provider, etc.
    561  UrlbarPrefs.set("maxRichResults", maxRichResults);
    562  let provider = registerBasicTestProvider(results);
    563  let context = createContext(undefined, { providers: [provider.name] });
    564  let controller = UrlbarTestUtils.newMockController();
    565 
    566  // Finally, search and check the results.
    567  let expectedResults = expected.map(i => results[i]);
    568  await UrlbarProvidersManager.startQuery(context, controller);
    569  Assert.deepEqual(context.results, expectedResults);
    570 }
    571 
    572 /**
    573 * Helper that generates an array of indexes.  Pass in [index, length] tuples.
    574 * Each tuple will produce the indexes starting from `index` to `index + length`
    575 * (not including the index at `index + length`).
    576 *
    577 * Examples:
    578 *
    579 *   indexes([0, 5]) => [0, 1, 2, 3, 4]
    580 *   indexes([0, 1], [4, 3], [8, 2]) => [0, 4, 5, 6, 8, 9]
    581 *
    582 * @param {Array} pairs
    583 *   [index, length] tuples as described above.
    584 * @returns {Array}
    585 *   An array of indexes.
    586 */
    587 function indexes(...pairs) {
    588  return pairs.reduce((indexesArray, [start, len]) => {
    589    for (let i = start; i < start + len; i++) {
    590      indexesArray.push(i);
    591    }
    592    return indexesArray;
    593  }, []);
    594 }