Make base store non Singleton (#6690)

* Remove Singleton from BaseStore to remove global shared state

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Remove more usages of Singleton

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Replace use of legacy global execHelm with injectable

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Remove last use of legacy global execHelm

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Extract BaseStore deps into constructor argument

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Introduce method to make store migrations injectable
- Use it for ClusterStore

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Switch HotbarStore to injectable migrations

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Switch UserStore to injectable migrations

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Move migration utils into common/utils/

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Switch WeblinkStore to injectable migrations

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Remove dead code

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix type error in base-store tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Remove tests that reference lastSeenVersion
- That value is not used anywhere in code

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Remove usage of legacy global .getInstance

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Remove usage of legacy global ClusterStore.getInstance

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add simple migrations dependency for stores without any preexisting migrations

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix messed up import

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add typing to transient injectable

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Cleanup formatting

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix typing in tests to satisfy requirement to have cacheFile

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* More consistent use of BaseStore.displayName

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add catching of error while starting main application

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Move initializing sentry to runnable

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Remove unneeded appPathsInjectionToken
- Only had once impl, which was in common anyway

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add support for multiple "runAfter" runnables
- Needed so that several dependencies can be declared

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Use multiple runAfter support to fix crash on renderer

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Remove traces

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add global override to fix tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix base store tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix runManyFor tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix hotbar store tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix user store tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add global override for getConfigurationFileModel to fix tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Remove overrides for configuration stores

- Now that there is an override for getConfiguration

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Overhaul FS fakes with full in-memory filesystem
- This increases our confidence in fs related logic

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Remove use of global shared Electron.App

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add fake access support

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Handle copy as part of fake FS

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add ensureDir/Sync support to fake FS

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix type error

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Use pathExistsSync instead of fsInjectable

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add createReadStream to fake FS

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add stat to fake FS

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Remove dead code

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix test failures due to incomplete overrides

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fully injectable-ize BaseStore so that ApplicationBuilder tests work

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Consolidate more bootstrapping into startFrame

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Move initializing CatalogCategories to runnable in bootstrap

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Convert contextMenuOpen initializers into runnables

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Convert navigateForExtension init to runnable

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Make cluster state sync fully injectable

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Move init hotbar store into runnables

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Make LensTheme fully injectable and runnable

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Cleanup old code from missed from previous commit

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Manually split out terminal color names and fully type LensTheme

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix old imports

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Remove unnecessart awaits

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Remove dead code

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fully cherry pick injectablizing custom monaco themes

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix duplicate mock warning

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix incorrectly fully cherry picking new runnable

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Complete cherry-pick of current cluster injcetablization

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix override file name

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix injecting before app paths are set up

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix injecting before app paths are set up

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix ordering of runnable and order of injection

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Convert all renderer runnables to late-inject style
- To help fix issues around injection time

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix react-beautiful-dnd mocks

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Update and fix WriteJson(Sync) to fix error in tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix HotbarStore.load being called twice is being buggy

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Update listing-active-helm-repositories-in-preferences snapshots

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix sidebar-and-tab-navigation-tests
- Move enabling extensions in tests to a proper location
- Fix flushing promises

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Remove props from dnd mock to make snapshot diffs smaller

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix import

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Update snapshots

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix tests by overriding things that are no longer overriden by default
- NOTE: They are overridden when using ApplicationBuilder

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix hotbar store tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix cluster store tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix extension-loader tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix extension-discovery tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix cluster-role-dialog tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix user store tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix kubeconfig sync tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix sidebar and tab tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Remove unused code

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix pick paths import type error and simplify signature

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix type error in legacy ipc registration

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Remove another use of legacy requestOpenPathPicker

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Replace use of legacy global PathPicker.Pick

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix usage in light of changed prop names

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix catalog tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix more type errors

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix test flakiness by removing side effects from userStore preferences

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Update snapshots

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix loading

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix type error

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix crash

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Cherry pick updated startFrameInjectable

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add tests to verify runMany behaviour in new possible incorrect configuration

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix init ordering during start frame

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix cluster state sync

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Update snapshots after removing side-effects

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add override for technical test

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Correctly mark currentlyInClusterFrame as causedSideEffects

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Better formatting

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix behaviour regression

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add better logging

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix BaseStore sync

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Update last snapshot

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add global override for randomBytes

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Make startMainApplication not an injection time side effect

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Choose better names for start-frame runnable tokens

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Remove duplication of code in RunManyFor

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add unit tests and fix handling empty runAfter array

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Replace use of mobx from runManyFor with custom barrier

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add missing test

Signed-off-by: Sebastian Malton <sebastian@malton.name>

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton authored and GitHub committed 2022-12-15 17:07:19 +02:00
1 parent 7c5faaaf1d
commit 25f37ac1d1
364 files changed
+10035 -5246

No files matched your search

-148
View File
@@ -1,148 +0,0 @@
/**
* 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 { 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";
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() {
super({
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);
TestStore.resetInstance();
const mockOpts = {
"some-user-data-directory": {
"test-store.json": JSON.stringify({}),
},
};
mockFs(mockOpts);
store = TestStore.createInstance();
});
afterEach(() => {
mockFs.restore();
store.disableSync();
TestStore.resetInstance();
});
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);
});
});
});
+15 -23
View File
@@ -93,10 +93,9 @@ describe("cluster-store", () => {
mainDi.override(normalizedPlatformInjectable, () => "darwin");
mainDi.permitSideEffects(getConfigurationFileModelInjectable);
mainDi.permitSideEffects(clusterStoreInjectable);
mainDi.permitSideEffects(fsInjectable);
mainDi.unoverride(getConfigurationFileModelInjectable);
mainDi.unoverride(clusterStoreInjectable);
mainDi.permitSideEffects(fsInjectable);
});
afterEach(() => {
@@ -107,23 +106,19 @@ describe("cluster-store", () => {
let getCustomKubeConfigDirectory: (directoryName: string) => string;
beforeEach(async () => {
getCustomKubeConfigDirectory = mainDi.inject(
getCustomKubeConfigDirectoryInjectable,
);
getCustomKubeConfigDirectory = mainDi.inject(getCustomKubeConfigDirectoryInjectable);
const mockOpts = {
mockFs({
"some-directory-for-user-data": {
"lens-cluster-store.json": JSON.stringify({}),
},
};
mockFs(mockOpts);
});
createCluster = mainDi.inject(createClusterInjectionToken);
clusterStore = mainDi.inject(clusterStoreInjectable);
clusterStore.unregisterIpcListener();
clusterStore.load();
});
afterEach(() => {
@@ -207,7 +202,7 @@ describe("cluster-store", () => {
describe("config with existing clusters", () => {
beforeEach(() => {
const mockOpts = {
mockFs({
"temp-kube-config": kubeconfig,
"some-directory-for-user-data": {
"lens-cluster-store.json": JSON.stringify({
@@ -241,13 +236,12 @@ describe("cluster-store", () => {
],
}),
},
};
mockFs(mockOpts);
});
createCluster = mainDi.inject(createClusterInjectionToken);
clusterStore = mainDi.inject(clusterStoreInjectable);
clusterStore.load();
});
afterEach(() => {
@@ -297,7 +291,7 @@ users:
token: kubeconfig-user-q4lm4:xxxyyyy
`;
const mockOpts = {
mockFs({
"invalid-kube-config": invalidKubeconfig,
"valid-kube-config": kubeconfig,
"some-directory-for-user-data": {
@@ -325,13 +319,12 @@ users:
],
}),
},
};
mockFs(mockOpts);
});
createCluster = mainDi.inject(createClusterInjectionToken);
clusterStore = mainDi.inject(clusterStoreInjectable);
clusterStore.load();
});
afterEach(() => {
@@ -347,7 +340,7 @@ users:
describe("pre 3.6.0-beta.1 config with an existing cluster", () => {
beforeEach(() => {
const mockOpts = {
mockFs({
"some-directory-for-user-data": {
"lens-cluster-store.json": JSON.stringify({
__internal__: {
@@ -368,15 +361,14 @@ users:
}),
icon_path: testDataIcon,
},
};
mockFs(mockOpts);
});
mainDi.override(storeMigrationVersionInjectable, () => "3.6.0");
createCluster = mainDi.inject(createClusterInjectionToken);
clusterStore = mainDi.inject(clusterStoreInjectable);
clusterStore.load();
});
afterEach(() => {
+6 -16
View File
@@ -19,6 +19,7 @@ import loggerInjectable from "../logger.injectable";
import type { Logger } from "../logger";
import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable";
import storeMigrationVersionInjectable from "../vars/store-migration-version.injectable";
import fsInjectable from "../fs/fs.injectable";
function getMockCatalogEntity(data: Partial<CatalogEntityData> & CatalogEntityKindData): CatalogEntity {
return {
@@ -46,7 +47,7 @@ describe("HotbarStore", () => {
beforeEach(async () => {
di = getDiForUnitTesting({ doGeneralOverrides: true });
(di as any).unoverride(hotbarStoreInjectable);
di.unoverride(hotbarStoreInjectable);
testCluster = getMockCatalogEntity({
apiVersion: "v1",
@@ -112,8 +113,9 @@ describe("HotbarStore", () => {
catalogCatalogEntity,
]));
di.permitSideEffects(fsInjectable);
di.permitSideEffects(getConfigurationFileModelInjectable);
di.permitSideEffects(hotbarStoreInjectable);
di.unoverride(getConfigurationFileModelInjectable);
});
afterEach(() => {
@@ -255,22 +257,12 @@ describe("HotbarStore", () => {
});
it("throws if invalid arguments provided", () => {
// Prevent writing to stderr during this render.
const { error, warn } = console;
console.error = jest.fn();
console.warn = jest.fn();
hotbarStore.addToHotbar(testCluster);
expect(() => hotbarStore.restackItems(-5, 0)).toThrow();
expect(() => hotbarStore.restackItems(2, -1)).toThrow();
expect(() => hotbarStore.restackItems(14, 1)).toThrow();
expect(() => hotbarStore.restackItems(11, 112)).toThrow();
// Restore writing to stderr.
console.error = error;
console.warn = warn;
});
it("checks if entity already pinned to hotbar", () => {
@@ -284,7 +276,7 @@ describe("HotbarStore", () => {
describe("given data from 5.0.0-beta.3 and version being 5.0.0-beta.10", () => {
beforeEach(() => {
const configurationToBeMigrated = {
mockFs({
"some-directory-for-user-data": {
"lens-hotbar-store.json": JSON.stringify({
__internal__: {
@@ -344,9 +336,7 @@ describe("HotbarStore", () => {
],
}),
},
};
mockFs(configurationToBeMigrated);
});
di.override(storeMigrationVersionInjectable, () => "5.0.0-beta.10");
+12 -18
View File
@@ -35,6 +35,7 @@ import getConfigurationFileModelInjectable from "../get-configuration-file-model
import storeMigrationVersionInjectable from "../vars/store-migration-version.injectable";
import releaseChannelInjectable from "../vars/release-channel.injectable";
import defaultUpdateChannelInjectable from "../../features/application-update/common/selected-update-channel/default-update-channel.injectable";
import fsInjectable from "../fs/fs.injectable";
console = new Console(stdout, stderr);
@@ -49,8 +50,10 @@ describe("user store tests", () => {
di.override(writeFileInjectable, () => () => Promise.resolve());
di.override(directoryForUserDataInjectable, () => "some-directory-for-user-data");
di.permitSideEffects(getConfigurationFileModelInjectable);
di.permitSideEffects(userStoreInjectable);
di.unoverride(getConfigurationFileModelInjectable);
di.permitSideEffects(fsInjectable);
di.override(releaseChannelInjectable, () => ({
get: () => "latest" as const,
@@ -58,7 +61,7 @@ describe("user store tests", () => {
}));
await di.inject(defaultUpdateChannelInjectable).init();
di.unoverride(userStoreInjectable);
userStore = di.inject(userStoreInjectable);
});
afterEach(() => {
@@ -67,17 +70,11 @@ describe("user store tests", () => {
describe("for an empty config", () => {
beforeEach(() => {
mockFs({ "some-directory-for-user-data": { "config.json": "{}", "kube_config": "{}" }});
mockFs({ "some-directory-for-user-data": { "lens-user-store.json": "{}", "kube_config": "{}" }});
userStore = di.inject(userStoreInjectable);
userStore.load();
});
it("allows setting and retrieving lastSeenAppVersion", () => {
userStore.lastSeenAppVersion = "1.2.3";
expect(userStore.lastSeenAppVersion).toBe("1.2.3");
});
it("allows setting and getting preferences", () => {
userStore.httpsProxy = "abcd://defg";
@@ -99,10 +96,8 @@ describe("user store tests", () => {
beforeEach(() => {
mockFs({
"some-directory-for-user-data": {
"config.json": JSON.stringify({
user: { username: "foobar" },
"lens-user-store.json": JSON.stringify({
preferences: { colorTheme: "light" },
lastSeenAppVersion: "1.2.3",
}),
"lens-cluster-store.json": JSON.stringify({
clusters: [
@@ -127,17 +122,16 @@ describe("user store tests", () => {
di.override(storeMigrationVersionInjectable, () => "10.0.0");
userStore = di.inject(userStoreInjectable);
userStore.load();
});
it("sets last seen app version to 0.0.0", () => {
expect(userStore.lastSeenAppVersion).toBe("0.0.0");
});
it.only("skips clusters for adding to kube-sync with files under extension_data/", () => {
it("skips clusters for adding to kube-sync with files under extension_data/", () => {
expect(userStore.syncKubeconfigEntries.has("some-directory-for-user-data/extension_data/foo/bar")).toBe(false);
expect(userStore.syncKubeconfigEntries.has("some/other/path")).toBe(true);
});
it("allows access to the colorTheme preference", () => {
expect(userStore.colorTheme).toBe("light");
});
});
});