mirror of
https://github.com/bitwarden/browser
synced 2025-12-16 16:23:44 +00:00
[PM-5539] Migrate ThemingService (#8219)
* Update ThemingService * Finish ThemingService * Lint * More Tests & Docs * Refactor to ThemeStateService * Rename File * Fix Import * Remove `type` added to imports * Update InitServices * Fix Test * Remove Unreferenced Code * Remove Unneeded Null Check * Add Ticket Link * Add Back THEMING_DISK * Fix Desktop * Create SYSTEM_THEME_OBSERVABLE * Fix Browser Injection * Update Desktop Manual Access * Fix Default Theme * Update Test
This commit is contained in:
@@ -30,6 +30,7 @@ import { EnableContextMenuMigrator } from "./migrations/31-move-enable-context-m
|
||||
import { PreferredLanguageMigrator } from "./migrations/32-move-preferred-language";
|
||||
import { AppIdMigrator } from "./migrations/33-move-app-id-to-state-providers";
|
||||
import { DomainSettingsMigrator } from "./migrations/34-move-domain-settings-to-state-providers";
|
||||
import { MoveThemeToStateProviderMigrator } from "./migrations/35-move-theme-to-state-providers";
|
||||
import { RemoveEverBeenUnlockedMigrator } from "./migrations/4-remove-ever-been-unlocked";
|
||||
import { AddKeyTypeToOrgKeysMigrator } from "./migrations/5-add-key-type-to-org-keys";
|
||||
import { RemoveLegacyEtmKeyMigrator } from "./migrations/6-remove-legacy-etm-key";
|
||||
@@ -39,7 +40,7 @@ import { MoveBrowserSettingsToGlobal } from "./migrations/9-move-browser-setting
|
||||
import { MinVersionMigrator } from "./migrations/min-version";
|
||||
|
||||
export const MIN_VERSION = 2;
|
||||
export const CURRENT_VERSION = 34;
|
||||
export const CURRENT_VERSION = 35;
|
||||
export type MinVersion = typeof MIN_VERSION;
|
||||
|
||||
export function createMigrationBuilder() {
|
||||
@@ -76,7 +77,8 @@ export function createMigrationBuilder() {
|
||||
.with(EnableContextMenuMigrator, 30, 31)
|
||||
.with(PreferredLanguageMigrator, 31, 32)
|
||||
.with(AppIdMigrator, 32, 33)
|
||||
.with(DomainSettingsMigrator, 33, CURRENT_VERSION);
|
||||
.with(DomainSettingsMigrator, 33, 34)
|
||||
.with(MoveThemeToStateProviderMigrator, 34, CURRENT_VERSION);
|
||||
}
|
||||
|
||||
export async function currentVersion(
|
||||
|
||||
@@ -286,7 +286,11 @@ function expectInjectedData(
|
||||
export async function runMigrator<
|
||||
TMigrator extends Migrator<number, number>,
|
||||
TUsers extends readonly string[] = string[],
|
||||
>(migrator: TMigrator, initalData?: InitialDataHint<TUsers>): Promise<Record<string, unknown>> {
|
||||
>(
|
||||
migrator: TMigrator,
|
||||
initalData?: InitialDataHint<TUsers>,
|
||||
direction: "migrate" | "rollback" = "migrate",
|
||||
): Promise<Record<string, unknown>> {
|
||||
// Inject fake data at every level of the object
|
||||
const allInjectedData = injectData(initalData, []);
|
||||
|
||||
@@ -294,7 +298,11 @@ export async function runMigrator<
|
||||
const helper = new MigrationHelper(migrator.fromVersion, fakeStorageService, mock());
|
||||
|
||||
// Run their migrations
|
||||
await migrator.migrate(helper);
|
||||
if (direction === "rollback") {
|
||||
await migrator.rollback(helper);
|
||||
} else {
|
||||
await migrator.migrate(helper);
|
||||
}
|
||||
const [data, leftoverInjectedData] = expectInjectedData(
|
||||
fakeStorageService.internalStore,
|
||||
allInjectedData,
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
import { runMigrator } from "../migration-helper.spec";
|
||||
|
||||
import { MoveThemeToStateProviderMigrator } from "./35-move-theme-to-state-providers";
|
||||
|
||||
describe("MoveThemeToStateProviders", () => {
|
||||
const sut = new MoveThemeToStateProviderMigrator(34, 35);
|
||||
|
||||
describe("migrate", () => {
|
||||
it("migrates global theme and deletes it", async () => {
|
||||
const output = await runMigrator(sut, {
|
||||
global: {
|
||||
theme: "dark",
|
||||
},
|
||||
});
|
||||
|
||||
expect(output).toEqual({
|
||||
global_theming_selection: "dark",
|
||||
global: {},
|
||||
});
|
||||
});
|
||||
|
||||
it.each([{}, null])(
|
||||
"doesn't touch it if global state looks like: '%s'",
|
||||
async (globalState) => {
|
||||
const output = await runMigrator(sut, {
|
||||
global: globalState,
|
||||
});
|
||||
|
||||
expect(output).toEqual({
|
||||
global: globalState,
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe("rollback", () => {
|
||||
it("migrates state provider theme back to original location when no global", async () => {
|
||||
const output = await runMigrator(
|
||||
sut,
|
||||
{
|
||||
global_theming_selection: "disk",
|
||||
},
|
||||
"rollback",
|
||||
);
|
||||
|
||||
expect(output).toEqual({
|
||||
global: {
|
||||
theme: "disk",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("migrates state provider theme back to legacy location when there is an existing global object", async () => {
|
||||
const output = await runMigrator(
|
||||
sut,
|
||||
{
|
||||
global_theming_selection: "disk",
|
||||
global: {
|
||||
other: "stuff",
|
||||
},
|
||||
},
|
||||
"rollback",
|
||||
);
|
||||
|
||||
expect(output).toEqual({
|
||||
global: {
|
||||
theme: "disk",
|
||||
other: "stuff",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("does nothing if no theme in state provider location", async () => {
|
||||
const output = await runMigrator(sut, {}, "rollback");
|
||||
expect(output).toEqual({});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,31 @@
|
||||
import { KeyDefinitionLike, MigrationHelper } from "../migration-helper";
|
||||
import { Migrator } from "../migrator";
|
||||
|
||||
type ExpectedGlobal = { theme?: string };
|
||||
|
||||
const THEME_SELECTION: KeyDefinitionLike = {
|
||||
key: "selection",
|
||||
stateDefinition: { name: "theming" },
|
||||
};
|
||||
|
||||
export class MoveThemeToStateProviderMigrator extends Migrator<34, 35> {
|
||||
async migrate(helper: MigrationHelper): Promise<void> {
|
||||
const legacyGlobalState = await helper.get<ExpectedGlobal>("global");
|
||||
const theme = legacyGlobalState?.theme;
|
||||
if (theme != null) {
|
||||
await helper.setToGlobal(THEME_SELECTION, theme);
|
||||
delete legacyGlobalState.theme;
|
||||
await helper.set("global", legacyGlobalState);
|
||||
}
|
||||
}
|
||||
|
||||
async rollback(helper: MigrationHelper): Promise<void> {
|
||||
const theme = await helper.getFromGlobal<string>(THEME_SELECTION);
|
||||
if (theme != null) {
|
||||
const legacyGlobal = (await helper.get<ExpectedGlobal>("global")) ?? {};
|
||||
legacyGlobal.theme = theme;
|
||||
await helper.set("global", legacyGlobal);
|
||||
await helper.removeFromGlobal(THEME_SELECTION);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user