tor-browser

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

test_link_preview_text.js (9072B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 * http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 const { LinkPreviewModel } = ChromeUtils.importESModule(
      5  "moz-src:///browser/components/genai/LinkPreviewModel.sys.mjs"
      6 );
      7 const { SentencePostProcessor } = ChromeUtils.importESModule(
      8  "moz-src:///browser/components/genai/LinkPreviewModel.sys.mjs"
      9 );
     10 
     11 const { sinon } = ChromeUtils.importESModule(
     12  "resource://testing-common/Sinon.sys.mjs"
     13 );
     14 
     15 const { BlockListManager } = ChromeUtils.importESModule(
     16  "chrome://global/content/ml/Utils.sys.mjs"
     17 );
     18 
     19 /**
     20 * Test that text is processed for ai.
     21 */
     22 add_task(function test_text_processing() {
     23  const text = "This is a test sentence. ";
     24  Assert.equal(
     25    LinkPreviewModel.preprocessText(text),
     26    "This is a test sentence.",
     27    "basic sentence should be trimmed"
     28  );
     29  Assert.equal(
     30    LinkPreviewModel.preprocessText("Too short."),
     31    "",
     32    "short sentence should be removed"
     33  );
     34  Assert.equal(
     35    LinkPreviewModel.preprocessText("Today is Mar. 12, 2025."),
     36    "Today is Mar. 12, 2025.",
     37    "abbreviations don't break sentences"
     38  );
     39  Assert.equal(
     40    LinkPreviewModel.preprocessText("Thisisatestsentence but fewwords."),
     41    "",
     42    "needs enough words"
     43  );
     44  Assert.equal(
     45    LinkPreviewModel.preprocessText(
     46      "This is a test sentence without punctuation"
     47    ),
     48    "",
     49    "needs punctuation"
     50  );
     51  Assert.equal(
     52    LinkPreviewModel.preprocessText(`${text}
     53    Too short.
     54    Today is Mar. 12, 2025.
     55    Thisisatestsentence but fewwords.
     56    This is a test sentence without punctuation`),
     57    "This is a test sentence. Today is Mar. 12, 2025.",
     58    "multiple sentences should be processed"
     59  );
     60 
     61  Assert.equal(
     62    LinkPreviewModel.preprocessText(`${text}
     63 
     64     Short \t\t\t\t\t\t\t\t\t\t                      without spaces.
     65 
     66 
     67 
     68      It has           \t \t \t multiple consecutive spaces in between words.
     69      They should all go away
     70   `),
     71    "This is a test sentence. It has multiple consecutive spaces in between words.",
     72    "Remove consecutive spaces by single."
     73  );
     74 
     75  Assert.equal(
     76    LinkPreviewModel.preprocessText(text.repeat(100)),
     77    text.repeat(6).trim(),
     78    "restrict to 6 sentences"
     79  );
     80 
     81  Assert.equal(
     82    LinkPreviewModel.preprocessText(
     83      "This is a test sentence with an emoji \ud83e\udd14."
     84    ),
     85    "This is a test sentence with an emoji .",
     86    "emoji should be removed from the sentence"
     87  );
     88 });
     89 
     90 /**
     91 * Test that prefs affect text processing.
     92 */
     93 add_task(function test_text_processing_prefs() {
     94  const text = "This is a test sentence. ";
     95  Services.prefs.setIntPref("browser.ml.linkPreview.inputSentences", 3);
     96  Assert.equal(
     97    LinkPreviewModel.preprocessText(text.repeat(100)),
     98    text.repeat(3).trim(),
     99    "restrict to 3 sentences"
    100  );
    101 
    102  Services.prefs.setIntPref(
    103    "browser.ml.linkPreview.minWordsPerOutputSentences",
    104    3
    105  );
    106  let processor = new SentencePostProcessor();
    107  let output = "";
    108  output += processor.put("I am writing unit test.").sentence;
    109 
    110  output += processor.put(" So great.").sentence;
    111 
    112  output += processor.put(" I like it.").sentence;
    113 
    114  output += processor.put(" Done. ").sentence;
    115 
    116  Assert.equal(
    117    output,
    118    "I am writing unit test. I like it. ",
    119    "ignore too short sentences"
    120  );
    121 
    122  Services.prefs.setIntPref(
    123    "browser.ml.linkPreview.minWordsPerOutputSentences",
    124    4
    125  );
    126  processor = new SentencePostProcessor();
    127  output = "";
    128  output += processor.put("I am writing unit test.").sentence;
    129 
    130  output += processor.put(" So great.").sentence;
    131 
    132  output += processor.put(" I like it.").sentence;
    133 
    134  output += processor.put(" Done. ").sentence;
    135 
    136  Assert.equal(
    137    output,
    138    "I am writing unit test. ",
    139    "ignore too short sentences"
    140  );
    141 
    142  Services.prefs.clearUserPref("browser.ml.linkPreview.inputSentences");
    143  Services.prefs.clearUserPref(
    144    "browser.ml.linkPreview.minWordsPerOutputSentences"
    145  );
    146 });
    147 
    148 /**
    149 * Test that post processor provides sentences.
    150 */
    151 add_task(function test_sentence_post_processor() {
    152  const processor = new SentencePostProcessor();
    153  Assert.deepEqual(
    154    processor.put("Hello "),
    155    { sentence: "", abort: false },
    156    "no sentence yet"
    157  );
    158  Assert.deepEqual(
    159    processor.put("world. "),
    160    { sentence: "", abort: false },
    161    "sentence complete but not next"
    162  );
    163  Assert.deepEqual(
    164    processor.put("How "),
    165    { sentence: "Hello world. ", abort: false },
    166    "previous sentence complete"
    167  );
    168  Assert.deepEqual(
    169    processor.put("are you today? I'm"),
    170    { sentence: "How are you today? ", abort: false },
    171    "question complete"
    172  );
    173  Assert.deepEqual(
    174    processor.put(" fine. And"),
    175    { sentence: "I'm fine. ", abort: true },
    176    "response complete"
    177  );
    178  Assert.deepEqual(
    179    processor.put("you? Good"),
    180    { sentence: "", abort: true },
    181    "hit limit"
    182  );
    183  Assert.equal(processor.flush(), "", "still nothing at limit");
    184 });
    185 
    186 /**
    187 * Test that generateTextAI works properly with the blocklist
    188 */
    189 add_task(async function test_generateAI_with_blocklist() {
    190  // Mocked ML Engine
    191  const engine = {
    192    async *runWithGenerator() {
    193      const preview =
    194        "Hello world, I am here and would like to make a sentence. Now, more sentences are coming.  Even more are raining here. Bye";
    195 
    196      for (const text of preview) {
    197        yield { text };
    198      }
    199    },
    200 
    201    terminate() {},
    202  };
    203 
    204  // Mocked Blocked List Manager
    205  let manager = new BlockListManager({
    206    blockNgrams: [BlockListManager.encodeBase64("hello")],
    207    language: "en",
    208  });
    209 
    210  // Disable block list
    211  Services.prefs.setBoolPref("browser.ml.linkPreview.blockListEnabled", false);
    212 
    213  let createEngineStub = sinon
    214    .stub(LinkPreviewModel, "createEngine")
    215    .returns(engine);
    216 
    217  let managerStub = sinon
    218    .stub(BlockListManager, "initializeFromRemoteSettings")
    219    .returns(manager);
    220 
    221  let numOutputs = 0;
    222 
    223  await LinkPreviewModel.generateTextAI(
    224    "This is the big article. Now give me its preview. Please.",
    225    {
    226      onText: () => {
    227        numOutputs += 1;
    228      },
    229    }
    230  );
    231 
    232  Assert.equal(
    233    numOutputs,
    234    3,
    235    "should output all sentences when block list is disabled"
    236  );
    237 
    238  // Enable block list
    239  Services.prefs.setBoolPref("browser.ml.linkPreview.blockListEnabled", true);
    240 
    241  numOutputs = 0;
    242 
    243  await LinkPreviewModel.generateTextAI(
    244    "This is the big article. Now give me its preview. Please.",
    245    {
    246      onText: () => {
    247        numOutputs += 1;
    248      },
    249    }
    250  );
    251 
    252  Assert.equal(
    253    numOutputs,
    254    0,
    255    "Should output no sentences when 1st sentence contains block word and block list enabled."
    256  );
    257 
    258  managerStub.restore();
    259  manager = new BlockListManager({
    260    blockNgrams: [BlockListManager.encodeBase64("coming")],
    261    language: "en",
    262  });
    263  managerStub = sinon
    264    .stub(BlockListManager, "initializeFromRemoteSettings")
    265    .returns(manager);
    266 
    267  // Force link preview to reload blockList manager
    268  Services.prefs.setBoolPref("browser.ml.linkPreview.blockListEnabled", false);
    269  await LinkPreviewModel.generateTextAI(
    270    "This is the big article. Now give me its preview. Please."
    271  );
    272 
    273  Assert.equal(LinkPreviewModel.blockListManager, null);
    274 
    275  // Now re-enable block list
    276  Services.prefs.setBoolPref("browser.ml.linkPreview.blockListEnabled", true);
    277 
    278  numOutputs = 0;
    279  await LinkPreviewModel.generateTextAI(
    280    "This is the big article. Now give me its preview. Please.",
    281    {
    282      onText: () => {
    283        numOutputs += 1;
    284      },
    285    }
    286  );
    287 
    288  Assert.equal(
    289    numOutputs,
    290    1,
    291    "Should output 1 sentence when blocked word found 1st time in 2nd sentence and block list enabled."
    292  );
    293 
    294  Services.prefs.setBoolPref("browser.ml.linkPreview.blockListEnabled", false);
    295 
    296  numOutputs = 0;
    297 
    298  await LinkPreviewModel.generateTextAI(
    299    "This is the big article. Now give me its preview. Please.",
    300    {
    301      onText: () => {
    302        numOutputs += 1;
    303      },
    304    }
    305  );
    306 
    307  Assert.equal(
    308    numOutputs,
    309    3,
    310    "all sentences should be outputted when block list disabled"
    311  );
    312 
    313  Services.prefs.clearUserPref("browser.ml.linkPreview.blockListEnabled");
    314  createEngineStub.restore();
    315  managerStub.restore();
    316 });
    317 
    318 /**
    319 * Test post processor respects limits.
    320 */
    321 add_task(function test_sentence_post_processor_limits() {
    322  const processor = new SentencePostProcessor({
    323    maxNumOutputSentences: 1,
    324  });
    325  Assert.deepEqual(
    326    processor.put("Hi. There. "),
    327    { sentence: "Hi. ", abort: true },
    328    "first sentence"
    329  );
    330  Assert.deepEqual(
    331    processor.put("Nope."),
    332    { sentence: "", abort: true },
    333    "no more sentences"
    334  );
    335 
    336  Services.prefs.setIntPref("browser.ml.linkPreview.outputSentences", 2);
    337  const viaPref = new SentencePostProcessor();
    338  Assert.deepEqual(
    339    viaPref.put("Hi. There. "),
    340    { sentence: "Hi. ", abort: false },
    341    "first sentence"
    342  );
    343  Assert.deepEqual(
    344    viaPref.put("Yup. "),
    345    { sentence: "There. ", abort: true },
    346    "second sentence"
    347  );
    348  Assert.deepEqual(
    349    viaPref.put("Nope."),
    350    { sentence: "", abort: true },
    351    "no more sentences"
    352  );
    353  Services.prefs.clearUserPref("browser.ml.linkPreview.outputSentences");
    354 });