forked from microsoft/vscode
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds a simple set of tests for custom editors in a new extension. This is currently not run during CI since we want more testing to make sure it is reliable
- Loading branch information
Showing
15 changed files
with
1,231 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
56 changes: 56 additions & 0 deletions
56
extensions/vscode-custom-editor-tests/customEditorMedia/textEditor.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
/*--------------------------------------------------------------------------------------------- | ||
* Copyright (c) Microsoft Corporation. All rights reserved. | ||
* Licensed under the MIT License. See License.txt in the project root for license information. | ||
*--------------------------------------------------------------------------------------------*/ | ||
// @ts-check | ||
(function () { | ||
// @ts-ignore | ||
const vscode = acquireVsCodeApi(); | ||
|
||
const textArea = document.querySelector('textarea'); | ||
|
||
const initialState = vscode.getState(); | ||
if (initialState) { | ||
textArea.value = initialState.value; | ||
} | ||
|
||
window.addEventListener('message', e => { | ||
switch (e.data.type) { | ||
case 'fakeInput': | ||
{ | ||
const value = e.data.value; | ||
textArea.value = value; | ||
onInput(); | ||
break; | ||
} | ||
|
||
case 'setValue': | ||
{ | ||
const value = e.data.value; | ||
textArea.value = value; | ||
vscode.setState({ value }); | ||
|
||
vscode.postMessage({ | ||
type: 'didChangeContent', | ||
value: value | ||
}); | ||
break; | ||
} | ||
} | ||
}); | ||
|
||
const onInput = () => { | ||
const value = textArea.value; | ||
vscode.setState({ value }); | ||
vscode.postMessage({ | ||
type: 'edit', | ||
value: value | ||
}); | ||
vscode.postMessage({ | ||
type: 'didChangeContent', | ||
value: value | ||
}); | ||
}; | ||
|
||
textArea.addEventListener('input', onInput); | ||
}()); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
{ | ||
"name": "vscode-custom-editor-tests", | ||
"description": "Custom editor tests for VS Code", | ||
"version": "0.0.1", | ||
"publisher": "vscode", | ||
"license": "MIT", | ||
"private": true, | ||
"activationEvents": [ | ||
"onCustomEditor:testWebviewEditor.abc" | ||
], | ||
"main": "./out/extension", | ||
"enableProposedApi": true, | ||
"engines": { | ||
"vscode": "^1.48.0" | ||
}, | ||
"scripts": { | ||
"compile": "node ./node_modules/vscode/bin/compile -watch -p ./", | ||
"vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:vscode-notebook-tests ./tsconfig.json" | ||
}, | ||
"dependencies": { | ||
"p-limit": "^3.0.2" | ||
}, | ||
"devDependencies": { | ||
"@types/node": "^12.11.7", | ||
"@types/p-limit": "^2.2.0", | ||
"mocha": "^2.3.3", | ||
"mocha-junit-reporter": "^1.17.0", | ||
"mocha-multi-reporters": "^1.1.7", | ||
"vscode": "^1.1.36" | ||
}, | ||
"contributes": { | ||
"customEditors": [ | ||
{ | ||
"viewType": "testWebviewEditor.abc", | ||
"displayName": "Test ABC editor", | ||
"selector": [ | ||
{ | ||
"filenamePattern": "*.abc" | ||
} | ||
] | ||
} | ||
] | ||
} | ||
} |
165 changes: 165 additions & 0 deletions
165
extensions/vscode-custom-editor-tests/src/customTextEditor.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
/*--------------------------------------------------------------------------------------------- | ||
* Copyright (c) Microsoft Corporation. All rights reserved. | ||
* Licensed under the MIT License. See License.txt in the project root for license information. | ||
*--------------------------------------------------------------------------------------------*/ | ||
|
||
import * as pLimit from 'p-limit'; | ||
import * as path from 'path'; | ||
import * as vscode from 'vscode'; | ||
import { Disposable } from './dispose'; | ||
|
||
export namespace Testing { | ||
export const abcEditorContentChangeCommand = '_abcEditor.contentChange'; | ||
export const abcEditorTypeCommand = '_abcEditor.type'; | ||
|
||
export interface CustomEditorContentChangeEvent { | ||
readonly content: string; | ||
readonly source: vscode.Uri; | ||
} | ||
} | ||
|
||
export class AbcTextEditorProvider implements vscode.CustomTextEditorProvider { | ||
|
||
public static readonly viewType = 'testWebviewEditor.abc'; | ||
|
||
private activeEditor?: AbcEditor; | ||
|
||
public constructor( | ||
private readonly context: vscode.ExtensionContext, | ||
) { } | ||
|
||
public register(): vscode.Disposable { | ||
const provider = vscode.window.registerCustomEditorProvider(AbcTextEditorProvider.viewType, this); | ||
|
||
const commands: vscode.Disposable[] = []; | ||
commands.push(vscode.commands.registerCommand(Testing.abcEditorTypeCommand, (content: string) => { | ||
this.activeEditor?.testing_fakeInput(content); | ||
})); | ||
|
||
return vscode.Disposable.from(provider, ...commands); | ||
} | ||
|
||
public async resolveCustomTextEditor(document: vscode.TextDocument, panel: vscode.WebviewPanel) { | ||
const editor = new AbcEditor(document, this.context.extensionPath, panel); | ||
|
||
this.activeEditor = editor; | ||
|
||
panel.onDidChangeViewState(({ webviewPanel }) => { | ||
if (this.activeEditor === editor && !webviewPanel.active) { | ||
this.activeEditor = undefined; | ||
} | ||
if (webviewPanel.active) { | ||
this.activeEditor = editor; | ||
} | ||
}); | ||
} | ||
} | ||
|
||
class AbcEditor extends Disposable { | ||
|
||
public readonly _onDispose = this._register(new vscode.EventEmitter<void>()); | ||
public readonly onDispose = this._onDispose.event; | ||
|
||
private readonly limit = pLimit(1); | ||
private syncedVersion: number = -1; | ||
private currentWorkspaceEdit?: Thenable<void>; | ||
|
||
constructor( | ||
private readonly document: vscode.TextDocument, | ||
private readonly _extensionPath: string, | ||
private readonly panel: vscode.WebviewPanel, | ||
) { | ||
super(); | ||
|
||
panel.webview.options = { | ||
enableScripts: true, | ||
}; | ||
panel.webview.html = this.html; | ||
|
||
this._register(vscode.workspace.onDidChangeTextDocument(e => { | ||
if (e.document === this.document) { | ||
this.update(); | ||
} | ||
})); | ||
|
||
this._register(panel.webview.onDidReceiveMessage(message => { | ||
switch (message.type) { | ||
case 'edit': | ||
this.doEdit(message.value); | ||
break; | ||
|
||
case 'didChangeContent': | ||
vscode.commands.executeCommand(Testing.abcEditorContentChangeCommand, { | ||
content: message.value, | ||
source: document.uri, | ||
} as Testing.CustomEditorContentChangeEvent); | ||
break; | ||
} | ||
})); | ||
|
||
this._register(panel.onDidDispose(() => { this.dispose(); })); | ||
|
||
this.update(); | ||
} | ||
|
||
public testing_fakeInput(value: string) { | ||
this.panel.webview.postMessage({ | ||
type: 'fakeInput', | ||
value: value, | ||
}); | ||
} | ||
|
||
private async doEdit(value: string) { | ||
const edit = new vscode.WorkspaceEdit(); | ||
edit.replace(this.document.uri, this.document.validateRange(new vscode.Range(new vscode.Position(0, 0), new vscode.Position(999999, 999999))), value); | ||
this.limit(() => { | ||
this.currentWorkspaceEdit = vscode.workspace.applyEdit(edit).then(() => { | ||
this.syncedVersion = this.document.version; | ||
this.currentWorkspaceEdit = undefined; | ||
}); | ||
return this.currentWorkspaceEdit; | ||
}); | ||
} | ||
|
||
public dispose() { | ||
if (this.isDisposed) { | ||
return; | ||
} | ||
|
||
this._onDispose.fire(); | ||
super.dispose(); | ||
} | ||
|
||
private get html() { | ||
const contentRoot = path.join(this._extensionPath, 'customEditorMedia'); | ||
const scriptUri = vscode.Uri.file(path.join(contentRoot, 'textEditor.js')); | ||
const nonce = Date.now() + ''; | ||
return /* html */`<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'nonce-${nonce}'; style-src 'unsafe-inline';"> | ||
<title>Document</title> | ||
</head> | ||
<body> | ||
<textarea style="width: 300px; height: 300px;"></textarea> | ||
<script nonce=${nonce} src="${this.panel.webview.asWebviewUri(scriptUri)}"></script> | ||
</body> | ||
</html>`; | ||
} | ||
|
||
public async update() { | ||
await this.currentWorkspaceEdit; | ||
|
||
if (this.isDisposed || this.syncedVersion >= this.document.version) { | ||
return; | ||
} | ||
|
||
this.panel.webview.postMessage({ | ||
type: 'setValue', | ||
value: this.document.getText(), | ||
}); | ||
this.syncedVersion = this.document.version; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
/*--------------------------------------------------------------------------------------------- | ||
* Copyright (c) Microsoft Corporation. All rights reserved. | ||
* Licensed under the MIT License. See License.txt in the project root for license information. | ||
*--------------------------------------------------------------------------------------------*/ | ||
|
||
import * as vscode from 'vscode'; | ||
|
||
export function disposeAll(disposables: vscode.Disposable[]) { | ||
while (disposables.length) { | ||
const item = disposables.pop(); | ||
if (item) { | ||
item.dispose(); | ||
} | ||
} | ||
} | ||
|
||
export abstract class Disposable { | ||
private _isDisposed = false; | ||
|
||
protected _disposables: vscode.Disposable[] = []; | ||
|
||
public dispose(): any { | ||
if (this._isDisposed) { | ||
return; | ||
} | ||
this._isDisposed = true; | ||
disposeAll(this._disposables); | ||
} | ||
|
||
protected _register<T extends vscode.Disposable>(value: T): T { | ||
if (this._isDisposed) { | ||
value.dispose(); | ||
} else { | ||
this._disposables.push(value); | ||
} | ||
return value; | ||
} | ||
|
||
protected get isDisposed() { | ||
return this._isDisposed; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/*--------------------------------------------------------------------------------------------- | ||
* Copyright (c) Microsoft Corporation. All rights reserved. | ||
* Licensed under the MIT License. See License.txt in the project root for license information. | ||
*--------------------------------------------------------------------------------------------*/ | ||
|
||
import * as vscode from 'vscode'; | ||
import { AbcTextEditorProvider } from './customTextEditor'; | ||
|
||
export function activate(context: vscode.ExtensionContext) { | ||
context.subscriptions.push(new AbcTextEditorProvider(context).register()); | ||
} |
Oops, something went wrong.