A function that accepts search configuration properties
// Test article search functionality with exact matching
const allArticles = await db.articles.findAll();
const searchValidator = TestValidator.search(
"article search API",
(req) => api.searchArticles(req),
allArticles,
5, // test with 5 random samples
);
// Test exact match search
await searchValidator({
fields: ["title"],
values: (article) => [article.title], // full title for exact match
filter: (article, [title]) => article.title === title, // exact match
request: ([title]) => ({ search: { title } }),
});
// Test partial match search with includes
await searchValidator({
fields: ["content"],
values: (article) => [article.content.substring(0, 20)], // partial content
filter: (article, [keyword]) => article.content.includes(keyword),
request: ([keyword]) => ({ q: keyword }),
});
// Test multi-field search with exact matching
await searchValidator({
fields: ["writer", "title"],
values: (article) => [article.writer, article.title],
filter: (article, [writer, title]) =>
article.writer === writer && article.title === title,
request: ([writer, title]) => ({ search: { writer, title } }),
});
contracts/common.md#principled-implementation A sample of entities is drawn, the search values are read from each, the expected set is computed by a manual filter over the whole dataset, the API is called with the request built from the values, and index compares the two lists, so the API is checked against a filter the test author wrote independently.
contracts/common.md#clear-and-simple-design The function is curried so the dataset and the API are given once and each search configuration is run against them, and the comparison is delegated to index.
Validates search functionality by testing API results against manual filtering.
Comprehensive search validation that samples entities from a complete dataset, extracts search values, applies manual filtering, calls the search API, and compares results. Validates that search APIs return the correct subset of data matching the search criteria.
Processing cost: For K sampled entities from N entries, sparse sampling costs O(K), each reference filter scans N entries and each returned page prefix is compared once. Calls are sequential and one sample result is live at a time.
Reuse: Each invocation must evaluate its supplied task or request to observe current behavior; prior results cannot replace these effectful checks.
Resource ownership: The returned promise retains invocation-local state until settlement. The callback owns its external resources, and this validator provides no cancellation or timeout.