[PM-24143] Search performance improvements (#16070)
* [PM-24143] Add perUserCache$ to SearchService index$ * [PM-24143] Cleanup and optimize isSearchable * [PM-24143] Remove unused search flags and subscription from the vault-items component * [PM-24143] Add search text for desktop vault items. Consolidate SearchTextDebounceInterval constant to SearchService * [PM-24143] Ensure cipher search indexing is non-blocking * [PM-24143] Remove redundant index ciphers operation * [PM-24143] Add search performance measurements * [PM-24143] Remove artificial delay * [PM-24143] Remove startWith from index$ to avoid basic search with lunr queries * [PM-24143] Re-organize isSearchable to check long lunr queries for index existencepull/16128/head
parent
ba7e5fdcde
commit
4676a122da
@ -0,0 +1,97 @@
|
||||
import { BehaviorSubject } from "rxjs";
|
||||
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
|
||||
import { FakeStateProvider, mockAccountServiceWith } from "../../../spec";
|
||||
|
||||
import { SearchService } from "./search.service";
|
||||
|
||||
describe("SearchService", () => {
|
||||
let fakeStateProvider: FakeStateProvider;
|
||||
let service: SearchService;
|
||||
|
||||
const userId = "user-id" as UserId;
|
||||
const mockLogService = {
|
||||
error: jest.fn(),
|
||||
measure: jest.fn(),
|
||||
};
|
||||
const mockLocale$ = new BehaviorSubject<string>("en");
|
||||
const mockI18nService = {
|
||||
locale$: mockLocale$.asObservable(),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
||||
fakeStateProvider = new FakeStateProvider(mockAccountServiceWith(userId));
|
||||
service = new SearchService(
|
||||
mockLogService as unknown as LogService,
|
||||
mockI18nService as unknown as I18nService,
|
||||
fakeStateProvider,
|
||||
);
|
||||
});
|
||||
|
||||
describe("isSearchable", () => {
|
||||
let mockIndex$: jest.Mock;
|
||||
beforeEach(() => {
|
||||
mockIndex$ = jest.fn();
|
||||
service["index$"] = mockIndex$;
|
||||
});
|
||||
|
||||
it("returns false if the query is empty", async () => {
|
||||
const result = await service.isSearchable(userId, "");
|
||||
expect(result).toBe(false);
|
||||
// Ensure we do not call the expensive index$ method
|
||||
expect(mockIndex$).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("returns false if the query is null", async () => {
|
||||
const result = await service.isSearchable(userId, null as any);
|
||||
expect(result).toBe(false);
|
||||
// Ensure we do not call the expensive index$ method
|
||||
expect(mockIndex$).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("return true if the query is longer than searchableMinLength", async () => {
|
||||
service["searchableMinLength"] = 3;
|
||||
const result = await service.isSearchable(userId, "test");
|
||||
expect(result).toBe(true);
|
||||
// Ensure we do not call the expensive index$ method
|
||||
expect(mockIndex$).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("returns false if the query is shorter than searchableMinLength", async () => {
|
||||
service["searchableMinLength"] = 5;
|
||||
const result = await service.isSearchable(userId, "test");
|
||||
expect(result).toBe(false);
|
||||
// Ensure we do not call the expensive index$ method
|
||||
expect(mockIndex$).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("returns false for short Lunr query with missing index", async () => {
|
||||
mockIndex$.mockReturnValue(new BehaviorSubject(null));
|
||||
service["searchableMinLength"] = 3;
|
||||
const result = await service.isSearchable(userId, ">l");
|
||||
expect(result).toBe(false);
|
||||
expect(mockIndex$).toHaveBeenCalledWith(userId);
|
||||
});
|
||||
|
||||
it("returns false for long Lunr query with missing index", async () => {
|
||||
mockIndex$.mockReturnValue(new BehaviorSubject(null));
|
||||
service["searchableMinLength"] = 3;
|
||||
const result = await service.isSearchable(userId, ">longer");
|
||||
expect(result).toBe(false);
|
||||
expect(mockIndex$).toHaveBeenCalledWith(userId);
|
||||
});
|
||||
|
||||
it("returns true for short Lunr query with index", async () => {
|
||||
mockIndex$.mockReturnValue(new BehaviorSubject(true));
|
||||
service["searchableMinLength"] = 3;
|
||||
const result = await service.isSearchable(userId, ">l");
|
||||
expect(result).toBe(true);
|
||||
expect(mockIndex$).toHaveBeenCalledWith(userId);
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
Reference in new issue