;
157 | sendRequest(
158 | type: ProtocolRequestType
,
159 | params: P,
160 | token?: vscode.CancellationToken
161 | ): Promise;
162 | sendRequest(type: RequestType0, token?: vscode.CancellationToken): Promise;
163 | sendRequest(type: RequestType
, params: P, token?: vscode.CancellationToken): Promise;
164 | sendRequest(method: string, token?: vscode.CancellationToken): Promise;
165 | /* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-unused-vars*/
166 | sendRequest(method: string, param: any, token?: vscode.CancellationToken): Promise;
167 | sendRequest(
168 | method: any,
169 | param?: any,
170 | token?: any
171 | ): Promise | Promise | Promise | Promise | Promise | Promise {
172 | return Promise.resolve(void 0);
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/test/index.ts:
--------------------------------------------------------------------------------
1 | /* --------------------------------------------------------------------------------------------
2 | * Copyright (c) Red Hat, Inc. All rights reserved.
3 | * Licensed under the MIT License. See License.txt in the project root for license information.
4 | * ------------------------------------------------------------------------------------------ */
5 |
6 | import * as path from 'path';
7 | import * as Mocha from 'mocha';
8 | import * as glob from 'glob';
9 |
10 | export function run(): Promise {
11 | // Create the mocha test
12 | const mocha = new Mocha({
13 | ui: 'bdd',
14 | timeout: 10000,
15 | });
16 |
17 | const testsRoot = path.resolve(__dirname, '..');
18 |
19 | return new Promise((c, e) => {
20 | glob('**/**.test.js', { cwd: testsRoot }, (err, files) => {
21 | if (err) {
22 | return e(err);
23 | }
24 |
25 | // Add files to the test suite
26 | files.forEach((f) => mocha.addFile(path.resolve(testsRoot, f)));
27 |
28 | try {
29 | // Run the mocha test
30 | mocha.run((failures) => {
31 | if (failures > 0) {
32 | e(new Error(`${failures} tests failed.`));
33 | } else {
34 | c();
35 | }
36 | });
37 | } catch (err) {
38 | console.error(err);
39 | e(err);
40 | }
41 | });
42 | });
43 | }
44 |
--------------------------------------------------------------------------------
/test/json-schema-cache.test.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Copyright (c) Red Hat, Inc. All rights reserved.
3 | * Licensed under the MIT License. See License.txt in the project root for license information.
4 | *--------------------------------------------------------------------------------------------*/
5 |
6 | import * as sinon from 'sinon';
7 | import * as sinonChai from 'sinon-chai';
8 | import * as chai from 'chai';
9 | import * as vscode from 'vscode';
10 | import * as fs from 'fs-extra';
11 | import { JSONSchemaCache } from '../src/json-schema-cache';
12 | import { TestMemento } from './helper';
13 |
14 | const expect = chai.expect;
15 | chai.use(sinonChai);
16 | describe('JSON Schema Cache Tests', () => {
17 | const sandbox = sinon.createSandbox();
18 | let memento: sinon.SinonStubbedInstance;
19 | let ensureDirStub: sinon.SinonStub;
20 | let readdirStub: sinon.SinonStub;
21 | let pathExistsStub: sinon.SinonStub;
22 | let readFileStub: sinon.SinonStub;
23 |
24 | afterEach(() => {
25 | sandbox.restore();
26 | });
27 |
28 | beforeEach(() => {
29 | memento = sandbox.stub(new TestMemento());
30 | ensureDirStub = sandbox.stub(fs, 'ensureDir');
31 | readdirStub = sandbox.stub(fs, 'readdir');
32 | pathExistsStub = sandbox.stub(fs, 'pathExists');
33 | readFileStub = sandbox.stub(fs, 'readFile');
34 | });
35 |
36 | it('should clean up cache if there are no schema file', async () => {
37 | memento.get.returns({ somePath: { schemaPath: '/foo/path/' } });
38 | memento.update.resolves();
39 |
40 | ensureDirStub.resolves();
41 | readdirStub.resolves([]);
42 |
43 | pathExistsStub.resolves(false);
44 | readFileStub.resolves();
45 |
46 | const cache = new JSONSchemaCache('/some/path/', (memento as unknown) as vscode.Memento);
47 | const result = await cache.getSchema('/some/uri');
48 | expect(result).is.undefined;
49 | expect(memento.update).calledOnceWith('json-schema-key', {});
50 | });
51 |
52 | it('should check cache', async () => {
53 | const mementoData = { somePath: { schemaPath: '/some/path/foo.json' } };
54 | memento.get.returns(mementoData);
55 | memento.update.resolves();
56 |
57 | ensureDirStub.resolves();
58 | readdirStub.resolves(['foo.json']);
59 |
60 | pathExistsStub.resolves(false);
61 | readFileStub.resolves();
62 |
63 | const cache = new JSONSchemaCache('/some/path/', (memento as unknown) as vscode.Memento);
64 | const result = await cache.getSchema('/some/uri');
65 | expect(result).is.undefined;
66 | expect(memento.update).calledOnceWith('json-schema-key', mementoData);
67 | });
68 | });
69 |
--------------------------------------------------------------------------------
/test/json-schema-selection.test.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Copyright (c) Red Hat, Inc. All rights reserved.
3 | * Licensed under the MIT License. See License.txt in the project root for license information.
4 | *--------------------------------------------------------------------------------------------*/
5 |
6 | import * as sinon from 'sinon';
7 | import * as sinonChai from 'sinon-chai';
8 | import * as chai from 'chai';
9 | import { createJSONSchemaStatusBarItem } from '../src/schema-status-bar-item';
10 | import { CommonLanguageClient } from 'vscode-languageclient';
11 | import * as vscode from 'vscode';
12 | import { TestLanguageClient } from './helper';
13 | import * as jsonStatusBar from '../src/schema-status-bar-item';
14 |
15 | const expect = chai.expect;
16 | chai.use(sinonChai);
17 |
18 | describe('Status bar should work in multiple different scenarios', () => {
19 | const sandbox = sinon.createSandbox();
20 | let clcStub: sinon.SinonStubbedInstance;
21 | let registerCommandStub: sinon.SinonStub;
22 | let createStatusBarItemStub: sinon.SinonStub;
23 | let onDidChangeActiveTextEditorStub: sinon.SinonStub;
24 |
25 | beforeEach(() => {
26 | clcStub = sandbox.stub(new TestLanguageClient());
27 | registerCommandStub = sandbox.stub(vscode.commands, 'registerCommand');
28 | createStatusBarItemStub = sandbox.stub(vscode.window, 'createStatusBarItem');
29 | onDidChangeActiveTextEditorStub = sandbox.stub(vscode.window, 'onDidChangeActiveTextEditor');
30 | sandbox.stub(vscode.window, 'activeTextEditor').returns(undefined);
31 | sandbox.stub(jsonStatusBar, 'statusBarItem').returns(undefined);
32 | });
33 |
34 | afterEach(() => {
35 | sandbox.restore();
36 | });
37 |
38 | it('Should create status bar item for JSON Schema', async () => {
39 | const context: vscode.ExtensionContext = {
40 | subscriptions: [],
41 | } as vscode.ExtensionContext;
42 | const statusBar = ({ show: sandbox.stub() } as unknown) as vscode.StatusBarItem;
43 | createStatusBarItemStub.returns(statusBar);
44 | clcStub.sendRequest.resolves([]);
45 |
46 | createJSONSchemaStatusBarItem(context, (clcStub as unknown) as CommonLanguageClient);
47 |
48 | expect(registerCommandStub).calledOnceWith('yaml.select.json.schema');
49 | expect(createStatusBarItemStub).calledOnceWith(vscode.StatusBarAlignment.Right);
50 | expect(context.subscriptions).has.length(2);
51 | });
52 |
53 | it('Should update status bar on editor change', async () => {
54 | const context: vscode.ExtensionContext = {
55 | subscriptions: [],
56 | } as vscode.ExtensionContext;
57 | const statusBar = ({ show: sandbox.stub() } as unknown) as vscode.StatusBarItem;
58 | createStatusBarItemStub.returns(statusBar);
59 | onDidChangeActiveTextEditorStub.returns({});
60 | clcStub.sendRequest.resolves([{ uri: 'https://foo.com/bar.json', name: 'bar schema' }]);
61 |
62 | createJSONSchemaStatusBarItem(context, (clcStub as unknown) as CommonLanguageClient);
63 | const callBackFn = onDidChangeActiveTextEditorStub.firstCall.firstArg;
64 | await callBackFn({ document: { languageId: 'yaml', uri: vscode.Uri.parse('/foo.yaml') } });
65 |
66 | expect(statusBar.text).to.equal('bar schema');
67 | expect(statusBar.tooltip).to.equal('Select JSON Schema');
68 | expect(statusBar.backgroundColor).to.be.undefined;
69 | expect(statusBar.show).calledTwice;
70 | });
71 |
72 | it('Should inform if there are no schema', async () => {
73 | const context: vscode.ExtensionContext = {
74 | subscriptions: [],
75 | } as vscode.ExtensionContext;
76 | const statusBar = ({ show: sandbox.stub() } as unknown) as vscode.StatusBarItem;
77 | createStatusBarItemStub.returns(statusBar);
78 | onDidChangeActiveTextEditorStub.returns({});
79 | clcStub.sendRequest.resolves([]);
80 |
81 | createJSONSchemaStatusBarItem(context, (clcStub as unknown) as CommonLanguageClient);
82 | const callBackFn = onDidChangeActiveTextEditorStub.firstCall.firstArg;
83 | await callBackFn({ document: { languageId: 'yaml', uri: vscode.Uri.parse('/foo.yaml') } });
84 |
85 | expect(statusBar.text).to.equal('No JSON Schema');
86 | expect(statusBar.tooltip).to.equal('Select JSON Schema');
87 | expect(statusBar.backgroundColor).to.be.undefined;
88 | expect(statusBar.show).calledTwice;
89 | });
90 |
91 | it('Should inform if there are more than one schema', async () => {
92 | const context: vscode.ExtensionContext = {
93 | subscriptions: [],
94 | } as vscode.ExtensionContext;
95 | const statusBar = ({ show: sandbox.stub() } as unknown) as vscode.StatusBarItem;
96 | createStatusBarItemStub.returns(statusBar);
97 | onDidChangeActiveTextEditorStub.returns({});
98 | clcStub.sendRequest.resolves([{}, {}]);
99 |
100 | createJSONSchemaStatusBarItem(context, (clcStub as unknown) as CommonLanguageClient);
101 | const callBackFn = onDidChangeActiveTextEditorStub.firstCall.firstArg;
102 | await callBackFn({ document: { languageId: 'yaml', uri: vscode.Uri.parse('/foo.yaml') } });
103 |
104 | expect(statusBar.text).to.equal('Multiple JSON Schemas...');
105 | expect(statusBar.tooltip).to.equal('Multiple JSON Schema used to validate this file, click to select one');
106 | expect(statusBar.backgroundColor).to.eql({ id: 'statusBarItem.warningBackground' });
107 | expect(statusBar.show).calledTwice;
108 | });
109 |
110 | it('Should show JSON Schema Store schema version', async () => {
111 | const context: vscode.ExtensionContext = {
112 | subscriptions: [],
113 | } as vscode.ExtensionContext;
114 | const statusBar = ({ show: sandbox.stub() } as unknown) as vscode.StatusBarItem;
115 | createStatusBarItemStub.returns(statusBar);
116 | onDidChangeActiveTextEditorStub.returns({ document: { uri: vscode.Uri.parse('/foo.yaml') } });
117 | clcStub.sendRequest
118 | .withArgs(sinon.match.has('method', 'yaml/get/jsonSchema'), sinon.match('/foo.yaml'))
119 | .resolves([{ uri: 'https://foo.com/bar.json', name: 'bar schema' }]);
120 | clcStub.sendRequest
121 | .withArgs(sinon.match.has('method', 'yaml/get/all/jsonSchemas'), sinon.match.any)
122 | .resolves([{ versions: { '1.0.0': 'https://foo.com/bar.json' } }]);
123 |
124 | createJSONSchemaStatusBarItem(context, (clcStub as unknown) as CommonLanguageClient);
125 | const callBackFn = onDidChangeActiveTextEditorStub.firstCall.firstArg;
126 | await callBackFn({ document: { languageId: 'yaml', uri: vscode.Uri.parse('/foo.yaml') } });
127 |
128 | expect(statusBar.text).to.equal('bar schema(1.0.0)');
129 | expect(statusBar.tooltip).to.equal('Select JSON Schema');
130 | expect(statusBar.backgroundColor).to.be.undefined;
131 | expect(statusBar.show).calledTwice;
132 | });
133 |
134 | it('Should show JSON Schema Store schema version, dont include version', async () => {
135 | const context: vscode.ExtensionContext = {
136 | subscriptions: [],
137 | } as vscode.ExtensionContext;
138 | const statusBar = ({ show: sandbox.stub() } as unknown) as vscode.StatusBarItem;
139 | createStatusBarItemStub.returns(statusBar);
140 | onDidChangeActiveTextEditorStub.returns({ document: { uri: vscode.Uri.parse('/foo.yaml') } });
141 | clcStub.sendRequest
142 | .withArgs(sinon.match.has('method', 'yaml/get/jsonSchema'), sinon.match('/foo.yaml'))
143 | .resolves([{ uri: 'https://foo.com/bar.json', name: 'bar schema(1.0.0)' }]);
144 | clcStub.sendRequest
145 | .withArgs(sinon.match.has('method', 'yaml/get/all/jsonSchemas'), sinon.match.any)
146 | .resolves([{ versions: { '1.0.0': 'https://foo.com/bar.json' } }]);
147 |
148 | createJSONSchemaStatusBarItem(context, (clcStub as unknown) as CommonLanguageClient);
149 | const callBackFn = onDidChangeActiveTextEditorStub.firstCall.firstArg;
150 | await callBackFn({ document: { languageId: 'yaml', uri: vscode.Uri.parse('/foo.yaml') } });
151 |
152 | expect(statusBar.text).to.equal('bar schema(1.0.0)');
153 | expect(statusBar.tooltip).to.equal('Select JSON Schema');
154 | expect(statusBar.backgroundColor).to.be.undefined;
155 | expect(statusBar.show).calledTwice;
156 | });
157 | });
158 |
--------------------------------------------------------------------------------
/test/json-shema-content-provider.test.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Copyright (c) Red Hat, Inc. All rights reserved.
3 | * Licensed under the MIT License. See License.txt in the project root for license information.
4 | *--------------------------------------------------------------------------------------------*/
5 | import * as vscode from 'vscode';
6 | import { getDocUri, activate } from './helper';
7 | import * as assert from 'assert';
8 |
9 | describe('Tests for JSON Schema content provider', () => {
10 | const SCHEMA = 'myschema';
11 | const schemaJSON = JSON.stringify({
12 | type: 'object',
13 | properties: {
14 | version: {
15 | type: 'string',
16 | description: 'A stringy string string',
17 | enum: ['test'],
18 | },
19 | },
20 | });
21 |
22 | function onRequestSchema1URI(resource: string): string | undefined {
23 | if (resource.endsWith('completion.yaml') || resource.endsWith('basic.yaml')) {
24 | return `${SCHEMA}://schema/porter`;
25 | }
26 | return undefined;
27 | }
28 |
29 | function onRequestSchema1Content(): string | undefined {
30 | return schemaJSON;
31 | }
32 |
33 | it('should handle "json-schema" url', async () => {
34 | const docUri = getDocUri('completion/completion.yaml');
35 | const client = await activate(docUri);
36 | client._customSchemaContributors = {};
37 | client.registerContributor(SCHEMA, onRequestSchema1URI, onRequestSchema1Content);
38 | const customUri = vscode.Uri.parse(`json-schema://some/url/schema.json#${SCHEMA}://some/path/schema.json`);
39 | const doc = await vscode.workspace.openTextDocument(customUri);
40 | const editor = await vscode.window.showTextDocument(doc);
41 | assert.strictEqual(editor.document.getText(), JSON.stringify(JSON.parse(schemaJSON), null, 2));
42 | client._customSchemaContributors = {};
43 | });
44 | });
45 |
--------------------------------------------------------------------------------
/test/schemaModification.test.ts:
--------------------------------------------------------------------------------
1 | /* --------------------------------------------------------------------------------------------
2 | * Copyright (c) Red Hat, Inc. All rights reserved.
3 | * Licensed under the MIT License. See License.txt in the project root for license information.
4 | * ------------------------------------------------------------------------------------------ */
5 |
6 | import * as vscode from 'vscode';
7 | import { getDocUri, activate, testCompletion, updateSettings, resetSettings } from './helper';
8 | import { ExtensionAPI, MODIFICATION_ACTIONS } from '../src/schema-extension-api';
9 |
10 | describe('Schema sections can be modified in memory', () => {
11 | const completionUri = getDocUri('completion/enum_completion.yaml');
12 |
13 | afterEach(async () => {
14 | await resetSettings('schemas', {});
15 | await resetSettings('schemaStore.enable', true);
16 | });
17 |
18 | it('Modified schema gets correct results', async () => {
19 | const extensionAPI: ExtensionAPI = await activate(completionUri);
20 |
21 | // Insert the original schema
22 | await updateSettings('schemas', {
23 | 'https://gist.githubusercontent.com/JPinkney/00b908178a64d3a6274e2c9523b39521/raw/53042c011c089b13ef0a42b4b037ea2431bbba8d/basic_completion_schema.json':
24 | 'enum_completion.yaml',
25 | });
26 |
27 | // Test that the schema was correctly loaded into memory
28 | await testCompletion(completionUri, new vscode.Position(0, 10), {
29 | items: [
30 | {
31 | label: 'my_value',
32 | kind: 11,
33 | },
34 | ],
35 | });
36 |
37 | // Modify the schema
38 | await extensionAPI.modifySchemaContent({
39 | action: MODIFICATION_ACTIONS.add,
40 | path: 'properties/my_key',
41 | key: 'enum',
42 | content: ['my_apple', 'my_banana', 'my_carrot'],
43 | schema:
44 | 'https://gist.githubusercontent.com/JPinkney/00b908178a64d3a6274e2c9523b39521/raw/53042c011c089b13ef0a42b4b037ea2431bbba8d/basic_completion_schema.json',
45 | });
46 |
47 | await testCompletion(completionUri, new vscode.Position(0, 9), {
48 | items: [
49 | {
50 | label: 'my_apple',
51 | kind: 11,
52 | },
53 | {
54 | label: 'my_banana',
55 | kind: 11,
56 | },
57 | {
58 | label: 'my_carrot',
59 | kind: 11,
60 | },
61 | ],
62 | });
63 | });
64 |
65 | it('Deleted schema gets correct results', async () => {
66 | const extensionAPI: ExtensionAPI = await activate(completionUri);
67 |
68 | // Insert the original schema
69 | await updateSettings('schemas', {
70 | 'https://gist.githubusercontent.com/JPinkney/ee1caa73523b8e0574b9e9b241e2991e/raw/9569ef35a76ce5165b3c1b35abe878c44e861b33/sample.json':
71 | 'enum_completion.yaml',
72 | });
73 |
74 | // Test that the schema was correctly loaded into memory
75 | await testCompletion(completionUri, new vscode.Position(0, 10), {
76 | items: [
77 | {
78 | label: 'my_test1',
79 | kind: 11,
80 | },
81 | {
82 | label: 'my_test2',
83 | kind: 11,
84 | },
85 | ],
86 | });
87 |
88 | // Modify the schema
89 | await extensionAPI.modifySchemaContent({
90 | action: MODIFICATION_ACTIONS.delete,
91 | path: 'properties/my_key',
92 | schema:
93 | 'https://gist.githubusercontent.com/JPinkney/ee1caa73523b8e0574b9e9b241e2991e/raw/9569ef35a76ce5165b3c1b35abe878c44e861b33/sample.json',
94 | key: 'enum',
95 | });
96 |
97 | await testCompletion(completionUri, new vscode.Position(0, 9), {
98 | items: [
99 | {
100 | label: 'my_test2',
101 | kind: 11,
102 | },
103 | ],
104 | });
105 | });
106 | });
107 |
--------------------------------------------------------------------------------
/test/schemaProvider.test.ts:
--------------------------------------------------------------------------------
1 | /* --------------------------------------------------------------------------------------------
2 | * Copyright (c) Red Hat, Inc. All rights reserved.
3 | * Licensed under the MIT License. See License.txt in the project root for license information.
4 | * ------------------------------------------------------------------------------------------ */
5 |
6 | import * as vscode from 'vscode';
7 | import { getDocUri, activate, testCompletion, testHover, testDiagnostics, sleep } from './helper';
8 |
9 | const SCHEMA = 'myschema';
10 | const SCHEMA2 = 'myschema2';
11 | const SCHEMA3 = 'myschema3';
12 |
13 | describe('Tests for schema provider feature', () => {
14 | const docUri = getDocUri('completion/completion.yaml');
15 | const hoverUri = getDocUri('hover/basic.yaml');
16 | const schemaProviderUri = getDocUri('completion/schemaProvider.yaml');
17 |
18 | it('completion, hover, and validation work with registered contributor schema', async () => {
19 | const client = await activate(docUri);
20 | client._customSchemaContributors = {};
21 | client.registerContributor(SCHEMA, onRequestSchema1URI, onRequestSchema1Content);
22 | await testCompletion(docUri, new vscode.Position(0, 0), {
23 | items: [
24 | {
25 | label: 'version',
26 | kind: 9,
27 | },
28 | ],
29 | });
30 |
31 | await vscode.window.showTextDocument(hoverUri);
32 | await testHover(hoverUri, new vscode.Position(0, 3), [
33 | {
34 | contents: ['A stringy string string\n\nAllowed Values:\n\n* `test`\n'],
35 | },
36 | ]);
37 |
38 | await sleep(2000); // Wait for the diagnostics to compute on this file
39 | await testDiagnostics(hoverUri, [
40 | {
41 | message: 'Value is not accepted. Valid values: "test".',
42 | range: new vscode.Range(new vscode.Position(0, 9), new vscode.Position(0, 14)),
43 | severity: 0,
44 | },
45 | ]);
46 | });
47 |
48 | it('Validation occurs automatically with registered contributor schema', async () => {
49 | const client = await activate(hoverUri);
50 | client._customSchemaContributors = {};
51 | client.registerContributor(SCHEMA, onRequestSchema1URI, onRequestSchema1Content);
52 |
53 | await sleep(2000); // Wait for the diagnostics to compute on this file
54 | await testDiagnostics(hoverUri, [
55 | {
56 | message: 'Value is not accepted. Valid values: "test".',
57 | range: new vscode.Range(new vscode.Position(0, 9), new vscode.Position(0, 14)),
58 | severity: 0,
59 | },
60 | ]);
61 | });
62 |
63 | it('Multiple contributors can match one file', async () => {
64 | const client = await activate(docUri);
65 | client._customSchemaContributors = {};
66 | client.registerContributor(SCHEMA2, onRequestSchema2URI, onRequestSchema2Content, 'apple: tastes_good');
67 | client.registerContributor(SCHEMA3, onRequestSchema3URI, onRequestSchema3Content);
68 |
69 | await testCompletion(docUri, new vscode.Position(0, 0), {
70 | items: [
71 | {
72 | label: 'apple',
73 | kind: 9,
74 | documentation: 'An apple',
75 | },
76 | {
77 | label: 'version',
78 | kind: 9,
79 | documentation: 'A stringy string string',
80 | },
81 | ],
82 | });
83 | });
84 |
85 | it('Multiple contributors with one label matches', async () => {
86 | const client = await activate(schemaProviderUri);
87 | client._customSchemaContributors = {};
88 | client.registerContributor(SCHEMA2, onRequestSchema2URI, onRequestSchema2Content, 'apple: tastes_good');
89 | client.registerContributor(SCHEMA3, onRequestSchema3URI, onRequestSchema3Content);
90 |
91 | await testCompletion(schemaProviderUri, new vscode.Position(0, 0), {
92 | items: [
93 | {
94 | label: 'apple',
95 | kind: 9,
96 | documentation: 'An apple',
97 | },
98 | ],
99 | });
100 | });
101 |
102 | it('Multiple contributors with labels but only one label matches', async () => {
103 | const client = await activate(schemaProviderUri);
104 | client._customSchemaContributors = {};
105 | client.registerContributor(SCHEMA2, onRequestSchema2URI, onRequestSchema2Content, 'apple: tastes_good');
106 | client.registerContributor(SCHEMA3, onRequestSchema3URI, onRequestSchema3Content, 'apple: bad');
107 |
108 | await testCompletion(schemaProviderUri, new vscode.Position(0, 0), {
109 | items: [
110 | {
111 | label: 'apple',
112 | kind: 9,
113 | documentation: 'An apple',
114 | },
115 | ],
116 | });
117 | });
118 |
119 | it('Multiple contributors with labels but no label matches', async () => {
120 | const client = await activate(schemaProviderUri);
121 | client._customSchemaContributors = {};
122 | client.registerContributor(SCHEMA2, onRequestSchema2URI, onRequestSchema2Content, 'apple: not_bad');
123 | client.registerContributor(SCHEMA3, onRequestSchema3URI, onRequestSchema3Content, 'apple: bad');
124 |
125 | await testCompletion(schemaProviderUri, new vscode.Position(0, 0), {
126 | items: [
127 | {
128 | label: 'apple',
129 | kind: 9,
130 | documentation: 'An apple',
131 | },
132 | {
133 | label: 'version',
134 | kind: 9,
135 | documentation: 'A stringy string string',
136 | },
137 | ],
138 | });
139 | });
140 |
141 | it('Multiple contributors with one throwing an error', async () => {
142 | const client = await activate(docUri);
143 | client._customSchemaContributors = {};
144 | client.registerContributor(SCHEMA2, onRequestSchema2URI, onRequestSchema2Content);
145 | client.registerContributor('schemathrowingerror', onRequestSchemaURIThrowError, onRequestSchemaContentThrowError);
146 |
147 | await testCompletion(docUri, new vscode.Position(0, 0), {
148 | items: [
149 | {
150 | label: 'apple',
151 | kind: 9,
152 | documentation: 'An apple',
153 | },
154 | ],
155 | });
156 | });
157 | });
158 |
159 | const schemaJSON = JSON.stringify({
160 | type: 'object',
161 | properties: {
162 | version: {
163 | type: 'string',
164 | description: 'A stringy string string',
165 | enum: ['test'],
166 | },
167 | },
168 | });
169 |
170 | function onRequestSchema1URI(resource: string): string | undefined {
171 | if (resource.endsWith('completion.yaml') || resource.endsWith('basic.yaml')) {
172 | return `${SCHEMA}://schema/porter`;
173 | }
174 | return undefined;
175 | }
176 |
177 | function onRequestSchema1Content(): string | undefined {
178 | return schemaJSON;
179 | }
180 |
181 | function onRequestSchemaURIThrowError(): string | undefined {
182 | throw new Error('test what happens when an error is thrown and not caught');
183 | }
184 |
185 | function onRequestSchemaContentThrowError(): string | undefined {
186 | throw new Error('test what happens when an error is thrown and not caught');
187 | }
188 |
189 | const schemaJSON2 = JSON.stringify({
190 | type: 'object',
191 | properties: {
192 | apple: {
193 | type: 'string',
194 | description: 'An apple',
195 | },
196 | },
197 | });
198 |
199 | function onRequestSchema2URI(): string | undefined {
200 | return `${SCHEMA2}://schema/porter`;
201 | }
202 |
203 | function onRequestSchema2Content(): string | undefined {
204 | return schemaJSON2;
205 | }
206 |
207 | function onRequestSchema3URI(): string | undefined {
208 | return `${SCHEMA3}://schema/porter`;
209 | }
210 |
211 | function onRequestSchema3Content(): string | undefined {
212 | return schemaJSON;
213 | }
214 |
--------------------------------------------------------------------------------
/test/telemetry.test.ts:
--------------------------------------------------------------------------------
1 | /* --------------------------------------------------------------------------------------------
2 | * Copyright (c) Red Hat, Inc. All rights reserved.
3 | * Licensed under the MIT License. See License.txt in the project root for license information.
4 | * ------------------------------------------------------------------------------------------ */
5 | import * as sinon from 'sinon';
6 | import * as sinonChai from 'sinon-chai';
7 | import * as chai from 'chai';
8 | import * as vscode from 'vscode';
9 | import { TelemetryErrorHandler, TelemetryOutputChannel } from '../src/telemetry';
10 | import { TelemetryEvent, TelemetryService } from '@redhat-developer/vscode-redhat-telemetry';
11 |
12 | const expect = chai.expect;
13 | chai.use(sinonChai);
14 | class TelemetryStub implements TelemetryService {
15 | sendStartupEvent(): Promise {
16 | throw new Error('Method not implemented.');
17 | }
18 | // eslint-disable-next-line @typescript-eslint/no-unused-vars
19 | send(event: TelemetryEvent): Promise {
20 | throw new Error('Method not implemented.');
21 | }
22 | sendShutdownEvent(): Promise {
23 | throw new Error('Method not implemented.');
24 | }
25 | flushQueue(): Promise {
26 | throw new Error('Method not implemented.');
27 | }
28 | dispose(): Promise {
29 | throw new Error('Method not implemented.');
30 | }
31 | }
32 | // skip this suite as `useFakeTimers` hung's vscode and CI newer finish build
33 | describe.skip('Telemetry Test', () => {
34 | const sandbox = sinon.createSandbox();
35 | const testOutputChannel = vscode.window.createOutputChannel('YAML_TEST');
36 | afterEach(() => {
37 | sandbox.restore();
38 | });
39 | describe('TelemetryOutputChannel', () => {
40 | let telemetryChannel: TelemetryOutputChannel;
41 | let outputChannel: sinon.SinonStubbedInstance;
42 | let telemetry: sinon.SinonStubbedInstance;
43 | let clock: sinon.SinonFakeTimers;
44 |
45 | beforeEach(() => {
46 | outputChannel = sandbox.stub(testOutputChannel);
47 | telemetry = sandbox.stub(new TelemetryStub());
48 | telemetryChannel = new TelemetryOutputChannel(
49 | (outputChannel as unknown) as vscode.OutputChannel,
50 | (telemetry as unknown) as TelemetryService
51 | );
52 | clock = sinon.useFakeTimers();
53 | });
54 |
55 | afterEach(() => {
56 | clock.restore();
57 | });
58 |
59 | it('should delegate "append" method', () => {
60 | telemetryChannel.append('Some');
61 | expect(outputChannel.append).calledOnceWith('Some');
62 | });
63 |
64 | it('should delegate "appendLine" method', () => {
65 | telemetryChannel.appendLine('Some');
66 | expect(outputChannel.appendLine).calledOnceWith('Some');
67 | });
68 |
69 | it('should delegate "clear" method', () => {
70 | telemetryChannel.clear();
71 | expect(outputChannel.clear).calledOnce;
72 | });
73 |
74 | it('should delegate "dispose" method', () => {
75 | telemetryChannel.dispose();
76 | expect(outputChannel.dispose).calledOnce;
77 | });
78 |
79 | it('should delegate "hide" method', () => {
80 | telemetryChannel.hide();
81 | expect(outputChannel.hide).calledOnce;
82 | });
83 |
84 | it('should delegate "show" method', () => {
85 | telemetryChannel.show();
86 | expect(outputChannel.show).calledOnce;
87 | });
88 |
89 | it('should send telemetry if log error in "append"', () => {
90 | telemetryChannel.append('[Error] Some');
91 | clock.tick(51);
92 | expect(telemetry.send).calledOnceWith({ name: 'yaml.server.error', properties: { error: 'Some' } });
93 | });
94 |
95 | it('should send telemetry if log error on "appendLine"', () => {
96 | telemetryChannel.appendLine('[Error] Some error');
97 | clock.tick(51);
98 | expect(telemetry.send).calledOnceWith({ name: 'yaml.server.error', properties: { error: 'Some error' } });
99 | });
100 |
101 | it("shouldn't send telemetry if error should be skipped", () => {
102 | telemetryChannel.append(
103 | "[Error - 15:10:33] (node:25052) Warning: Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0' makes TLS connections and HTTPS requests insecure by disabling certificate verification."
104 | );
105 | clock.tick(51);
106 | expect(telemetry.send).not.called;
107 | });
108 |
109 | it('should throttle send telemetry if "append" called multiple times', () => {
110 | telemetryChannel.append('[Error] Some');
111 | telemetryChannel.append('[Error] Second Error');
112 | clock.tick(51);
113 | expect(telemetry.send).calledOnceWith({ name: 'yaml.server.error', properties: { error: 'Some\nSecond Error' } });
114 | });
115 |
116 | it('should throttle send telemetry if "appendLine" called multiple times', () => {
117 | telemetryChannel.appendLine('[Error] Some');
118 | telemetryChannel.appendLine('[Error] Second Error');
119 | telemetryChannel.appendLine('[Error] Third Error');
120 | clock.tick(51);
121 | expect(telemetry.send).calledOnceWith({
122 | name: 'yaml.server.error',
123 | properties: { error: 'Some\nSecond Error\nThird Error' },
124 | });
125 | });
126 | });
127 |
128 | describe('TelemetryErrorHandler', () => {
129 | let telemetry: sinon.SinonStubbedInstance;
130 | let errorHandler: TelemetryErrorHandler;
131 |
132 | beforeEach(() => {
133 | telemetry = sandbox.stub(new TelemetryStub());
134 | errorHandler = new TelemetryErrorHandler(telemetry, 'YAML LS', 3);
135 | });
136 |
137 | it('should log telemetry on error', () => {
138 | errorHandler.error(new Error('Some'), { jsonrpc: 'Error message' }, 3);
139 | expect(telemetry.send).calledOnceWith({
140 | name: 'yaml.lsp.error',
141 | properties: { jsonrpc: 'Error message', error: 'Some' },
142 | });
143 | });
144 | });
145 | });
146 |
--------------------------------------------------------------------------------
/test/testFixture/completion/.travis.yml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-yaml/cc15df699148c614db963c53a880aa4590030ec8/test/testFixture/completion/.travis.yml
--------------------------------------------------------------------------------
/test/testFixture/completion/completion.yaml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/redhat-developer/vscode-yaml/cc15df699148c614db963c53a880aa4590030ec8/test/testFixture/completion/completion.yaml
--------------------------------------------------------------------------------
/test/testFixture/completion/enum_completion.yaml:
--------------------------------------------------------------------------------
1 | my_key: my_
2 |
--------------------------------------------------------------------------------
/test/testFixture/completion/schemaProvider.yaml:
--------------------------------------------------------------------------------
1 | apple: tastes_good
2 |
--------------------------------------------------------------------------------
/test/testFixture/hover/basic.yaml:
--------------------------------------------------------------------------------
1 | version: apple
2 |
--------------------------------------------------------------------------------
/test/testFixture/schemas/basic_completion_schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "object",
3 | "properties": {
4 | "my_key": {
5 | "type": "string",
6 | "description": "My string",
7 | "enum": ["my_value"]
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/test/testFixture/validation/schemaProvider.yaml:
--------------------------------------------------------------------------------
1 | version: False
2 |
--------------------------------------------------------------------------------
/test/testRunner.ts:
--------------------------------------------------------------------------------
1 | /* --------------------------------------------------------------------------------------------
2 | * Copyright (c) Red Hat, Inc. All rights reserved.
3 | * Licensed under the MIT License. See License.txt in the project root for license information.
4 | * ------------------------------------------------------------------------------------------ */
5 | import * as path from 'path';
6 | import * as cp from 'child_process';
7 | import { runTests, downloadAndUnzipVSCode, resolveCliPathFromVSCodeExecutablePath } from '@vscode/test-electron';
8 |
9 | async function main(): Promise {
10 | try {
11 | const executable = await downloadAndUnzipVSCode();
12 | const cliPath = resolveCliPathFromVSCodeExecutablePath(executable);
13 | const dependencies = [];
14 | for (const dep of dependencies) {
15 | const installLog = cp.execSync(`"${cliPath}" --install-extension ${dep}`);
16 | console.log(installLog.toString());
17 | }
18 | // The folder containing the Extension Manifest package.json
19 | // Passed to `--extensionDevelopmentPath`
20 | const extensionDevelopmentPath = path.resolve(__dirname, '../../');
21 |
22 | // The path to test runner
23 | // Passed to --extensionTestsPath
24 | const extensionTestsPath = path.resolve(__dirname, './index');
25 |
26 | // Download VS Code, unzip it and run the integration test
27 | await runTests({
28 | vscodeExecutablePath: executable,
29 | extensionDevelopmentPath,
30 | extensionTestsPath,
31 | launchArgs: ['--disable-extension=ms-kubernetes-tools.vscode-kubernetes-tools', '.'],
32 | });
33 | } catch (err) {
34 | console.error('Failed to run tests');
35 | process.exit(1);
36 | }
37 | }
38 |
39 | main();
40 |
--------------------------------------------------------------------------------
/test/ui-test/allTestsSuite.ts:
--------------------------------------------------------------------------------
1 | import { extensionUIAssetsTest } from './extensionUITest';
2 | import { contentAssistSuggestionTest } from './contentAssistTest';
3 | import { customTagsTest } from './customTagsTest';
4 | import { schemaIsSetTest } from './schemaIsSetTest';
5 | import { autocompletionTest } from './autocompletionTest';
6 |
7 | describe('VSCode YAML - UI tests', () => {
8 | extensionUIAssetsTest();
9 | contentAssistSuggestionTest();
10 | customTagsTest();
11 | schemaIsSetTest();
12 | autocompletionTest();
13 | });
14 |
--------------------------------------------------------------------------------
/test/ui-test/autocompletionTest.ts:
--------------------------------------------------------------------------------
1 | import os = require('os');
2 | import path = require('path');
3 | import { expect } from 'chai';
4 | import { WebDriver, TextEditor, EditorView, VSBrowser, ContentAssist } from 'vscode-extension-tester';
5 | import { getSchemaLabel, deleteFileInHomeDir, createCustomFile } from './util/utility';
6 |
7 | /**
8 | * @author Zbynek Cervinka
9 | * @author Ondrej Dockal
10 | */
11 | export function autocompletionTest(): void {
12 | describe('Verify autocompletion completes what should be completed', () => {
13 | let driver: WebDriver;
14 | const yamlFileName = 'kustomization.yaml';
15 | const homeDir = os.homedir();
16 | const yamlFilePath = path.join(homeDir, yamlFileName);
17 | let editor: TextEditor;
18 |
19 | before(async function setup() {
20 | this.timeout(20000);
21 | driver = VSBrowser.instance.driver;
22 | await createCustomFile(yamlFilePath);
23 | await driver.wait(async () => {
24 | return await getSchemaLabel(yamlFileName);
25 | }, 18000);
26 | });
27 |
28 | it('Autocompletion works as expected', async function () {
29 | this.timeout(30000);
30 |
31 | editor = new TextEditor();
32 | await editor.typeTextAt(1, 1, 'api');
33 | const contentAssist = (await editor.toggleContentAssist(true)) as ContentAssist;
34 | if (contentAssist.hasItem('apiVersion')) {
35 | await (await contentAssist.getItem('apiVersion')).click();
36 | }
37 | const text = await editor.getText();
38 |
39 | if (text != 'apiVersion: ') {
40 | expect.fail("The 'apiVersion: ' string has not been autocompleted.");
41 | }
42 | });
43 |
44 | after(async function () {
45 | this.timeout(5000);
46 | await editor.save();
47 | await new EditorView().closeAllEditors();
48 | deleteFileInHomeDir(yamlFileName);
49 | });
50 | });
51 | }
52 |
--------------------------------------------------------------------------------
/test/ui-test/common/YAMLConstants.ts:
--------------------------------------------------------------------------------
1 | export class YamlConstants {
2 | // General
3 | public static readonly YES = 'Yes';
4 | public static readonly NO = 'No';
5 | public static readonly LICENSE_EDITOR = 'workflow.license';
6 |
7 | public static readonly YAML_NAME = 'YAML';
8 | }
9 |
--------------------------------------------------------------------------------
/test/ui-test/contentAssistTest.ts:
--------------------------------------------------------------------------------
1 | import os = require('os');
2 | import path = require('path');
3 | import { expect } from 'chai';
4 | import { WebDriver, VSBrowser, ContentAssist, EditorView, TextEditor } from 'vscode-extension-tester';
5 | import { createCustomFile, deleteFileInHomeDir, getSchemaLabel } from './util/utility';
6 | /**
7 | * @author Zbynek Cervinka
8 | * @author Ondrej Dockal
9 | */
10 | export function contentAssistSuggestionTest(): void {
11 | describe('Verify content assist suggests right sugestion', () => {
12 | let driver: WebDriver;
13 | let editor: TextEditor;
14 | const yamlFileName = 'kustomization.yaml';
15 | const homeDir = os.homedir();
16 | const yamlFilePath = path.join(homeDir, yamlFileName);
17 |
18 | before(async function setup() {
19 | this.timeout(20000);
20 | driver = VSBrowser.instance.driver;
21 | editor = await createCustomFile(yamlFilePath);
22 | await driver.wait(async () => {
23 | return await getSchemaLabel(yamlFileName);
24 | }, 18000);
25 | });
26 |
27 | it('Content assist suggests right suggestion', async function () {
28 | this.timeout(15000);
29 | editor = new TextEditor();
30 | await editor.setText('api');
31 | const contentAssist = await editor.toggleContentAssist(true);
32 |
33 | // find if an item with given label is present
34 | if (contentAssist instanceof ContentAssist) {
35 | const hasItem = await contentAssist.hasItem('apiVersion');
36 | if (!hasItem) {
37 | expect.fail("The 'apiVersion' string did not appear in the content assist's suggestion list.");
38 | }
39 | } else {
40 | expect.fail("The 'apiVersion' string did not appear in the content assist's suggestion list.");
41 | }
42 | });
43 |
44 | after(async function () {
45 | this.timeout(5000);
46 | await editor.save();
47 | await new EditorView().closeAllEditors();
48 | deleteFileInHomeDir(yamlFileName);
49 | });
50 | });
51 | }
52 |
--------------------------------------------------------------------------------
/test/ui-test/customTagsTest.ts:
--------------------------------------------------------------------------------
1 | import os = require('os');
2 | import path = require('path');
3 | import { expect } from 'chai';
4 | import { By, WebDriver, TextEditor, Workbench, ContentAssist, EditorView, VSBrowser } from 'vscode-extension-tester';
5 | import { createCustomFile, deleteFileInHomeDir, getSchemaLabel, hardDelay } from './util/utility';
6 |
7 | /**
8 | * @author Zbynek Cervinka
9 | * @author Ondrej Dockal
10 | */
11 | export function customTagsTest(): void {
12 | describe("Verify extension's custom tags", () => {
13 | let driver: WebDriver;
14 | const yamlFileName = 'kustomization.yaml';
15 | const homeDir = os.homedir();
16 | const yamlFilePath = path.join(homeDir, yamlFileName);
17 | let editor: TextEditor;
18 | let editorView: EditorView;
19 |
20 | before(async function setup() {
21 | this.timeout(20000);
22 | driver = VSBrowser.instance.driver;
23 | editorView = new EditorView();
24 | await createCustomFile(yamlFilePath);
25 | await driver.wait(async () => {
26 | return await getSchemaLabel(yamlFileName);
27 | }, 18000);
28 | });
29 |
30 | it('YAML custom tags works as expected', async function () {
31 | this.timeout(30000);
32 |
33 | const settingsEditor = await new Workbench().openSettings();
34 | const setting = await settingsEditor.findSetting('Custom Tags', 'Yaml');
35 | await setting.findElement(By.className('edit-in-settings-button')).click();
36 |
37 | await hardDelay(2000);
38 | const textSettingsEditor = (await editorView.openEditor('settings.json')) as TextEditor;
39 | if (process.platform === 'darwin') {
40 | await driver.actions().sendKeys(' "customTag1"').perform();
41 | } else {
42 | const coor = await textSettingsEditor.getCoordinates();
43 | await textSettingsEditor.typeTextAt(coor[0], coor[1], ' "customTag1"');
44 | }
45 | await textSettingsEditor.save();
46 | await hardDelay(1_000);
47 |
48 | editor = (await editorView.openEditor(yamlFileName)) as TextEditor;
49 | await editor.setText('custom');
50 | await editor.save();
51 |
52 | const contentAssist = await editor.toggleContentAssist(true);
53 |
54 | // find if an item with given label is present in the content assist
55 | if (contentAssist instanceof ContentAssist) {
56 | const hasItem = await contentAssist.hasItem('customTag1');
57 | if (!hasItem) {
58 | expect.fail("The 'customTag1' custom tag did not appear in the content assist's suggestion list.");
59 | }
60 | } else {
61 | expect.fail("The 'customTag1' custom tag did not appear in the content assist's suggestion list.");
62 | }
63 | });
64 |
65 | after(async function () {
66 | this.timeout(5000);
67 | await new EditorView().closeAllEditors();
68 | deleteFileInHomeDir(yamlFileName);
69 | });
70 | });
71 | }
72 |
--------------------------------------------------------------------------------
/test/ui-test/extensionUITest.ts:
--------------------------------------------------------------------------------
1 | import { expect } from 'chai';
2 | import { YamlConstants } from './common/YAMLConstants';
3 | import {
4 | ActivityBar,
5 | ExtensionsViewItem,
6 | ExtensionsViewSection,
7 | SideBarView,
8 | VSBrowser,
9 | ViewControl,
10 | WebDriver,
11 | } from 'vscode-extension-tester';
12 |
13 | /**
14 | * @author Ondrej Dockal
15 | */
16 | export function extensionUIAssetsTest(): void {
17 | describe("Verify extension's base assets available after install", () => {
18 | let driver: WebDriver;
19 | let sideBar: SideBarView;
20 | let view: ViewControl;
21 | let section: ExtensionsViewSection;
22 | let yamlItem: ExtensionsViewItem;
23 |
24 | before(async function () {
25 | this.timeout(20000);
26 | driver = VSBrowser.instance.driver;
27 | view = await new ActivityBar().getViewControl('Extensions');
28 | sideBar = await view.openView();
29 | driver.wait(
30 | async () => !(await sideBar.getContent().hasProgress()),
31 | 5000,
32 | "Progress bar hasn't been hidden within the timeout"
33 | );
34 | section = (await sideBar.getContent().getSection('Installed')) as ExtensionsViewSection;
35 | await section.expand();
36 | yamlItem = await driver.wait(
37 | async () => {
38 | return await section.findItem(`@installed ${YamlConstants.YAML_NAME}`);
39 | },
40 | 5000,
41 | 'There were not visible items available under installed section'
42 | );
43 | });
44 |
45 | it('YAML extension is installed', async function () {
46 | this.timeout(5000);
47 | expect(yamlItem).not.undefined;
48 | let author: string;
49 | let name: string;
50 | try {
51 | name = await yamlItem.getTitle();
52 | author = await yamlItem.getAuthor();
53 | } catch (error) {
54 | if ((error as Error).name === 'StaleElementReferenceError') {
55 | yamlItem = await section.findItem(`@installed ${YamlConstants.YAML_NAME}`);
56 | name = await yamlItem.getTitle();
57 | author = await yamlItem.getAuthor();
58 | }
59 | throw error;
60 | }
61 | expect(name).to.equal(YamlConstants.YAML_NAME);
62 | expect(author).to.equal('Red Hat');
63 | });
64 |
65 | after(async () => {
66 | if (sideBar && (await sideBar.isDisplayed()) && view) {
67 | await view.closeView();
68 | }
69 | });
70 | });
71 | }
72 |
--------------------------------------------------------------------------------
/test/ui-test/schemaIsSetTest.ts:
--------------------------------------------------------------------------------
1 | import os = require('os');
2 | import path = require('path');
3 | import { WebDriver, VSBrowser, EditorView, WebElement } from 'vscode-extension-tester';
4 | import { createCustomFile, deleteFileInHomeDir, getSchemaLabel } from './util/utility';
5 | import { expect } from 'chai';
6 |
7 | /**
8 | * @author Zbynek Cervinka
9 | * @author Ondrej Dockal
10 | */
11 | export function schemaIsSetTest(): void {
12 | describe('Verify that the right JSON schema has been selected', () => {
13 | let driver: WebDriver;
14 | const yamlFileName = 'kustomization.yaml';
15 | const homeDir = os.homedir();
16 | const yamlFilePath = path.join(homeDir, yamlFileName);
17 | let schema: WebElement;
18 |
19 | before(async function setup() {
20 | this.timeout(20000);
21 | driver = VSBrowser.instance.driver;
22 | await createCustomFile(yamlFilePath);
23 | schema = await driver.wait(async () => {
24 | return await getSchemaLabel(yamlFileName);
25 | }, 18000);
26 | });
27 |
28 | it('The right JSON schema has been selected', async function () {
29 | this.timeout(5000);
30 | expect(schema).not.undefined;
31 | expect(await schema.getText()).to.include('kustomization');
32 | });
33 |
34 | after(async function () {
35 | this.timeout(5000);
36 | await new EditorView().closeAllEditors();
37 | deleteFileInHomeDir(yamlFileName);
38 | });
39 | });
40 | }
41 |
--------------------------------------------------------------------------------
/test/ui-test/util/utility.ts:
--------------------------------------------------------------------------------
1 | import os = require('os');
2 | import path = require('path');
3 | import { StatusBar, By, WebElement, InputBox, TextEditor, Workbench } from 'vscode-extension-tester';
4 |
5 | /**
6 | * @author Zbynek Cervinka
7 | * @author Ondrej Dockal
8 | */
9 |
10 | export async function createCustomFile(path: string): Promise {
11 | await new Workbench().openCommandPrompt();
12 |
13 | let input = await InputBox.create();
14 | await input.setText('>new file');
15 | await input.confirm();
16 | await input.confirm();
17 | const editor = new TextEditor();
18 | editor.save();
19 | input = await InputBox.create();
20 | await input.setText(path);
21 | await input.confirm();
22 | return editor;
23 | }
24 |
25 | export function deleteFileInHomeDir(filename: string): void {
26 | const homeDir = os.homedir();
27 | const pathtofile = path.join(homeDir, filename);
28 |
29 | // eslint-disable-next-line @typescript-eslint/no-var-requires
30 | const fs = require('fs');
31 | if (fs.existsSync(pathtofile)) {
32 | fs.rmSync(pathtofile, { recursive: true, force: true });
33 | }
34 | }
35 |
36 | export async function getSchemaLabel(text: string): Promise {
37 | const schemalabel = await new StatusBar().findElements(By.xpath('.//a[@aria-label="' + text + ', Select JSON Schema"]'));
38 | return schemalabel[0];
39 | }
40 |
41 | export async function hardDelay(milliseconds: number): Promise {
42 | return new Promise((resolve) => setTimeout(resolve, milliseconds));
43 | }
44 |
--------------------------------------------------------------------------------
/thirdpartynotices.txt:
--------------------------------------------------------------------------------
1 | redhat-developer/vscode-yaml
2 |
3 | THIRD-PARTY SOFTWARE NOTICES AND INFORMATION
4 | Do Not Translate or Localize
5 |
6 | This project incorporates components from the projects listed below. The original copyright notices and the licenses under which Red Hat received such components are set forth below. Red Hat reserves all rights not expressly granted herein, whether by implication, estoppel or otherwise.
7 |
8 | 1. textmate/yaml.tmbundle (https://github.com/textmate/yaml.tmbundle)
9 | 2. microsoft/vscode (https://github.com/Microsoft/vscode)
10 |
11 | %% textmate/yaml.tmbundle NOTICES AND INFORMATION BEGIN HERE
12 | =========================================
13 | Copyright (c) 2015 FichteFoll
14 |
15 | Permission is hereby granted, free of charge, to any person obtaining a copy
16 | of this software and associated documentation files (the "Software"), to deal
17 | in the Software without restriction, including without limitation the rights
18 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19 | copies of the Software, and to permit persons to whom the Software is
20 | furnished to do so, subject to the following conditions:
21 |
22 | The above copyright notice and this permission notice shall be included in all
23 | copies or substantial portions of the Software.
24 |
25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 | =========================================
32 | END OF textmate/yaml.tmbundle NOTICES AND INFORMATION
33 |
34 | %% vscode NOTICES AND INFORMATION BEGIN HERE
35 | =========================================
36 | MIT License
37 |
38 | Copyright (c) 2015 - present Microsoft Corporation
39 |
40 | All rights reserved.
41 |
42 | Permission is hereby granted, free of charge, to any person obtaining a copy
43 | of this software and associated documentation files (the "Software"), to deal
44 | in the Software without restriction, including without limitation the rights
45 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
46 | copies of the Software, and to permit persons to whom the Software is
47 | furnished to do so, subject to the following conditions:
48 |
49 | The above copyright notice and this permission notice shall be included in all
50 | copies or substantial portions of the Software.
51 |
52 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
53 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
54 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
55 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
56 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
57 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
58 | SOFTWARE.
59 | =========================================
60 | END OF vscode NOTICES AND INFORMATION
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "lib": ["es2022","WebWorker"],
4 | "module": "commonjs",
5 | "moduleResolution": "node",
6 | "outDir": "out",
7 | "skipLibCheck": true,
8 | "sourceMap": true,
9 | "target": "es2022"
10 | },
11 | "exclude": ["node_modules", "server", "src/webworker"],
12 | "include": ["src", "test"]
13 | }
14 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license.
3 |
4 | //@ts-check
5 |
6 | 'use strict';
7 |
8 | // eslint-disable-next-line @typescript-eslint/no-var-requires
9 | const path = require('path');
10 | // eslint-disable-next-line @typescript-eslint/no-var-requires
11 | const webpack = require('webpack');
12 |
13 | /**@type {import('webpack').Configuration}*/
14 | const config = {
15 | target: 'node', // vscode extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/
16 | node: {
17 | __dirname: false,
18 | __filename: false,
19 | },
20 | entry: {
21 | extension: './src/node/yamlClientMain.ts', // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/
22 | languageserver: './node_modules/yaml-language-server/out/server/src/server.js',
23 | },
24 | output: {
25 | // the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/
26 | path: path.resolve(__dirname, 'dist'),
27 | filename: '[name].js',
28 | libraryTarget: 'commonjs2',
29 | devtoolModuleFilenameTemplate: '../[resource-path]',
30 | },
31 | devtool: 'source-map',
32 | externals: {
33 | vscode: 'commonjs vscode', // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/
34 | prettier: 'commonjs prettier',
35 | },
36 | resolve: {
37 | // support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader
38 | extensions: ['.ts', '.js'],
39 | },
40 | module: {
41 | rules: [
42 | {
43 | test: /\.ts$/,
44 | exclude: /node_modules/,
45 | use: [
46 | {
47 | loader: 'ts-loader',
48 | },
49 | ],
50 | },
51 | {
52 | test: /node_modules[\\|/](vscode-json-languageservice)/,
53 | use: { loader: 'umd-compat-loader' },
54 | },
55 | ],
56 | },
57 | };
58 |
59 | /**@type {import('webpack').Configuration}*/
60 | const clientWeb = {
61 | mode: 'none', // this leaves the source code as close as possible to the original (when packaging we set this to 'production')
62 | target: 'webworker', // extensions run in a webworker context
63 | entry: {
64 | 'extension-web': './src/webworker/yamlClientMain.ts',
65 | },
66 | output: {
67 | filename: 'extension-web.js',
68 | path: path.join(__dirname, './dist'),
69 | libraryTarget: 'commonjs',
70 | devtoolModuleFilenameTemplate: '../[resource-path]',
71 | },
72 | resolve: {
73 | mainFields: ['module', 'main'],
74 | extensions: ['.ts', '.js'], // support ts-files and js-files
75 | alias: {
76 | 'node-fetch': 'whatwg-fetch',
77 | 'object-hash': 'object-hash/dist/object_hash.js',
78 | },
79 | fallback: {
80 | path: require.resolve('path-browserify'),
81 | 'node-fetch': require.resolve('whatwg-fetch'),
82 | util: require.resolve('util'),
83 | fs: false,
84 | },
85 | },
86 | module: {
87 | rules: [
88 | {
89 | test: /\.ts$/,
90 | exclude: /node_modules/,
91 | use: [
92 | {
93 | // configure TypeScript loader:
94 | // * enable sources maps for end-to-end source maps
95 | loader: 'ts-loader',
96 | options: {
97 | compilerOptions: {
98 | sourceMap: true,
99 | declaration: false,
100 | },
101 | },
102 | },
103 | ],
104 | },
105 | ],
106 | },
107 | plugins: [
108 | new webpack.ProvidePlugin({
109 | process: path.resolve(path.join(__dirname, 'node_modules/process/browser.js')), // provide a shim for the global `process` variable
110 | }),
111 | ],
112 | externals: {
113 | vscode: 'commonjs vscode', // ignored because it doesn't exist
114 | },
115 | performance: {
116 | hints: false,
117 | },
118 | devtool: 'nosources-source-map',
119 | };
120 |
121 | /**@type {import('webpack').Configuration}*/
122 | const serverWeb = {
123 | mode: 'none', // this leaves the source code as close as possible to the original (when packaging we set this to 'production')
124 | target: 'webworker', // extensions run in a webworker context
125 | entry: {
126 | 'languageserver-web': './node_modules/yaml-language-server/lib/esm/webworker/yamlServerMain',
127 | },
128 | output: {
129 | filename: 'languageserver-web.js',
130 | path: path.join(__dirname, './dist'),
131 | libraryTarget: 'var',
132 | library: 'serverExportVar',
133 | devtoolModuleFilenameTemplate: '../[resource-path]',
134 | },
135 | resolve: {
136 | mainFields: ['browser', 'module', 'main'],
137 | extensions: ['.ts', '.js'], // support ts-files and js-files
138 | alias: {
139 | './services/yamlFormatter': path.resolve(__dirname, './build/polyfills/yamlFormatter.js'), // not supported for now. prettier can run in the web, but it's a bit more work.
140 | 'vscode-json-languageservice/lib/umd': 'vscode-json-languageservice/lib/esm',
141 | },
142 | fallback: {
143 | path: require.resolve('path-browserify/'),
144 | url: require.resolve('url/'),
145 | buffer: require.resolve('buffer/'),
146 | fs: false,
147 | },
148 | },
149 | plugins: [
150 | new webpack.ProvidePlugin({
151 | process: path.resolve(path.join(__dirname, 'node_modules/process/browser.js')), // provide a shim for the global `process` variable
152 | }),
153 | ],
154 | module: {},
155 | externals: {},
156 | performance: {
157 | hints: false,
158 | },
159 |
160 | devtool: 'nosources-source-map',
161 | };
162 |
163 | module.exports = [config, clientWeb, serverWeb];
164 |
--------------------------------------------------------------------------------