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");
|
return path.resolve(os.homedir(), "~/.k8slens/templates");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async init() {
|
async init() {
|
||||||
super.init();
|
super.init();
|
||||||
|
|
||||||
// scan all available templates immediately
|
// scan all available templates immediately
|
||||||
|
|||||||
@ -24,18 +24,21 @@ import { autoBind, createStorage, disposer, StorageHelper } from "../../utils";
|
|||||||
import { dockStore, TabId } from "./dock.store";
|
import { dockStore, TabId } from "./dock.store";
|
||||||
|
|
||||||
export interface DockTabStoreOptions {
|
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
|
storageKey?: string; // save data to persistent storage under the key
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DockTabStore<T extends {}> {
|
export type DockTabStoreShape<T> = Record<TabId, T>;
|
||||||
@observable.ref private storage?: StorageHelper<Record<TabId, T>>; // available only with `options.storageKey`
|
|
||||||
@observable private _data: 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 dataReady = false; // dock-tab's data ready to interact, e.g. start editing resource
|
||||||
|
@observable initialized = false;
|
||||||
|
|
||||||
protected dispose = disposer();
|
protected dispose = disposer();
|
||||||
|
|
||||||
get data() {
|
get data(): DockTabStoreShape<T> {
|
||||||
if (this.options.storageKey) {
|
if (this.options.storageKey) {
|
||||||
return this.storage.get();
|
return this.storage.get();
|
||||||
}
|
}
|
||||||
@ -43,7 +46,7 @@ export class DockTabStore<T extends {}> {
|
|||||||
return this._data;
|
return this._data;
|
||||||
}
|
}
|
||||||
|
|
||||||
set data(value: Record<TabId, T>) {
|
set data(value: DockTabStoreShape<T>) {
|
||||||
if (this.options.storageKey) {
|
if (this.options.storageKey) {
|
||||||
this.storage.set(value);
|
this.storage.set(value);
|
||||||
} else {
|
} 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
|
makeObservable(this); // must be called *before* autoBind() when used with mobx's method decorators
|
||||||
autoBind(this);
|
autoBind(this);
|
||||||
|
|
||||||
@ -74,12 +77,13 @@ export class DockTabStore<T extends {}> {
|
|||||||
return Promise.all([
|
return Promise.all([
|
||||||
dockStore.whenReady,
|
dockStore.whenReady,
|
||||||
this.storage?.whenReady,
|
this.storage?.whenReady,
|
||||||
]);
|
]).then(() => this.dataReady = true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
protected init() {
|
async init(): Promise<any> {
|
||||||
this.dataReady = true;
|
if (this.initialized) return;
|
||||||
|
this.initialized = true;
|
||||||
|
|
||||||
this.dispose.push(
|
this.dispose.push(
|
||||||
dockStore.onTabClose(({ tabId }) => this.clearData(tabId)),
|
dockStore.onTabClose(({ tabId }) => this.clearData(tabId)),
|
||||||
@ -102,8 +106,9 @@ export class DockTabStore<T extends {}> {
|
|||||||
|
|
||||||
@action
|
@action
|
||||||
reset() {
|
reset() {
|
||||||
this.data = {};
|
this.data = {}; // clears json-file storage when initialized with `opts.storageKey`
|
||||||
this.dataReady = false;
|
this.dataReady = false;
|
||||||
|
this.initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
|
|||||||
@ -40,7 +40,7 @@ export class EditResourceStore extends DockTabStore<EditingResource> {
|
|||||||
autoBind(this);
|
autoBind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected init() {
|
async init() {
|
||||||
super.init();
|
super.init();
|
||||||
|
|
||||||
this.dispose.push(
|
this.dispose.push(
|
||||||
|
|||||||
@ -45,7 +45,7 @@ export class InstallChartStore extends DockTabStore<IChartInstallData> {
|
|||||||
makeObservable(this);
|
makeObservable(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected init() {
|
async init() {
|
||||||
super.init();
|
super.init();
|
||||||
|
|
||||||
this.dispose.push(
|
this.dispose.push(
|
||||||
|
|||||||
@ -59,7 +59,7 @@ export class LogTabStore extends DockTabStore<LogTabData> {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected init() {
|
async init() {
|
||||||
super.init();
|
super.init();
|
||||||
|
|
||||||
this.dispose.push(
|
this.dispose.push(
|
||||||
|
|||||||
@ -25,5 +25,5 @@
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
margin: 10px;
|
margin: $padding*2 $padding $padding $padding*2;
|
||||||
}
|
}
|
||||||
@ -41,7 +41,7 @@ export class UpgradeChartStore extends DockTabStore<IChartUpgradeData> {
|
|||||||
makeObservable(this);
|
makeObservable(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async init() {
|
async init() {
|
||||||
super.init();
|
super.init();
|
||||||
await releaseStore.loadFromContextNamespaces();
|
await releaseStore.loadFromContextNamespaces();
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user