提交 24dfa08f 编写于 作者: M Martin Aeschlimann

Theme tests as extension test

上级 4d1a9fe4
import org.junit.Test;
/*
* Multi line comment
*/
public class TestClass {
private String aString;
/**
* @param args
*/
public void doSomething(int a) {
double b = 0.0;
double c = 10e3;
long l = 134l;
}
/*
* multiline comment
*/
@SuppressWarnings(value = "aString")
private long privateMethod(long b){
for (int i = 0; i < 9; i++) {
System.out.println("Hello" + i);
}
return 10;
}
//single line comment
@Test
public void someTests() {
int hex = 0x5;
Vector<Number> v = new Vector();
}
}
此差异已折叠。
......@@ -13,6 +13,17 @@
"sourceMaps": true,
"outDir": "${workspaceRoot}/client/out",
"preLaunchTask": "npm"
}
},
{
"name": "Launch Tests",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": ["--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/client/out/test" ],
"stopOnEntry": false,
"sourceMaps": true,
"outDir": "${workspaceRoot}/client/out/test",
"preLaunchTask": "npm"
}
]
}
\ No newline at end of file
{
// a comment
"options": {
"myBool": true,
"myInteger": 1,
"myString": "String\u0056",
"myNumber": 1.24,
"myNull": null,
"myArray": [ 1, "Hello", true, null, [], {}],
"myObject" : {
"foo": "bar"
}
}
}
\ No newline at end of file
此差异已折叠。
out
node_modules
\ No newline at end of file
// A launch configuration that compiles the extension and then opens it inside a new window
{
"version": "0.1.0",
"configurations": [
{
"name": "Launch Tests",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": ["${workspaceRoot}/../../", "${workspaceRoot}/test", "--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out" ],
"stopOnEntry": false,
"sourceMaps": true,
"outDir": "${workspaceRoot}/out",
"preLaunchTask": "npm"
}
]
}
\ No newline at end of file
// Available variables which can be used inside of strings.
// ${workspaceRoot}: the root folder of the team
// ${file}: the current opened file
// ${fileBasename}: the current opened file's basename
// ${fileDirname}: the current opened file's dirname
// ${fileExtname}: the current opened file's extension
// ${cwd}: the current working directory of the spawned process
// A task runner that calls a custom npm script that compiles the extension.
{
"version": "0.1.0",
// we want to run npm
"command": "npm",
// the command is a shell script
"isShellCommand": true,
// show the output window only if unrecognized errors occur.
"showOutput": "silent",
// we run the custom script "compile" as defined in package.json
"args": ["run", "compile", "--loglevel", "silent"],
// The tsc compiler is started in watching mode
"isWatching": true,
// use the standard tsc in watch mode problem matcher to find compile problems in the output.
"problemMatcher": "$tsc-watch"
}
\ No newline at end of file
{
"name": "vscode-colorize-tests",
"description": "Colorize tests for VS Code",
"version": "0.0.1",
"publisher": "vscode",
"private": true,
"engines": {
"vscode": "*"
},
"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-api-tests ./tsconfig.json",
"postinstall": "node ./node_modules/vscode/bin/install"
},
"devDependencies": {
"typescript": "^1.6.2",
"vscode": "^0.11.1"
}
}
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as assert from 'assert';
import {commands, Uri} from 'vscode';
import {join, basename, normalize, dirname} from 'path';
import * as fs from 'fs';
function assertUnchangedTokens(testFixurePath:string, done) {
let fileName = basename(testFixurePath);
return commands.executeCommand('_workbench.captureSyntaxTokens', Uri.file(testFixurePath)).then(data => {
try {
let resultsFolderPath = join(dirname(dirname(testFixurePath)), 'colorize-results');
let resultPath = join(resultsFolderPath, fileName.replace('.', '_') + '.json');
if (fs.existsSync(resultPath)) {
let previosData = JSON.parse(fs.readFileSync(resultPath).toString());
try {
assert.deepEqual(data, previosData);
} catch (e) {
let errorResultPath = join(resultsFolderPath, fileName.replace('.', '_') + '.error.json');
fs.writeFileSync(errorResultPath, JSON.stringify(data, null, '\t'));
throw e;
}
} else {
fs.writeFileSync(resultPath, JSON.stringify(data, null, '\t'));
}
done();
} catch (e) {
done(e);
}
}, done);
}
suite("colorization", () => {
let extensionsFolder = normalize(join(__dirname, '../../'));
console.log(extensionsFolder);
let extensions = fs.readdirSync(extensionsFolder);
extensions.forEach(extension => {
let extensionColorizeFixurePath = join(extensionsFolder, extension, 'test', 'colorize-fixtures');
if (fs.existsSync(extensionColorizeFixurePath)) {
console.log(extensionColorizeFixurePath);
let fixturesFiles = fs.readdirSync(extensionColorizeFixurePath);
fixturesFiles.forEach(fixturesFile => {
// define a test for each fixture
test(extension + '-' + fixturesFile, function(done) {
assertUnchangedTokens(join(extensionColorizeFixurePath, fixturesFile), done);
});
});
}
});
});
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
//
// PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING
//
// This file is providing the test runner to use when running extension tests.
// By default the test runner in use is Mocha based.
//
// You can provide your own test runner if you want to override it by exporting
// a function run(testRoot: string, clb: (error:Error) => void) that the extension
// host can call to run the tests. The test runner is expected to use console.log
// to report the results back to the caller. When the tests are finished, return
// a possible error to the callback or null if none.
const testRunner = require('vscode/lib/testrunner');
// You can directly control Mocha options by uncommenting the following lines
// See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info
testRunner.configure({
ui: 'tdd', // the TDD UI is being used in extension.test.ts (suite, test, etc.)
useColors: process.platform !== 'win32', // colored output from test results (only windows cannot handle)
timeout: 10000
});
export= testRunner;
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/// <reference path='../../../../src/vs/vscode.d.ts'/>
/// <reference path='../../../../src/typings/mocha.d.ts'/>
/// <reference path='../../../../extensions/declares.d.ts'/>
/// <reference path='../../../../extensions/node.d.ts'/>
/// <reference path='../../../../extensions/lib.core.d.ts'/>
\ No newline at end of file
{
"compilerOptions": {
"module": "commonjs",
"target": "ES5",
"outDir": "out",
"noLib": true,
"sourceMap": true
},
"exclude": [
"node_modules"
]
}
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
declare function run(): void;
declare function suite(name: string, fn: (err?)=>void);
declare function test(name: string, fn: (done?: (err?)=>void)=>void);
declare function suiteSetup(fn: (done?: (err?)=>void)=>void);
declare function suiteTeardown(fn: (done?: (err?)=>void)=>void);
declare function setup(fn: (done?: (err?)=>void)=>void);
declare function teardown(fn: (done?: (err?)=>void)=>void);
......@@ -13,7 +13,7 @@
"scripts": {
"test": "mocha",
"preinstall": "node build/npm/preinstall.js",
"postinstall": "npm --prefix extensions/vscode-api-tests/ install extensions/vscode-api-tests/ && npm --prefix extensions/json/ install extensions/json/ && npm --prefix extensions/typescript/ install extensions/typescript/ && npm --prefix extensions/php/ install extensions/php/",
"postinstall": "npm --prefix extensions/vscode-api-tests/ install extensions/vscode-api-tests/ && npm --prefix extensions/vscode-colorize-tests/ install extensions/vscode-colorize-tests/ && npm --prefix extensions/json/ install extensions/json/ && npm --prefix extensions/typescript/ install extensions/typescript/ && npm --prefix extensions/php/ install extensions/php/",
"watch": "gulp watch"
},
"dependencies": {
......
......@@ -9,4 +9,5 @@ else
fi
# Integration Tests
./scripts/code.sh $ROOT/extensions/vscode-api-tests/testWorkspace --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out
\ No newline at end of file
./scripts/code.sh $ROOT/extensions/vscode-api-tests/testWorkspace --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out
./scripts/code.sh $ROOT/extensions/vscode-colorize-tests/test --extensionDevelopmentPath=$ROOT/extensions/vscode-colorize-tests --extensionTestsPath=$ROOT/extensions/vscode-colorize-tests/out
......@@ -23,94 +23,106 @@ import {TextModelWithTokens} from 'vs/editor/common/model/textModelWithTokens';
import {TextModel} from 'vs/editor/common/model/textModel';
import {IModeService} from 'vs/editor/common/services/modeService';
import pfs = require('vs/base/node/pfs');
import {KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegistry';
import {IInstantiationService, ServicesAccessor} from 'vs/platform/instantiation/common/instantiation';
import {IThemeService} from 'vs/workbench/services/themes/common/themeService';
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
import {KeyCode, KeyMod} from 'vs/base/common/keyCodes';
import {asFileEditorInput} from 'vs/workbench/common/editor';
interface Data {
c: string; // content
t: string; // token
r: string; // rule
r: { [theme:string]:string}
}
const ID = 'workbench.action.snapshotAction';
const LABEL = nls.localize('togglePosition', "Take Theme Snapshot");
class Snapper {
class SnapshotAction extends Action {
private currentSrcFolder: string;
constructor(id: string, label: string,
@IModeService private modeService: IModeService
constructor(
@IModeService private modeService: IModeService,
@IThemeService private themeService: IThemeService
) {
super(id, label);
let outFolder = require.toUrl('');
this.currentSrcFolder = paths.normalize(paths.join(outFolder, "../src/vs/workbench/parts/themes/test/electron-browser"));
}
public run(): TPromise<any> {
let fixturesPath = URI.parse(paths.join(this.currentSrcFolder, 'fixtures')).fsPath;
return pfs.readdir(fixturesPath).then(fileNames => {
return TPromise.join(fileNames.map(fileName => {
return pfs.readFile(paths.join(fixturesPath, fileName)).then(content => {
return this.snap(fileName, content.toString()).then(result => {
return this.verify(fileName, result);
});
});
}));
}, err => {
console.log(err.toString());
});
}
private getTestNode(themeId: string) : Element {
let editorNode = document.createElement('div');
editorNode.className = 'monaco-editor ' + themeId;
document.body.appendChild(editorNode);
public getId() : string {
return "TokenizationSnapshotController";
}
let element = document.createElement('span');
private getEditorNode() : Element {
let editorNodes = document.getElementsByClassName('monaco-editor');
if (editorNodes.length > 0) {
return editorNodes.item(0);
}
return null;
editorNode.appendChild(element);
return element;
}
private getStyle(scope: string) : string {
private getStyle(testNode: Element, scope: string) : string {
let element = document.createElement('span');
element.className = scope;
element.hidden = true;
testNode.className = 'token ' + scope;
let cssStyles = window.getComputedStyle(element);
let cssStyles = window.getComputedStyle(testNode);
if (cssStyles) {
return cssStyles.color;
}
return '';
}
private getMatchedCSSRule(scope: string) : string {
let element = document.createElement('span');
element.className = 'token ' + scope;
element.hidden = true;
let editorNode = this.getEditorNode();
editorNode.appendChild(element);
private getMatchedCSSRule(testNode: Element, scope: string) : string {
let rulesList = window.getMatchedCSSRules(element);
testNode.className = 'token ' + scope.replace(/\./g, ' ');
editorNode.removeChild(element);
let rulesList = window.getMatchedCSSRules(testNode);
if (rulesList) {
for (let i = rulesList.length - 1; i >= 0 ; i--) {
let selectorText = <string> rulesList.item(i)['selectorText'];
if (selectorText && selectorText.indexOf('.monaco-editor.vs') === 0) {
if (selectorText && selectorText.match(/\.monaco-editor\..+token/) ) {
return selectorText.substr(14);
}
}
} else {
console.log('no match ' + scope);
}
return '';
}
public snap(fileName: string, content: string) : TPromise<Data[]> {
public appendThemeInformation(data: Data[]) : TPromise<Data[]> {
let currentTheme = this.themeService.getTheme();
let getThemeName = (id: string) => {
let part = 'vscode-theme-defaults-themes-';
let startIdx = id.indexOf(part);
if (startIdx !== -1) {
return id.substring(startIdx + part.length, id.length - 5);
}
return void 0;
}
return this.themeService.getThemes().then(themeDatas => {
let defaultThemes = themeDatas.filter(themeData => !!getThemeName(themeData.id));
return TPromise.join(defaultThemes.map(defaultTheme => {
let themeId = defaultTheme.id;
return this.themeService.setTheme(themeId, false).then(success => {
if (success) {
let testNode = this.getTestNode(themeId);
let themeName = getThemeName(themeId);
data.forEach(entry => {
entry.r[themeName] = this.getMatchedCSSRule(testNode, entry.t);
});
}
});
}));
}).then(_ => {
return this.themeService.setTheme(currentTheme, false).then(_ => {
return data;
});
});
}
public captureSyntaxTokens(fileName: string, content: string) : TPromise<Data[]> {
return this.modeService.getOrCreateModeByFilenameOrFirstLine(fileName).then(mode => {
let result : Data[] = [];
let model = new TextModelWithTokens([], TextModel.toRawText(content, TextModel.DEFAULT_CREATION_OPTIONS), false, mode);
......@@ -122,39 +134,48 @@ class SnapshotAction extends Action {
result.push({
c: content,
t: tokenInfo.token.type,
r: this.getMatchedCSSRule(tokenInfo.token.type)
r: {}
});
}
});
return result;
return this.appendThemeInformation(result);
});
}
}
public verify(fileName: string, data: Data[]) : TPromise<any> {
let dataString = JSON.stringify(data, null, '\t');
let resultFileName = fileName.replace('.', '_') + '.json';
let resultPath = URI.parse(paths.join(this.currentSrcFolder, 'results', resultFileName)).fsPath;
return pfs.fileExists(resultPath).then(success => {
if (success) {
return pfs.readFile(resultPath).then(content => {
let previousDataString = content.toString();
if (previousDataString !== dataString) {
let errorResultFileName = fileName.replace('.', '_') + '.error.json';
let errorResultPath = URI.parse(paths.join(this.currentSrcFolder, 'results', errorResultFileName)).fsPath;
console.log(`Different result for ${fileName}`);
return pfs.writeFile(errorResultPath, dataString);
}
return true;
KeybindingsRegistry.registerCommandDesc({
id: '_workbench.captureSyntaxTokens',
weight: KeybindingsRegistry.WEIGHT.workbenchContrib(0),
handler(accessor: ServicesAccessor, args: [URI]) {
let process = (resource: URI) => {
let filePath = resource.fsPath;
let fileName = paths.basename(filePath);
let snapper = accessor.get(IInstantiationService).createInstance(Snapper);
return pfs.readFile(filePath).then(content => {
return snapper.captureSyntaxTokens(fileName, content.toString());
});
}
let [resource] = args;
if (!resource) {
let editorService = accessor.get(IWorkbenchEditorService);
let fileEditorInput = asFileEditorInput(editorService.getActiveEditorInput());
if (fileEditorInput) {
process(fileEditorInput.getResource()).then(result => {
console.log(result);
});
} else {
return pfs.writeFile(resultPath, dataString);
console.log('No file editor active');
}
});
}
}
var workbenchActionsRegistry = <WorkbenchActionRegistry.IWorkbenchActionRegistry> Platform.Registry.as(WorkbenchActionRegistry.Extensions.WorkbenchActions);
} else {
return process(resource);
}
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(SnapshotAction, ID, LABEL), nls.localize('view', "View"));
},
context: undefined,
primary: KeyMod.Shift | KeyCode.F11
});
......@@ -142,7 +142,7 @@ export class ThemeService implements IThemeService {
if (broadcastToAllWindows) {
this.windowService.broadcast({ channel: THEME_CHANNEL, payload: themeId });
}
return TPromise.as(false);
return TPromise.as(true);
}
themeId = validateThemeId(themeId); // migrate theme ids
......@@ -191,7 +191,7 @@ export class ThemeService implements IThemeService {
if (theme) {
return applyTheme(theme, onApply);
}
return null;
return false;
});
}
......@@ -253,7 +253,7 @@ function applyTheme(theme: IThemeData, onApply: (themeId:string) => void): TProm
theme.styleSheetContent = styleSheetContent;
_applyRules(styleSheetContent);
onApply(theme.id);
return false;
return true;
}, error => {
return TPromise.wrapError(nls.localize('error.cannotloadtheme', "Unable to load {0}", theme.path));
});
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册