1
0
mirror of https://github.com/bitwarden/browser.git synced 2025-03-18 14:39:21 +01:00

Split session key and synced item property key ()

This commit is contained in:
Matt Gibson 2022-08-16 09:59:50 -06:00 committed by GitHub
parent 16c41b823b
commit 7c3facec80
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 31 additions and 21 deletions

View File

@ -39,7 +39,7 @@ export function browserSession<TCtor extends Constructor<any>>(constructor: TCto
}
buildSyncer(metadata: SyncedItemMetadata, stateService: StateService) {
const syncer = new SessionSyncer((this as any)[metadata.key], stateService, metadata);
const syncer = new SessionSyncer((this as any)[metadata.propertyKey], stateService, metadata);
syncer.init();
return syncer;
}

View File

@ -14,7 +14,8 @@ describe("sessionSync decorator", () => {
const testClass = new TestClass();
expect((testClass as any).__syncedItemMetadata).toEqual([
expect.objectContaining({
key: "TestClass_testProperty",
propertyKey: "testProperty",
sessionKey: "TestClass_testProperty",
ctor: ctor,
initializer: initializer,
}),

View File

@ -42,7 +42,8 @@ export function sessionSync<T>(buildOptions: BuildOptions<T>) {
}
p.__syncedItemMetadata.push({
key: `${prototype.constructor.name}_${propertyKey}`,
propertyKey,
sessionKey: `${prototype.constructor.name}_${propertyKey}`,
ctor: buildOptions.ctor,
initializer: buildOptions.initializer,
initializeAsArray: buildOptions.initializeAsArray,

View File

@ -7,8 +7,9 @@ import { StateService } from "../../services/abstractions/state.service";
import { SessionSyncer } from "./session-syncer";
describe("session syncer", () => {
const key = "Test__behaviorSubject";
const metaData = { key, initializer: (s: string) => s };
const propertyKey = "behaviorSubject";
const sessionKey = "Test__" + propertyKey;
const metaData = { propertyKey, sessionKey, initializer: (s: string) => s };
let stateService: MockProxy<StateService>;
let sut: SessionSyncer;
let behaviorSubject: BehaviorSubject<string>;
@ -40,18 +41,19 @@ describe("session syncer", () => {
it("should create if either ctor or initializer is provided", () => {
expect(
new SessionSyncer(behaviorSubject, stateService, { key: key, ctor: String })
new SessionSyncer(behaviorSubject, stateService, { propertyKey, sessionKey, ctor: String })
).toBeDefined();
expect(
new SessionSyncer(behaviorSubject, stateService, {
key: key,
propertyKey,
sessionKey,
initializer: (s: any) => s,
})
).toBeDefined();
});
it("should throw if neither ctor or initializer is provided", () => {
expect(() => {
new SessionSyncer(behaviorSubject, stateService, { key: key });
new SessionSyncer(behaviorSubject, stateService, { propertyKey, sessionKey });
}).toThrowError("ctor or initializer must be provided");
});
});
@ -96,7 +98,7 @@ describe("session syncer", () => {
// await finishing of fire-and-forget operation
await new Promise((resolve) => setTimeout(resolve, 100));
expect(stateService.setInSessionMemory).toHaveBeenCalledTimes(1);
expect(stateService.setInSessionMemory).toHaveBeenCalledWith(key, "test");
expect(stateService.setInSessionMemory).toHaveBeenCalledWith(sessionKey, "test");
});
it("should update sessionSyncers in other contexts", async () => {
@ -104,7 +106,7 @@ describe("session syncer", () => {
await new Promise((resolve) => setTimeout(resolve, 100));
expect(sendMessageSpy).toHaveBeenCalledTimes(1);
expect(sendMessageSpy).toHaveBeenCalledWith(`${key}_update`, { id: sut.id });
expect(sendMessageSpy).toHaveBeenCalledWith(`${sessionKey}_update`, { id: sut.id });
});
});
@ -131,7 +133,7 @@ describe("session syncer", () => {
});
it("should ignore messages from itself", async () => {
await sut.updateFromMessage({ command: `${key}_update`, id: sut.id });
await sut.updateFromMessage({ command: `${sessionKey}_update`, id: sut.id });
expect(stateService.getFromSessionMemory).not.toHaveBeenCalled();
expect(nextSpy).not.toHaveBeenCalled();
@ -140,10 +142,10 @@ describe("session syncer", () => {
it("should update from message on emit from another instance", async () => {
stateService.getFromSessionMemory.mockResolvedValue("test");
await sut.updateFromMessage({ command: `${key}_update`, id: "different_id" });
await sut.updateFromMessage({ command: `${sessionKey}_update`, id: "different_id" });
expect(stateService.getFromSessionMemory).toHaveBeenCalledTimes(1);
expect(stateService.getFromSessionMemory).toHaveBeenCalledWith(key);
expect(stateService.getFromSessionMemory).toHaveBeenCalledWith(sessionKey);
expect(nextSpy).toHaveBeenCalledTimes(1);
expect(nextSpy).toHaveBeenCalledWith("test");

View File

@ -62,18 +62,18 @@ export class SessionSyncer {
if (message.command != this.updateMessageCommand || message.id === this.id) {
return;
}
const keyValuePair = await this.stateService.getFromSessionMemory(this.metaData.key);
const keyValuePair = await this.stateService.getFromSessionMemory(this.metaData.sessionKey);
const value = SyncedItemMetadata.buildFromKeyValuePair(keyValuePair, this.metaData);
this.ignoreNextUpdate = true;
this.behaviorSubject.next(value);
}
private async updateSession(value: any) {
await this.stateService.setInSessionMemory(this.metaData.key, value);
await this.stateService.setInSessionMemory(this.metaData.sessionKey, value);
await BrowserApi.sendMessage(this.updateMessageCommand, { id: this.id });
}
private get updateMessageCommand() {
return `${this.metaData.key}_update`;
return `${this.metaData.sessionKey}_update`;
}
}

View File

@ -1,5 +1,6 @@
export class SyncedItemMetadata {
key: string;
propertyKey: string;
sessionKey: string;
ctor?: new () => any;
initializer?: (keyValuePair: any) => any;
initializeAsArray?: boolean;

View File

@ -1,6 +1,7 @@
import { SyncedItemMetadata } from "./sync-item-metadata";
describe("build from key value pair", () => {
const propertyKey = "propertyKey";
const key = "key";
const initializer = (s: any) => "used initializer";
class TestClass {}
@ -10,7 +11,8 @@ describe("build from key value pair", () => {
const actual = SyncedItemMetadata.buildFromKeyValuePair(
{},
{
key: "key",
propertyKey,
sessionKey: "key",
initializer: initializer,
}
);
@ -21,7 +23,8 @@ describe("build from key value pair", () => {
it("should call ctor if provided", () => {
const expected = { provided: "value" };
const actual = SyncedItemMetadata.buildFromKeyValuePair(expected, {
key: key,
propertyKey,
sessionKey: key,
ctor: ctor,
});
@ -33,7 +36,8 @@ describe("build from key value pair", () => {
const actual = SyncedItemMetadata.buildFromKeyValuePair(
{},
{
key: key,
propertyKey,
sessionKey: key,
initializer: initializer,
ctor: ctor,
}
@ -44,7 +48,8 @@ describe("build from key value pair", () => {
it("should honor initialize as array", () => {
const actual = SyncedItemMetadata.buildFromKeyValuePair([1, 2], {
key: key,
propertyKey,
sessionKey: key,
initializer: initializer,
initializeAsArray: true,
});