mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
- added initial tests for dock/__test__/dock-tab.store.test.ts
- fix: make DockTabStore.init() as public/async / handle opts.autoInit == false - fix: increased terminal-tab window spacing Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
parent
10a7db54d0
commit
59efe2a544
115
src/renderer/components/dock/__test__/dock-tab.store.test.ts
Normal file
115
src/renderer/components/dock/__test__/dock-tab.store.test.ts
Normal file
@ -0,0 +1,115 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OpenLens Authors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { jest } from "@jest/globals";
|
||||
import { observable, reaction, toJS } from "mobx";
|
||||
import { StorageHelper } from "../../../utils";
|
||||
import { DockTabStore } from "../dock-tab.store";
|
||||
import type { TabId } from "../dock.store";
|
||||
|
||||
type UtilsModule = typeof import("../../../utils");
|
||||
|
||||
jest.mock("../../../utils", () => {
|
||||
const localStorageMock = observable.map<TabId, unknown>({});
|
||||
const Utils = jest.requireActual("../../../utils") as UtilsModule;
|
||||
|
||||
// Partial module mocking
|
||||
// https://jestjs.io/docs/mock-functions#mocking-partials
|
||||
return {
|
||||
...Utils,
|
||||
createStorage: jest.fn((key: string, defaultValue: unknown) => {
|
||||
return new StorageHelper(key, {
|
||||
defaultValue,
|
||||
storage: {
|
||||
getItem(key: TabId) {
|
||||
localStorageMock.get(key);
|
||||
},
|
||||
setItem(key: TabId, value: unknown) {
|
||||
localStorageMock.set(key, value);
|
||||
},
|
||||
removeItem(key: TabId) {
|
||||
localStorageMock.delete(key);
|
||||
},
|
||||
},
|
||||
});
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
// TODO: add more tests
|
||||
describe(`[DockTabStore]: dock tabs data class-helper`, () => {
|
||||
test("options.autoInit = true (default)", async () => {
|
||||
const tabStorage = new DockTabStore({ autoInit: true });
|
||||
|
||||
expect(tabStorage.initialized).toBeFalsy();
|
||||
expect(tabStorage.dataReady).toBeFalsy();
|
||||
await tabStorage.whenReady;
|
||||
|
||||
expect(tabStorage.dataReady).toBeTruthy();
|
||||
expect(tabStorage.initialized).toBeTruthy();
|
||||
});
|
||||
|
||||
test("options.autoInit = false", async () => {
|
||||
const tabStorage = new DockTabStore({ autoInit: false });
|
||||
|
||||
await tabStorage.whenReady;
|
||||
expect(tabStorage.dataReady).toBeTruthy();
|
||||
expect(tabStorage.initialized).toBeFalsy();
|
||||
|
||||
await tabStorage.init();
|
||||
expect(tabStorage.initialized).toBeTruthy();
|
||||
});
|
||||
|
||||
test(`dockTabStore.getData(tabId) is deeply observable`, async () => {
|
||||
interface TabDataStorageShape {
|
||||
[key: string]: any;
|
||||
account: {
|
||||
name: string;
|
||||
description?: string;
|
||||
}
|
||||
}
|
||||
|
||||
const tabDataHistory: TabDataStorageShape[] = [];
|
||||
const randomTabId = getRandomTabId();
|
||||
const tabStorage = new DockTabStore<TabDataStorageShape>();
|
||||
|
||||
await tabStorage.whenReady;
|
||||
|
||||
reaction(() => toJS(tabStorage.getData(randomTabId)),
|
||||
data => tabDataHistory.push(data),
|
||||
);
|
||||
|
||||
tabStorage.setData(randomTabId, { account: { name: "test" } });
|
||||
|
||||
expect(tabStorage.getData(randomTabId)).toBe(tabStorage.data[randomTabId]);
|
||||
expect(tabStorage.getData(randomTabId).account.name).toBe("test");
|
||||
tabStorage.data[randomTabId].account.name = "updated"; // update deep in the tree
|
||||
|
||||
expect(tabDataHistory.length).toBe(2);
|
||||
expect(tabDataHistory[1].account.name).toBe("updated");
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
export function getRandomTabId(): TabId {
|
||||
return `tab-id-${(Math.random() * Date.now()).toString(16)}`;
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@ export class CreateResourceStore extends DockTabStore<string> {
|
||||
return path.resolve(os.homedir(), "~/.k8slens/templates");
|
||||
}
|
||||
|
||||
protected async init() {
|
||||
async init() {
|
||||
super.init();
|
||||
|
||||
// scan all available templates immediately
|
||||
|
||||
@ -24,18 +24,21 @@ import { autoBind, createStorage, disposer, StorageHelper } from "../../utils";
|
||||
import { dockStore, TabId } from "./dock.store";
|
||||
|
||||
export interface DockTabStoreOptions {
|
||||
autoInit?: boolean; // load data from storage when `storageKey` is provided and bind events, default: true
|
||||
autoInit?: boolean; // load data from storage when `storageKey` is provided and bind events (default: true)
|
||||
storageKey?: string; // save data to persistent storage under the key
|
||||
}
|
||||
|
||||
export class DockTabStore<T extends {}> {
|
||||
@observable.ref private storage?: StorageHelper<Record<TabId, T>>; // available only with `options.storageKey`
|
||||
@observable private _data: Record<TabId, T> = {};
|
||||
export type DockTabStoreShape<T> = Record<TabId, T>;
|
||||
|
||||
export class DockTabStore<T> {
|
||||
@observable.ref private storage?: StorageHelper<DockTabStoreShape<T>>; // available only with `options.storageKey`
|
||||
@observable private _data: DockTabStoreShape<T> = {};
|
||||
@observable dataReady = false; // dock-tab's data ready to interact, e.g. start editing resource
|
||||
@observable initialized = false;
|
||||
|
||||
protected dispose = disposer();
|
||||
|
||||
get data() {
|
||||
get data(): DockTabStoreShape<T> {
|
||||
if (this.options.storageKey) {
|
||||
return this.storage.get();
|
||||
}
|
||||
@ -43,7 +46,7 @@ export class DockTabStore<T extends {}> {
|
||||
return this._data;
|
||||
}
|
||||
|
||||
set data(value: Record<TabId, T>) {
|
||||
set data(value: DockTabStoreShape<T>) {
|
||||
if (this.options.storageKey) {
|
||||
this.storage.set(value);
|
||||
} else {
|
||||
@ -51,7 +54,7 @@ export class DockTabStore<T extends {}> {
|
||||
}
|
||||
}
|
||||
|
||||
protected constructor(protected options: DockTabStoreOptions = {}) {
|
||||
constructor(protected options: DockTabStoreOptions = {}) {
|
||||
makeObservable(this); // must be called *before* autoBind() when used with mobx's method decorators
|
||||
autoBind(this);
|
||||
|
||||
@ -74,12 +77,13 @@ export class DockTabStore<T extends {}> {
|
||||
return Promise.all([
|
||||
dockStore.whenReady,
|
||||
this.storage?.whenReady,
|
||||
]);
|
||||
]).then(() => this.dataReady = true);
|
||||
}
|
||||
|
||||
@action
|
||||
protected init() {
|
||||
this.dataReady = true;
|
||||
async init(): Promise<any> {
|
||||
if (this.initialized) return;
|
||||
this.initialized = true;
|
||||
|
||||
this.dispose.push(
|
||||
dockStore.onTabClose(({ tabId }) => this.clearData(tabId)),
|
||||
@ -102,8 +106,9 @@ export class DockTabStore<T extends {}> {
|
||||
|
||||
@action
|
||||
reset() {
|
||||
this.data = {};
|
||||
this.data = {}; // clears json-file storage when initialized with `opts.storageKey`
|
||||
this.dataReady = false;
|
||||
this.initialized = false;
|
||||
}
|
||||
|
||||
@action
|
||||
|
||||
@ -40,7 +40,7 @@ export class EditResourceStore extends DockTabStore<EditingResource> {
|
||||
autoBind(this);
|
||||
}
|
||||
|
||||
protected init() {
|
||||
async init() {
|
||||
super.init();
|
||||
|
||||
this.dispose.push(
|
||||
|
||||
@ -45,7 +45,7 @@ export class InstallChartStore extends DockTabStore<IChartInstallData> {
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
protected init() {
|
||||
async init() {
|
||||
super.init();
|
||||
|
||||
this.dispose.push(
|
||||
|
||||
@ -59,7 +59,7 @@ export class LogTabStore extends DockTabStore<LogTabData> {
|
||||
]);
|
||||
}
|
||||
|
||||
protected init() {
|
||||
async init() {
|
||||
super.init();
|
||||
|
||||
this.dispose.push(
|
||||
|
||||
@ -25,5 +25,5 @@
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
margin: 10px;
|
||||
margin: $padding*2 $padding $padding $padding*2;
|
||||
}
|
||||
@ -41,7 +41,7 @@ export class UpgradeChartStore extends DockTabStore<IChartUpgradeData> {
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
protected async init() {
|
||||
async init() {
|
||||
super.init();
|
||||
await releaseStore.loadFromContextNamespaces();
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user