Ps/allow state provider migrations from v 9 (#7263)

* Provide missing spec helpers and fakers

* We need to be able to migrate v9 stuff to state providers
This commit is contained in:
Matt Gibson 2023-12-18 07:50:04 -05:00 committed by GitHub
parent bc1f93d098
commit 69657a5ab5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 60 additions and 24 deletions

View File

@ -4,6 +4,9 @@ import {
KeyDefinition, KeyDefinition,
ActiveUserState, ActiveUserState,
SingleUserState, SingleUserState,
SingleUserStateProvider,
StateProvider,
ActiveUserStateProvider,
} from "../src/platform/state"; } from "../src/platform/state";
import { UserId } from "../src/types/guid"; import { UserId } from "../src/types/guid";
@ -26,7 +29,7 @@ export class FakeGlobalStateProvider implements GlobalStateProvider {
} }
} }
export class FakeSingleUserStateProvider { export class FakeSingleUserStateProvider implements SingleUserStateProvider {
states: Map<string, SingleUserState<unknown>> = new Map(); states: Map<string, SingleUserState<unknown>> = new Map();
get<T>(userId: UserId, keyDefinition: KeyDefinition<T>): SingleUserState<T> { get<T>(userId: UserId, keyDefinition: KeyDefinition<T>): SingleUserState<T> {
let result = this.states.get(keyDefinition.buildCacheKey("user", userId)) as SingleUserState<T>; let result = this.states.get(keyDefinition.buildCacheKey("user", userId)) as SingleUserState<T>;
@ -43,7 +46,7 @@ export class FakeSingleUserStateProvider {
} }
} }
export class FakeActiveUserStateProvider { export class FakeActiveUserStateProvider implements ActiveUserStateProvider {
states: Map<string, ActiveUserState<unknown>> = new Map(); states: Map<string, ActiveUserState<unknown>> = new Map();
get<T>(keyDefinition: KeyDefinition<T>): ActiveUserState<T> { get<T>(keyDefinition: KeyDefinition<T>): ActiveUserState<T> {
let result = this.states.get( let result = this.states.get(
@ -61,3 +64,21 @@ export class FakeActiveUserStateProvider {
return this.get(keyDefinition) as FakeActiveUserState<T>; return this.get(keyDefinition) as FakeActiveUserState<T>;
} }
} }
export class FakeStateProvider implements StateProvider {
getActive<T>(keyDefinition: KeyDefinition<T>): ActiveUserState<T> {
return this.activeUser.get(keyDefinition);
}
getGlobal<T>(keyDefinition: KeyDefinition<T>): GlobalState<T> {
return this.global.get(keyDefinition);
}
getUser<T>(userId: UserId, keyDefinition: KeyDefinition<T>): SingleUserState<T> {
return this.singleUser.get(userId, keyDefinition);
}
global: FakeGlobalStateProvider = new FakeGlobalStateProvider();
singleUser: FakeSingleUserStateProvider = new FakeSingleUserStateProvider();
activeUser: FakeActiveUserStateProvider = new FakeActiveUserStateProvider();
}

View File

@ -69,7 +69,7 @@ describe("RemoveLegacyEtmKeyMigrator", () => {
describe("getFromGlobal", () => { describe("getFromGlobal", () => {
it("should return the correct value", async () => { it("should return the correct value", async () => {
sut.currentVersion = 10; sut.currentVersion = 9;
const value = await sut.getFromGlobal({ const value = await sut.getFromGlobal({
stateDefinition: { name: "serviceName" }, stateDefinition: { name: "serviceName" },
key: "key", key: "key",
@ -77,33 +77,33 @@ describe("RemoveLegacyEtmKeyMigrator", () => {
expect(value).toEqual("global_serviceName_key"); expect(value).toEqual("global_serviceName_key");
}); });
it("should throw if the current version is less than 10", () => { it("should throw if the current version is less than 9", () => {
expect(() => expect(() =>
sut.getFromGlobal({ stateDefinition: { name: "serviceName" }, key: "key" }), sut.getFromGlobal({ stateDefinition: { name: "serviceName" }, key: "key" }),
).toThrowError("No key builder should be used for versions prior to 10."); ).toThrowError("No key builder should be used for versions prior to 9.");
}); });
}); });
describe("setToGlobal", () => { describe("setToGlobal", () => {
it("should set the correct value", async () => { it("should set the correct value", async () => {
sut.currentVersion = 10; sut.currentVersion = 9;
await sut.setToGlobal({ stateDefinition: { name: "serviceName" }, key: "key" }, "new_value"); await sut.setToGlobal({ stateDefinition: { name: "serviceName" }, key: "key" }, "new_value");
expect(storage.save).toHaveBeenCalledWith("global_serviceName_key", "new_value"); expect(storage.save).toHaveBeenCalledWith("global_serviceName_key", "new_value");
}); });
it("should throw if the current version is less than 10", () => { it("should throw if the current version is less than 9", () => {
expect(() => expect(() =>
sut.setToGlobal( sut.setToGlobal(
{ stateDefinition: { name: "serviceName" }, key: "key" }, { stateDefinition: { name: "serviceName" }, key: "key" },
"global_serviceName_key", "global_serviceName_key",
), ),
).toThrowError("No key builder should be used for versions prior to 10."); ).toThrowError("No key builder should be used for versions prior to 9.");
}); });
}); });
describe("getFromUser", () => { describe("getFromUser", () => {
it("should return the correct value", async () => { it("should return the correct value", async () => {
sut.currentVersion = 10; sut.currentVersion = 9;
const value = await sut.getFromUser("userId", { const value = await sut.getFromUser("userId", {
stateDefinition: { name: "serviceName" }, stateDefinition: { name: "serviceName" },
key: "key", key: "key",
@ -111,16 +111,16 @@ describe("RemoveLegacyEtmKeyMigrator", () => {
expect(value).toEqual("user_userId_serviceName_key"); expect(value).toEqual("user_userId_serviceName_key");
}); });
it("should throw if the current version is less than 10", () => { it("should throw if the current version is less than 9", () => {
expect(() => expect(() =>
sut.getFromUser("userId", { stateDefinition: { name: "serviceName" }, key: "key" }), sut.getFromUser("userId", { stateDefinition: { name: "serviceName" }, key: "key" }),
).toThrowError("No key builder should be used for versions prior to 10."); ).toThrowError("No key builder should be used for versions prior to 9.");
}); });
}); });
describe("setToUser", () => { describe("setToUser", () => {
it("should set the correct value", async () => { it("should set the correct value", async () => {
sut.currentVersion = 10; sut.currentVersion = 9;
await sut.setToUser( await sut.setToUser(
"userId", "userId",
{ stateDefinition: { name: "serviceName" }, key: "key" }, { stateDefinition: { name: "serviceName" }, key: "key" },
@ -129,31 +129,46 @@ describe("RemoveLegacyEtmKeyMigrator", () => {
expect(storage.save).toHaveBeenCalledWith("user_userId_serviceName_key", "new_value"); expect(storage.save).toHaveBeenCalledWith("user_userId_serviceName_key", "new_value");
}); });
it("should throw if the current version is less than 10", () => { it("should throw if the current version is less than 9", () => {
expect(() => expect(() =>
sut.setToUser( sut.setToUser(
"userId", "userId",
{ stateDefinition: { name: "serviceName" }, key: "key" }, { stateDefinition: { name: "serviceName" }, key: "key" },
"new_value", "new_value",
), ),
).toThrowError("No key builder should be used for versions prior to 10."); ).toThrowError("No key builder should be used for versions prior to 9.");
}); });
}); });
}); });
/** Helper to create well-mocked migration helpers in migration tests */ /** Helper to create well-mocked migration helpers in migration tests */
export function mockMigrationHelper(storageJson: any): MockProxy<MigrationHelper> { export function mockMigrationHelper(
storageJson: any,
stateVersion = 0,
): MockProxy<MigrationHelper> {
const logService: MockProxy<LogService> = mock(); const logService: MockProxy<LogService> = mock();
const storage: MockProxy<AbstractStorageService> = mock(); const storage: MockProxy<AbstractStorageService> = mock();
storage.get.mockImplementation((key) => (storageJson as any)[key]); storage.get.mockImplementation((key) => (storageJson as any)[key]);
storage.save.mockImplementation(async (key, value) => { storage.save.mockImplementation(async (key, value) => {
(storageJson as any)[key] = value; (storageJson as any)[key] = value;
}); });
const helper = new MigrationHelper(0, storage, logService); const helper = new MigrationHelper(stateVersion, storage, logService);
const mockHelper = mock<MigrationHelper>(); const mockHelper = mock<MigrationHelper>();
mockHelper.get.mockImplementation((key) => helper.get(key)); mockHelper.get.mockImplementation((key) => helper.get(key));
mockHelper.set.mockImplementation((key, value) => helper.set(key, value)); mockHelper.set.mockImplementation((key, value) => helper.set(key, value));
mockHelper.getFromGlobal.mockImplementation((keyDefinition) =>
helper.getFromGlobal(keyDefinition),
);
mockHelper.setToGlobal.mockImplementation((keyDefinition, value) =>
helper.setToGlobal(keyDefinition, value),
);
mockHelper.getFromUser.mockImplementation((userId, keyDefinition) =>
helper.getFromUser(userId, keyDefinition),
);
mockHelper.setToUser.mockImplementation((userId, keyDefinition, value) =>
helper.setToUser(userId, keyDefinition, value),
);
mockHelper.getAccounts.mockImplementation(() => helper.getAccounts()); mockHelper.getAccounts.mockImplementation(() => helper.getAccounts());
return mockHelper; return mockHelper;
} }

View File

@ -123,8 +123,8 @@ export class MigrationHelper {
* @returns * @returns
*/ */
private getUserKey(userId: string, keyDefinition: KeyDefinitionLike): string { private getUserKey(userId: string, keyDefinition: KeyDefinitionLike): string {
if (this.currentVersion < 10) { if (this.currentVersion < 9) {
return userKeyBuilderPre10(); return userKeyBuilderPre9();
} else { } else {
return userKeyBuilder(userId, keyDefinition); return userKeyBuilder(userId, keyDefinition);
} }
@ -137,8 +137,8 @@ export class MigrationHelper {
* @returns * @returns
*/ */
private getGlobalKey(keyDefinition: KeyDefinitionLike): string { private getGlobalKey(keyDefinition: KeyDefinitionLike): string {
if (this.currentVersion < 10) { if (this.currentVersion < 9) {
return globalKeyBuilderPre10(); return globalKeyBuilderPre9();
} else { } else {
return globalKeyBuilder(keyDefinition); return globalKeyBuilder(keyDefinition);
} }
@ -158,8 +158,8 @@ function userKeyBuilder(userId: string, keyDefinition: KeyDefinitionLike): strin
return `user_${userId}_${keyDefinition.stateDefinition.name}_${keyDefinition.key}`; return `user_${userId}_${keyDefinition.stateDefinition.name}_${keyDefinition.key}`;
} }
function userKeyBuilderPre10(): string { function userKeyBuilderPre9(): string {
throw Error("No key builder should be used for versions prior to 10."); throw Error("No key builder should be used for versions prior to 9.");
} }
/** /**
@ -174,6 +174,6 @@ function globalKeyBuilder(keyDefinition: KeyDefinitionLike): string {
return `global_${keyDefinition.stateDefinition.name}_${keyDefinition.key}`; return `global_${keyDefinition.stateDefinition.name}_${keyDefinition.key}`;
} }
function globalKeyBuilderPre10(): string { function globalKeyBuilderPre9(): string {
throw Error("No key builder should be used for versions prior to 10."); throw Error("No key builder should be used for versions prior to 9.");
} }