Files
outline/server/models/helpers/SearchHelper.test.ts
Copilot d02f35b770 Fix collection filter returning documents from all collections when no search query (#10775)
* Initial plan

* Fix search filtering by collection to exclude other collections

Co-authored-by: tommoor <380914+tommoor@users.noreply.github.com>

* Add API-level test for collection filtering without search term

Co-authored-by: tommoor <380914+tommoor@users.noreply.github.com>

* fix: Private collections

* refactor

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: tommoor <380914+tommoor@users.noreply.github.com>
Co-authored-by: Tom Moor <tom@getoutline.com>
2025-12-03 20:49:57 -05:00

1090 lines
32 KiB
TypeScript

import { DocumentPermission, StatusFilter } from "@shared/types";
import SearchHelper from "@server/models/helpers/SearchHelper";
import {
buildDocument,
buildDraftDocument,
buildCollection,
buildTeam,
buildUser,
buildShare,
buildGroup,
} from "@server/test/factories";
import UserMembership from "../UserMembership";
import GroupMembership from "../GroupMembership";
beforeEach(async () => {
jest.resetAllMocks();
await buildDocument();
});
describe("SearchHelper", () => {
describe("#searchForTeam", () => {
it("should return search results from public collections", async () => {
const team = await buildTeam();
const collection = await buildCollection({
teamId: team.id,
});
const document = await buildDocument({
teamId: team.id,
collectionId: collection.id,
title: "test",
});
const { results } = await SearchHelper.searchForTeam(team, {
query: "test",
});
expect(results.length).toBe(1);
expect(results[0].document?.id).toBe(document.id);
});
it("should return search results from a collection without search term", async () => {
const team = await buildTeam();
const collection = await buildCollection({
teamId: team.id,
});
const documents = await Promise.all([
buildDocument({
teamId: team.id,
collectionId: collection.id,
title: "document 1",
}),
buildDocument({
teamId: team.id,
collectionId: collection.id,
title: "document 2",
}),
]);
const { results } = await SearchHelper.searchForTeam(team);
expect(results.length).toBe(2);
expect(results.map((r) => r.document.id).sort()).toEqual(
documents.map((doc) => doc.id).sort()
);
});
it("should not return results from private collections without providing collectionId", async () => {
const team = await buildTeam();
const collection = await buildCollection({
permission: null,
teamId: team.id,
});
await buildDocument({
teamId: team.id,
collectionId: collection.id,
title: "test",
});
const { results } = await SearchHelper.searchForTeam(team, {
query: "test",
});
expect(results.length).toBe(0);
});
it("should return results from private collections when collectionId is provided", async () => {
const team = await buildTeam();
const collection = await buildCollection({
permission: null,
teamId: team.id,
});
await buildDocument({
teamId: team.id,
collectionId: collection.id,
title: "test",
});
const { results } = await SearchHelper.searchForTeam(team, {
query: "test",
collectionId: collection.id,
});
expect(results.length).toBe(1);
});
it("should return results from document tree of shared document", async () => {
const team = await buildTeam();
const collection = await buildCollection({
permission: null,
teamId: team.id,
});
const document = await buildDocument({
teamId: team.id,
collectionId: collection.id,
title: "test 1",
});
await buildDocument({
teamId: team.id,
collectionId: collection.id,
title: "test 2",
});
const share = await buildShare({
documentId: document.id,
includeChildDocuments: true,
});
const { results } = await SearchHelper.searchForTeam(team, {
query: "test",
collectionId: collection.id,
share,
});
expect(results.length).toBe(1);
});
it("should handle no collections", async () => {
const team = await buildTeam();
const { results } = await SearchHelper.searchForTeam(team, {
query: "test",
});
expect(results.length).toBe(0);
});
it("should handle backslashes in search term", async () => {
const team = await buildTeam();
const collection = await buildCollection({
teamId: team.id,
});
const document = await buildDocument({
teamId: team.id,
collectionId: collection.id,
title: "test with backslash \\",
});
const { results } = await SearchHelper.searchForTeam(team, {
query: "test with backslash \\",
});
expect(results.length).toBe(1);
expect(results[0].document?.id).toBe(document.id);
});
it("should return the total count of search results", async () => {
const team = await buildTeam();
const collection = await buildCollection({
teamId: team.id,
});
await buildDocument({
teamId: team.id,
collectionId: collection.id,
title: "test number 1",
});
await buildDocument({
teamId: team.id,
collectionId: collection.id,
title: "test number 2",
});
const { total } = await SearchHelper.searchForTeam(team, {
query: "test",
});
expect(total).toBe(2);
});
it("should return the document when searched with their previous titles", async () => {
const team = await buildTeam();
const collection = await buildCollection({
teamId: team.id,
});
const document = await buildDocument({
teamId: team.id,
collectionId: collection.id,
title: "test number 1",
});
document.title = "change";
await document.save();
const { total } = await SearchHelper.searchForTeam(team, {
query: "test number",
});
expect(total).toBe(1);
});
it("should not return the document when searched with neither the titles nor the previous titles", async () => {
const team = await buildTeam();
const collection = await buildCollection({
teamId: team.id,
});
const document = await buildDocument({
teamId: team.id,
collectionId: collection.id,
title: "test number 1",
});
document.title = "change";
await document.save();
const { total } = await SearchHelper.searchForTeam(team, {
query: "title doesn't exist",
});
expect(total).toBe(0);
});
});
describe("#searchForUser", () => {
it("should return search results from collections", async () => {
const team = await buildTeam();
const user = await buildUser({ teamId: team.id });
const collection = await buildCollection({
userId: user.id,
teamId: team.id,
});
const document = await buildDocument({
userId: user.id,
teamId: team.id,
collectionId: collection.id,
title: "test",
});
await buildDocument({
userId: user.id,
teamId: team.id,
collectionId: collection.id,
deletedAt: new Date(),
title: "test",
});
const { results } = await SearchHelper.searchForUser(user, {
query: "test",
});
expect(results.length).toBe(1);
expect(results[0].ranking).toBeTruthy();
expect(results[0].document?.id).toBe(document.id);
});
it("should return search results for a user without search term", async () => {
const team = await buildTeam();
const user = await buildUser({ teamId: team.id });
const collection = await buildCollection({
teamId: team.id,
userId: user.id,
});
const documents = await Promise.all([
buildDocument({
teamId: team.id,
userId: user.id,
collectionId: collection.id,
title: "document 1",
}),
buildDocument({
teamId: team.id,
userId: user.id,
collectionId: collection.id,
title: "document 2",
}),
]);
const { results } = await SearchHelper.searchForUser(user);
expect(results.length).toBe(2);
expect(results.map((r) => r.document.id).sort()).toEqual(
documents.map((doc) => doc.id).sort()
);
});
it("should return search results from a collection without search term", async () => {
const team = await buildTeam();
const user = await buildUser({ teamId: team.id });
const collection = await buildCollection({
teamId: team.id,
userId: user.id,
});
const documents = await Promise.all([
buildDocument({
teamId: team.id,
userId: user.id,
collectionId: collection.id,
title: "document 1",
}),
buildDocument({
teamId: team.id,
userId: user.id,
collectionId: collection.id,
title: "document 2",
}),
]);
const { results } = await SearchHelper.searchForUser(user, {
collectionId: collection.id,
});
expect(results.length).toBe(2);
expect(results.map((r) => r.document.id).sort()).toEqual(
documents.map((doc) => doc.id).sort()
);
});
it("should not return documents from other collections when filtering by specific collection without search term", async () => {
const team = await buildTeam();
const user = await buildUser({ teamId: team.id });
const collection1 = await buildCollection({
teamId: team.id,
userId: user.id,
});
const collection2 = await buildCollection({
teamId: team.id,
userId: user.id,
});
const docsInCollection1 = await Promise.all([
buildDocument({
teamId: team.id,
userId: user.id,
collectionId: collection1.id,
title: "document 1 in collection 1",
}),
buildDocument({
teamId: team.id,
userId: user.id,
collectionId: collection1.id,
title: "document 2 in collection 1",
}),
]);
await Promise.all([
buildDocument({
teamId: team.id,
userId: user.id,
collectionId: collection2.id,
title: "document 1 in collection 2",
}),
buildDocument({
teamId: team.id,
userId: user.id,
collectionId: collection2.id,
title: "document 2 in collection 2",
}),
]);
const { results } = await SearchHelper.searchForUser(user, {
collectionId: collection1.id,
});
expect(results.length).toBe(2);
expect(results.map((r) => r.document.id).sort()).toEqual(
docsInCollection1.map((doc) => doc.id).sort()
);
});
it("should handle no collections", async () => {
const team = await buildTeam();
const user = await buildUser({ teamId: team.id });
const { results } = await SearchHelper.searchForUser(user, {
query: "test",
});
expect(results.length).toBe(0);
});
it("should search only drafts created by user", async () => {
const user = await buildUser();
await buildDraftDocument({
title: "test",
});
await buildDraftDocument({
teamId: user.teamId,
userId: user.id,
createdById: user.id,
title: "test",
});
await buildDocument({
userId: user.id,
teamId: user.teamId,
createdById: user.id,
title: "test",
});
await buildDocument({
userId: user.id,
teamId: user.teamId,
createdById: user.id,
title: "test",
archivedAt: new Date(),
});
const { results } = await SearchHelper.searchForUser(user, {
query: "test",
statusFilter: [StatusFilter.Draft],
});
expect(results.length).toBe(1);
});
it("should not include drafts with user read permission", async () => {
const user = await buildUser();
await buildDraftDocument({
title: "test",
});
const draft = await buildDraftDocument({
teamId: user.teamId,
userId: user.id,
createdById: user.id,
title: "test",
});
await UserMembership.create({
createdById: user.id,
documentId: draft.id,
userId: user.id,
permission: DocumentPermission.Read,
});
const { results } = await SearchHelper.searchForUser(user, {
query: "test",
statusFilter: [StatusFilter.Published, StatusFilter.Archived],
});
expect(results.length).toBe(0);
});
it("should search only published created by user", async () => {
const user = await buildUser();
await buildDocument({
title: "test",
});
await buildDraftDocument({
teamId: user.teamId,
userId: user.id,
createdById: user.id,
title: "test",
});
await buildDocument({
userId: user.id,
teamId: user.teamId,
createdById: user.id,
title: "test",
});
await buildDocument({
userId: user.id,
teamId: user.teamId,
createdById: user.id,
title: "test",
archivedAt: new Date(),
});
const { results } = await SearchHelper.searchForUser(user, {
query: "test",
statusFilter: [StatusFilter.Published],
});
expect(results.length).toBe(1);
});
it("should search only archived documents created by user", async () => {
const user = await buildUser();
await buildDocument({
title: "test",
});
await buildDraftDocument({
teamId: user.teamId,
userId: user.id,
createdById: user.id,
title: "test",
});
await buildDocument({
userId: user.id,
teamId: user.teamId,
createdById: user.id,
title: "test",
});
await buildDocument({
userId: user.id,
teamId: user.teamId,
createdById: user.id,
title: "test",
});
await buildDocument({
userId: user.id,
teamId: user.teamId,
createdById: user.id,
title: "test",
archivedAt: new Date(),
});
const { results } = await SearchHelper.searchForUser(user, {
query: "test",
statusFilter: [StatusFilter.Archived],
});
expect(results.length).toBe(1);
});
it("should return results from archived and published", async () => {
const user = await buildUser();
await buildDraftDocument({
teamId: user.teamId,
userId: user.id,
createdById: user.id,
title: "test",
});
await buildDocument({
userId: user.id,
teamId: user.teamId,
createdById: user.id,
title: "test",
});
await buildDocument({
userId: user.id,
teamId: user.teamId,
createdById: user.id,
title: "test",
archivedAt: new Date(),
});
const { results } = await SearchHelper.searchForUser(user, {
query: "test",
statusFilter: [StatusFilter.Archived, StatusFilter.Published],
});
expect(results.length).toBe(2);
});
it("should return results from drafts and published", async () => {
const user = await buildUser();
await buildDocument({
userId: user.id,
teamId: user.teamId,
createdById: user.id,
title: "not draft",
});
await buildDraftDocument({
teamId: user.teamId,
userId: user.id,
createdById: user.id,
title: "draft",
});
await buildDocument({
userId: user.id,
teamId: user.teamId,
createdById: user.id,
title: "archived not draft",
archivedAt: new Date(),
});
const { results } = await SearchHelper.searchForUser(user, {
query: "draft",
statusFilter: [StatusFilter.Published, StatusFilter.Draft],
});
expect(results.length).toBe(2);
});
it("should include results from drafts and archived", async () => {
const user = await buildUser();
await buildDocument({
userId: user.id,
teamId: user.teamId,
createdById: user.id,
title: "not draft",
});
await buildDraftDocument({
teamId: user.teamId,
userId: user.id,
createdById: user.id,
title: "draft",
});
await buildDocument({
userId: user.id,
teamId: user.teamId,
createdById: user.id,
title: "archived not draft",
archivedAt: new Date(),
});
const { results } = await SearchHelper.searchForUser(user, {
query: "draft",
statusFilter: [StatusFilter.Draft, StatusFilter.Archived],
});
expect(results.length).toBe(2);
});
it("should return the total count of search results", async () => {
const team = await buildTeam();
const user = await buildUser({ teamId: team.id });
const collection = await buildCollection({
userId: user.id,
teamId: team.id,
});
await buildDocument({
userId: user.id,
teamId: team.id,
collectionId: collection.id,
title: "test number 1",
});
await buildDocument({
userId: user.id,
teamId: team.id,
collectionId: collection.id,
title: "test number 2",
});
const { total } = await SearchHelper.searchForUser(user, {
query: "test",
});
expect(total).toBe(2);
});
it("should return the document when searched with their previous titles", async () => {
const team = await buildTeam();
const user = await buildUser({ teamId: team.id });
const collection = await buildCollection({
teamId: team.id,
userId: user.id,
});
const document = await buildDocument({
teamId: team.id,
userId: user.id,
collectionId: collection.id,
title: "test number 1",
});
document.title = "change";
await document.save();
const { total } = await SearchHelper.searchForUser(user, {
query: "test number",
});
expect(total).toBe(1);
});
it("should not return the document when searched with neither the titles nor the previous titles", async () => {
const team = await buildTeam();
const user = await buildUser({ teamId: team.id });
const collection = await buildCollection({
teamId: team.id,
userId: user.id,
});
const document = await buildDocument({
teamId: team.id,
userId: user.id,
collectionId: collection.id,
title: "test number 1",
});
document.title = "change";
await document.save();
const { total } = await SearchHelper.searchForUser(user, {
query: "title doesn't exist",
});
expect(total).toBe(0);
});
it("should find exact phrases", async () => {
const team = await buildTeam();
const user = await buildUser({ teamId: team.id });
const collection = await buildCollection({
teamId: team.id,
userId: user.id,
});
const document = await buildDocument({
teamId: team.id,
userId: user.id,
collectionId: collection.id,
text: "test number 1",
});
document.title = "change";
await document.save();
const { total } = await SearchHelper.searchForUser(user, {
query: `"test number"`,
});
expect(total).toBe(1);
});
it("should correctly handle removal of trailing spaces", async () => {
const team = await buildTeam();
const user = await buildUser({ teamId: team.id });
const collection = await buildCollection({
teamId: team.id,
userId: user.id,
});
const document = await buildDocument({
teamId: team.id,
userId: user.id,
collectionId: collection.id,
text: "env: some env",
});
document.title = "change";
await document.save();
const { total } = await SearchHelper.searchForUser(user, {
query: "env: ",
});
expect(total).toBe(1);
});
it("should return search results from group memberships", async () => {
const team = await buildTeam();
const user = await buildUser({ teamId: team.id });
const otherUser = await buildUser({ teamId: team.id });
const collection = await buildCollection({
userId: otherUser.id,
teamId: team.id,
permission: null, // private collection
});
const document = await buildDocument({
userId: otherUser.id,
teamId: team.id,
collectionId: collection.id,
title: "group test document",
});
// Document with no access should not appear in results
await buildDocument({
userId: otherUser.id,
teamId: team.id,
collectionId: collection.id,
title: "group test document 2",
});
// Create a group and add the user to it
const group = await buildGroup({
teamId: team.id,
});
await group.$add("user", user, {
through: {
createdById: otherUser.id,
},
});
// Add group membership to the document
await GroupMembership.create({
createdById: otherUser.id,
groupId: group.id,
documentId: document.id,
});
const { results } = await SearchHelper.searchForUser(user, {
query: "group test",
});
expect(results.length).toBe(1);
expect(results[0].ranking).toBeTruthy();
expect(results[0].document?.id).toBe(document.id);
});
});
describe("#searchTitlesForUser", () => {
it("should return search results from collections", async () => {
const team = await buildTeam();
const user = await buildUser({ teamId: team.id });
const collection = await buildCollection({
userId: user.id,
teamId: team.id,
});
const document = await buildDocument({
userId: user.id,
teamId: team.id,
collectionId: collection.id,
title: "test",
});
const documents = await SearchHelper.searchTitlesForUser(user, {
query: "test",
});
expect(documents.length).toBe(1);
expect(documents[0]?.id).toBe(document.id);
});
it("should filter to specific collection", async () => {
const team = await buildTeam();
const user = await buildUser({ teamId: team.id });
const collection = await buildCollection({
userId: user.id,
teamId: team.id,
});
const collection1 = await buildCollection({
userId: user.id,
teamId: team.id,
});
const document = await buildDocument({
userId: user.id,
teamId: team.id,
collectionId: collection.id,
title: "test",
});
await buildDraftDocument({
teamId: team.id,
userId: user.id,
title: "test",
});
await buildDocument({
userId: user.id,
teamId: team.id,
collectionId: collection1.id,
title: "test",
});
const documents = await SearchHelper.searchTitlesForUser(user, {
query: "test",
collectionId: collection.id,
});
expect(documents.length).toBe(1);
expect(documents[0]?.id).toBe(document.id);
});
it("should handle no collections", async () => {
const team = await buildTeam();
const user = await buildUser({ teamId: team.id });
const documents = await SearchHelper.searchTitlesForUser(user, {
query: "test",
});
expect(documents.length).toBe(0);
});
it("should search only drafts created by user", async () => {
const user = await buildUser();
await buildDraftDocument({
title: "test",
});
await buildDraftDocument({
teamId: user.teamId,
userId: user.id,
createdById: user.id,
title: "test",
});
await buildDocument({
userId: user.id,
teamId: user.teamId,
createdById: user.id,
title: "test",
});
await buildDocument({
userId: user.id,
teamId: user.teamId,
createdById: user.id,
title: "test",
archivedAt: new Date(),
});
const documents = await SearchHelper.searchTitlesForUser(user, {
query: "test",
statusFilter: [StatusFilter.Draft],
});
expect(documents.length).toBe(1);
});
it("should search only published created by user", async () => {
const user = await buildUser();
await buildDocument({
title: "test",
});
await buildDraftDocument({
teamId: user.teamId,
userId: user.id,
createdById: user.id,
title: "test",
});
await buildDocument({
userId: user.id,
teamId: user.teamId,
createdById: user.id,
title: "test",
});
await buildDocument({
userId: user.id,
teamId: user.teamId,
createdById: user.id,
title: "test",
archivedAt: new Date(),
});
const documents = await SearchHelper.searchTitlesForUser(user, {
query: "test",
statusFilter: [StatusFilter.Published],
});
expect(documents.length).toBe(1);
});
it("should search only archived documents created by user", async () => {
const user = await buildUser();
await buildDocument({
title: "test",
});
await buildDraftDocument({
teamId: user.teamId,
userId: user.id,
createdById: user.id,
title: "test",
});
await buildDocument({
userId: user.id,
teamId: user.teamId,
createdById: user.id,
title: "test",
});
await buildDocument({
userId: user.id,
teamId: user.teamId,
createdById: user.id,
title: "test",
});
await buildDocument({
userId: user.id,
teamId: user.teamId,
createdById: user.id,
title: "test",
archivedAt: new Date(),
});
const documents = await SearchHelper.searchTitlesForUser(user, {
query: "test",
statusFilter: [StatusFilter.Archived],
});
expect(documents.length).toBe(1);
});
it("should return results from archived and published", async () => {
const user = await buildUser();
await buildDraftDocument({
teamId: user.teamId,
userId: user.id,
createdById: user.id,
title: "test",
});
await buildDocument({
userId: user.id,
teamId: user.teamId,
createdById: user.id,
title: "test",
});
await buildDocument({
userId: user.id,
teamId: user.teamId,
createdById: user.id,
title: "test",
archivedAt: new Date(),
});
const documents = await SearchHelper.searchTitlesForUser(user, {
query: "test",
statusFilter: [StatusFilter.Archived, StatusFilter.Published],
});
expect(documents.length).toBe(2);
});
it("should return results from drafts and published", async () => {
const user = await buildUser();
await buildDocument({
userId: user.id,
teamId: user.teamId,
createdById: user.id,
title: "not draft",
});
await buildDraftDocument({
teamId: user.teamId,
userId: user.id,
createdById: user.id,
title: "draft",
});
await buildDocument({
userId: user.id,
teamId: user.teamId,
createdById: user.id,
title: "archived not draft",
archivedAt: new Date(),
});
const documents = await SearchHelper.searchTitlesForUser(user, {
query: "draft",
statusFilter: [StatusFilter.Published, StatusFilter.Draft],
});
expect(documents.length).toBe(2);
});
it("should include results from drafts and archived", async () => {
const user = await buildUser();
await buildDocument({
userId: user.id,
teamId: user.teamId,
createdById: user.id,
title: "not draft",
});
await buildDraftDocument({
teamId: user.teamId,
userId: user.id,
createdById: user.id,
title: "draft",
});
await buildDocument({
userId: user.id,
teamId: user.teamId,
createdById: user.id,
title: "archived not draft",
archivedAt: new Date(),
});
const documents = await SearchHelper.searchTitlesForUser(user, {
query: "draft",
statusFilter: [StatusFilter.Draft, StatusFilter.Archived],
});
expect(documents.length).toBe(2);
});
it("should return search results from group memberships", async () => {
const team = await buildTeam();
const user = await buildUser({ teamId: team.id });
const otherUser = await buildUser({ teamId: team.id });
const collection = await buildCollection({
userId: otherUser.id,
teamId: team.id,
permission: null, // private collection
});
const document = await buildDocument({
userId: otherUser.id,
teamId: team.id,
collectionId: collection.id,
title: "group title test document",
});
// Document with no access should not appear in results
await buildDocument({
userId: otherUser.id,
teamId: team.id,
collectionId: collection.id,
title: "group title test document 2",
});
// Create a group and add the user to it
const group = await buildGroup({
teamId: team.id,
});
await group.$add("user", user, {
through: {
createdById: otherUser.id,
},
});
// Add group membership to the document
await GroupMembership.create({
createdById: otherUser.id,
groupId: group.id,
documentId: document.id,
});
const documents = await SearchHelper.searchTitlesForUser(user, {
query: "group title",
});
expect(documents.length).toBe(1);
expect(documents[0].id).toBe(document.id);
});
});
describe("#searchCollectionsForUser", () => {
it("should return search results from collections", async () => {
const team = await buildTeam();
const user = await buildUser({ teamId: team.id });
const collection1 = await buildCollection({
teamId: team.id,
userId: user.id,
name: "Test Collection",
});
await buildCollection({
teamId: team.id,
userId: user.id,
name: "Other Collection",
});
const results = await SearchHelper.searchCollectionsForUser(user, {
query: "test",
});
expect(results.length).toBe(1);
expect(results[0].id).toBe(collection1.id);
});
it("should return all collections when no query provided", async () => {
const team = await buildTeam();
const user = await buildUser({ teamId: team.id });
const collection1 = await buildCollection({
teamId: team.id,
userId: user.id,
name: "Alpha",
});
const collection2 = await buildCollection({
teamId: team.id,
userId: user.id,
name: "Beta",
});
const results = await SearchHelper.searchCollectionsForUser(user);
expect(results.length).toBe(2);
expect(results[0].id).toBe(collection1.id);
expect(results[1].id).toBe(collection2.id);
});
});
describe("webSearchQuery", () => {
it("should correctly sanitize query", () => {
expect(SearchHelper.webSearchQuery("one/two")).toBe("one/two:*");
expect(SearchHelper.webSearchQuery("one\\two")).toBe("one\\\\two:*");
expect(SearchHelper.webSearchQuery("test''")).toBe("test");
});
it("should wildcard unquoted queries", () => {
expect(SearchHelper.webSearchQuery("test")).toBe("test:*");
expect(SearchHelper.webSearchQuery("'")).toBe("");
expect(SearchHelper.webSearchQuery("'quoted'")).toBe(`"quoted":*`);
});
it("should wildcard multi-word queries", () => {
expect(SearchHelper.webSearchQuery("this is a test")).toBe(
"this&is&a&test:*"
);
});
it("should not wildcard quoted queries", () => {
expect(SearchHelper.webSearchQuery(`"this is a test"`)).toBe(
`"this<->is<->a<->test"`
);
});
});
});