Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,6 @@
"outFiles": ["${workspaceRoot}/out/src/**/*.js"],
"preLaunchTask": "compile typescript"
},
{
// A launch configuration that compiles the extension and runs mocha unit tests
"type": "node",
"request": "launch",
"name": "Launch Tests",
"program": "${workspaceRoot}/node_modules/mocha/bin/_mocha",
"args": ["-u", "tdd", "--timeout", "999999", "--colors", "-r", "ts-node/register", "${workspaceRoot}/test/*.test.ts"],
"preLaunchTask": "compile typescript"
},
{
"name": "Extension Tests",
"type": "extensionHost",
Expand Down
2 changes: 1 addition & 1 deletion .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"command": "yarn run compile",
// show the output window only if unrecognized errors occur.
"presentation": {
"reveal": "silent"
"reveal": "never"
},
// The tsc compiler is started in watching mode
"isBackground": true,
Expand Down
2 changes: 1 addition & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export async function activate(context: ExtensionContext): Promise<SchemaExtensi
// Create the language client and start it
client = new LanguageClient('yaml', lsName, serverOptions, clientOptions);

const schemaCache = new JSONSchemaCache(context.globalStoragePath, context.globalState, client.outputChannel);
const schemaCache = new JSONSchemaCache(context.globalStorageUri.fsPath, context.globalState, client.outputChannel);
const disposable = client.start();

const schemaExtensionAPI = new SchemaExtensionAPI(client);
Expand Down
15 changes: 15 additions & 0 deletions src/json-schema-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,18 @@ export class JSONSchemaCache {

private async init(): Promise<void> {
await fs.ensureDir(this.cachePath);
const cachedFiles = await fs.readdir(this.cachePath);
// clean up memento if cached files was deleted from fs
const cachedValues = cachedFiles.map((it) => path.join(this.cachePath, it));
for (const key in this.cache) {
if (Object.prototype.hasOwnProperty.call(this.cache, key)) {
const cacheEntry = this.cache[key];
if (!cachedValues.includes(cacheEntry.schemaPath)) {
delete this.cache[key];
}
}
}
await this.memento.update(CACHE_KEY, this.cache);
this.isInitialized = true;
}

Expand All @@ -44,6 +56,9 @@ export class JSONSchemaCache {
}

getETag(schemaUri: string): string | undefined {
if (!this.isInitialized) {
return undefined;
}
return this.cache[schemaUri]?.eTag;
}

Expand Down
13 changes: 13 additions & 0 deletions test/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,16 @@ export async function testDiagnostics(docUri: vscode.Uri, expectedDiagnostics: v
assert.equal(actualDiagnostic.severity, expectedDiagnostic.severity);
});
}

export class TestMemento implements vscode.Memento {
get<T>(key: string): T;
get<T>(key: string, defaultValue: T): T;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
get<T>(key: string, defaultValue?: T): T | undefined {
throw new Error('Method not implemented.');
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
update(key: string, value: unknown): Thenable<void> {
throw new Error('Method not implemented.');
}
}
68 changes: 68 additions & 0 deletions test/json-schema-cache.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Red Hat, Inc. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as sinon from 'sinon';
import * as sinonChai from 'sinon-chai';
import * as chai from 'chai';
import * as vscode from 'vscode';
import * as fs from 'fs-extra';
import { JSONSchemaCache } from '../src/json-schema-cache';
import { TestMemento } from './helper';

const expect = chai.expect;
chai.use(sinonChai);
describe('JSON Schema Cache Tests', () => {
const sandbox = sinon.createSandbox();
let memento: sinon.SinonStubbedInstance<vscode.Memento>;
let ensureDirStub: sinon.SinonStub;
let readdirStub: sinon.SinonStub;
let pathExistsStub: sinon.SinonStub;
let readFileStub: sinon.SinonStub;

afterEach(() => {
sandbox.restore();
});

beforeEach(() => {
memento = sandbox.stub(new TestMemento());
ensureDirStub = sandbox.stub(fs, 'ensureDir');
readdirStub = sandbox.stub(fs, 'readdir');
pathExistsStub = sandbox.stub(fs, 'pathExists');
readFileStub = sandbox.stub(fs, 'readFile');
});

it('should clean up cache if there are no schema file', async () => {
memento.get.returns({ somePath: { schemaPath: '/foo/path/' } });
memento.update.resolves();

ensureDirStub.resolves();
readdirStub.resolves([]);

pathExistsStub.resolves(false);
readFileStub.resolves();

const cache = new JSONSchemaCache('/some/path/', (memento as unknown) as vscode.Memento, {} as vscode.OutputChannel);
const result = await cache.getSchema('/some/uri');
expect(result).is.undefined;
expect(memento.update).calledOnceWith('json-schema-key', {});
});

it('should check cache', async () => {
const mementoData = { somePath: { schemaPath: '/some/path/foo.json' } };
memento.get.returns(mementoData);
memento.update.resolves();

ensureDirStub.resolves();
readdirStub.resolves(['foo.json']);

pathExistsStub.resolves(false);
readFileStub.resolves();

const cache = new JSONSchemaCache('/some/path/', (memento as unknown) as vscode.Memento, {} as vscode.OutputChannel);
const result = await cache.getSchema('/some/uri');
expect(result).is.undefined;
expect(memento.update).calledOnceWith('json-schema-key', mementoData);
});
});