summaryrefslogtreecommitdiff
path: root/test/search-url.test.ts
blob: 2425f7648ad472106239e841fae6d8d1d0fb243c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import assert from "node:assert/strict";
import { test } from "node:test";

import { RECENCY_VALUES, allEngines, getEngine, type Recency } from "../src/engines.ts";
import { buildSearchUrl } from "../src/search.ts";

const urlFor = (id: Parameters<typeof getEngine>[0], recency?: Recency) =>
  new URL(buildSearchUrl(getEngine(id), { query: "sqlite wal mode", numResults: 7, recency }));

test("google uses the Web tab, and swaps it for as_qdr when time-limited", () => {
  const plain = urlFor("google");
  assert.equal(plain.origin + plain.pathname, "https://www.google.com/search");
  assert.equal(plain.searchParams.get("udm"), "14");
  assert.equal(plain.searchParams.get("num"), "7");
  assert.equal(plain.searchParams.get("as_qdr"), null);

  const dated = urlFor("google", "month");
  // Both findings in one assertion pair: tbs is never used, and udm must be
  // dropped when a date filter is present or the page renders empty.
  assert.equal(dated.searchParams.get("as_qdr"), "m");
  assert.equal(dated.searchParams.get("udm"), null);
  assert.equal(dated.searchParams.get("tbs"), null);
});

test("duckduckgo uses the no-JS html endpoint and df=", () => {
  const plain = urlFor("duckduckgo");
  assert.equal(plain.origin + plain.pathname, "https://html.duckduckgo.com/html/");
  assert.equal(plain.searchParams.get("q"), "sqlite wal mode");
  assert.equal(plain.searchParams.get("df"), null);

  for (const [recency, code] of [
    ["day", "d"],
    ["week", "w"],
    ["month", "m"],
    ["year", "y"],
  ] as const) {
    assert.equal(urlFor("duckduckgo", recency).searchParams.get("df"), code, recency);
  }
});

test("bing uses count=, and drops it when filtering because count cancels filters", () => {
  const plain = urlFor("bing");
  assert.equal(plain.origin + plain.pathname, "https://www.bing.com/search");
  assert.equal(plain.searchParams.get("count"), "7");
  assert.equal(plain.searchParams.get("filters"), null);

  for (const [recency, code] of [
    ["day", "ez1"],
    ["week", "ez2"],
    ["month", "ez3"],
  ] as const) {
    const dated = urlFor("bing", recency);
    assert.equal(dated.searchParams.get("filters"), `ex1:"${code}"`, recency);
    // Observed: sending count alongside filters silently returns unfiltered
    // results that look entirely plausible. This assertion is the regression.
    assert.equal(dated.searchParams.get("count"), null, `${recency}: count must be dropped`);
  }
});

test("brave is a plain query — it advertises no time filter at all", () => {
  const plain = urlFor("brave");
  assert.equal(plain.origin + plain.pathname, "https://search.brave.com/search");
  assert.equal(plain.searchParams.get("q"), "sqlite wal mode");
  assert.deepEqual(getEngine("brave").recency, {});
});

test("every advertised recency window maps to a non-empty parameter value", () => {
  // Guards the failure this whole design exists to prevent: an engine claiming
  // support for a window it then silently drops from the URL.
  for (const engine of allEngines()) {
    for (const recency of RECENCY_VALUES) {
      const code = engine.recency[recency];
      if (code === undefined) continue;
      assert.ok(code.length > 0, `${engine.id}/${recency} maps to an empty value`);
      const url = buildSearchUrl(engine, { query: "q", numResults: 5, recency });
      assert.ok(url.includes(encodeURIComponent(code)) || url.includes(code), `${engine.id}/${recency} lost its value`);
    }
  }
});

test("queries with characters that would break a URL are encoded, on every engine", () => {
  const query = 'site:example.com "exact phrase" a&b?c=d #frag +plus/slash';
  for (const engine of allEngines()) {
    const url = buildSearchUrl(engine, { query, numResults: 3 });
    assert.equal(new URL(url).searchParams.get("q"), query, engine.id);
    assert.ok(!url.includes(" "), `${engine.id}: no raw spaces in the URL`);
  }
});