[PM-6965] Add `type` Property to `MigrationHelper` (#8411)

* Add `type` Property to `MigrationHelper`

* Fix Tests

* Make `type` parameter required

* Fix mockHelper.type

* Remove `readonly` from `type`
This commit is contained in:
Justin Baur 2024-03-25 09:28:42 -05:00 committed by GitHub
parent 8639f494f3
commit 908d3d165e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 37 additions and 14 deletions

View File

@ -46,7 +46,7 @@ class WebMigrationHelper extends MigrationHelper {
storageService: WindowStorageService,
logService: LogService,
) {
super(currentVersion, storageService, logService);
super(currentVersion, storageService, logService, "web-disk-local");
this.diskLocalStorageService = storageService;
}

View File

@ -82,6 +82,7 @@ describe("MigrationBuilderService", () => {
startingStateVersion,
new FakeStorageService(startingState),
mock(),
"general",
);
await sut.build().migrate(helper);

View File

@ -18,6 +18,7 @@ export class MigrationRunner {
await currentVersion(this.diskStorage, this.logService),
this.diskStorage,
this.logService,
"general",
);
if (migrationHelper.currentVersion < 0) {

View File

@ -83,35 +83,35 @@ describe("MigrationBuilder", () => {
});
it("should migrate", async () => {
const helper = new MigrationHelper(0, mock(), mock());
const helper = new MigrationHelper(0, mock(), mock(), "general");
const spy = jest.spyOn(migrator, "migrate");
await sut.migrate(helper);
expect(spy).toBeCalledWith(helper);
});
it("should rollback", async () => {
const helper = new MigrationHelper(1, mock(), mock());
const helper = new MigrationHelper(1, mock(), mock(), "general");
const spy = jest.spyOn(rollback_migrator, "rollback");
await sut.migrate(helper);
expect(spy).toBeCalledWith(helper);
});
it("should update version on migrate", async () => {
const helper = new MigrationHelper(0, mock(), mock());
const helper = new MigrationHelper(0, mock(), mock(), "general");
const spy = jest.spyOn(migrator, "updateVersion");
await sut.migrate(helper);
expect(spy).toBeCalledWith(helper, "up");
});
it("should update version on rollback", async () => {
const helper = new MigrationHelper(1, mock(), mock());
const helper = new MigrationHelper(1, mock(), mock(), "general");
const spy = jest.spyOn(rollback_migrator, "updateVersion");
await sut.migrate(helper);
expect(spy).toBeCalledWith(helper, "down");
});
it("should not run the migrator if the current version does not match the from version", async () => {
const helper = new MigrationHelper(3, mock(), mock());
const helper = new MigrationHelper(3, mock(), mock(), "general");
const migrate = jest.spyOn(migrator, "migrate");
const rollback = jest.spyOn(rollback_migrator, "rollback");
await sut.migrate(helper);
@ -120,7 +120,7 @@ describe("MigrationBuilder", () => {
});
it("should not update version if the current version does not match the from version", async () => {
const helper = new MigrationHelper(3, mock(), mock());
const helper = new MigrationHelper(3, mock(), mock(), "general");
const migrate = jest.spyOn(migrator, "updateVersion");
const rollback = jest.spyOn(rollback_migrator, "updateVersion");
await sut.migrate(helper);
@ -130,7 +130,7 @@ describe("MigrationBuilder", () => {
});
it("should be able to call instance methods", async () => {
const helper = new MigrationHelper(0, mock(), mock());
const helper = new MigrationHelper(0, mock(), mock(), "general");
await sut.with(TestMigratorWithInstanceMethod, 0, 1).migrate(helper);
});
});

View File

@ -9,7 +9,7 @@ import { AbstractStorageService } from "../platform/abstractions/storage.service
// eslint-disable-next-line import/no-restricted-paths -- Needed to generate unique strings for injection
import { Utils } from "../platform/misc/utils";
import { MigrationHelper } from "./migration-helper";
import { MigrationHelper, MigrationHelperType } from "./migration-helper";
import { Migrator } from "./migrator";
const exampleJSON = {
@ -37,7 +37,7 @@ describe("RemoveLegacyEtmKeyMigrator", () => {
storage = mock();
storage.get.mockImplementation((key) => (exampleJSON as any)[key]);
sut = new MigrationHelper(0, storage, logService);
sut = new MigrationHelper(0, storage, logService, "general");
});
describe("get", () => {
@ -150,6 +150,7 @@ describe("RemoveLegacyEtmKeyMigrator", () => {
export function mockMigrationHelper(
storageJson: any,
stateVersion = 0,
type: MigrationHelperType = "general",
): MockProxy<MigrationHelper> {
const logService: MockProxy<LogService> = mock();
const storage: MockProxy<AbstractStorageService> = mock();
@ -157,7 +158,7 @@ export function mockMigrationHelper(
storage.save.mockImplementation(async (key, value) => {
(storageJson as any)[key] = value;
});
const helper = new MigrationHelper(stateVersion, storage, logService);
const helper = new MigrationHelper(stateVersion, storage, logService, type);
const mockHelper = mock<MigrationHelper>();
mockHelper.get.mockImplementation((key) => helper.get(key));
@ -175,6 +176,9 @@ export function mockMigrationHelper(
helper.setToUser(userId, keyDefinition, value),
);
mockHelper.getAccounts.mockImplementation(() => helper.getAccounts());
mockHelper.type = helper.type;
return mockHelper;
}
@ -291,7 +295,7 @@ export async function runMigrator<
const allInjectedData = injectData(initalData, []);
const fakeStorageService = new FakeStorageService(initalData);
const helper = new MigrationHelper(migrator.fromVersion, fakeStorageService, mock());
const helper = new MigrationHelper(migrator.fromVersion, fakeStorageService, mock(), "general");
// Run their migrations
if (direction === "rollback") {

View File

@ -9,12 +9,29 @@ export type KeyDefinitionLike = {
key: string;
};
export type MigrationHelperType = "general" | "web-disk-local";
export class MigrationHelper {
constructor(
public currentVersion: number,
private storageService: AbstractStorageService,
public logService: LogService,
) {}
type: MigrationHelperType,
) {
this.type = type;
}
/**
* On some clients, migrations are ran multiple times without direct action from the migration writer.
*
* All clients will run through migrations at least once, this run is referred to as `"general"`. If a migration is
* ran more than that single time, they will get a unique name if that the write can make conditional logic based on which
* migration run this is.
*
* @remarks The preferrable way of writing migrations is ALWAYS to be defensive and reflect on the data you are given back. This
* should really only be used when reflecting on the data given isn't enough.
*/
type: MigrationHelperType;
/**
* Gets a value from the storage service at the given key.

View File

@ -26,7 +26,7 @@ describe("migrator default methods", () => {
beforeEach(() => {
storage = mock();
logService = mock();
helper = new MigrationHelper(0, storage, logService);
helper = new MigrationHelper(0, storage, logService, "general");
sut = new TestMigrator(0, 1);
});