12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 | // node --test test/
'use strict';
const test = require('node:test');
const assert = require('node:assert/strict');
const search = require('../internal/render/static/search.js');
const files = [
{ p: 'src/main.c', l: ['#include <stdio.h>', 'int main(void) {', ' printf("Hello World");', ' return 0;', '}'] },
{ p: 'README.md', l: ['# hello', 'say hello to the world', 'HELLO again'] },
{ p: 'lib/helper.lua', l: ['local hello_world = 1', 'return hello_world'] },
];
test('literal, case-insensitive by default', () => {
const r = search.searchSync(files, 'hello', {}, 100);
assert.equal(r.total, 6);
assert.deepEqual(r.files.map((f) => f.p), ['src/main.c', 'README.md', 'lib/helper.lua']);
const m = r.files[1].matches[2];
assert.equal(m.n, 3);
assert.equal(m.text.slice(m.s, m.e), 'HELLO');
});
test('case-sensitive literal', () => {
const r = search.searchSync(files, 'hello', { caseSensitive: true }, 100);
assert.equal(r.total, 4);
assert.equal(search.searchSync(files, 'HELLO', { caseSensitive: true }, 100).total, 1);
});
test('whole word', () => {
const r = search.searchSync(files, 'hello', { word: true }, 100);
// "hello_world" and "Hello World"? word chars include _, so helper.lua is excluded;
// "Hello World" matches (space after).
assert.deepEqual(r.files.map((f) => f.p), ['src/main.c', 'README.md']);
assert.equal(r.total, 4);
});
test('regex with line anchors', () => {
const r = search.searchSync(files, '^\\s*return', { regex: true }, 100);
assert.equal(r.total, 2);
assert.throws(() => search.compile('(', { regex: true }));
});
test('path glob filter', () => {
assert.equal(search.searchSync(files, 'hello', { path: '*.lua' }, 100).total, 2);
assert.equal(search.searchSync(files, 'hello', { path: 'src/*' }, 100).total, 1);
assert.equal(search.searchSync(files, 'hello', { path: '**/*.c' }, 100).total, 1);
assert.equal(search.searchSync(files, 'hello', { path: 'nope/*' }, 100).total, 0);
assert.ok(search.globToRegExp('a?c').test('abc'));
assert.ok(!search.globToRegExp('a?c').test('a/c'));
});
test('result cap and truncation flag', () => {
const r = search.searchSync(files, 'hello', {}, 3);
assert.equal(r.total, 3);
assert.ok(r.truncated);
assert.equal(r.files.reduce((n, f) => n + f.matches.length, 0), 3);
});
test('empty query matches nothing', () => {
assert.equal(search.searchSync(files, '', {}, 10).total, 0);
assert.equal(search.compile('', {}), null);
});
test('regex special characters are literal by default', () => {
assert.equal(search.searchSync(files, 'printf(', {}, 10).total, 1);
assert.equal(search.searchSync(files, '.', { caseSensitive: true }, 100).total, 1); // only "stdio.h"
assert.equal(search.searchSync(files, '.', { regex: true }, 100).total, 10); // every line
});
test('iterSearch can be driven incrementally (cancellation point)', () => {
const m = search.compile('hello', {});
const it = search.iterSearch(files, m, null, []);
const first = it.next();
assert.equal(first.done, false);
assert.equal(first.value.p, 'src/main.c');
it.return();
});
|