1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00
lens/src/common/__tests__/base-store.test.ts
Sebastian Malton 3dce6f916e Extract BaseStore deps into constructor argument
Signed-off-by: Sebastian Malton <sebastian@malton.name>
2022-12-06 09:18:58 -05:00

154 lines
4.0 KiB
TypeScript

/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import mockFs from "mock-fs";
import type { BaseStoreDependencies } from "../base-store";
import { BaseStore } from "../base-store";
import { action, comparer, makeObservable, observable, toJS } from "mobx";
import { readFileSync } from "fs";
import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable";
import { getDiForUnitTesting } from "../../main/getDiForUnitTesting";
import getConfigurationFileModelInjectable from "../get-configuration-file-model/get-configuration-file-model.injectable";
import loggerInjectable from "../logger.injectable";
import storeMigrationVersionInjectable from "../vars/store-migration-version.injectable";
jest.mock("electron", () => ({
ipcMain: {
on: jest.fn(),
off: jest.fn(),
},
}));
interface TestStoreModel {
a: string;
b: string;
c: string;
}
class TestStore extends BaseStore<TestStoreModel> {
@observable a = "";
@observable b = "";
@observable c = "";
constructor(deps: BaseStoreDependencies) {
super(deps, {
configName: "test-store",
accessPropertiesByDotNotation: false, // To make dots safe in cluster context names
syncOptions: {
equals: comparer.structural,
},
});
makeObservable(this);
this.load();
}
@action updateAll(data: TestStoreModel) {
this.a = data.a;
this.b = data.b;
this.c = data.c;
}
@action fromStore(data: Partial<TestStoreModel> = {}) {
this.a = data.a || "";
this.b = data.b || "";
this.c = data.c || "";
}
onSync(data: TestStoreModel) {
super.onSync(data);
}
async saveToFile(model: TestStoreModel) {
return super.saveToFile(model);
}
toJSON(): TestStoreModel {
const data: TestStoreModel = {
a: this.a,
b: this.b,
c: this.c,
};
return toJS(data);
}
}
describe("BaseStore", () => {
let store: TestStore;
beforeEach(() => {
const mainDi = getDiForUnitTesting({ doGeneralOverrides: true });
mainDi.override(directoryForUserDataInjectable, () => "some-user-data-directory");
mainDi.permitSideEffects(getConfigurationFileModelInjectable);
const mockOpts = {
"some-user-data-directory": {
"test-store.json": JSON.stringify({}),
},
};
mockFs(mockOpts);
store = new TestStore({
directoryForUserData: mainDi.inject(directoryForUserDataInjectable),
getConfigurationFileModel: mainDi.inject(getConfigurationFileModelInjectable),
logger: mainDi.inject(loggerInjectable),
storeMigrationVersion: mainDi.inject(storeMigrationVersionInjectable),
});
});
afterEach(() => {
mockFs.restore();
store.disableSync();
});
describe("persistence", () => {
it("persists changes to the filesystem", () => {
store.updateAll({
a: "foo", b: "bar", c: "hello",
});
const data = JSON.parse(readFileSync("some-user-data-directory/test-store.json").toString());
expect(data).toEqual({ a: "foo", b: "bar", c: "hello" });
});
it("persists transaction only once", () => {
const fileSpy = jest.spyOn(store, "saveToFile");
store.updateAll({
a: "foo", b: "bar", c: "hello",
});
expect(fileSpy).toHaveBeenCalledTimes(1);
});
it("persists changes one-by-one without transaction", () => {
const fileSpy = jest.spyOn(store, "saveToFile");
store.a = "a";
store.b = "b";
expect(fileSpy).toHaveBeenCalledTimes(2);
const data = JSON.parse(readFileSync("some-user-data-directory/test-store.json").toString());
expect(data).toEqual({ a: "a", b: "b", c: "" });
});
it("persists changes coming via onSync (sync from different process)", () => {
const fileSpy = jest.spyOn(store, "saveToFile");
store.onSync({ a: "foo", b: "", c: "bar" });
expect(store.toJSON()).toEqual({ a: "foo", b: "", c: "bar" });
expect(fileSpy).toHaveBeenCalledTimes(1);
});
});
});