mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-13 17:22:15 -05:00
Merge VS Code 1.26.1 (#2394)
* Squash merge commits for 1.26 (#1) (#2323) * Polish tag search as per feedback (#55269) * Polish tag search as per feedback * Updated regex * Allow users to opt-out of features that send online requests in the background (#55097) * settings sweep #54690 * Minor css tweaks to enable eoverflow elipsis in more places (#55277) * fix an issue with titlebarheight when not scaling with zoom * Settings descriptions update #54690 * fixes #55209 * Settings editor - many padding fixes * More space above level 2 label * Fixing Cannot debug npm script using Yarn #55103 * Settings editor - show ellipsis when description overflows * Settings editor - ... fix measuring around links, relayout * Setting descriptions * Settings editor - fix ... for some short lines, fix select container width * Settings editor - overlay trees so scrollable shadow is full width * Fix #54133 - missing extension settings after reload * Settings color token description tweak * Settings editor - disable overflow indicator temporarily, needs to be faster * Added command to Run the selected npm script * fixes #54452 * fixes #54929 * fixes #55248 * prefix command with extension name * Contribute run selected to the context menu * node-debug@1.26.6 * Allow terminal rendererType to be swapped out at runtime Part of #53274 Fixes #55344 * Settings editor - fix not focusing search when restoring editor setInput must be actually async. Will be fixed naturally when we aren't using winJS promises... * Settings editor - TOC should only expand the section with a selected item * Bump node-debug2 * Settings editor - Tree focus outlines * Settings editor - don't blink the scrollbar when toc selection changes And hide TOC correctly when the editor is narrow * Settings editor - header rows should not be selectable * fixes #54877 * change debug assignee to isi * Settings sweep (#54690) * workaround for #55051 * Settings sweep (#54690) * settings sweep #54690 * Don't try closing tags when you type > after another > * Describe what implementation code lens does Fixes #55370 * fix javadoc formatter setting description * fixes #55325 * update to officical TS version * Settings editor - Even more padding, use semibold instead of bold * Fix #55357 - fix TOC twistie * fixes #55288 * explorer: refresh on di change file system provider registration fixes #53256 * Disable push to Linux repo to test standalone publisher * New env var to notify log level to extensions #54001 * Disable snippets in extension search (when not in suggest dropdown) (#55281) * Disable snippits in extension search (when not in suggest dropdown) * Add monaco input contributions * Fix bug preventing snippetSuggestions from taking effect in sub-editors * Latest emmet helper to fix #52366 * Fix comment updates for threads within same file * Allow extensions to log telemetry to log files #54001 * Pull latest css grammar * files.exclude control - use same style for "add" vs "edit" * files.exclude control - focus/keyboard behavior * don't show menubar too early * files.exclude - better styling * Place cursor at end of extensions search box on autofill (#55254) * Place cursor at end of extensions search box on autofill * Use position instead of selection * fix linux build issue (empty if block) * Settings editor - fix extension category prefixes * Settings editor - add simple ellipsis for first line that overflows, doesn't cover case when first line does not overflow but there is more text, TODO * File/Text search provider docs * Fixes #52655 * Include epoch (#55008) * Fixes #53385 * Fixes #49480 * VS Code Insiders (Users) not opening Fixes #55353 * Better handling of the case when the extension host fails to start * Fixes #53966 * Remove confusing Start from wordPartLeft commands ID * vscode-xterm@3.6.0-beta12 Fixes #55488 * Initial size is set to infinity!! Fixes #55461 * Polish embeddedEditorBackground * configuration service misses event * Fix #55224 - fix duplicate results in multiroot workspace from splitting the diskseach query * Select all not working in issue reporter on mac, fixes #55424 * Disable fuzzy matching for extensions autosuggest (#55498) * Fix clipping of extensions search border in some third party themes (#55504) * fixes #55538 * Fix bug causing an aria alert to not be shown the third time (and odd numbers thereafter) * Settings editor - work around rendering glitch with webkit-line-clamp * Settings editor - revert earlier '...' changes * Settings editor - move enumDescription to its own div, because it disturbs -webkit-line-clamp for some reason * Settings editor - better overflow indicator * Don't show existing filters in autocomplete (#55495) * Dont show existing filters in autocomplete * Simplify * Settings Editor: Add aria labels for input elements Fixes: #54836 (#55543) * fixes #55223 * Update vscode-css-languageservice to 3.0.10-next.1 * Fix #55509 - settings navigation * Fix #55519 * Fix #55520 * FIx #55524 * Fix #55556 - include wordSeparators in all search queries, so findTextInFiles can respect isWordMatch correctly * oss updates for endgame * Fix unit tests * fixes #55522 * Avoid missing manifest error from bubbling up #54757 * Settings format crawl * Search provider - Fix FileSearchProvider to return array, not progress * Fix #55598 * Settings editor - fix NPE rendering settings with no description * dont render inden guides in search box (#55600) * fixes #55454 * More settings crawl * Another change for #55598 - maxResults applies to FileSearch and TextSearch but not FileIndex * Fix FileSearchProvider unit tests for progress change * fixes #55561 * Settings description update for #54690 * Update setting descriptions for online services * Minor edits * fixes #55513 * fixes #55451 * Fix #55612 - fix findTextInFiles cancellation * fixes #55539 * More setting description tweaks * Setting to disable online experiments #54354 * fixes #55507 * fixes #55515 * Show online services action only in Insiders for now * Settings editor - change toc behavior default to 'filter' * Settings editor - nicer filter count style during search * Fix #55617 - search viewlet icons * Settings editor - better styling for element count indicator * SearchProvider - fix NPE when searching extraFileResources * Allow extends to work without json suffix Fixes #16905 * Remove accessability options logic entirely Follow up on #55451 * use latest version of DAP * fixes #55490 * fixes #55122 * fixes #52332 * Avoid assumptions about git: URIs (fixes #36236) * relative path for descriptions * resourece: get rid of isFile context key fixes #48275 * Register previous ids for compatibility (#53497) * more tuning for #48275 * no need to always re-read "files explorer" fixes #52003 * read out active composites properly fixes #51967 * Update link colors for hc theme to meet color contrast ratio, fixes #55651 Also updated link color for `textLinkActiveForeground` to be the same as `textLinkForeground` as it wasn't properly updated * detect 'winpty-agent.exe'; fixes #55672 * node-debug@1.26.7 * reset counter on new label * Settings editor - fix multiple setting links in one description * Settings editor - color code blocks in setting descriptions, fix #55532 * Settings editor - hover color in TOC * Settings editor - fix navigation NPE * Settings editor - fix text control width * Settings editor - maybe fix #55684 * Fix bug causing cursor to not move on paste * fixes #53582 * Use ctrlCmd instead of ctrl for go down from search box * fixes #55264 * fixes #55456 * filter for spcaes before triggering search (#55611) * Fix #55698 - don't lose filtered TOC counts when refreshing TOC * fixes #55421 * fixes #28979 * fixes #55576 * only add check for updates to windows/linux help * readonly files: append decoration to label fixes #53022 * debug: do not show toolbar while initialising fixes #55026 * Opening launch.json should not activate debug extensions fixes #55029 * fixes #55435 * fixes #55434 * fixes #55439 * trigger menu only on altkey up * Fix #50555 - fix settings editor memory leak * Fix #55712 - no need to focus 'a' anymore when restoring control focus after tree render * fixes #55335 * proper fix for readonly model fixes #53022 * improve FoldingRangeKind spec (for #55686) * Use class with static fields (fixes #55494) * Fixes #53671 * fixes #54630 * [html] should disable ionic suggestions by default. Currently forces deprecated Ionic v1 suggestions in .html files while typing. Fixes #53324 * cleanup deps * debug issues back to andre * update electron for smoketest * Fix #55757 - prevent settings tabs from overflowing * Fix #53897 - revert setting menu defaults to old editor * Add enum descriptions to `typescript.preferences.importModuleSpecifier` * Fix #55767 - leaking style elements from settings editor * Fix #55521 - prevent flashing when clicking in exclude control * Update Git modified color for contrast ratio, fixes #53140 * Revert "Merge branch 'master' of github.com:Microsoft/vscode" This reverts commit bf46b6bfbae0cab99c2863e1244a916181fa9fbc, reversing changes made to e275a424483dfb4ed33b428c97d5e2c441d6b917. * Revert "Revert "Merge branch 'master' of github.com:Microsoft/vscode"" This reverts commit 53949d963f39e40757557c6526332354a31d9154. * don't ask to install an incomplete menu * Fix NPE in terminal AccessibilityManager Fixes #55744 * don't display fallback menu unless we've closed the last window * fixes #55547 * Fix smoke tests for extension search box * Update OSSREADME.json for Electron 2.0.5 * Update distro Includes Chromium license changes * fix #55455 * fix #55865 * fixes #55893 * Fix bug causing workspace recommendations to go away upon ignoring a recommendation (#55805) * Fix bug causing workspace recommendations to go away upon ignoring a recommendation * ONly show on @recommended or @recommended:workspace * Make more consistant * Fix #55911 * Understand json activity (#55926) * Understand json file activity * Refactoring * adding composer.json * Distro update for experiments * use terminal.processId for auto-attach; fixes #55918 * Reject invalid URI with vscode.openFolder (for #55891) * improve win32 setup system vs user detection fixes #55840 fixes #55840 delay winreg import related to #55840 show notification earlier related to #55840 fix #55840 update inno setup message related to #55840 * Fix #55593 - this code only operates on local paths, so use fsPath and Uri.file instead * Bring back the old menu due to electron 2.0 issues (#55913) * add the old menu back for native menus * make menu labels match * `vscode.openFolder`: treat missing URI schema gracefully (for #55891) * delay EH reattach; fixes #55955 * Mark all json files under appSettingsHome as settings * Use localized strings for telemetry opt-out * Exception when saving file editor opened from remote file provider (fixes #55051) * Remove terminal menu from stable Fixes 56003 * VSCode Insiders crashes on open with TypeError: Cannot read property 'lastIndexOf' of undefined. Fixes #54933 * improve fix for #55891 * fix #55916 * Improve #55891 * increase EH debugging restart delay; fixes #55955 * Revert "Don't include non-resource entries in history quick pick" This reverts commit 37209a838e9f7e9abe6dc53ed73cdf1e03b72060. * Diff editor: horizontal scrollbar height is smaller (fixes #56062) * improve openFolder uri fix (correctly treat backslashes) * fixes #56116 repair ipc for native menubar keybindings * Fix #56240 - Open the JSON settings editor instead of the UI editor * Fix #55536 * uriDisplay: if no formatter is registered fall back to getPathlabel fixes #56104 * VSCode hangs when opening python file. Fixes #56377 * VS Code Hangs When Opening Specific PowerShell File. Fixes #56430 * Fix #56433 - search extraFileResources even when no folders open * Workaround #55649 * Fix in master #56371 * Fix tests #56371 * Fix in master #56317 * increase version to 1.26.1 * Fixes #56387: Handle SIGPIPE in extension host * fixes #56185 * Fix merge issues (part 1) * Fix build breaks (part 1) * Build breaks (part 2) * Build breaks (part 3) * More build breaks (part 4) * Fix build breaks (part 5) * WIP * Fix menus * Render query result and message panels (#2363) * Put back query editor hot exit changes * Fix grid changes that broke profiler (#2365) * Update APIs for saving query editor state * Fix restore view state for profiler and edit data * Updating custom default themes to support 4.5:1 contrast ratio * Test updates * Fix Extension Manager and Windows Setup * Update license headers * Add appveyor and travis files back * Fix hidden modal dropdown issue
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
"name": "Jxck/assert",
|
||||
"license": "MIT",
|
||||
"licenseDetail": [
|
||||
"The Source EULA",
|
||||
"The MIT License (MIT)",
|
||||
"",
|
||||
"Copyright (c) 2011 Jxck",
|
||||
"",
|
||||
|
||||
@@ -9,6 +9,7 @@ const { join } = require('path');
|
||||
const path = require('path');
|
||||
const mocha = require('mocha');
|
||||
const events = require('events');
|
||||
const MochaJUnitReporter = require('mocha-junit-reporter');
|
||||
|
||||
const defaultReporterName = process.platform === 'win32' ? 'list' : 'spec';
|
||||
|
||||
@@ -21,7 +22,7 @@ const optimist = require('optimist')
|
||||
.describe('debug', 'open dev tools, keep window open, reuse app data').string('debug')
|
||||
.describe('reporter', 'the mocha reporter').string('reporter').default('reporter', defaultReporterName)
|
||||
.describe('reporter-options', 'the mocha reporter options').string('reporter-options').default('reporter-options', '')
|
||||
.describe('tfs').boolean('tfs')
|
||||
.describe('tfs').string('tfs')
|
||||
.describe('help', 'show the help').alias('help', 'h');
|
||||
|
||||
const argv = optimist.argv;
|
||||
@@ -96,26 +97,6 @@ function parseReporterOption(value) {
|
||||
return r ? { [r[1]]: r[2] } : {};
|
||||
}
|
||||
|
||||
class TFSReporter extends mocha.reporters.Base {
|
||||
|
||||
constructor(runner) {
|
||||
super(runner);
|
||||
|
||||
runner.on('pending', test => {
|
||||
console.log('PEND', test.fullTitle());
|
||||
});
|
||||
runner.on('pass', test => {
|
||||
console.log('OK ', test.fullTitle(), `(${test.duration}ms)`);
|
||||
});
|
||||
runner.on('fail', test => {
|
||||
console.log('FAIL', test.fullTitle(), `(${test.duration}ms)`);
|
||||
});
|
||||
runner.once('end', () => {
|
||||
this.epilogue();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
app.on('ready', () => {
|
||||
|
||||
const win = new BrowserWindow({
|
||||
@@ -141,7 +122,13 @@ app.on('ready', () => {
|
||||
const runner = new IPCRunner();
|
||||
|
||||
if (argv.tfs) {
|
||||
new TFSReporter(runner);
|
||||
new mocha.reporters.Spec(runner);
|
||||
new MochaJUnitReporter(runner, {
|
||||
reporterOptions: {
|
||||
testsuitesTitle: `${argv.tfs} ${process.platform}`,
|
||||
mochaFile: process.env.BUILD_ARTIFACTSTAGINGDIRECTORY ? path.join(process.env.BUILD_ARTIFACTSTAGINGDIRECTORY, `test-results/${process.platform}-${argv.tfs.toLowerCase().replace(/[^\w]/g, '-')}-results.xml`) : undefined
|
||||
}
|
||||
});
|
||||
} else {
|
||||
const reporterPath = path.join(path.dirname(require.resolve('mocha')), 'lib', 'reporters', argv.reporter);
|
||||
let Reporter;
|
||||
|
||||
@@ -270,5 +270,5 @@ function runTests(opts) {
|
||||
|
||||
ipcRenderer.on('run', (e, opts) => {
|
||||
initLoader(opts);
|
||||
runTests(opts).catch(err => console.error(err));
|
||||
runTests(opts).catch(err => console.error(typeof err === 'string' ? err : JSON.stringify(err)));
|
||||
});
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>Grid Example</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<script src="../out/vs/loader.js"></script>
|
||||
<script>
|
||||
require.config({ baseUrl: '../out' });
|
||||
|
||||
require(['vs/base/browser/ui/splitview/grid'], ({ Grid }) => {
|
||||
const grid = new Grid(document.body);
|
||||
const layout = () => grid.layout(document.body.clientWidth, document.body.clientHeight);
|
||||
window.onresize = layout;
|
||||
layout();
|
||||
});
|
||||
</script>
|
||||
<style>
|
||||
html,
|
||||
body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.node {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.action {
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border: 1px solid #3c3c3c;
|
||||
text-align: center;
|
||||
line-height: 16px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.action:hover {
|
||||
cursor: pointer;
|
||||
background-color: #ffffff54;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -7,8 +7,6 @@
|
||||
<body>
|
||||
<div id="mocha"></div>
|
||||
|
||||
<!--<script src="https://cdn.rawgit.com/jquery/jquery/2.1.4/dist/jquery.min.js"></script>
|
||||
<script src="https://cdn.rawgit.com/Automattic/expect.js/0.3.1/index.js"></script>-->
|
||||
<script src="/out/vs/loader.js"></script>
|
||||
<script src="https://cdn.rawgit.com/mochajs/mocha/2.2.5/mocha.js"></script>
|
||||
|
||||
|
||||
@@ -1,20 +1,39 @@
|
||||
# VS Code Smoke Test
|
||||
|
||||
## How to run
|
||||
### Run
|
||||
|
||||
```
|
||||
# Dev
|
||||
yarn smoketest
|
||||
|
||||
# Build
|
||||
yarn smoketest --build "path/to/code"
|
||||
yarn smoketest --build PATH_TO_BUILD
|
||||
```
|
||||
|
||||
The script calls mocha, so all mocha arguments should work fine. For example, use `-f Git` to filter all tests except the `Git` tests.
|
||||
### Run for a release
|
||||
|
||||
A `--verbose` flag can be used to log to the console all the low level driver calls make to Code.
|
||||
You must always run the smoketest version which matches the release you are testing. So, if you want to run the smoketest for a release build (eg `release/1.22`), you need that version of the smoke tests too:
|
||||
|
||||
Screenshots can be captured when tests fail. In order to get them,you need to use the argument `--screenshots SCREENSHOT_DIR`.
|
||||
```
|
||||
git checkout release/1.22
|
||||
yarn
|
||||
yarn smoketest --build PATH_TO_RELEASE_BUILD
|
||||
```
|
||||
|
||||
### Debug
|
||||
|
||||
- `--verbose` logs all the low level driver calls made to Code;
|
||||
- `-f PATTERN` filters the tests to be run. You can also use pretty much any mocha argument;
|
||||
- `--screenshots SCREENSHOT_DIR` captures screenshots when tests fail.
|
||||
|
||||
### Develop
|
||||
|
||||
Start a watch task in `test/smoke`:
|
||||
|
||||
```
|
||||
cd test/smoke
|
||||
yarn watch
|
||||
```
|
||||
|
||||
## Pitfalls
|
||||
|
||||
|
||||
@@ -22,10 +22,12 @@
|
||||
"@types/webdriverio": "4.6.1",
|
||||
"concurrently": "^3.5.1",
|
||||
"cpx": "^1.5.0",
|
||||
"electron": "1.7.7",
|
||||
"electron": "^2.0.6",
|
||||
"htmlparser2": "^3.9.2",
|
||||
"mkdirp": "^0.5.1",
|
||||
"mocha": "^3.2.0",
|
||||
"mocha": "^5.2.0",
|
||||
"mocha-junit-reporter": "^1.17.0",
|
||||
"mocha-multi-reporters": "^1.1.7",
|
||||
"ncp": "^2.0.0",
|
||||
"portastic": "^1.0.1",
|
||||
"rimraf": "^2.6.1",
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Workbench } from './areas/workbench/workbench';
|
||||
import * as fs from 'fs';
|
||||
import * as cp from 'child_process';
|
||||
import { Code, spawn, SpawnOptions } from './vscode/code';
|
||||
import { Logger } from './logger';
|
||||
@@ -26,7 +25,6 @@ export class Application {
|
||||
|
||||
private _code: Code | undefined;
|
||||
private _workbench: Workbench;
|
||||
private keybindings: any[];
|
||||
|
||||
constructor(private options: ApplicationOptions) { }
|
||||
|
||||
@@ -65,7 +63,7 @@ export class Application {
|
||||
async start(): Promise<any> {
|
||||
await this._start();
|
||||
await this.code.waitForElement('.explorer-folders-view');
|
||||
await this.code.waitForActiveElement(`.editor-container[id="workbench.editor.walkThroughPart"] > div > div[tabIndex="0"]`);
|
||||
await this.code.waitForActiveElement(`.editor-instance[id="workbench.editor.walkThroughPart"] > div > div[tabIndex="0"]`);
|
||||
}
|
||||
|
||||
async restart(options: { workspaceOrFolder?: string, extraArgs?: string[] }): Promise<any> {
|
||||
@@ -75,7 +73,6 @@ export class Application {
|
||||
}
|
||||
|
||||
private async _start(workspaceOrFolder = this.options.workspacePath, extraArgs: string[] = []): Promise<any> {
|
||||
await this.retrieveKeybindings();
|
||||
cp.execSync('git checkout .', { cwd: this.options.workspacePath });
|
||||
await this.startApplication(workspaceOrFolder, extraArgs);
|
||||
await this.checkWindowReady();
|
||||
@@ -108,10 +105,12 @@ export class Application {
|
||||
userDataDir: this.options.userDataDir,
|
||||
extensionsPath: this.options.extensionsPath,
|
||||
logger: this.options.logger,
|
||||
extraArgs
|
||||
verbose: this.options.verbose,
|
||||
log: this.options.log,
|
||||
extraArgs,
|
||||
});
|
||||
|
||||
this._workbench = new Workbench(this._code, this.keybindings, this.userDataPath);
|
||||
this._workbench = new Workbench(this._code, this.userDataPath);
|
||||
}
|
||||
|
||||
private async checkWindowReady(): Promise<any> {
|
||||
@@ -127,20 +126,4 @@ export class Application {
|
||||
// as soon as they open (eg quick open)
|
||||
await new Promise(c => setTimeout(c, 500));
|
||||
}
|
||||
|
||||
private retrieveKeybindings(): Promise<void> {
|
||||
return new Promise((c, e) => {
|
||||
fs.readFile(process.env.VSCODE_KEYBINDINGS_PATH as string, 'utf8', (err, data) => {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
try {
|
||||
this.keybindings = JSON.parse(data);
|
||||
c();
|
||||
} catch (e) {
|
||||
throw new Error(`Error parsing keybindings JSON: ${e}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ export function setup() {
|
||||
|
||||
await app.code.waitForElement(Problems.getSelectorInEditor(ProblemSeverity.ERROR));
|
||||
|
||||
const problems = new Problems(app.code, app.workbench);
|
||||
const problems = new Problems(app.code);
|
||||
await problems.showProblemsView();
|
||||
await app.code.waitForElement(Problems.getSelectorInProblemsView(ProblemSeverity.ERROR));
|
||||
await problems.hideProblemsView();
|
||||
|
||||
@@ -25,6 +25,8 @@ export function setup() {
|
||||
config.configurations[0].protocol = 'inspector';
|
||||
fs.writeFileSync(launchJsonPath, JSON.stringify(config, undefined, 4), 'utf8');
|
||||
|
||||
// force load from disk since file events are sometimes missing
|
||||
await app.workbench.quickopen.runCommand('File: Revert File');
|
||||
await app.workbench.editor.waitForEditorContents('launch.json', contents => /"protocol": "inspector"/.test(contents));
|
||||
|
||||
assert.equal(config.configurations[0].request, 'launch');
|
||||
@@ -47,15 +49,12 @@ export function setup() {
|
||||
it('start debugging', async function () {
|
||||
const app = this.app as Application;
|
||||
|
||||
// TODO@isidor
|
||||
await new Promise(c => setTimeout(c, 100));
|
||||
|
||||
port = await app.workbench.debug.startDebugging();
|
||||
|
||||
await new Promise((c, e) => {
|
||||
const request = http.get(`http://localhost:${port}`);
|
||||
request.on('error', e);
|
||||
app.workbench.debug.waitForStackFrame(sf => sf.name === 'index.js' && sf.lineNumber === 6, 'looking for index.js and line 6').then(c, e);
|
||||
app.workbench.debug.waitForStackFrame(sf => /index\.js$/.test(sf.name) && sf.lineNumber === 6, 'looking for index.js and line 6').then(c, e);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -79,13 +78,13 @@ export function setup() {
|
||||
|
||||
await app.workbench.debug.stepIn();
|
||||
|
||||
const first = await app.workbench.debug.waitForStackFrame(sf => sf.name === 'response.js', 'looking for response.js');
|
||||
const first = await app.workbench.debug.waitForStackFrame(sf => /response\.js$/.test(sf.name), 'looking for response.js');
|
||||
await app.workbench.debug.stepOver();
|
||||
|
||||
await app.workbench.debug.waitForStackFrame(sf => sf.name === 'response.js' && sf.lineNumber === first.lineNumber + 1, `looking for response.js and line ${first.lineNumber + 1}`);
|
||||
await app.workbench.debug.waitForStackFrame(sf => /response\.js$/.test(sf.name) && sf.lineNumber === first.lineNumber + 1, `looking for response.js and line ${first.lineNumber + 1}`);
|
||||
await app.workbench.debug.stepOut();
|
||||
|
||||
await app.workbench.debug.waitForStackFrame(sf => sf.name === 'index.js' && sf.lineNumber === 7, `looking for index.js and line 7`);
|
||||
await app.workbench.debug.waitForStackFrame(sf => /index\.js$/.test(sf.name) && sf.lineNumber === 7, `looking for index.js and line 7`);
|
||||
});
|
||||
|
||||
it('continue', async function () {
|
||||
@@ -96,7 +95,7 @@ export function setup() {
|
||||
await new Promise((c, e) => {
|
||||
const request = http.get(`http://localhost:${port}`);
|
||||
request.on('error', e);
|
||||
app.workbench.debug.waitForStackFrame(sf => sf.name === 'index.js' && sf.lineNumber === 6, `looking for index.js and line 6`).then(c, e);
|
||||
app.workbench.debug.waitForStackFrame(sf => /index\.js$/.test(sf.name) && sf.lineNumber === 6, `looking for index.js and line 6`).then(c, e);
|
||||
});
|
||||
|
||||
});
|
||||
@@ -113,4 +112,4 @@ export function setup() {
|
||||
await app.workbench.debug.stopDebugging();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,12 @@ export class Debug extends Viewlet {
|
||||
}
|
||||
|
||||
async openDebugViewlet(): Promise<any> {
|
||||
await this.commands.runCommand('workbench.view.debug');
|
||||
if (process.platform === 'darwin') {
|
||||
await this.code.dispatchKeybinding('cmd+shift+d');
|
||||
} else {
|
||||
await this.code.dispatchKeybinding('ctrl+shift+d');
|
||||
}
|
||||
|
||||
await this.code.waitForElement(DEBUG_VIEW);
|
||||
}
|
||||
|
||||
@@ -71,7 +76,7 @@ export class Debug extends Viewlet {
|
||||
}
|
||||
|
||||
async startDebugging(): Promise<number> {
|
||||
await this.commands.runCommand('workbench.action.debug.start');
|
||||
await this.code.dispatchKeybinding('f5');
|
||||
await this.code.waitForElement(PAUSE);
|
||||
await this.code.waitForElement(DEBUG_STATUS_BAR);
|
||||
const portPrefix = 'Port: ';
|
||||
@@ -115,7 +120,7 @@ export class Debug extends Viewlet {
|
||||
}
|
||||
|
||||
async focusStackFrame(name: string, message: string): Promise<any> {
|
||||
await this.code.waitAndClick(SPECIFIC_STACK_FRAME(name));
|
||||
await this.code.waitAndClick(SPECIFIC_STACK_FRAME(name), 0, 0);
|
||||
await this.editors.waitForTab(name);
|
||||
}
|
||||
|
||||
@@ -125,7 +130,7 @@ export class Debug extends Viewlet {
|
||||
await this.code.waitForSetValue(REPL_FOCUSED, text);
|
||||
|
||||
// Wait for the keys to be picked up by the editor model such that repl evalutes what just got typed
|
||||
await this.editor.waitForEditorContents('debug:input', s => s.indexOf(text) >= 0);
|
||||
await this.editor.waitForEditorContents('debug:replinput', s => s.indexOf(text) >= 0);
|
||||
await this.code.dispatchKeybinding('enter');
|
||||
await this.code.waitForElement(CONSOLE_INPUT_OUTPUT);
|
||||
await this.waitForOutput(output => accept(output[output.length - 1] || ''));
|
||||
|
||||
@@ -53,18 +53,18 @@ export function setup() {
|
||||
const app = this.app as Application;
|
||||
await app.workbench.quickopen.openFile('app.js');
|
||||
|
||||
await app.workbench.editor.gotoDefinition('app.js', 'express', 11);
|
||||
await app.workbench.editor.gotoDefinition('app.js', 'app', 14);
|
||||
|
||||
await app.workbench.editors.waitForActiveTab('index.d.ts');
|
||||
await app.workbench.editor.waitForHighlightingLine('app.js', 11);
|
||||
});
|
||||
|
||||
it(`verifies that 'Peek Definition' works`, async function () {
|
||||
const app = this.app as Application;
|
||||
await app.workbench.quickopen.openFile('app.js');
|
||||
|
||||
const peek = await app.workbench.editor.peekDefinition('app.js', 'express', 11);
|
||||
const peek = await app.workbench.editor.peekDefinition('app.js', 'app', 14);
|
||||
|
||||
await peek.waitForFile('index.d.ts');
|
||||
await peek.waitForFile('app.js');
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -3,15 +3,18 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Commands } from '../workbench/workbench';
|
||||
import { Code } from '../../vscode/code';
|
||||
|
||||
export class Editors {
|
||||
|
||||
constructor(private code: Code, private commands: Commands) { }
|
||||
constructor(private code: Code) { }
|
||||
|
||||
async saveOpenedFile(): Promise<any> {
|
||||
await this.commands.runCommand('workbench.action.files.save');
|
||||
if (process.platform === 'darwin') {
|
||||
await this.code.dispatchKeybinding('cmd+s');
|
||||
} else {
|
||||
await this.code.dispatchKeybinding('ctrl+s');
|
||||
}
|
||||
}
|
||||
|
||||
async selectTab(tabName: string, untitled: boolean = false): Promise<void> {
|
||||
@@ -20,7 +23,7 @@ export class Editors {
|
||||
}
|
||||
|
||||
async waitForActiveEditor(filename: string): Promise<any> {
|
||||
const selector = `.editor-container .monaco-editor[data-uri$="${filename}"] textarea`;
|
||||
const selector = `.editor-instance .monaco-editor[data-uri$="${filename}"] textarea`;
|
||||
return this.code.waitForActiveElement(selector);
|
||||
}
|
||||
|
||||
@@ -38,7 +41,12 @@ export class Editors {
|
||||
}
|
||||
|
||||
async newUntitledFile(): Promise<void> {
|
||||
await this.commands.runCommand('workbench.action.files.newUntitledFile');
|
||||
if (process.platform === 'darwin') {
|
||||
await this.code.dispatchKeybinding('cmd+n');
|
||||
} else {
|
||||
await this.code.dispatchKeybinding('ctrl+n');
|
||||
}
|
||||
|
||||
await this.waitForEditorFocus('Untitled-1', true);
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
import { Viewlet } from '../workbench/viewlet';
|
||||
import { Editors } from '../editor/editors';
|
||||
import { Commands } from '../workbench/workbench';
|
||||
import { Code } from '../../vscode/code';
|
||||
|
||||
export class Explorer extends Viewlet {
|
||||
@@ -13,12 +12,16 @@ export class Explorer extends Viewlet {
|
||||
private static readonly EXPLORER_VIEWLET = 'div[id="workbench.view.explorer"]';
|
||||
private static readonly OPEN_EDITORS_VIEW = `${Explorer.EXPLORER_VIEWLET} .split-view-view:nth-child(1) .title`;
|
||||
|
||||
constructor(code: Code, private commands: Commands, private editors: Editors) {
|
||||
constructor(code: Code, private editors: Editors) {
|
||||
super(code);
|
||||
}
|
||||
|
||||
openExplorerView(): Promise<any> {
|
||||
return this.commands.runCommand('workbench.view.explorer');
|
||||
async openExplorerView(): Promise<any> {
|
||||
if (process.platform === 'darwin') {
|
||||
await this.code.dispatchKeybinding('cmd+shift+e');
|
||||
} else {
|
||||
await this.code.dispatchKeybinding('ctrl+shift+e');
|
||||
}
|
||||
}
|
||||
|
||||
async waitForOpenEditorsViewTitle(fn: (title: string) => boolean): Promise<void> {
|
||||
|
||||
@@ -22,7 +22,7 @@ export function setup() {
|
||||
|
||||
await app.reload();
|
||||
await app.workbench.extensions.openExtensionsViewlet();
|
||||
await app.workbench.runCommand('Smoke Test Check');
|
||||
await app.workbench.quickopen.runCommand('Smoke Test Check');
|
||||
await app.workbench.statusbar.waitForStatusbarText('smoke test', 'VS Code Smoke Test Check');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,31 +4,36 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Viewlet } from '../workbench/viewlet';
|
||||
import { Commands } from '../workbench/workbench';
|
||||
import { Code } from '../../vscode/code';
|
||||
|
||||
const SEARCH_BOX = 'div.extensions-viewlet[id="workbench.view.extensions"] input.search-box';
|
||||
const SEARCH_BOX = 'div.extensions-viewlet[id="workbench.view.extensions"] .monaco-editor textarea';
|
||||
|
||||
export class Extensions extends Viewlet {
|
||||
|
||||
constructor(code: Code, private commands: Commands) {
|
||||
constructor(code: Code) {
|
||||
super(code);
|
||||
}
|
||||
|
||||
async openExtensionsViewlet(): Promise<any> {
|
||||
await this.commands.runCommand('workbench.view.extensions');
|
||||
if (process.platform === 'darwin') {
|
||||
await this.code.dispatchKeybinding('cmd+shift+x');
|
||||
} else {
|
||||
await this.code.dispatchKeybinding('ctrl+shift+x');
|
||||
}
|
||||
|
||||
await this.code.waitForActiveElement(SEARCH_BOX);
|
||||
}
|
||||
|
||||
async searchForExtension(name: string): Promise<any> {
|
||||
await this.code.waitAndClick(SEARCH_BOX);
|
||||
await this.code.waitForActiveElement(SEARCH_BOX);
|
||||
await this.code.waitForSetValue(SEARCH_BOX, `name:"${name}"`);
|
||||
await this.code.waitForTypeInEditor(SEARCH_BOX, `name:"${name}"`);
|
||||
}
|
||||
|
||||
async installExtension(name: string): Promise<void> {
|
||||
await this.searchForExtension(name);
|
||||
await this.code.waitAndClick(`div.extensions-viewlet[id="workbench.view.extensions"] .monaco-list-row[aria-label="${name}"] .extension li[class='action-item'] .extension-action.install`);
|
||||
await this.code.waitForElement(`div.extensions-viewlet[id="workbench.view.extensions"] .monaco-list-row[aria-label="${name}"] .extension li[class='action-item'] .extension-action.reload`);
|
||||
const ariaLabel = `${name}. Press enter for extension details.`;
|
||||
await this.code.waitAndClick(`div.extensions-viewlet[id="workbench.view.extensions"] .monaco-list-row[aria-label="${ariaLabel}"] .extension li[class='action-item'] .extension-action.install`);
|
||||
await this.code.waitForElement(`div.extensions-viewlet[id="workbench.view.extensions"] .monaco-list-row[aria-label="${ariaLabel}"] .extension li[class='action-item'] .extension-action.reload`);
|
||||
}
|
||||
}
|
||||
@@ -48,29 +48,24 @@ export function setup() {
|
||||
const app = this.app as Application;
|
||||
|
||||
await app.workbench.scm.openSCMViewlet();
|
||||
|
||||
await app.workbench.scm.waitForChange('app.js', 'Modified');
|
||||
|
||||
await app.workbench.scm.stage('app.js');
|
||||
|
||||
await app.workbench.scm.waitForChange('app.js', 'Index Modified');
|
||||
await app.workbench.scm.unstage('app.js');
|
||||
|
||||
await app.workbench.scm.waitForChange('app.js', 'Modified');
|
||||
});
|
||||
|
||||
it(`stages, commits changes and verifies outgoing change`, async function () {
|
||||
const app = this.app as Application;
|
||||
|
||||
await app.workbench.scm.openSCMViewlet();
|
||||
|
||||
await app.workbench.scm.waitForChange('app.js', 'Modified');
|
||||
|
||||
await app.workbench.scm.stage('app.js');
|
||||
await app.workbench.scm.waitForChange('app.js', 'Index Modified');
|
||||
|
||||
await app.workbench.scm.commit('first commit');
|
||||
await app.code.waitForTextContent(SYNC_STATUSBAR, ' 0↓ 1↑');
|
||||
|
||||
await app.workbench.runCommand('Git: Stage All Changes');
|
||||
await app.workbench.quickopen.runCommand('Git: Stage All Changes');
|
||||
await app.workbench.scm.waitForChange('index.jade', 'Index Modified');
|
||||
|
||||
await app.workbench.scm.commit('second commit');
|
||||
|
||||
@@ -4,19 +4,16 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Viewlet } from '../workbench/viewlet';
|
||||
import { Commands } from '../workbench/workbench';
|
||||
import { IElement } from '../../vscode/driver';
|
||||
import { findElement, findElements, Code } from '../../vscode/code';
|
||||
|
||||
const VIEWLET = 'div[id="workbench.view.scm"]';
|
||||
const SCM_INPUT = `${VIEWLET} .scm-editor textarea`;
|
||||
const SCM_RESOURCE = `${VIEWLET} .monaco-list-row > .resource`;
|
||||
const SCM_RESOURCE_GROUP = `${VIEWLET} .monaco-list-row > .resource-group`;
|
||||
const REFRESH_COMMAND = `div[id="workbench.parts.sidebar"] .actions-container a.action-label[title="Refresh"]`;
|
||||
const COMMIT_COMMAND = `div[id="workbench.parts.sidebar"] .actions-container a.action-label[title="Commit"]`;
|
||||
const SCM_RESOURCE_CLICK = (name: string) => `${SCM_RESOURCE} .monaco-icon-label[title*="${name}"] .label-name`;
|
||||
const SCM_RESOURCE_ACTION_CLICK = (name: string, actionName: string) => `${SCM_RESOURCE} .monaco-icon-label[title*="${name}"] .actions .action-label[title="${actionName}"]`;
|
||||
const SCM_RESOURCE_GROUP_COMMAND_CLICK = (name: string) => `${SCM_RESOURCE_GROUP} .actions .action-label[title="${name}"]`;
|
||||
|
||||
interface Change {
|
||||
name: string;
|
||||
@@ -41,12 +38,12 @@ function toChange(element: IElement): Change {
|
||||
|
||||
export class SCM extends Viewlet {
|
||||
|
||||
constructor(code: Code, private commands: Commands) {
|
||||
constructor(code: Code) {
|
||||
super(code);
|
||||
}
|
||||
|
||||
async openSCMViewlet(): Promise<any> {
|
||||
await this.commands.runCommand('workbench.view.scm');
|
||||
await this.code.dispatchKeybinding('ctrl+shift+g');
|
||||
await this.code.waitForElement(SCM_INPUT);
|
||||
}
|
||||
|
||||
@@ -65,14 +62,12 @@ export class SCM extends Viewlet {
|
||||
|
||||
async stage(name: string): Promise<void> {
|
||||
await this.code.waitAndClick(SCM_RESOURCE_ACTION_CLICK(name, 'Stage Changes'));
|
||||
}
|
||||
|
||||
async stageAll(): Promise<void> {
|
||||
await this.code.waitAndClick(SCM_RESOURCE_GROUP_COMMAND_CLICK('Stage All Changes'));
|
||||
await this.waitForChange(name, 'Index Modified');
|
||||
}
|
||||
|
||||
async unstage(name: string): Promise<void> {
|
||||
await this.code.waitAndClick(SCM_RESOURCE_ACTION_CLICK(name, 'Unstage Changes'));
|
||||
await this.waitForChange('app.js', 'Modified');
|
||||
}
|
||||
|
||||
async commit(message: string): Promise<void> {
|
||||
|
||||
@@ -3,28 +3,32 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Commands } from '../workbench/workbench';
|
||||
import { Code } from '../../vscode/code';
|
||||
|
||||
const SEARCH_INPUT = '.settings-search-input input';
|
||||
|
||||
export class KeybindingsEditor {
|
||||
|
||||
constructor(private code: Code, private commands: Commands) { }
|
||||
constructor(private code: Code) { }
|
||||
|
||||
async updateKeybinding(command: string, keybinding: string, ariaLabel: string): Promise<any> {
|
||||
await this.commands.runCommand('workbench.action.openGlobalKeybindings');
|
||||
if (process.platform === 'darwin') {
|
||||
await this.code.dispatchKeybinding('cmd+k cmd+s');
|
||||
} else {
|
||||
await this.code.dispatchKeybinding('ctrl+k ctrl+s');
|
||||
}
|
||||
|
||||
await this.code.waitForActiveElement(SEARCH_INPUT);
|
||||
await this.code.waitForSetValue(SEARCH_INPUT, command);
|
||||
|
||||
await this.code.waitAndClick('div[aria-label="Keybindings"] .monaco-list-row.keybinding-item');
|
||||
await this.code.waitForElement('div[aria-label="Keybindings"] .monaco-list-row.keybinding-item.focused.selected');
|
||||
await this.code.waitAndClick('.keybindings-list-container .monaco-list-row.keybinding-item');
|
||||
await this.code.waitForElement('.keybindings-list-container .monaco-list-row.keybinding-item.focused.selected');
|
||||
|
||||
await this.code.waitAndClick('div[aria-label="Keybindings"] .monaco-list-row.keybinding-item .action-item .icon.add');
|
||||
await this.code.waitForElement('.defineKeybindingWidget .monaco-inputbox.synthetic-focus');
|
||||
await this.code.waitAndClick('.keybindings-list-container .monaco-list-row.keybinding-item .action-item .icon.add');
|
||||
await this.code.waitForActiveElement('.defineKeybindingWidget .monaco-inputbox input');
|
||||
|
||||
await this.code.dispatchKeybinding(keybinding);
|
||||
await this.code.dispatchKeybinding('enter');
|
||||
await this.code.waitForElement(`div[aria-label="Keybindings"] div[aria-label="Keybinding is ${ariaLabel}."]`);
|
||||
await this.code.waitForElement(`.keybindings-list-container div[aria-label="Keybinding is ${ariaLabel}."]`);
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ export function setup() {
|
||||
it('turns off editor line numbers and verifies the live change', async function () {
|
||||
const app = this.app as Application;
|
||||
|
||||
await app.workbench.explorer.openFile('app.js');
|
||||
await app.workbench.quickopen.openFile('app.js');
|
||||
await app.code.waitForElements('.line-numbers', false, elements => !!elements.length);
|
||||
|
||||
await app.workbench.settingsEditor.addUserSetting('editor.lineNumbers', '"off"');
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { Commands } from '../workbench/workbench';
|
||||
import { Editor } from '../editor/editor';
|
||||
import { Editors } from '../editor/editors';
|
||||
import { Code } from '../../vscode/code';
|
||||
import { QuickOpen } from '../quickopen/quickopen';
|
||||
|
||||
export enum ActivityBarPosition {
|
||||
LEFT = 0,
|
||||
@@ -19,10 +19,10 @@ const SEARCH_INPUT = '.settings-search-input input';
|
||||
|
||||
export class SettingsEditor {
|
||||
|
||||
constructor(private code: Code, private userDataPath: string, private commands: Commands, private editors: Editors, private editor: Editor) { }
|
||||
constructor(private code: Code, private userDataPath: string, private editors: Editors, private editor: Editor, private quickopen: QuickOpen) { }
|
||||
|
||||
async addUserSetting(setting: string, value: string): Promise<void> {
|
||||
await this.commands.runCommand('workbench.action.openGlobalSettings');
|
||||
await this.openSettings();
|
||||
await this.code.waitAndClick(SEARCH_INPUT);
|
||||
await this.code.waitForActiveElement(SEARCH_INPUT);
|
||||
|
||||
@@ -37,7 +37,11 @@ export class SettingsEditor {
|
||||
const settingsPath = path.join(this.userDataPath, 'User', 'settings.json');
|
||||
await new Promise((c, e) => fs.writeFile(settingsPath, '{}', 'utf8', err => err ? e(err) : c()));
|
||||
|
||||
await this.commands.runCommand('workbench.action.openGlobalSettings');
|
||||
await this.openSettings();
|
||||
await this.editor.waitForEditorContents('settings.json', c => c === '{}', '.editable-preferences-editor-container');
|
||||
}
|
||||
|
||||
private async openSettings(): Promise<void> {
|
||||
await this.quickopen.runCommand('Preferences: Open User Settings');
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Commands } from '../workbench/workbench';
|
||||
import { Code } from '../../vscode/code';
|
||||
|
||||
export enum ProblemSeverity {
|
||||
@@ -15,18 +14,26 @@ export class Problems {
|
||||
|
||||
static PROBLEMS_VIEW_SELECTOR = '.panel.markers-panel';
|
||||
|
||||
constructor(private code: Code, private commands: Commands) { }
|
||||
constructor(private code: Code) { }
|
||||
|
||||
public async showProblemsView(): Promise<any> {
|
||||
await this.commands.runCommand('workbench.actions.view.problems');
|
||||
await this.toggleProblemsView();
|
||||
await this.waitForProblemsView();
|
||||
}
|
||||
|
||||
public async hideProblemsView(): Promise<any> {
|
||||
await this.commands.runCommand('workbench.actions.view.problems');
|
||||
await this.toggleProblemsView();
|
||||
await this.code.waitForElement(Problems.PROBLEMS_VIEW_SELECTOR, el => !el);
|
||||
}
|
||||
|
||||
private async toggleProblemsView(): Promise<void> {
|
||||
if (process.platform === 'darwin') {
|
||||
await this.code.dispatchKeybinding('cmd+shift+m');
|
||||
} else {
|
||||
await this.code.dispatchKeybinding('ctrl+shift+m');
|
||||
}
|
||||
}
|
||||
|
||||
public async waitForProblemsView(): Promise<void> {
|
||||
await this.code.waitForElement(Problems.PROBLEMS_VIEW_SELECTOR);
|
||||
}
|
||||
|
||||
28
test/smoke/src/areas/quickinput/quickinput.ts
Normal file
28
test/smoke/src/areas/quickinput/quickinput.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Code } from '../../vscode/code';
|
||||
|
||||
export class QuickInput {
|
||||
|
||||
static QUICK_INPUT = '.quick-input-widget';
|
||||
static QUICK_INPUT_INPUT = `${QuickInput.QUICK_INPUT} .quick-input-box input`;
|
||||
static QUICK_INPUT_FOCUSED_ELEMENT = `${QuickInput.QUICK_INPUT} .quick-open-tree .monaco-tree-row.focused .monaco-highlighted-label`;
|
||||
|
||||
constructor(private code: Code) { }
|
||||
|
||||
async closeQuickInput(): Promise<void> {
|
||||
await this.code.dispatchKeybinding('escape');
|
||||
await this.waitForQuickInputClosed();
|
||||
}
|
||||
|
||||
async waitForQuickInputOpened(retryCount?: number): Promise<void> {
|
||||
await this.code.waitForActiveElement(QuickInput.QUICK_INPUT_INPUT, retryCount);
|
||||
}
|
||||
|
||||
private async waitForQuickInputClosed(): Promise<void> {
|
||||
await this.code.waitForElement(QuickInput.QUICK_INPUT, r => !!r && r.attributes.style.indexOf('display: none;') !== -1);
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Editors } from '../editor/editors';
|
||||
import { Commands } from '../workbench/workbench';
|
||||
import { Code } from '../../vscode/code';
|
||||
|
||||
export class QuickOpen {
|
||||
@@ -16,14 +15,18 @@ export class QuickOpen {
|
||||
static QUICK_OPEN_ENTRY_SELECTOR = 'div[aria-label="Quick Picker"] .monaco-tree-rows.show-twisties .monaco-tree-row .quick-open-entry';
|
||||
static QUICK_OPEN_ENTRY_LABEL_SELECTOR = 'div[aria-label="Quick Picker"] .monaco-tree-rows.show-twisties .monaco-tree-row .quick-open-entry .label-name';
|
||||
|
||||
constructor(private code: Code, private commands: Commands, private editors: Editors) { }
|
||||
constructor(private code: Code, private editors: Editors) { }
|
||||
|
||||
async openQuickOpen(value: string): Promise<void> {
|
||||
let retries = 0;
|
||||
|
||||
// other parts of code might steal focus away from quickopen :(
|
||||
while (retries < 5) {
|
||||
await this.commands.runCommand('workbench.action.quickOpen');
|
||||
if (process.platform === 'darwin') {
|
||||
await this.code.dispatchKeybinding('cmd+p');
|
||||
} else {
|
||||
await this.code.dispatchKeybinding('ctrl+p');
|
||||
}
|
||||
|
||||
try {
|
||||
await this.waitForQuickOpenOpened(10);
|
||||
@@ -43,7 +46,7 @@ export class QuickOpen {
|
||||
}
|
||||
|
||||
async closeQuickOpen(): Promise<void> {
|
||||
await this.commands.runCommand('workbench.action.closeQuickOpen');
|
||||
await this.code.dispatchKeybinding('escape');
|
||||
await this.waitForQuickOpenClosed();
|
||||
}
|
||||
|
||||
@@ -97,7 +100,11 @@ export class QuickOpen {
|
||||
let retries = 0;
|
||||
|
||||
while (++retries < 10) {
|
||||
await this.commands.runCommand('workbench.action.gotoSymbol');
|
||||
if (process.platform === 'darwin') {
|
||||
await this.code.dispatchKeybinding('cmd+shift+o');
|
||||
} else {
|
||||
await this.code.dispatchKeybinding('ctrl+shift+o');
|
||||
}
|
||||
|
||||
const text = await this.code.waitForTextContent('div[aria-label="Quick Picker"] .monaco-tree-rows.show-twisties div.monaco-tree-row .quick-open-entry .monaco-icon-label .label-name .monaco-highlighted-label span');
|
||||
|
||||
|
||||
@@ -3,16 +3,23 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as cp from 'child_process';
|
||||
import { Application } from '../../application';
|
||||
|
||||
export function setup() {
|
||||
describe('Search', () => {
|
||||
after(function () {
|
||||
const app = this.app as Application;
|
||||
cp.execSync('git checkout .', { cwd: app.workspacePath });
|
||||
cp.execSync('git reset --hard origin/master', { cwd: app.workspacePath });
|
||||
});
|
||||
|
||||
it('searches for body & checks for correct result number', async function () {
|
||||
const app = this.app as Application;
|
||||
await app.workbench.search.openSearchViewlet();
|
||||
await app.workbench.search.searchFor('body');
|
||||
|
||||
await app.workbench.search.waitForResultText('14 results in 5 files');
|
||||
await app.workbench.search.waitForResultText('21 results in 6 files');
|
||||
});
|
||||
|
||||
it('searches only for *.js files & checks for correct result number', async function () {
|
||||
@@ -30,8 +37,8 @@ export function setup() {
|
||||
it('dismisses result & checks for correct result number', async function () {
|
||||
const app = this.app as Application;
|
||||
await app.workbench.search.searchFor('body');
|
||||
await app.workbench.search.removeFileMatch(1);
|
||||
await app.workbench.search.waitForResultText('10 results in 4 files');
|
||||
await app.workbench.search.removeFileMatch('app.js');
|
||||
await app.workbench.search.waitForResultText('17 results in 5 files');
|
||||
});
|
||||
|
||||
it('replaces first search result with a replace term', async function () {
|
||||
@@ -40,13 +47,13 @@ export function setup() {
|
||||
await app.workbench.search.searchFor('body');
|
||||
await app.workbench.search.expandReplace();
|
||||
await app.workbench.search.setReplaceText('ydob');
|
||||
await app.workbench.search.replaceFileMatch(1);
|
||||
|
||||
await app.workbench.search.waitForResultText('10 results in 4 files');
|
||||
await app.workbench.search.replaceFileMatch('app.js');
|
||||
await app.workbench.search.waitForResultText('17 results in 5 files');
|
||||
|
||||
await app.workbench.search.searchFor('ydob');
|
||||
await app.workbench.search.setReplaceText('body');
|
||||
await app.workbench.search.replaceFileMatch(1);
|
||||
await app.workbench.search.replaceFileMatch('app.js');
|
||||
await app.workbench.search.waitForNoResultText();
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -4,42 +4,60 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Viewlet } from '../workbench/viewlet';
|
||||
import { Commands } from '../workbench/workbench';
|
||||
import { Code } from '../../vscode/code';
|
||||
|
||||
const VIEWLET = 'div[id="workbench.view.search"] .search-view';
|
||||
const INPUT = `${VIEWLET} .search-widget .search-container .monaco-inputbox input`;
|
||||
const INCLUDE_INPUT = `${VIEWLET} .query-details .file-types.includes .monaco-inputbox input`;
|
||||
const FILE_MATCH = filename => `${VIEWLET} .results .filematch[data-resource$="${filename}"]`;
|
||||
|
||||
async function retry(setup: () => Promise<any>, attempt: () => Promise<any>) {
|
||||
let count = 0;
|
||||
while (true) {
|
||||
await setup();
|
||||
|
||||
try {
|
||||
await attempt();
|
||||
return;
|
||||
} catch (err) {
|
||||
if (++count > 5) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class Search extends Viewlet {
|
||||
|
||||
constructor(code: Code, private commands: Commands) {
|
||||
constructor(code: Code) {
|
||||
super(code);
|
||||
}
|
||||
|
||||
async openSearchViewlet(): Promise<any> {
|
||||
await this.commands.runCommand('workbench.view.search');
|
||||
await this.code.waitForActiveElement(INPUT);
|
||||
if (process.platform === 'darwin') {
|
||||
await this.code.dispatchKeybinding('cmd+shift+f');
|
||||
} else {
|
||||
await this.code.dispatchKeybinding('ctrl+shift+f');
|
||||
}
|
||||
|
||||
await this.waitForInputFocus(INPUT);
|
||||
}
|
||||
|
||||
async searchFor(text: string): Promise<void> {
|
||||
await this.code.waitAndClick(INPUT);
|
||||
await this.code.waitForActiveElement(INPUT);
|
||||
await this.waitForInputFocus(INPUT);
|
||||
await this.code.waitForSetValue(INPUT, text);
|
||||
await this.submitSearch();
|
||||
}
|
||||
|
||||
async submitSearch(): Promise<void> {
|
||||
await this.code.waitAndClick(INPUT);
|
||||
await this.code.waitForActiveElement(INPUT);
|
||||
await this.waitForInputFocus(INPUT);
|
||||
|
||||
await this.code.dispatchKeybinding('enter');
|
||||
await this.code.waitForElement(`${VIEWLET} .messages[aria-hidden="false"]`);
|
||||
}
|
||||
|
||||
async setFilesToIncludeText(text: string): Promise<void> {
|
||||
await this.code.waitAndClick(INCLUDE_INPUT);
|
||||
await this.code.waitForActiveElement(INCLUDE_INPUT);
|
||||
await this.waitForInputFocus(INCLUDE_INPUT);
|
||||
await this.code.waitForSetValue(INCLUDE_INPUT, text || '');
|
||||
}
|
||||
|
||||
@@ -51,29 +69,68 @@ export class Search extends Viewlet {
|
||||
await this.code.waitAndClick(`${VIEWLET} .query-details.more .more`);
|
||||
}
|
||||
|
||||
async removeFileMatch(index: number): Promise<void> {
|
||||
await this.code.waitAndMove(`${VIEWLET} .results .monaco-tree-rows>:nth-child(${index}) .filematch`);
|
||||
const file = await this.code.waitForTextContent(`${VIEWLET} .results .monaco-tree-rows>:nth-child(${index}) .filematch a.label-name`);
|
||||
await this.code.waitAndClick(`${VIEWLET} .results .monaco-tree-rows>:nth-child(${index}) .filematch .action-label.icon.action-remove`);
|
||||
await this.code.waitForTextContent(`${VIEWLET} .results .monaco-tree-rows>:nth-child(${index}) .filematch a.label-name`, void 0, result => result !== file);
|
||||
async removeFileMatch(filename: string): Promise<void> {
|
||||
const fileMatch = FILE_MATCH(filename);
|
||||
|
||||
await retry(
|
||||
() => this.code.waitAndClick(fileMatch),
|
||||
() => this.code.waitForElement(`${fileMatch} .action-label.icon.action-remove`, el => !!el && el.top > 0 && el.left > 0, 10)
|
||||
);
|
||||
|
||||
// ¯\_(ツ)_/¯
|
||||
await new Promise(c => setTimeout(c, 500));
|
||||
await this.code.waitAndClick(`${fileMatch} .action-label.icon.action-remove`);
|
||||
await this.code.waitForElement(fileMatch, el => !el);
|
||||
}
|
||||
|
||||
async expandReplace(): Promise<void> {
|
||||
await this.code.waitAndClick(`${VIEWLET} .search-widget .monaco-button.toggle-replace-button.collapse`);
|
||||
}
|
||||
|
||||
async setReplaceText(text: string): Promise<void> {
|
||||
await this.code.waitAndClick(`${VIEWLET} .search-widget .replace-container .monaco-inputbox input[title="Replace"]`);
|
||||
await this.code.waitForElement(`${VIEWLET} .search-widget .replace-container .monaco-inputbox.synthetic-focus input[title="Replace"]`);
|
||||
await this.code.waitForSetValue(`${VIEWLET} .search-widget .replace-container .monaco-inputbox.synthetic-focus input[title="Replace"]`, text);
|
||||
async collapseReplace(): Promise<void> {
|
||||
await this.code.waitAndClick(`${VIEWLET} .search-widget .monaco-button.toggle-replace-button.expand`);
|
||||
}
|
||||
|
||||
async replaceFileMatch(index: number): Promise<void> {
|
||||
await this.code.waitAndMove(`${VIEWLET} .results .monaco-tree-rows>:nth-child(${index}) .filematch`);
|
||||
await this.code.waitAndClick(`${VIEWLET} .results .monaco-tree-rows>:nth-child(${index}) .filematch .action-label.icon.action-replace-all`);
|
||||
async setReplaceText(text: string): Promise<void> {
|
||||
await this.code.waitForSetValue(`${VIEWLET} .search-widget .replace-container .monaco-inputbox input[title="Replace"]`, text);
|
||||
}
|
||||
|
||||
async replaceFileMatch(filename: string): Promise<void> {
|
||||
const fileMatch = FILE_MATCH(filename);
|
||||
|
||||
await retry(
|
||||
() => this.code.waitAndClick(fileMatch),
|
||||
() => this.code.waitForElement(`${fileMatch} .action-label.icon.action-replace-all`, el => !!el && el.top > 0 && el.left > 0, 10)
|
||||
);
|
||||
|
||||
// ¯\_(ツ)_/¯
|
||||
await new Promise(c => setTimeout(c, 500));
|
||||
await this.code.waitAndClick(`${fileMatch} .action-label.icon.action-replace-all`);
|
||||
}
|
||||
|
||||
async waitForResultText(text: string): Promise<void> {
|
||||
await this.code.waitForTextContent(`${VIEWLET} .messages[aria-hidden="false"] .message>p`, text);
|
||||
}
|
||||
|
||||
async waitForNoResultText(): Promise<void> {
|
||||
await this.code.waitForElement(`${VIEWLET} .messages[aria-hidden="false"] .message>p`, el => !el);
|
||||
}
|
||||
|
||||
private async waitForInputFocus(selector: string): Promise<void> {
|
||||
let retries = 0;
|
||||
|
||||
// other parts of code might steal focus away from input boxes :(
|
||||
while (retries < 5) {
|
||||
await this.code.waitAndClick(INPUT, 2, 2);
|
||||
|
||||
try {
|
||||
await this.code.waitForActiveElement(INPUT, 10);
|
||||
break;
|
||||
} catch (err) {
|
||||
if (++retries > 5) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,8 +30,8 @@ export function setup() {
|
||||
const app = this.app as Application;
|
||||
|
||||
await app.workbench.statusbar.clickOn(StatusBarElement.BRANCH_STATUS);
|
||||
await app.workbench.quickopen.waitForQuickOpenOpened();
|
||||
await app.workbench.quickopen.closeQuickOpen();
|
||||
await app.workbench.quickinput.waitForQuickInputOpened();
|
||||
await app.workbench.quickinput.closeQuickInput();
|
||||
|
||||
await app.workbench.quickopen.openFile('app.js');
|
||||
await app.workbench.statusbar.clickOn(StatusBarElement.INDENTATION_STATUS);
|
||||
|
||||
@@ -3,24 +3,24 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
// import { Application } from '../../application';
|
||||
import { Application } from '../../application';
|
||||
|
||||
export function setup() {
|
||||
describe('Terminal', () => {
|
||||
// it(`opens terminal, runs 'echo' and verifies the output`, async function () {
|
||||
// const app = this.app as Application;
|
||||
it(`opens terminal, runs 'echo' and verifies the output`, async function () {
|
||||
const app = this.app as Application;
|
||||
|
||||
// const expected = new Date().getTime().toString();
|
||||
// await app.workbench.terminal.showTerminal();
|
||||
// await app.workbench.terminal.runCommand(`echo ${expected}`);
|
||||
// await app.workbench.terminal.waitForTerminalText(terminalText => {
|
||||
// for (let index = terminalText.length - 2; index >= 0; index--) {
|
||||
// if (!!terminalText[index] && terminalText[index].trim() === expected) {
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
// return false;
|
||||
// });
|
||||
// });
|
||||
const expected = new Date().getTime().toString();
|
||||
await app.workbench.terminal.showTerminal();
|
||||
await app.workbench.terminal.runCommand(`echo ${expected}`);
|
||||
await app.workbench.terminal.waitForTerminalText(terminalText => {
|
||||
for (let index = terminalText.length - 2; index >= 0; index--) {
|
||||
if (!!terminalText[index] && terminalText[index].trim() === expected) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Code } from '../../vscode/code';
|
||||
import { Commands } from '../workbench/workbench';
|
||||
|
||||
const PANEL_SELECTOR = 'div[id="workbench.panel.terminal"]';
|
||||
const XTERM_SELECTOR = `${PANEL_SELECTOR} .terminal-wrapper`;
|
||||
@@ -12,16 +11,18 @@ const XTERM_TEXTAREA = `${XTERM_SELECTOR} textarea.xterm-helper-textarea`;
|
||||
|
||||
export class Terminal {
|
||||
|
||||
constructor(private code: Code, private commands: Commands) { }
|
||||
constructor(private code: Code) { }
|
||||
|
||||
async showTerminal(): Promise<void> {
|
||||
await this.commands.runCommand('workbench.action.terminal.toggleTerminal');
|
||||
await this.code.dispatchKeybinding('ctrl+`');
|
||||
await this.code.waitForActiveElement(XTERM_TEXTAREA);
|
||||
await this.code.waitForTerminalBuffer(XTERM_SELECTOR, lines => lines.some(line => line.length > 0));
|
||||
}
|
||||
|
||||
async runCommand(commandText: string): Promise<void> {
|
||||
await this.code.waitForPaste(XTERM_TEXTAREA, commandText);
|
||||
await this.code.writeInTerminal(XTERM_SELECTOR, commandText);
|
||||
// hold your horses
|
||||
await new Promise(c => setTimeout(c, 500));
|
||||
await this.code.dispatchKeybinding('enter');
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ export function setup() {
|
||||
|
||||
const readmeMd = 'readme.md';
|
||||
const textToType = 'Hello, Code';
|
||||
await app.workbench.explorer.openFile(readmeMd);
|
||||
await app.workbench.quickopen.openFile(readmeMd);
|
||||
await app.workbench.editor.waitForTypeInEditor(readmeMd, textToType);
|
||||
|
||||
await app.reload();
|
||||
|
||||
@@ -14,6 +14,10 @@ export function setup() {
|
||||
return;
|
||||
}
|
||||
|
||||
const extensionName = 'German Language Pack for Visual Studio Code';
|
||||
await app.workbench.extensions.openExtensionsViewlet();
|
||||
await app.workbench.extensions.installExtension(extensionName);
|
||||
|
||||
await app.restart({ extraArgs: ['--locale=DE'] });
|
||||
});
|
||||
|
||||
|
||||
@@ -12,6 +12,6 @@ export abstract class Viewlet {
|
||||
constructor(protected code: Code) { }
|
||||
|
||||
async waitForTitle(fn: (title: string) => boolean): Promise<void> {
|
||||
await this.code.waitForTextContent('.monaco-workbench-container .part.sidebar > .title > .title-label > span', undefined, fn);
|
||||
await this.code.waitForTextContent('.monaco-workbench .part.sidebar > .title > .title-label > h2', undefined, fn);
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
import { Explorer } from '../explorer/explorer';
|
||||
import { ActivityBar } from '../activitybar/activityBar';
|
||||
import { QuickOpen } from '../quickopen/quickopen';
|
||||
import { QuickInput } from '../quickinput/quickinput';
|
||||
import { Extensions } from '../extensions/extensions';
|
||||
import { Search } from '../search/search';
|
||||
import { Editor } from '../editor/editor';
|
||||
@@ -23,9 +24,10 @@ export interface Commands {
|
||||
runCommand(command: string): Promise<any>;
|
||||
}
|
||||
|
||||
export class Workbench implements Commands {
|
||||
export class Workbench {
|
||||
|
||||
readonly quickopen: QuickOpen;
|
||||
readonly quickinput: QuickInput;
|
||||
readonly editors: Editors;
|
||||
readonly explorer: Explorer;
|
||||
readonly activitybar: ActivityBar;
|
||||
@@ -40,35 +42,22 @@ export class Workbench implements Commands {
|
||||
readonly keybindingsEditor: KeybindingsEditor;
|
||||
readonly terminal: Terminal;
|
||||
|
||||
constructor(private code: Code, private keybindings: any[], userDataPath: string) {
|
||||
this.editors = new Editors(code, this);
|
||||
this.quickopen = new QuickOpen(code, this, this.editors);
|
||||
this.explorer = new Explorer(code, this.quickopen, this.editors);
|
||||
constructor(code: Code, userDataPath: string) {
|
||||
this.editors = new Editors(code);
|
||||
this.quickopen = new QuickOpen(code, this.editors);
|
||||
this.quickinput = new QuickInput(code);
|
||||
this.explorer = new Explorer(code, this.editors);
|
||||
this.activitybar = new ActivityBar(code);
|
||||
this.search = new Search(code, this);
|
||||
this.extensions = new Extensions(code, this);
|
||||
this.editor = new Editor(code, this);
|
||||
this.scm = new SCM(code, this);
|
||||
this.debug = new Debug(code, this, this.editors, this.editor);
|
||||
this.search = new Search(code);
|
||||
this.extensions = new Extensions(code);
|
||||
this.editor = new Editor(code, this.quickopen);
|
||||
this.scm = new SCM(code);
|
||||
this.debug = new Debug(code, this.quickopen, this.editors, this.editor);
|
||||
this.statusbar = new StatusBar(code);
|
||||
this.problems = new Problems(code, this);
|
||||
this.settingsEditor = new SettingsEditor(code, userDataPath, this, this.editors, this.editor);
|
||||
this.keybindingsEditor = new KeybindingsEditor(code, this);
|
||||
this.terminal = new Terminal(code, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the command from keybindings file and executes it with WebdriverIO client API
|
||||
* @param command command (e.g. 'workbench.action.files.newUntitledFile')
|
||||
*/
|
||||
async runCommand(command: string): Promise<void> {
|
||||
const binding = this.keybindings.find(x => x['command'] === command);
|
||||
|
||||
if (binding) {
|
||||
await this.code.dispatchKeybinding(binding.key);
|
||||
} else {
|
||||
await this.quickopen.runCommand(command);
|
||||
}
|
||||
this.problems = new Problems(code);
|
||||
this.settingsEditor = new SettingsEditor(code, userDataPath, this.editors, this.editor, this.quickopen);
|
||||
this.keybindingsEditor = new KeybindingsEditor(code);
|
||||
this.terminal = new Terminal(code);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as https from 'https';
|
||||
import * as cp from 'child_process';
|
||||
import * as path from 'path';
|
||||
import * as minimist from 'minimist';
|
||||
import * as tmp from 'tmp';
|
||||
import * as rimraf from 'rimraf';
|
||||
import * as mkdirp from 'mkdirp';
|
||||
import { ncp } from 'ncp';
|
||||
import { Application, Quality } from './application';
|
||||
|
||||
import { setup as setupDataMigrationTests } from './areas/workbench/data-migration.test';
|
||||
@@ -40,7 +40,6 @@ const opts = minimist(args, {
|
||||
'stable-build',
|
||||
'wait-time',
|
||||
'test-repo',
|
||||
'keybindings',
|
||||
'screenshots',
|
||||
'log'
|
||||
],
|
||||
@@ -55,7 +54,6 @@ const opts = minimist(args, {
|
||||
const workspaceFilePath = path.join(testDataPath, 'smoketest.code-workspace');
|
||||
const testRepoUrl = 'https://github.com/Microsoft/vscode-smoketest-express';
|
||||
const workspacePath = path.join(testDataPath, 'vscode-smoketest-express');
|
||||
const keybindingsPath = path.join(testDataPath, 'keybindings.json');
|
||||
const extensionsPath = path.join(testDataPath, 'extensions-dir');
|
||||
mkdirp.sync(extensionsPath);
|
||||
|
||||
@@ -133,8 +131,6 @@ if (!fs.existsSync(electronPath || '')) {
|
||||
}
|
||||
|
||||
const userDataDir = path.join(testDataPath, 'd');
|
||||
// process.env.VSCODE_WORKSPACE_PATH = workspaceFilePath;
|
||||
process.env.VSCODE_KEYBINDINGS_PATH = keybindingsPath;
|
||||
|
||||
let quality: Quality;
|
||||
if (process.env.VSCODE_DEV === '1') {
|
||||
@@ -145,14 +141,6 @@ if (process.env.VSCODE_DEV === '1') {
|
||||
quality = Quality.Stable;
|
||||
}
|
||||
|
||||
function getKeybindingPlatform(): string {
|
||||
switch (process.platform) {
|
||||
case 'darwin': return 'osx';
|
||||
case 'win32': return 'win';
|
||||
default: return process.platform;
|
||||
}
|
||||
}
|
||||
|
||||
function toUri(path: string): string {
|
||||
if (process.platform === 'win32') {
|
||||
return `${path.replace(/\\/g, '/')}`;
|
||||
@@ -161,27 +149,6 @@ function toUri(path: string): string {
|
||||
return `${path}`;
|
||||
}
|
||||
|
||||
async function getKeybindings(): Promise<void> {
|
||||
if (opts.keybindings) {
|
||||
console.log('*** Using keybindings: ', opts.keybindings);
|
||||
const rawKeybindings = fs.readFileSync(opts.keybindings);
|
||||
fs.writeFileSync(keybindingsPath, rawKeybindings);
|
||||
} else {
|
||||
const keybindingsUrl = `https://raw.githubusercontent.com/Microsoft/vscode-docs/master/build/keybindings/doc.keybindings.${getKeybindingPlatform()}.json`;
|
||||
console.log('*** Fetching keybindings...');
|
||||
|
||||
await new Promise((c, e) => {
|
||||
https.get(keybindingsUrl, res => {
|
||||
const output = fs.createWriteStream(keybindingsPath);
|
||||
res.on('error', e);
|
||||
output.on('error', e);
|
||||
output.on('close', c);
|
||||
res.pipe(output);
|
||||
}).on('error', e);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function createWorkspaceFile(): Promise<void> {
|
||||
if (fs.existsSync(workspaceFilePath)) {
|
||||
return;
|
||||
@@ -222,8 +189,8 @@ async function setupRepository(): Promise<void> {
|
||||
cp.spawnSync('git', ['clean', '-xdf'], { cwd: workspacePath });
|
||||
}
|
||||
|
||||
console.log('*** Running npm install...');
|
||||
cp.execSync('npm install', { cwd: workspacePath, stdio: 'inherit' });
|
||||
console.log('*** Running yarn...');
|
||||
cp.execSync('yarn', { cwd: workspacePath, stdio: 'inherit' });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,7 +198,6 @@ async function setup(): Promise<void> {
|
||||
console.log('*** Test data:', testDataPath);
|
||||
console.log('*** Preparing smoketest setup...');
|
||||
|
||||
await getKeybindings();
|
||||
await createWorkspaceFile();
|
||||
await setupRepository();
|
||||
|
||||
@@ -245,8 +211,11 @@ function createApp(quality: Quality): Application {
|
||||
loggers.push(new ConsoleLogger());
|
||||
}
|
||||
|
||||
let log: string | undefined = undefined;
|
||||
|
||||
if (opts.log) {
|
||||
loggers.push(new FileLogger(opts.log));
|
||||
log = 'trace';
|
||||
}
|
||||
|
||||
return new Application({
|
||||
@@ -257,7 +226,9 @@ function createApp(quality: Quality): Application {
|
||||
extensionsPath,
|
||||
workspaceFilePath,
|
||||
waitTime: parseInt(opts['wait-time'] || '0') || 20,
|
||||
logger: new MultiLogger(loggers)
|
||||
logger: new MultiLogger(loggers),
|
||||
verbose: opts.verbose,
|
||||
log
|
||||
});
|
||||
}
|
||||
|
||||
@@ -269,6 +240,13 @@ before(async function () {
|
||||
|
||||
after(async function () {
|
||||
await new Promise(c => setTimeout(c, 500)); // wait for shutdown
|
||||
|
||||
if (opts.log) {
|
||||
const logsDir = path.join(userDataDir, 'logs');
|
||||
const destLogsDir = path.join(path.dirname(opts.log), 'logs');
|
||||
await new Promise((c, e) => ncp(logsDir, destLogsDir, err => err ? e(err) : c()));
|
||||
}
|
||||
|
||||
await new Promise((c, e) => rimraf(testDataPath, { maxBusyTries: 10 }, err => err ? e(err) : c()));
|
||||
});
|
||||
|
||||
|
||||
18
test/smoke/src/utils.ts
Normal file
18
test/smoke/src/utils.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ISuiteCallbackContext, ITestCallbackContext } from 'mocha';
|
||||
|
||||
export function describeRepeat(n: number, description: string, callback: (this: ISuiteCallbackContext) => void): void {
|
||||
for (let i = 0; i < n; i++) {
|
||||
describe(`${description} (iteration ${i})`, callback);
|
||||
}
|
||||
}
|
||||
|
||||
export function itRepeat(n: number, description: string, callback: (this: ITestCallbackContext, done: MochaDone) => any): void {
|
||||
for (let i = 0; i < n; i++) {
|
||||
it(`${description} (iteration ${i})`, callback);
|
||||
}
|
||||
}
|
||||
@@ -87,7 +87,9 @@ export interface SpawnOptions {
|
||||
userDataDir: string;
|
||||
extensionsPath: string;
|
||||
logger: Logger;
|
||||
verbose?: boolean;
|
||||
extraArgs?: string[];
|
||||
log?: string;
|
||||
}
|
||||
|
||||
async function createDriverHandle(): Promise<string> {
|
||||
@@ -122,6 +124,14 @@ export async function spawn(options: SpawnOptions): Promise<Code> {
|
||||
args.unshift(repoPath);
|
||||
}
|
||||
|
||||
if (options.verbose) {
|
||||
args.push('--driver-verbose');
|
||||
}
|
||||
|
||||
if (options.log) {
|
||||
args.push('--log', options.log);
|
||||
}
|
||||
|
||||
if (options.extraArgs) {
|
||||
args.push(...options.extraArgs);
|
||||
}
|
||||
@@ -144,9 +154,13 @@ async function poll<T>(
|
||||
retryInterval: number = 100 // millis
|
||||
): Promise<T> {
|
||||
let trial = 1;
|
||||
let lastError: string = '';
|
||||
|
||||
while (true) {
|
||||
if (trial > retryCount) {
|
||||
console.error('** Timeout!');
|
||||
console.error(lastError);
|
||||
|
||||
throw new Error(`Timeout: ${timeoutMessage} after ${(retryCount * retryInterval) / 1000} seconds.`);
|
||||
}
|
||||
|
||||
@@ -156,13 +170,11 @@ async function poll<T>(
|
||||
|
||||
if (acceptFn(result)) {
|
||||
return result;
|
||||
} else {
|
||||
lastError = 'Did not pass accept function';
|
||||
}
|
||||
} catch (e) {
|
||||
// console.warn(e);
|
||||
|
||||
if (/Method not implemented/.test(e.message)) {
|
||||
throw e;
|
||||
}
|
||||
lastError = Array.isArray(e.stack) ? e.stack.join(os.EOL) : e.stack;
|
||||
}
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, retryInterval));
|
||||
@@ -183,6 +195,10 @@ export class Code {
|
||||
) {
|
||||
this.driver = new Proxy(driver, {
|
||||
get(target, prop, receiver) {
|
||||
if (typeof prop === 'symbol') {
|
||||
throw new Error('Invalid usage');
|
||||
}
|
||||
|
||||
if (typeof target[prop] !== 'function') {
|
||||
return target[prop];
|
||||
}
|
||||
@@ -217,7 +233,12 @@ export class Code {
|
||||
async waitForTextContent(selector: string, textContent?: string, accept?: (result: string) => boolean): Promise<string> {
|
||||
const windowId = await this.getActiveWindowId();
|
||||
accept = accept || (result => textContent !== void 0 ? textContent === result : !!result);
|
||||
return await poll(() => this.driver.getElements(windowId, selector).then(els => els[0].textContent), s => accept!(typeof s === 'string' ? s : ''), `get text content '${selector}'`);
|
||||
|
||||
return await poll(
|
||||
() => this.driver.getElements(windowId, selector).then(els => els.length > 0 ? Promise.resolve(els[0].textContent) : Promise.reject(new Error('Element not found for textContent'))),
|
||||
s => accept!(typeof s === 'string' ? s : ''),
|
||||
`get text content '${selector}'`
|
||||
);
|
||||
}
|
||||
|
||||
async waitAndClick(selector: string, xoffset?: number, yoffset?: number): Promise<void> {
|
||||
@@ -230,21 +251,11 @@ export class Code {
|
||||
await poll(() => this.driver.doubleClick(windowId, selector), () => true, `double click '${selector}'`);
|
||||
}
|
||||
|
||||
async waitAndMove(selector: string): Promise<void> {
|
||||
const windowId = await this.getActiveWindowId();
|
||||
await poll(() => this.driver.move(windowId, selector), () => true, `move '${selector}'`);
|
||||
}
|
||||
|
||||
async waitForSetValue(selector: string, value: string): Promise<void> {
|
||||
const windowId = await this.getActiveWindowId();
|
||||
await poll(() => this.driver.setValue(windowId, selector, value), () => true, `set value '${selector}'`);
|
||||
}
|
||||
|
||||
async waitForPaste(selector: string, value: string): Promise<void> {
|
||||
const windowId = await this.getActiveWindowId();
|
||||
await poll(() => this.driver.paste(windowId, selector, value), () => true, `paste '${selector}'`);
|
||||
}
|
||||
|
||||
async waitForElements(selector: string, recursive: boolean, accept: (result: IElement[]) => boolean = result => result.length > 0): Promise<IElement[]> {
|
||||
const windowId = await this.getActiveWindowId();
|
||||
return await poll(() => this.driver.getElements(windowId, selector, recursive), accept, `get elements '${selector}'`);
|
||||
@@ -275,6 +286,11 @@ export class Code {
|
||||
await poll(() => this.driver.getTerminalBuffer(windowId, selector), accept, `get terminal buffer '${selector}'`);
|
||||
}
|
||||
|
||||
async writeInTerminal(selector: string, value: string): Promise<void> {
|
||||
const windowId = await this.getActiveWindowId();
|
||||
await poll(() => this.driver.writeInTerminal(windowId, selector, value), () => true, `writeInTerminal '${selector}'`);
|
||||
}
|
||||
|
||||
private async getActiveWindowId(): Promise<number> {
|
||||
if (typeof this._activeWindowId !== 'number') {
|
||||
const windows = await this.driver.getWindowIds();
|
||||
|
||||
39
test/smoke/test/index.js
Normal file
39
test/smoke/test/index.js
Normal file
@@ -0,0 +1,39 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
const path = require('path');
|
||||
const Mocha = require('mocha');
|
||||
const minimist = require('minimist');
|
||||
|
||||
const suite = 'Smoke Tests';
|
||||
|
||||
const [, , ...args] = process.argv;
|
||||
const opts = minimist(args, {
|
||||
string: [
|
||||
'f'
|
||||
]
|
||||
});
|
||||
|
||||
const options = {
|
||||
useColors: true,
|
||||
timeout: 60000,
|
||||
slow: 30000,
|
||||
grep: opts['f']
|
||||
};
|
||||
|
||||
if (process.env.BUILD_ARTIFACTSTAGINGDIRECTORY) {
|
||||
options.reporter = 'mocha-multi-reporters';
|
||||
options.reporterOptions = {
|
||||
reporterEnabled: 'spec, mocha-junit-reporter',
|
||||
mochaJunitReporterReporterOptions: {
|
||||
testsuitesTitle: `${suite} ${process.platform}`,
|
||||
mochaFile: path.join(process.env.BUILD_ARTIFACTSTAGINGDIRECTORY, `test-results/${process.platform}-${suite.toLowerCase().replace(/[^\w]/g, '-')}-results.xml`)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const mocha = new Mocha(options);
|
||||
mocha.addFile('out/main.js');
|
||||
mocha.run(failures => process.exit(failures ? -1 : 0));
|
||||
@@ -1,3 +0,0 @@
|
||||
--timeout 20000
|
||||
--slow 20000
|
||||
out/main.js
|
||||
@@ -41,9 +41,9 @@
|
||||
version "8.0.33"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.33.tgz#1126e94374014e54478092830704f6ea89df04cd"
|
||||
|
||||
"@types/node@^7.0.18":
|
||||
version "7.0.46"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.46.tgz#c3dedd25558c676b3d6303e51799abb9c3f8f314"
|
||||
"@types/node@^8.0.24":
|
||||
version "8.10.23"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.23.tgz#e5ccfdafff42af5397c29669b6d7d65f7d629a00"
|
||||
|
||||
"@types/rimraf@2.0.2":
|
||||
version "2.0.2"
|
||||
@@ -86,6 +86,10 @@ ansi-regex@^2.0.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
|
||||
|
||||
ansi-regex@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
|
||||
|
||||
ansi-styles@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.1.0.tgz#eaecbf66cd706882760b2f4691582b8f55d7a7de"
|
||||
@@ -238,9 +242,9 @@ braces@^1.8.2:
|
||||
preserve "^0.2.0"
|
||||
repeat-element "^1.1.2"
|
||||
|
||||
browser-stdout@1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f"
|
||||
browser-stdout@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
|
||||
|
||||
builtin-modules@^1.0.0:
|
||||
version "1.1.1"
|
||||
@@ -271,6 +275,10 @@ chalk@0.5.1:
|
||||
strip-ansi "^0.3.0"
|
||||
supports-color "^0.2.0"
|
||||
|
||||
charenc@~0.0.1:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
|
||||
|
||||
chokidar@^1.6.0:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468"
|
||||
@@ -300,16 +308,14 @@ combined-stream@^1.0.5, combined-stream@~1.0.5:
|
||||
dependencies:
|
||||
delayed-stream "~1.0.0"
|
||||
|
||||
commander@2.15.1:
|
||||
version "2.15.1"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f"
|
||||
|
||||
commander@2.6.0:
|
||||
version "2.6.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.6.0.tgz#9df7e52fb2a0cb0fb89058ee80c3104225f37e1d"
|
||||
|
||||
commander@2.9.0:
|
||||
version "2.9.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4"
|
||||
dependencies:
|
||||
graceful-readlink ">= 1.0.0"
|
||||
|
||||
commander@^2.8.1:
|
||||
version "2.11.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563"
|
||||
@@ -367,6 +373,10 @@ cpx@^1.5.0:
|
||||
shell-quote "^1.6.1"
|
||||
subarg "^1.0.0"
|
||||
|
||||
crypt@~0.0.1:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
|
||||
|
||||
cryptiles@2.x.x:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8"
|
||||
@@ -395,18 +405,18 @@ date-fns@^1.23.0:
|
||||
version "1.29.0"
|
||||
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.29.0.tgz#12e609cdcb935127311d04d33334e2960a2a54e6"
|
||||
|
||||
debug@2.6.8:
|
||||
version "2.6.8"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc"
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@2.6.9, debug@^2.1.3, debug@^2.2.0:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@3.1.0, debug@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
decamelize@^1.1.2:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
|
||||
@@ -427,9 +437,9 @@ detect-libc@^1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
|
||||
|
||||
diff@3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9"
|
||||
diff@3.5.0:
|
||||
version "3.5.0"
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
|
||||
|
||||
dom-serializer@0:
|
||||
version "0.1.0"
|
||||
@@ -483,11 +493,11 @@ electron-download@^3.0.1:
|
||||
semver "^5.3.0"
|
||||
sumchecker "^1.2.0"
|
||||
|
||||
electron@1.7.7:
|
||||
version "1.7.7"
|
||||
resolved "https://registry.yarnpkg.com/electron/-/electron-1.7.7.tgz#cfd89ca9eba79d763ac0b0c6dcc583792097b9b6"
|
||||
electron@^2.0.6:
|
||||
version "2.0.6"
|
||||
resolved "https://registry.yarnpkg.com/electron/-/electron-2.0.6.tgz#8e5c1bd2ebc08fa7a6ee906de3753c1ece9d7300"
|
||||
dependencies:
|
||||
"@types/node" "^7.0.18"
|
||||
"@types/node" "^8.0.24"
|
||||
electron-download "^3.0.1"
|
||||
extract-zip "^1.0.3"
|
||||
|
||||
@@ -699,18 +709,7 @@ glob2base@^0.0.12:
|
||||
dependencies:
|
||||
find-index "^0.1.1"
|
||||
|
||||
glob@7.1.1:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
inherits "2"
|
||||
minimatch "^3.0.2"
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
glob@^7.0.5:
|
||||
glob@7.1.2, glob@^7.0.5:
|
||||
version "7.1.2"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
|
||||
dependencies:
|
||||
@@ -725,13 +724,9 @@ graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9:
|
||||
version "4.1.11"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
|
||||
|
||||
"graceful-readlink@>= 1.0.0":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
|
||||
|
||||
growl@1.9.2:
|
||||
version "1.9.2"
|
||||
resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f"
|
||||
growl@1.10.5:
|
||||
version "1.10.5"
|
||||
resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e"
|
||||
|
||||
har-schema@^1.0.5:
|
||||
version "1.0.5"
|
||||
@@ -765,6 +760,10 @@ has-flag@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
|
||||
|
||||
has-flag@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
|
||||
|
||||
has-unicode@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
|
||||
@@ -865,7 +864,7 @@ is-binary-path@^1.0.0:
|
||||
dependencies:
|
||||
binary-extensions "^1.0.0"
|
||||
|
||||
is-buffer@^1.1.5:
|
||||
is-buffer@^1.1.5, is-buffer@~1.1.1:
|
||||
version "1.1.6"
|
||||
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
|
||||
|
||||
@@ -979,10 +978,6 @@ json-stringify-safe@~5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
|
||||
|
||||
json3@3.3.2:
|
||||
version "3.3.2"
|
||||
resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1"
|
||||
|
||||
jsonfile@^2.1.0:
|
||||
version "2.4.0"
|
||||
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8"
|
||||
@@ -1030,52 +1025,9 @@ load-json-file@^1.0.0:
|
||||
pinkie-promise "^2.0.0"
|
||||
strip-bom "^2.0.0"
|
||||
|
||||
lodash._baseassign@^3.0.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e"
|
||||
dependencies:
|
||||
lodash._basecopy "^3.0.0"
|
||||
lodash.keys "^3.0.0"
|
||||
|
||||
lodash._basecopy@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36"
|
||||
|
||||
lodash._basecreate@^3.0.0:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821"
|
||||
|
||||
lodash._getnative@^3.0.0:
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5"
|
||||
|
||||
lodash._isiterateecall@^3.0.0:
|
||||
version "3.0.9"
|
||||
resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c"
|
||||
|
||||
lodash.create@3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7"
|
||||
dependencies:
|
||||
lodash._baseassign "^3.0.0"
|
||||
lodash._basecreate "^3.0.0"
|
||||
lodash._isiterateecall "^3.0.0"
|
||||
|
||||
lodash.isarguments@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a"
|
||||
|
||||
lodash.isarray@^3.0.0:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55"
|
||||
|
||||
lodash.keys@^3.0.0:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a"
|
||||
dependencies:
|
||||
lodash._getnative "^3.0.0"
|
||||
lodash.isarguments "^3.0.0"
|
||||
lodash.isarray "^3.0.0"
|
||||
lodash@^4.16.4:
|
||||
version "4.17.10"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7"
|
||||
|
||||
lodash@^4.5.1:
|
||||
version "4.17.5"
|
||||
@@ -1092,6 +1044,14 @@ map-obj@^1.0.0, map-obj@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
|
||||
|
||||
md5@^2.1.0:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/md5/-/md5-2.2.1.tgz#53ab38d5fe3c8891ba465329ea23fac0540126f9"
|
||||
dependencies:
|
||||
charenc "~0.0.1"
|
||||
crypt "~0.0.1"
|
||||
is-buffer "~1.1.1"
|
||||
|
||||
meow@^3.1.0:
|
||||
version "3.7.0"
|
||||
resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb"
|
||||
@@ -1149,7 +1109,7 @@ mime-types@~2.1.7:
|
||||
dependencies:
|
||||
mime-db "~1.33.0"
|
||||
|
||||
minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4:
|
||||
minimatch@3.0.4, minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
dependencies:
|
||||
@@ -1169,28 +1129,44 @@ mkdirp@0.5.0:
|
||||
dependencies:
|
||||
minimist "0.0.8"
|
||||
|
||||
mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.1:
|
||||
mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.1, mkdirp@~0.5.1:
|
||||
version "0.5.1"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
|
||||
dependencies:
|
||||
minimist "0.0.8"
|
||||
|
||||
mocha@^3.2.0:
|
||||
version "3.5.3"
|
||||
resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.5.3.tgz#1e0480fe36d2da5858d1eb6acc38418b26eaa20d"
|
||||
mocha-junit-reporter@^1.17.0:
|
||||
version "1.17.0"
|
||||
resolved "https://registry.yarnpkg.com/mocha-junit-reporter/-/mocha-junit-reporter-1.17.0.tgz#2e5149ed40fc5d2e3ca71e42db5ab1fec9c6d85c"
|
||||
dependencies:
|
||||
browser-stdout "1.3.0"
|
||||
commander "2.9.0"
|
||||
debug "2.6.8"
|
||||
diff "3.2.0"
|
||||
debug "^2.2.0"
|
||||
md5 "^2.1.0"
|
||||
mkdirp "~0.5.1"
|
||||
strip-ansi "^4.0.0"
|
||||
xml "^1.0.0"
|
||||
|
||||
mocha-multi-reporters@^1.1.7:
|
||||
version "1.1.7"
|
||||
resolved "https://registry.yarnpkg.com/mocha-multi-reporters/-/mocha-multi-reporters-1.1.7.tgz#cc7f3f4d32f478520941d852abb64d9988587d82"
|
||||
dependencies:
|
||||
debug "^3.1.0"
|
||||
lodash "^4.16.4"
|
||||
|
||||
mocha@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6"
|
||||
dependencies:
|
||||
browser-stdout "1.3.1"
|
||||
commander "2.15.1"
|
||||
debug "3.1.0"
|
||||
diff "3.5.0"
|
||||
escape-string-regexp "1.0.5"
|
||||
glob "7.1.1"
|
||||
growl "1.9.2"
|
||||
glob "7.1.2"
|
||||
growl "1.10.5"
|
||||
he "1.1.1"
|
||||
json3 "3.3.2"
|
||||
lodash.create "3.1.1"
|
||||
minimatch "3.0.4"
|
||||
mkdirp "0.5.1"
|
||||
supports-color "3.1.2"
|
||||
supports-color "5.4.0"
|
||||
|
||||
ms@2.0.0:
|
||||
version "2.0.0"
|
||||
@@ -1726,6 +1702,12 @@ strip-ansi@^3.0.0, strip-ansi@^3.0.1:
|
||||
dependencies:
|
||||
ansi-regex "^2.0.0"
|
||||
|
||||
strip-ansi@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
|
||||
dependencies:
|
||||
ansi-regex "^3.0.0"
|
||||
|
||||
strip-bom@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
|
||||
@@ -1755,11 +1737,11 @@ sumchecker@^1.2.0:
|
||||
debug "^2.2.0"
|
||||
es6-promise "^4.0.5"
|
||||
|
||||
supports-color@3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5"
|
||||
supports-color@5.4.0:
|
||||
version "5.4.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54"
|
||||
dependencies:
|
||||
has-flag "^1.0.0"
|
||||
has-flag "^3.0.0"
|
||||
|
||||
supports-color@^0.2.0:
|
||||
version "0.2.0"
|
||||
@@ -1895,6 +1877,10 @@ wrappy@1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||
|
||||
xml@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5"
|
||||
|
||||
xtend@~2.1.1:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b"
|
||||
|
||||
13
test/tree/package.json
Normal file
13
test/tree/package.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "tree",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"koa": "^2.5.1",
|
||||
"koa-mount": "^3.0.0",
|
||||
"koa-route": "^3.2.0",
|
||||
"koa-static": "^5.0.0",
|
||||
"mz": "^2.7.0"
|
||||
}
|
||||
}
|
||||
62
test/tree/public/index.html
Normal file
62
test/tree/public/index.html
Normal file
@@ -0,0 +1,62 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Tree</title>
|
||||
<style>
|
||||
#container {
|
||||
width: 400;
|
||||
height: 600;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.monaco-scrollable-element>.scrollbar>.slider {
|
||||
background: rgba(100, 100, 100, .4);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container"></div>
|
||||
|
||||
<script src="/static/vs/loader.js"></script>
|
||||
<script>
|
||||
require.config({ baseUrl: '/static' });
|
||||
|
||||
require(['vs/base/browser/ui/tree/tree', 'vs/base/common/iterator'], ({ Tree }, { iter }) => {
|
||||
const delegate = {
|
||||
getHeight() { return 22; },
|
||||
getTemplateId() { return 'template'; }
|
||||
};
|
||||
|
||||
const renderer = {
|
||||
templateId: 'template',
|
||||
renderTemplate(container) { return container; },
|
||||
renderElement(element, index, container) {
|
||||
container.textContent = element;
|
||||
},
|
||||
disposeTemplate() { }
|
||||
};
|
||||
|
||||
const tree = new Tree(container, delegate, [renderer]);
|
||||
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', '/api/ls?path=');
|
||||
xhr.send();
|
||||
xhr.onreadystatechange = function () {
|
||||
if (this.readyState == 4 && this.status == 200) {
|
||||
const data = JSON.parse(this.responseText);
|
||||
|
||||
performance.mark('before splice');
|
||||
const start = performance.now();
|
||||
tree.splice([0], 0, [data]);
|
||||
console.log('splice took', performance.now() - start);
|
||||
performance.mark('after splice');
|
||||
|
||||
}
|
||||
};
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
39
test/tree/server.js
Normal file
39
test/tree/server.js
Normal file
@@ -0,0 +1,39 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
const fs = require('mz/fs');
|
||||
const path = require('path');
|
||||
const Koa = require('koa');
|
||||
const _ = require('koa-route');
|
||||
const serve = require('koa-static');
|
||||
const mount = require('koa-mount');
|
||||
|
||||
const app = new Koa();
|
||||
const root = path.dirname(path.dirname(__dirname));
|
||||
|
||||
async function getTree(fsPath, level) {
|
||||
const element = path.basename(fsPath);
|
||||
const stat = await fs.stat(fsPath);
|
||||
|
||||
if (!stat.isDirectory() || element === '.git' || element === '.build' || level >= 3) {
|
||||
return { element };
|
||||
}
|
||||
|
||||
const childNames = await fs.readdir(fsPath);
|
||||
const children = await Promise.all(childNames.map(async childName => await getTree(path.join(fsPath, childName), level + 1)));
|
||||
return { element, collapsible: true, collapsed: false, children };
|
||||
}
|
||||
|
||||
app.use(serve('public'));
|
||||
app.use(mount('/static', serve('../../out')));
|
||||
app.use(_.get('/api/ls', async ctx => {
|
||||
const relativePath = ctx.query.path;
|
||||
const absolutePath = path.join(root, relativePath);
|
||||
|
||||
ctx.body = await getTree(absolutePath, 0);
|
||||
}))
|
||||
|
||||
app.listen(3000);
|
||||
console.log('http://localhost:3000');
|
||||
290
test/tree/yarn.lock
Normal file
290
test/tree/yarn.lock
Normal file
@@ -0,0 +1,290 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
accepts@^1.2.2:
|
||||
version "1.3.5"
|
||||
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2"
|
||||
dependencies:
|
||||
mime-types "~2.1.18"
|
||||
negotiator "0.6.1"
|
||||
|
||||
any-promise@^1.0.0, any-promise@^1.1.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
|
||||
|
||||
co@^4.6.0:
|
||||
version "4.6.0"
|
||||
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
|
||||
|
||||
content-disposition@~0.5.0:
|
||||
version "0.5.2"
|
||||
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4"
|
||||
|
||||
content-type@^1.0.0:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
|
||||
|
||||
cookies@~0.7.0:
|
||||
version "0.7.1"
|
||||
resolved "https://registry.yarnpkg.com/cookies/-/cookies-0.7.1.tgz#7c8a615f5481c61ab9f16c833731bcb8f663b99b"
|
||||
dependencies:
|
||||
depd "~1.1.1"
|
||||
keygrip "~1.0.2"
|
||||
|
||||
debug@*, debug@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@^2.6.1:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
deep-equal@~1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
|
||||
|
||||
delegates@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
|
||||
|
||||
depd@^1.1.0, depd@~1.1.1, depd@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
|
||||
|
||||
destroy@^1.0.3:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
|
||||
|
||||
ee-first@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
|
||||
|
||||
error-inject@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/error-inject/-/error-inject-1.0.0.tgz#e2b3d91b54aed672f309d950d154850fa11d4f37"
|
||||
|
||||
escape-html@~1.0.1:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
|
||||
|
||||
fresh@^0.5.2:
|
||||
version "0.5.2"
|
||||
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
|
||||
|
||||
http-assert@^1.1.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/http-assert/-/http-assert-1.3.0.tgz#a31a5cf88c873ecbb5796907d4d6f132e8c01e4a"
|
||||
dependencies:
|
||||
deep-equal "~1.0.1"
|
||||
http-errors "~1.6.1"
|
||||
|
||||
http-errors@^1.2.8, http-errors@^1.6.3, http-errors@~1.6.1, http-errors@~1.6.2:
|
||||
version "1.6.3"
|
||||
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d"
|
||||
dependencies:
|
||||
depd "~1.1.2"
|
||||
inherits "2.0.3"
|
||||
setprototypeof "1.1.0"
|
||||
statuses ">= 1.4.0 < 2"
|
||||
|
||||
inherits@2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
|
||||
|
||||
is-generator-function@^1.0.3:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.7.tgz#d2132e529bb0000a7f80794d4bdf5cd5e5813522"
|
||||
|
||||
isarray@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
|
||||
|
||||
keygrip@~1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.0.2.tgz#ad3297c557069dea8bcfe7a4fa491b75c5ddeb91"
|
||||
|
||||
koa-compose@^3.0.0, koa-compose@^3.2.1:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/koa-compose/-/koa-compose-3.2.1.tgz#a85ccb40b7d986d8e5a345b3a1ace8eabcf54de7"
|
||||
dependencies:
|
||||
any-promise "^1.1.0"
|
||||
|
||||
koa-compose@^4.0.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/koa-compose/-/koa-compose-4.1.0.tgz#507306b9371901db41121c812e923d0d67d3e877"
|
||||
|
||||
koa-convert@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/koa-convert/-/koa-convert-1.2.0.tgz#da40875df49de0539098d1700b50820cebcd21d0"
|
||||
dependencies:
|
||||
co "^4.6.0"
|
||||
koa-compose "^3.0.0"
|
||||
|
||||
koa-is-json@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/koa-is-json/-/koa-is-json-1.0.0.tgz#273c07edcdcb8df6a2c1ab7d59ee76491451ec14"
|
||||
|
||||
koa-mount@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/koa-mount/-/koa-mount-3.0.0.tgz#08cab3b83d31442ed8b7e75c54b1abeb922ec197"
|
||||
dependencies:
|
||||
debug "^2.6.1"
|
||||
koa-compose "^3.2.1"
|
||||
|
||||
koa-route@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/koa-route/-/koa-route-3.2.0.tgz#76298b99a6bcfa9e38cab6fe5c79a8733e758bce"
|
||||
dependencies:
|
||||
debug "*"
|
||||
methods "~1.1.0"
|
||||
path-to-regexp "^1.2.0"
|
||||
|
||||
koa-send@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/koa-send/-/koa-send-5.0.0.tgz#5e8441e07ef55737734d7ced25b842e50646e7eb"
|
||||
dependencies:
|
||||
debug "^3.1.0"
|
||||
http-errors "^1.6.3"
|
||||
mz "^2.7.0"
|
||||
resolve-path "^1.4.0"
|
||||
|
||||
koa-static@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/koa-static/-/koa-static-5.0.0.tgz#5e92fc96b537ad5219f425319c95b64772776943"
|
||||
dependencies:
|
||||
debug "^3.1.0"
|
||||
koa-send "^5.0.0"
|
||||
|
||||
koa@^2.5.1:
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/koa/-/koa-2.5.1.tgz#79f8b95f8d72d04fe9a58a8da5ebd6d341103f9c"
|
||||
dependencies:
|
||||
accepts "^1.2.2"
|
||||
content-disposition "~0.5.0"
|
||||
content-type "^1.0.0"
|
||||
cookies "~0.7.0"
|
||||
debug "*"
|
||||
delegates "^1.0.0"
|
||||
depd "^1.1.0"
|
||||
destroy "^1.0.3"
|
||||
error-inject "~1.0.0"
|
||||
escape-html "~1.0.1"
|
||||
fresh "^0.5.2"
|
||||
http-assert "^1.1.0"
|
||||
http-errors "^1.2.8"
|
||||
is-generator-function "^1.0.3"
|
||||
koa-compose "^4.0.0"
|
||||
koa-convert "^1.2.0"
|
||||
koa-is-json "^1.0.0"
|
||||
mime-types "^2.0.7"
|
||||
on-finished "^2.1.0"
|
||||
only "0.0.2"
|
||||
parseurl "^1.3.0"
|
||||
statuses "^1.2.0"
|
||||
type-is "^1.5.5"
|
||||
vary "^1.0.0"
|
||||
|
||||
media-typer@0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
|
||||
|
||||
methods@~1.1.0:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
|
||||
|
||||
mime-db@~1.33.0:
|
||||
version "1.33.0"
|
||||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db"
|
||||
|
||||
mime-types@^2.0.7, mime-types@~2.1.18:
|
||||
version "2.1.18"
|
||||
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8"
|
||||
dependencies:
|
||||
mime-db "~1.33.0"
|
||||
|
||||
ms@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||
|
||||
mz@^2.7.0:
|
||||
version "2.7.0"
|
||||
resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32"
|
||||
dependencies:
|
||||
any-promise "^1.0.0"
|
||||
object-assign "^4.0.1"
|
||||
thenify-all "^1.0.0"
|
||||
|
||||
negotiator@0.6.1:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9"
|
||||
|
||||
object-assign@^4.0.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
|
||||
on-finished@^2.1.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
|
||||
dependencies:
|
||||
ee-first "1.1.1"
|
||||
|
||||
only@0.0.2:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/only/-/only-0.0.2.tgz#2afde84d03e50b9a8edc444e30610a70295edfb4"
|
||||
|
||||
parseurl@^1.3.0:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3"
|
||||
|
||||
path-is-absolute@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||
|
||||
path-to-regexp@^1.2.0:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d"
|
||||
dependencies:
|
||||
isarray "0.0.1"
|
||||
|
||||
resolve-path@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve-path/-/resolve-path-1.4.0.tgz#c4bda9f5efb2fce65247873ab36bb4d834fe16f7"
|
||||
dependencies:
|
||||
http-errors "~1.6.2"
|
||||
path-is-absolute "1.0.1"
|
||||
|
||||
setprototypeof@1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
|
||||
|
||||
"statuses@>= 1.4.0 < 2", statuses@^1.2.0:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
|
||||
|
||||
thenify-all@^1.0.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726"
|
||||
dependencies:
|
||||
thenify ">= 3.1.0 < 4"
|
||||
|
||||
"thenify@>= 3.1.0 < 4":
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.0.tgz#e69e38a1babe969b0108207978b9f62b88604839"
|
||||
dependencies:
|
||||
any-promise "^1.0.0"
|
||||
|
||||
type-is@^1.5.5:
|
||||
version "1.6.16"
|
||||
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194"
|
||||
dependencies:
|
||||
media-typer "0.3.0"
|
||||
mime-types "~2.1.18"
|
||||
|
||||
vary@^1.0.0:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
|
||||
Reference in New Issue
Block a user