Add extension and storage paths to App container (#1756)
This commit is contained in:
@@ -2,4 +2,7 @@ import { AppEventEmitter } from './events';
|
||||
|
||||
export interface App {
|
||||
createEventEmitter<T>(): AppEventEmitter<T>;
|
||||
extensionPath: string;
|
||||
globalStoragePath: string;
|
||||
workspaceStoragePath?: string;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,26 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { App } from '../app';
|
||||
import { AppEventEmitter } from '../events';
|
||||
import { VSCodeAppEventEmitter } from './events';
|
||||
|
||||
export class ExtensionApp implements App {
|
||||
public constructor(
|
||||
public readonly extensionContext: vscode.ExtensionContext
|
||||
) {
|
||||
}
|
||||
|
||||
public get extensionPath(): string {
|
||||
return this.extensionContext.extensionPath;
|
||||
}
|
||||
|
||||
public get globalStoragePath(): string {
|
||||
return this.extensionContext.globalStorageUri.fsPath;
|
||||
}
|
||||
|
||||
public get workspaceStoragePath(): string | undefined {
|
||||
return this.extensionContext.storageUri?.fsPath;
|
||||
}
|
||||
|
||||
public createEventEmitter<T>(): AppEventEmitter<T> {
|
||||
return new VSCodeAppEventEmitter<T>();
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import * as chokidar from 'chokidar';
|
||||
import { DisposableObject } from '../pure/disposable-object';
|
||||
import { DbConfigValidator } from './db-config-validator';
|
||||
import { ValueResult } from '../common/value-result';
|
||||
import { App } from '../common/app';
|
||||
|
||||
export class DbConfigStore extends DisposableObject {
|
||||
private readonly configPath: string;
|
||||
@@ -14,17 +15,16 @@ export class DbConfigStore extends DisposableObject {
|
||||
private configErrors: string[];
|
||||
private configWatcher: chokidar.FSWatcher | undefined;
|
||||
|
||||
public constructor(
|
||||
workspaceStoragePath: string,
|
||||
extensionPath: string) {
|
||||
public constructor(app: App) {
|
||||
super();
|
||||
|
||||
this.configPath = path.join(workspaceStoragePath, 'workspace-databases.json');
|
||||
const storagePath = app.workspaceStoragePath || app.globalStoragePath;
|
||||
this.configPath = path.join(storagePath, 'workspace-databases.json');
|
||||
|
||||
this.config = this.createEmptyConfig();
|
||||
this.configErrors = [];
|
||||
this.configWatcher = undefined;
|
||||
this.configValidator = new DbConfigValidator(extensionPath);
|
||||
this.configValidator = new DbConfigValidator(app.extensionPath);
|
||||
}
|
||||
|
||||
public async initialize(): Promise<void> {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { ExtensionApp } from '../common/vscode/vscode-app';
|
||||
import { isCanary, isNewQueryRunExperienceEnabled } from '../config';
|
||||
import { logger } from '../logging';
|
||||
import { DisposableObject } from '../pure/disposable-object';
|
||||
@@ -21,9 +22,9 @@ export class DbModule extends DisposableObject {
|
||||
|
||||
void logger.log('Initializing database module');
|
||||
|
||||
const storagePath = extensionContext.storageUri?.fsPath || extensionContext.globalStorageUri.fsPath;
|
||||
const extensionPath = extensionContext.extensionPath;
|
||||
const dbConfigStore = new DbConfigStore(storagePath, extensionPath);
|
||||
const app = new ExtensionApp(extensionContext);
|
||||
|
||||
const dbConfigStore = new DbConfigStore(app);
|
||||
await dbConfigStore.initialize();
|
||||
|
||||
const dbManager = new DbManager(dbConfigStore);
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
/**
|
||||
* Creates a partially implemented mock of vscode.ExtensionContext.
|
||||
*/
|
||||
export function createMockExtensionContext({
|
||||
extensionPath = '/mock/extension/path',
|
||||
workspaceStoragePath = '/mock/workspace/storage/path',
|
||||
globalStoragePath = '/mock/global/storage/path',
|
||||
}: {
|
||||
extensionPath?: string,
|
||||
workspaceStoragePath?: string,
|
||||
globalStoragePath?: string,
|
||||
}): vscode.ExtensionContext {
|
||||
|
||||
return {
|
||||
extensionPath: extensionPath,
|
||||
globalStorageUri: vscode.Uri.file(globalStoragePath),
|
||||
storageUri: vscode.Uri.file(workspaceStoragePath),
|
||||
} as any as vscode.ExtensionContext;
|
||||
}
|
||||
@@ -10,11 +10,14 @@ import { DbTreeDataProvider } from '../../../databases/ui/db-tree-data-provider'
|
||||
import { DbPanel } from '../../../databases/ui/db-panel';
|
||||
import { DbItemKind } from '../../../databases/db-item';
|
||||
import { DbTreeViewItem } from '../../../databases/ui/db-tree-view-item';
|
||||
import { ExtensionApp } from '../../../common/vscode/vscode-app';
|
||||
import { createMockExtensionContext } from '../../factories/extension-context';
|
||||
|
||||
const proxyquire = pq.noPreserveCache();
|
||||
|
||||
describe('db panel', async () => {
|
||||
const workspaceStoragePath = path.join(__dirname, 'test-workspace');
|
||||
const workspaceStoragePath = path.join(__dirname, 'test-workspace-storage');
|
||||
const globalStoragePath = path.join(__dirname, 'test-global-storage');
|
||||
const extensionPath = path.join(__dirname, '../../../../');
|
||||
const dbConfigFilePath = path.join(workspaceStoragePath, 'workspace-databases.json');
|
||||
let dbTreeDataProvider: DbTreeDataProvider;
|
||||
@@ -23,7 +26,14 @@ describe('db panel', async () => {
|
||||
let dbPanel: DbPanel;
|
||||
|
||||
before(async () => {
|
||||
dbConfigStore = new DbConfigStore(workspaceStoragePath, extensionPath);
|
||||
const extensionContext = createMockExtensionContext({
|
||||
extensionPath,
|
||||
globalStoragePath,
|
||||
workspaceStoragePath
|
||||
});
|
||||
const app = new ExtensionApp(extensionContext);
|
||||
|
||||
dbConfigStore = new DbConfigStore(app);
|
||||
dbManager = new DbManager(dbConfigStore);
|
||||
|
||||
// Create a modified version of the DbPanel module that allows
|
||||
|
||||
36
extensions/ql-vscode/test/__mocks__/appMock.ts
Normal file
36
extensions/ql-vscode/test/__mocks__/appMock.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { App } from '../../src/common/app';
|
||||
import { AppEvent, AppEventEmitter } from '../../src/common/events';
|
||||
import { Disposable } from '../../src/pure/disposable-object';
|
||||
|
||||
export function createMockApp({
|
||||
extensionPath = '/mock/extension/path',
|
||||
workspaceStoragePath = '/mock/workspace/storage/path',
|
||||
globalStoragePath = '/mock/global/storage/path',
|
||||
createEventEmitter = <T>() => new MockAppEventEmitter<T>()
|
||||
}: {
|
||||
extensionPath?: string,
|
||||
workspaceStoragePath?: string,
|
||||
globalStoragePath?: string,
|
||||
createEventEmitter?: <T>() => AppEventEmitter<T>
|
||||
}): App {
|
||||
return {
|
||||
createEventEmitter,
|
||||
extensionPath,
|
||||
workspaceStoragePath,
|
||||
globalStoragePath
|
||||
};
|
||||
}
|
||||
|
||||
export class MockAppEventEmitter<T> implements AppEventEmitter<T> {
|
||||
public event: AppEvent<T>;
|
||||
|
||||
constructor() {
|
||||
this.event = () => {
|
||||
return {} as Disposable;
|
||||
};
|
||||
}
|
||||
|
||||
public fire(): void {
|
||||
// no-op
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import * as fs from 'fs-extra';
|
||||
import * as path from 'path';
|
||||
import { DbConfigStore } from '../../../src/databases/db-config-store';
|
||||
import { expect } from 'chai';
|
||||
import { createMockApp } from '../../__mocks__/appMock';
|
||||
|
||||
describe('db config store', async () => {
|
||||
const extensionPath = path.join(__dirname, '../../..');
|
||||
@@ -17,9 +18,14 @@ describe('db config store', async () => {
|
||||
});
|
||||
|
||||
it('should create a new config if one does not exist', async () => {
|
||||
const app = createMockApp({
|
||||
extensionPath,
|
||||
workspaceStoragePath: tempWorkspaceStoragePath
|
||||
});
|
||||
|
||||
const configPath = path.join(tempWorkspaceStoragePath, 'workspace-databases.json');
|
||||
|
||||
const configStore = new DbConfigStore(tempWorkspaceStoragePath, extensionPath);
|
||||
const configStore = new DbConfigStore(app);
|
||||
await configStore.initialize();
|
||||
|
||||
expect(await fs.pathExists(configPath)).to.be.true;
|
||||
@@ -32,7 +38,11 @@ describe('db config store', async () => {
|
||||
});
|
||||
|
||||
it('should load an existing config', async () => {
|
||||
const configStore = new DbConfigStore(testDataStoragePath, extensionPath);
|
||||
const app = createMockApp({
|
||||
extensionPath,
|
||||
workspaceStoragePath: testDataStoragePath
|
||||
});
|
||||
const configStore = new DbConfigStore(app);
|
||||
await configStore.initialize();
|
||||
|
||||
const config = configStore.getConfig().value;
|
||||
@@ -70,7 +80,11 @@ describe('db config store', async () => {
|
||||
});
|
||||
|
||||
it('should not allow modification of the config', async () => {
|
||||
const configStore = new DbConfigStore(testDataStoragePath, extensionPath);
|
||||
const app = createMockApp({
|
||||
extensionPath,
|
||||
workspaceStoragePath: testDataStoragePath
|
||||
});
|
||||
const configStore = new DbConfigStore(app);
|
||||
await configStore.initialize();
|
||||
|
||||
const config = configStore.getConfig().value;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"exclude": [],
|
||||
"compilerOptions": {
|
||||
"noEmit": true,
|
||||
"resolveJsonModule": true
|
||||
"resolveJsonModule": true,
|
||||
"rootDirs": [".", "../src"]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user