diff --git a/.gitignore b/.gitignore index 4f4c09820c..60a775b76f 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,5 @@ packages tools examples sqltoolsservice -coverage/ \ No newline at end of file +coverage +test-reports \ No newline at end of file diff --git a/coverconfig.json b/coverconfig.json index 40d93ade95..e856ffaad7 100644 --- a/coverconfig.json +++ b/coverconfig.json @@ -2,8 +2,8 @@ "enabled": false, "relativeSourcePath": "../src", "relativeCoverageDir": "../../coverage", - "ignorePatterns": ["**/node_modules/**", "**/libs/**", "**/lib/**", "**/*.min.js", "**/*.bundle.js"], + "ignorePatterns": ["**/node_modules/**", "**/libs/**", "**/lib/**", "**/htmlcontent/**/*.js", "**/*.bundle.js"], "includePid": false, - "reports": ["lcov", "cobertura"], + "reports": ["json"], "verbose": false } \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index 31dbca2dbc..7f90b41224 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -18,7 +18,6 @@ const path = require('path'); require('./tasks/htmltasks') require('./tasks/packagetasks') -require('./tasks/covertasks') gulp.task('ext:lint', () => { return gulp.src([ @@ -117,6 +116,16 @@ gulp.task('ext:copy', gulp.series('ext:copy-tests', 'ext:copy-js', 'ext:copy-con gulp.task('ext:build', gulp.series('ext:lint', 'ext:compile', 'ext:copy')); +gulp.task('ext:test', (done) => { + process.env.JUNIT_REPORT_PATH = process.env['WORKSPACE'] + '\\test-reports\\ext_xunit.xml'; + cproc.execSync('code --extensionDevelopmentPath="%WORKSPACE%" --extensionTestsPath="%WORKSPACE%/out/test" --verbose'); + done(); +}); + +gulp.task('test', gulp.series('html:test', 'ext:test')); + +require('./tasks/covertasks'); + gulp.task('clean', function (done) { return del('out', done); }); diff --git a/karma-test-shim.js b/karma-test-shim.js new file mode 100644 index 0000000000..6ce71d1a10 --- /dev/null +++ b/karma-test-shim.js @@ -0,0 +1,88 @@ +// #docregion +// /*global jasmine, __karma__, window*/ +Error.stackTraceLimit = 0; // "No stacktrace"" is usually best for app testing. + +// Uncomment to get full stacktrace output. Sometimes helpful, usually not. +Error.stackTraceLimit = Infinity; // + +var builtPath = '/base/out/src/views/htmlcontent/dist/js/'; + +__karma__.loaded = function () { }; + +function isJsFile(path) { + return path.slice(-3) == '.js'; +} + +function isSpecFile(path) { + return /\.spec\.(.*\.)?js$/.test(path); +} + +function isBuiltFile(path) { + return isJsFile(path) && (path.substr(0, builtPath.length) == builtPath); +} + +var allSpecFiles = Object.keys(window.__karma__.files) + .filter(isSpecFile); + +System.config({ + baseURL: 'base/out/src/views/htmlcontent', + // Extend usual application package list with test folder + packages: { 'testing': { main: 'index.js', defaultExtension: 'js' } }, + + // Assume npm: is set in `paths` in systemjs.config + // Map the angular testing umd bundles + map: { + '@angular/core/testing': 'lib/js/@angular/core/bundles/core-testing.umd.js', + '@angular/common/testing': 'lib/js/@angular/common/bundles/common-testing.umd.js', + '@angular/compiler/testing': 'lib/js/@angular/compiler/bundles/compiler-testing.umd.js', + '@angular/platform-browser/testing': 'lib/js/@angular/platform-browser/bundles/platform-browser-testing.umd.js', + '@angular/platform-browser-dynamic/testing': 'lib/js/@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js', + '@angular/http/testing': 'lib/js/@angular/http/bundles/http-testing.umd.js', + '@angular/router/testing': 'lib/js/@angular/router/bundles/router-testing.umd.js', + '@angular/forms/testing': 'ib/js/@angular/forms/bundles/forms-testing.umd.js', + }, +}); + +System.import('lib/js/systemjs.config.js') + .then(importSystemJsExtras) + .then(initTestBed) + .then(initTesting); + +/** Optional SystemJS configuration extras. Keep going w/o it */ +function importSystemJsExtras(){ + return System.import('lib/js/systemjs.config.extras.js') + .catch(function(reason) { + console.log( + 'Warning: System.import could not load the optional "systemjs.config.extras.js". Did you omit it by accident? Continuing without it.' + ); + console.log(reason); + }); +} + +function initTestBed(){ + return Promise.all([ + System.import('@angular/core/testing'), + System.import('@angular/platform-browser-dynamic/testing') + ]) + + .then(function (providers) { + var coreTesting = providers[0]; + var browserTesting = providers[1]; + + jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; + + coreTesting.TestBed.initTestEnvironment( + browserTesting.BrowserDynamicTestingModule, + browserTesting.platformBrowserDynamicTesting()); + }) +} + +// Import all spec files and start karma +function initTesting () { + return Promise.all( + allSpecFiles.map(function (moduleName) { + return System.import(moduleName); + }) + ) + .then(__karma__.start, __karma__.error); +} diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 0000000000..cd601447a2 --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,141 @@ +// #docregion +const path = require('path'); + +module.exports = function(config) { + + var appBase = 'out/src/views/htmlcontent/dist/'; // transpiled app JS and map files + var appSrcBase = 'src/views/htmlcontent/src/js/'; // app source TS files + var appAssets = 'base/out/src/views/htmlcontent/'; // component assets fetched by Angular's compiler + + var testBase = 'out/test/angular/'; // transpiled test JS and map files + var testSrcBase = 'test/angular/'; // test source TS files + + config.set({ + basePath: path.join(__dirname), + frameworks: ['jasmine'], + plugins: [ + require('karma-remap-istanbul'), + require('karma-coverage'), + require('karma-jasmine'), + require('karma-chrome-launcher'), + require('karma-jasmine-html-reporter'), // click "Debug" in browser to see it + require('karma-htmlfile-reporter'), // crashing w/ strange socket error + require('karma-junit-reporter') + ], + + customLaunchers: { + // From the CLI. Not used here but interesting + // chrome setup for travis CI using chromium + Chrome_travis_ci: { + base: 'Chrome', + flags: ['--no-sandbox'] + } + }, + files: [ + 'out/src/views/htmlcontent/lib/js/jquery-1.7.min.js', + 'out/src/views/htmlcontent/lib/js/jquery.event.drag-2.2.js', + 'out/src/views/htmlcontent/lib/js/jquery-ui-1.8.16.custom.min.js', + 'out/src/views/htmlcontent/lib/js/underscore-min.js', + 'out/src/views/htmlcontent/lib/js/slick.core.js', + 'out/src/views/htmlcontent/lib/js/slick.grid.js', + 'out/src/views/htmlcontent/lib/js/slick.editors.js', + 'out/src/views/htmlcontent/lib/js/slick.autosizecolumn.js', + 'out/src/views/htmlcontent/lib/js/slick.dragrowselector.js', + // System.js for module loading + 'out/src/views/htmlcontent/lib/js/system.src.js', + + // Polyfills + 'out/src/views/htmlcontent/lib/js/shim.min.js', + 'out/src/views/htmlcontent/lib/js/Reflect.js', + + // zone.js + 'out/src/views/htmlcontent/lib/js/zone.js/dist/zone.js', + 'out/src/views/htmlcontent/lib/js/zone.js/dist/long-stack-trace-zone.js', + 'out/src/views/htmlcontent/lib/js/zone.js/dist/proxy.js', + 'out/src/views/htmlcontent/lib/js/zone.js/dist/sync-test.js', + 'out/src/views/htmlcontent/lib/js/zone.js/dist/jasmine-patch.js', + 'out/src/views/htmlcontent/lib/js/zone.js/dist/async-test.js', + 'out/src/views/htmlcontent/lib/js/zone.js/dist/fake-async-test.js', + + // RxJs + { pattern: 'out/src/views/htmlcontent/lib/js/rxjs/**/*.js', included: false, watched: false }, + { pattern: 'out/src/views/htmlcontent/lib/js/rxjs/**/*.js.map', included: false, watched: false }, + + + { pattern: 'out/src/views/htmlcontent/lib/js/angular2-slickgrid/**/*.js', included: false, watched: false }, + { pattern: 'out/src/views/htmlcontent/lib/js/angular2-slickgrid/**/*.js.map', included: false, watched: false }, + + { pattern: 'out/src/views/htmlcontent/lib/js/json.js', included: false, watched: false}, + + // Paths loaded via module imports: + // Angular itself + { pattern: 'out/src/views/htmlcontent/lib/js/@angular/**/*.js', included: false, watched: false }, + { pattern: 'out/src/views/htmlcontent/lib/js/@angular/**/*.js.map', included: false, watched: false }, + + { pattern: 'out/src/views/htmlcontent/lib/js/systemjs.config.js', included: false, watched: false }, + { pattern: 'out/src/views/htmlcontent/lib/js/systemjs.config.extras.js', included: false, watched: false }, + 'karma-test-shim.js', + + // transpiled application & spec code paths loaded via module imports + { pattern: appBase + '**/*.js', included: false, watched: true }, + { pattern: appBase + '**/*.json', included: false, watched: false }, + { pattern: testBase + '**/*.js', included: false, watched: false }, + + + // Asset (HTML & CSS) paths loaded via Angular's component compiler + // (these paths need to be rewritten, see proxies section) + { pattern: appBase + '**/*.html', included: false, watched: false }, + { pattern: appBase + '**/*.css', included: false, watched: false }, + + // Paths for debugging with source maps in dev tools + { pattern: appSrcBase + '**/*.ts', included: false, watched: false }, + { pattern: appBase + '**/*.js.map', included: false, watched: false }, + { pattern: testSrcBase + '**/*.ts', included: false, watched: false }, + { pattern: testBase + '**/*.js.map', included: false, watched: false } + ], + + // Proxied base paths for loading assets + proxies: { + // required for component assets fetched by Angular's compiler + "/dist/": 'base/out/src/views/htmlcontent/dist/' + }, + + exclude: [], + preprocessors: { + 'out/src/views/htmlcontent/dist/**/!(*spec)*.js': 'coverage', + }, + // disabled HtmlReporter; suddenly crashing w/ strange socket error + reporters: ['progress', 'coverage', 'karma-remap-istanbul', 'junit'],//'html'], + + // HtmlReporter configuration + htmlReporter: { + // Open this file to see results in browser + outputFile: '_test-output/tests.html', + + // Optional + pageTitle: 'Unit Tests', + subPageTitle: __dirname + }, + coverageReporter: { + dir : 'coverage/', + reporters: [ + {type: 'json'} + ] + }, + remapIstanbulReporter: { + reports: { + json: 'coverage/coverage-html.json' + } + }, + junitReporter: { + outputDir: 'test-reports/' + }, + + port: 9876, + colors: true, + logLevel: config.LOG_INFO, + autoWatch: true, + browsers: ['Chrome'], + singleRun: true + }) +} \ No newline at end of file diff --git a/package.json b/package.json index 50b05d55fe..4c75a2fcd3 100644 --- a/package.json +++ b/package.json @@ -47,21 +47,33 @@ "gulp-clean-css": "^2.0.13", "gulp-concat": "^2.6.0", "gulp-install": "^0.6.0", + "gulp-istanbul-report": "0.0.1", "gulp-json-editor": "^2.2.1", "gulp-rename": "^1.2.2", + "gulp-shell": "^0.5.2", "gulp-sourcemaps": "^1.6.0", "gulp-tslint": "^6.0.2", "gulp-typescript": "^2.13.6", - "istanbul": "^0.4.5", - "remap-istanbul": "^0.6.4", "gulp-uglify": "^2.0.0", + "istanbul": "^0.4.5", + "jasmine-core": "~2.4.1", + "karma": "^1.3.0", + "karma-chrome-launcher": "^2.0.0", + "karma-coverage": "^1.1.1", + "karma-htmlfile-reporter": "^0.3.4", + "karma-jasmine": "^1.0.2", + "karma-jasmine-html-reporter": "^0.2.2", + "karma-junit-reporter": "^1.1.0", + "karma-remap-istanbul": "^0.2.1", "pm-mocha-jenkins-reporter": "^0.2.6", + "remap-istanbul": "^0.6.4", "systemjs-builder": "^0.15.32", "tslint": "^3.14.0", "typemoq": "^0.3.2", "typescript": "^1.8.9", "uglify-js": "mishoo/UglifyJS2#harmony", - "vscode": "^0.11.0" + "vscode": "^0.11.0", + "yargs": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz" }, "dependencies": { "applicationinsights": "^0.15.0", @@ -223,7 +235,7 @@ "type": "string", "default": "{{put-username-here}}", "description": "[Optional] Specify the user name for SQL Server authentication. If user name is not specified, when you connect, you will be asked again." - }, + }, "password": { "type": "string", "default": "{{put-password-here}}", diff --git a/src/models/SqlOutputContentProvider.ts b/src/models/SqlOutputContentProvider.ts index f7c3d43ae6..b0e4973c24 100644 --- a/src/models/SqlOutputContentProvider.ts +++ b/src/models/SqlOutputContentProvider.ts @@ -12,6 +12,7 @@ import StatusView from '../views/statusView'; import VscodeWrapper from './../controllers/vscodeWrapper'; import { ISelectionData } from './interfaces'; const pd = require('pretty-data').pd; +const fs = require('fs'); const deletionTimeoutTime = 1.8e6; // in ms, currently 30 minutes @@ -70,6 +71,13 @@ export class SqlOutputContentProvider implements vscode.TextDocumentContentProvi let theme: string = req.query.theme; let backgroundcolor: string = req.query.backgroundcolor; let color: string = req.query.color; + let prod; + try { + fs.accessSync(path.join(LocalWebService.staticContentPath, Constants.contentProviderMinFile), fs.F_OK); + prod = true; + } catch (e) { + prod = false; + } let editorConfig = self._vscodeWrapper.getConfiguration('editor'); let fontfamily = editorConfig.get('fontFamily').split('\'').join('').split('"').join(''); let fontsize = editorConfig.get('fontSize') + 'px'; @@ -82,7 +90,8 @@ export class SqlOutputContentProvider implements vscode.TextDocumentContentProvi color: color, fontfamily: fontfamily, fontsize: fontsize, - fontweight: fontweight + fontweight: fontweight, + prod: prod } ); }); diff --git a/src/models/constants.ts b/src/models/constants.ts index 4ec615f9d3..838f9ba603 100644 --- a/src/models/constants.ts +++ b/src/models/constants.ts @@ -43,6 +43,7 @@ export const outputContentTypeShowError = 'showError'; export const outputContentTypeShowWarning = 'showWarning'; export const outputServiceLocalhost = 'http://localhost:'; export const msgContentProviderSqlOutputHtml = 'dist/html/sqlOutput.ejs'; +export const contentProviderMinFile = 'dist/js/app.min.js'; export const configLogDebugInfo = 'logDebugInfo'; export const configMyConnections = 'connections'; diff --git a/src/models/interfaces.ts b/src/models/interfaces.ts index 503dcf33ef..1c82f6312c 100644 --- a/src/models/interfaces.ts +++ b/src/models/interfaces.ts @@ -229,6 +229,11 @@ export interface IDbColumn { isHidden?: boolean; isIdentity?: boolean; isKey?: boolean; + isBytes?: boolean; + isChars?: boolean; + isSqlVariant?: boolean; + isUdt?: boolean; + dataType: string; isXml?: boolean; isJson?: boolean; isLong?: boolean; diff --git a/src/views/htmlcontent/package.json b/src/views/htmlcontent/package.json index 2dbf379d81..5f39d45606 100644 --- a/src/views/htmlcontent/package.json +++ b/src/views/htmlcontent/package.json @@ -3,26 +3,28 @@ "version": "1.0.0", "description": "", "dependencies": { - "@angular/common": "2.0.0-rc.5", - "@angular/compiler": "2.0.0-rc.5", - "@angular/core": "2.0.0-rc.5", - "@angular/forms": "0.3.0", - "@angular/http": "2.0.0-rc.5", - "@angular/platform-browser": "2.0.0-rc.5", - "@angular/platform-browser-dynamic": "2.0.0-rc.5", - "@angular/router": "3.0.0-rc.1", - "@angular/router-deprecated": "2.0.0-rc.2", - "@angular/upgrade": "2.0.0-rc.5", - "angular2-in-memory-web-api": "0.0.15", + "@angular/common": "~2.1.2", + "@angular/compiler": "~2.1.2", + "@angular/core": "~2.1.2", + "@angular/forms": "~2.1.2", + "@angular/http": "~2.1.2", + "@angular/platform-browser": "~2.1.2", + "@angular/platform-browser-dynamic": "~2.1.2", + "@angular/router": "~3.1.2", + "@angular/upgrade": "~2.1.2", + "angular-in-memory-web-api": "~0.1.13", "angular2-slickgrid": "git+ssh://git@github.com:microsoft/angular2-slickgrid", - "bootstrap": "^3.3.6", - "core-js": "^2.4.0", + "core-js": "^2.4.1", + "jasmine-core": "~2.4.1", "moment": "^2.15.1", - "reflect-metadata": "^0.1.3", - "rxjs": "5.0.0-beta.6", - "systemjs": "0.19.27", + "reflect-metadata": "^0.1.8", + "rxjs": "5.0.0-beta.12", + "systemjs": "0.19.40", "systemjs-plugin-json": "^0.2.0", "underscore": "^1.8.3", - "zone.js": "^0.6.12" + "zone.js": "^0.6.26" + }, + "devDependencies": { + "assert": "^1.4.1" } } diff --git a/src/views/htmlcontent/src/html/app.html b/src/views/htmlcontent/src/html/app.html index 5fcb0dae11..61503936a4 100644 --- a/src/views/htmlcontent/src/html/app.html +++ b/src/views/htmlcontent/src/html/app.html @@ -20,7 +20,7 @@
-
+
@@ -61,7 +61,7 @@ [{{startString}}] - {{Constants.executeQueryLabel}} + {{Constants.executeQueryLabel}} diff --git a/src/views/htmlcontent/src/html/navigation.component.html b/src/views/htmlcontent/src/html/navigation.component.html deleted file mode 100644 index 713cd31ab4..0000000000 --- a/src/views/htmlcontent/src/html/navigation.component.html +++ /dev/null @@ -1,14 +0,0 @@ - - \ No newline at end of file diff --git a/src/views/htmlcontent/src/html/sqlOutput.ejs b/src/views/htmlcontent/src/html/sqlOutput.ejs index b1adcd64e8..0cc83af8b9 100644 --- a/src/views/htmlcontent/src/html/sqlOutput.ejs +++ b/src/views/htmlcontent/src/html/sqlOutput.ejs @@ -33,8 +33,25 @@ - + <% if (prod) { %> + <% } else { %> + + + + + + + + + + + + + + + + <% } %> diff --git a/src/views/htmlcontent/src/js/app.module.ts b/src/views/htmlcontent/src/js/app.module.ts index b0c0432d8a..84d5d6a670 100644 --- a/src/views/htmlcontent/src/js/app.module.ts +++ b/src/views/htmlcontent/src/js/app.module.ts @@ -12,6 +12,7 @@ import { SlickGrid } from 'angular2-slickgrid'; import { AppComponent } from './components/app.component'; import { ScrollDirective } from './directives/scroll.directive'; import { MouseDownDirective } from './directives/mousedown.directive'; +import { ContextMenu } from './components/contextmenu.component'; /** * Top level angular module, no actual content here @@ -24,7 +25,7 @@ import { MouseDownDirective } from './directives/mousedown.directive'; JsonpModule, FormsModule ], - declarations: [ AppComponent, SlickGrid, ScrollDirective, MouseDownDirective], + declarations: [ AppComponent, SlickGrid, ScrollDirective, MouseDownDirective, ContextMenu], bootstrap: [ AppComponent ] }) export class AppModule { } diff --git a/src/views/htmlcontent/src/js/components/app.component.spec.ts b/src/views/htmlcontent/src/js/components/app.component.spec.ts new file mode 100644 index 0000000000..ce1fe244ca --- /dev/null +++ b/src/views/htmlcontent/src/js/components/app.component.spec.ts @@ -0,0 +1,119 @@ +import { async, inject, ComponentFixture, TestBed } from '@angular/core/testing'; +import { Http, BaseRequestOptions, Response, ResponseOptions, RequestMethod } from '@angular/http'; +import { MockBackend, MockConnection } from '@angular/http/testing'; +import { SlickGrid } from 'angular2-slickgrid'; + +import { IResultsConfig } from './../interfaces'; +import { ScrollDirective } from './../directives/scroll.directive'; +import { MouseDownDirective } from './../directives/mousedown.directive'; +import { ContextMenu } from './contextmenu.component'; +import { DataService } from './../services/data.service'; +import { ShortcutService } from './../services/shortcuts.service'; +import { AppComponent } from './app.component'; +import * as Constants from './../constants'; + +import MockBatch1 from './../testResources/mockBatch1.spec'; + +//////// SPECS ///////////// +describe('AppComponent', function (): void { + let fixture: ComponentFixture; + let comp: AppComponent; + let ele: Element; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ AppComponent, SlickGrid, ScrollDirective, MouseDownDirective, ContextMenu], + providers: [ + ShortcutService, + DataService, + MockBackend, + BaseRequestOptions, + { + provide: Http, + useFactory: (backend, options) => { return new Http(backend, options); }, + deps: [MockBackend, BaseRequestOptions] + } + ] + }); + })); + + describe('basic behaviors', () => { + + beforeEach(() => { + fixture = TestBed.createComponent(AppComponent); + fixture.detectChanges(); + comp = fixture.componentInstance; + ele = fixture.nativeElement; + }); + + it('should create component', () => { + expect(comp).toBeDefined(); + expect(ele).toBeDefined(); + }); + + it('initialized properly', () => { + let messages = ele.querySelector('#messages'); + let results = ele.querySelector('#results'); + expect(messages).toBeDefined(); + expect(messages.className.indexOf('hidden')).toEqual(-1, 'messages not visible'); + expect(messages.getElementsByTagName('tbody').length).toBeGreaterThan(0, 'no table body in messages'); + expect(messages.getElementsByTagName('tbody')[0] + .getElementsByTagName('td')[1] + .innerText.indexOf(Constants.executeQueryLabel)) + .not.toEqual(-1, 'Wrong executing label'); + expect(results).toBeNull('results pane is showing'); + }); + }); + + describe('full initialization', () => { + const mockConfig: IResultsConfig = { + shortcuts: { + + }, + messagesDefaultOpen: true + }; + + beforeEach(async(inject([MockBackend], (mockBackend: MockBackend) => { + mockBackend.connections.subscribe((conn: MockConnection) => { + let isGetConfig = conn.request.url && + conn.request.method === RequestMethod.Get && + conn.request.url.match(/\/config/) && + conn.request.url.match(/\/config/).length === 1 ? true : false; + let isGetRows = conn.request.url && + conn.request.method === RequestMethod.Get && + conn.request.url.match(/\/rows/) && + conn.request.url.match(/\/rows/).length === 1 ? true : false; + if (isGetConfig) { + conn.mockRespond(new Response(new ResponseOptions({body: JSON.stringify(mockConfig)}))); + } else if (isGetRows) { + let parser = document.createElement('a'); + parser.href = conn.request.url; + console.log(parser['rowStart']); + console.log(parser['numberOfRows']); + } + }); + }))); + + beforeEach(() => { + fixture = TestBed.createComponent(AppComponent); + fixture.detectChanges(); + comp = fixture.componentInstance; + ele = fixture.nativeElement; + }); + + beforeEach(() => { + comp.dataService.webSocket.dispatchEvent(new MessageEvent('message', { + data: JSON.stringify(MockBatch1) + })); + }); + + it('should have initilized the grids correctly', () => { + fixture.detectChanges(); + let results = ele.querySelector('#results'); + expect(results).not.toBeNull('results pane is not visible'); + expect(results.getElementsByTagName('slick-grid').length).toEqual(1); + // let slickgrid = results.getElementsByTagName('slick-grid')[0]; + // let viewport = slickgrid.firstElementChild.getElementsByClassName('slick-viewport')[0] + }); + }); +}); diff --git a/src/views/htmlcontent/src/js/components/app.component.ts b/src/views/htmlcontent/src/js/components/app.component.ts index 34b19ee54c..53e44acb32 100644 --- a/src/views/htmlcontent/src/js/components/app.component.ts +++ b/src/views/htmlcontent/src/js/components/app.component.ts @@ -2,13 +2,13 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. * ------------------------------------------------------------------------------------------ */ -import {Component, OnInit, Inject, forwardRef, ViewChild, ViewChildren, QueryList, ElementRef, - EventEmitter, ChangeDetectorRef, AfterViewChecked} from '@angular/core'; +import { Component, OnInit, Inject, forwardRef, ViewChild, ViewChildren, QueryList, ElementRef, + EventEmitter, ChangeDetectorRef, AfterViewChecked } from '@angular/core'; import { IColumnDefinition, IObservableCollection, IGridDataRow, ISlickRange, SlickGrid, VirtualizedCollection, FieldType } from 'angular2-slickgrid'; -import {DataService} from './../services/data.service'; -import {ShortcutService} from './../services/shortcuts.service'; +import { DataService } from './../services/data.service'; +import { ShortcutService } from './../services/shortcuts.service'; import { ContextMenu } from './contextmenu.component'; import { IGridIcon, ISelectionData, IResultMessage } from './../interfaces'; @@ -43,14 +43,88 @@ interface IMessages { endTime: string; } + // tslint:disable:max-line-length +const template = ` +
+
+ {{Constants.resultPaneLabel}} + {{resultShortcut}} +
+
+ +
+
+ {{Constants.messagePaneLabel}} + {{messageShortcut}} +
+
+
+ + + + + + + + + + + + + + + + + +
{{Utils.formatString(Constants.elapsedTimeLabel, Utils.parseNumAsTimeString(totalElapseExecution))}}
[{{startString}}] {{Constants.executeQueryLabel}}
+
+
+
+`; + // tslint:enable:max-line-length + /** * Top level app component which runs and controls the SlickGrid implementation */ @Component({ selector: 'my-app', host: { '(window:keydown)': 'keyEvent($event)', '(window:gridnav)': 'keyEvent($event)' }, - templateUrl: 'dist/html/app.html', - directives: [ContextMenu, SlickGrid], + template: template, providers: [DataService, ShortcutService], styles: [` .errorMessage { @@ -201,7 +275,7 @@ export class AppComponent implements OnInit, AfterViewChecked { return this._messageActive; } - constructor(@Inject(forwardRef(() => DataService)) private dataService: DataService, + constructor(@Inject(forwardRef(() => DataService)) public dataService: DataService, @Inject(forwardRef(() => ShortcutService)) private shortcuts: ShortcutService, @Inject(forwardRef(() => ElementRef)) private _el: ElementRef, @Inject(forwardRef(() => ChangeDetectorRef)) private cd: ChangeDetectorRef) {} diff --git a/src/views/htmlcontent/src/js/components/contextmenu.component.ts b/src/views/htmlcontent/src/js/components/contextmenu.component.ts index fee032adf3..88e8445424 100644 --- a/src/views/htmlcontent/src/js/components/contextmenu.component.ts +++ b/src/views/htmlcontent/src/js/components/contextmenu.component.ts @@ -13,10 +13,20 @@ import * as Utils from './../utils'; * The component that acts as the contextMenu for slick grid */ +const template = ` +`; + @Component({ selector: 'context-menu', providers: [ShortcutService], - templateUrl: 'dist/html/contextmenu.component.html' + template: template }) export class ContextMenu { diff --git a/src/views/htmlcontent/src/js/components/navigation.component.ts b/src/views/htmlcontent/src/js/components/navigation.component.ts deleted file mode 100644 index adc8d902fb..0000000000 --- a/src/views/htmlcontent/src/js/components/navigation.component.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* -------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - * ------------------------------------------------------------------------------------------ */ -import { Component, Input, Output, EventEmitter } from '@angular/core'; - -/** - * The component that handles the navigation for the results UI - */ - -@Component({ - selector: 'navigator', - templateUrl: 'dist/html/navigation.component.html' -}) - -export class NavigatorComponent { - @Input() batches: number[][]; - @Output() selectionChange: EventEmitter<{ batch: number; result: number; }> = new EventEmitter<{ batch: number; result: number; }>(); - - /** - * Emits the selected value that was chosen in the navigator - * @param value The Json object to emit in the event - */ - public selected(value: {batch: number; result: number; }): void { - this.selectionChange.emit(value); - } -} diff --git a/src/views/htmlcontent/src/js/components/tab.component.ts b/src/views/htmlcontent/src/js/components/tab.component.ts deleted file mode 100644 index 69f5397c54..0000000000 --- a/src/views/htmlcontent/src/js/components/tab.component.ts +++ /dev/null @@ -1,71 +0,0 @@ -/* -------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - * ------------------------------------------------------------------------------------------ */ -import { Component, Input, ElementRef, forwardRef, Inject, EventEmitter, OnInit, - Output } from '@angular/core'; -import { Observable } from 'rxjs/RX'; - -import { IGridIcon } from './../interfaces'; - -enum SelectedTab { - Results = 0, - Messages = 1, -} - -export class ScrollEvent { - scrollTop: number; -} - -/** - * Defines a Tab component which is the content of a tab on the page (to be used with the Tabs - * component) - */ -@Component({ - selector: 'tab', - styles: [` - .pane{ - padding: 1em; - }`], - template: ` - ` -}) -export class Tab implements OnInit { - @Input('tabTitle') title: string; - @Input() id: SelectedTab; - @Input() show: boolean; - @Input() icons: IGridIcon[]; - @Output() onScroll: EventEmitter = new EventEmitter(); - - private _active = true; - - constructor(@Inject(forwardRef(() => ElementRef)) private _el: ElementRef) { - Observable.fromEvent(this._el.nativeElement, 'scroll').subscribe((event) => { - this.onScroll.emit({ - scrollTop: this._el.nativeElement.scrollTop - }); - }); - }; - - ngOnInit(): void { - this.updateActive(); - } - - private updateActive(): void { - if (!this._active) { - this._el.nativeElement.getElementsByClassName('content')[0].className += ' hidden'; - } else { - this._el.nativeElement.getElementsByClassName('content')[0].className = - this._el.nativeElement.getElementsByClassName('content')[0].className.replace( /(?:^|\s)hidden(?!\S)/g , '' ); - } - } - - public set active(active: boolean) { - this._active = active; - this.updateActive(); - } - - public get active(): boolean { - return this._active; - } -} diff --git a/src/views/htmlcontent/src/js/components/tabs.component.ts b/src/views/htmlcontent/src/js/components/tabs.component.ts deleted file mode 100644 index fef86e924e..0000000000 --- a/src/views/htmlcontent/src/js/components/tabs.component.ts +++ /dev/null @@ -1,61 +0,0 @@ -/* -------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - * ------------------------------------------------------------------------------------------ */ -import { Component, ContentChildren, QueryList, AfterContentInit, Input, OnChanges, - SimpleChanges, Output, EventEmitter } from '@angular/core'; - -import { Tab } from './tab.component'; -import { TabFilter } from './../filters/tab.filter'; - -enum SelectedTab { - Results = 0, - Messages = 1, -} - -@Component({ - selector: 'tabs', - pipes: [TabFilter], - template: ` - - ` -}) -export class Tabs implements AfterContentInit, OnChanges { - @Input() selected: SelectedTab; - @Output() tabChange: EventEmitter = new EventEmitter(); - @ContentChildren(Tab) tabs: QueryList; - - ngOnChanges(changes: SimpleChanges): void { - if (changes['selected'] && this.tabs && this.tabs.length > 0 && typeof this.selected !== 'undefined') { - let activeTabs = this.tabs.filter((tab) => tab.id === this.selected); - this.tabs.toArray().forEach(tab => tab.active = false); - activeTabs[0].active = true; - } - } - - /** - * Called by Angular - */ - ngAfterContentInit(): void { - // get all active tabs - let activeTabs = this.tabs.filter((tab) => tab.active); - - // if there is no active tab set, activate the first - if (activeTabs.length === 0 && this.tabs.length > 0) { - this.selectTab(this.tabs.first); - } - } - - /** - * Emits a changed tab - * @param selectedTab The tab to emit in the event - */ - selectTab(selectedTab: Tab): void { - // deactivate all tabs - this.tabChange.emit(selectedTab.id); - } -} diff --git a/src/views/htmlcontent/src/js/filters/tab.filter.ts b/src/views/htmlcontent/src/js/filters/tab.filter.ts deleted file mode 100644 index 7616d05962..0000000000 --- a/src/views/htmlcontent/src/js/filters/tab.filter.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* -------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - * ------------------------------------------------------------------------------------------ */ -import { Pipe, PipeTransform } from '@angular/core'; -import { Tab } from './../components/tab.component'; - -/** - * Defines a custom pipe filter for filtering tabs that should not be shown via the show field. - * See tabs.ts for usage. - */ - -@Pipe({ - name: 'tabFilter', - pure: false -}) -export class TabFilter implements PipeTransform { - /** - * Defines the transform function called by angular. - */ - transform(items: Tab[]): any { - return items.filter(item => item.show); - } -} diff --git a/src/views/htmlcontent/src/js/interfaces.ts b/src/views/htmlcontent/src/js/interfaces.ts index 01a7e19b1e..ed539e5124 100644 --- a/src/views/htmlcontent/src/js/interfaces.ts +++ b/src/views/htmlcontent/src/js/interfaces.ts @@ -25,6 +25,11 @@ export interface IDbColumn { isHidden?: boolean; isIdentity?: boolean; isKey?: boolean; + isBytes?: boolean; + isChars?: boolean; + isSqlVariant?: boolean; + isUdt?: boolean; + dataType: string; isXml?: boolean; isJson?: boolean; isLong?: boolean; diff --git a/src/views/htmlcontent/src/js/services/data.service.ts b/src/views/htmlcontent/src/js/services/data.service.ts index d72785e6c8..023d583d7e 100644 --- a/src/views/htmlcontent/src/js/services/data.service.ts +++ b/src/views/htmlcontent/src/js/services/data.service.ts @@ -27,10 +27,15 @@ export class DataService { private _shortcuts; private _config; + /* for testing purposes only */ + public get webSocket(): WebSocket { + return this.ws; + } + constructor(@Inject(forwardRef(() => Http)) private http) { const self = this; // grab the uri from the document for requests - this.uri = encodeURI(document.getElementById('uri').innerText.trim()); + this.uri = encodeURI(document.getElementById('uri') ? document.getElementById('uri').innerText.trim() : ''); this.ws = new WebSocket(WS_URL + '?uri=' + this.uri); let observable = Observable.create( (obs: Observer) => { diff --git a/src/views/htmlcontent/src/js/testResources/mockBatch1.spec.ts b/src/views/htmlcontent/src/js/testResources/mockBatch1.spec.ts new file mode 100644 index 0000000000..9f7adb6557 --- /dev/null +++ b/src/views/htmlcontent/src/js/testResources/mockBatch1.spec.ts @@ -0,0 +1,405 @@ +import { WebSocketEvent } from './../interfaces'; + +const batch: WebSocketEvent = { + type: 'batch', + data: { + 'executionElapsed': '00:00:00.1879820', + 'executionEnd': '2016-11-10T17:39:27.9893860-08:00', + 'executionStart': '2016-11-10T17:39:27.8014040-08:00', + 'hasError': false, + 'id': 0, + 'selection': { + 'endColumn': 1, + 'endLine': 5, + 'startColumn': 0, + 'startLine': 3 + }, + 'messages': [ + { + 'time': '2016-11-10T17:39:27.9773300-08:00', + 'message': '(115 rows affected)' + } + ], + 'resultSetSummaries': [ + { + 'id': 0, + 'rowCount': 10, + 'columnInfo': [ + { + 'isBytes': false, + 'isChars': true, + 'isLong': false, + 'isSqlVariant': false, + 'isUdt': false, + 'isXml': false, + 'isJson': false, + 'columnName': 'name', + 'allowDBundefined': false, + 'baseCatalogName': undefined, + 'baseColumnName': undefined, + 'baseServerName': undefined, + 'baseTableName': undefined, + 'columnOrdinal': 0, + 'columnSize': 128, + 'isAliased': undefined, + 'isAutoIncrement': false, + 'isExpression': undefined, + 'isHidden': undefined, + 'isIdentity': false, + 'isKey': undefined, + 'isReadOnly': false, + 'isUnique': false, + 'numericPrecision': 255, + 'numericScale': 255, + 'udtAssemblyQualifiedName': undefined, + 'dataType': 'System.String, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e', + 'dataTypeName': 'nvarchar', + 'baseSchemaName': undefined + }, + { + 'isBytes': false, + 'isChars': false, + 'isLong': false, + 'isSqlVariant': false, + 'isUdt': false, + 'isXml': false, + 'isJson': false, + 'columnName': 'object_id', + 'allowDBundefined': false, + 'baseCatalogName': undefined, + 'baseColumnName': undefined, + 'baseServerName': undefined, + 'baseTableName': undefined, + 'columnOrdinal': 1, + 'columnSize': 4, + 'isAliased': undefined, + 'isAutoIncrement': false, + 'isExpression': undefined, + 'isHidden': undefined, + 'isIdentity': false, + 'isKey': undefined, + 'isReadOnly': false, + 'isUnique': false, + 'numericPrecision': 10, + 'numericScale': 255, + 'udtAssemblyQualifiedName': undefined, + 'dataType': 'System.Int32, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e', + 'dataTypeName': 'int', + 'baseSchemaName': undefined + }, + { + 'isBytes': false, + 'isChars': false, + 'isLong': false, + 'isSqlVariant': false, + 'isUdt': false, + 'isXml': false, + 'isJson': false, + 'columnName': 'principal_id', + 'allowDBundefined': true, + 'baseCatalogName': undefined, + 'baseColumnName': undefined, + 'baseServerName': undefined, + 'baseTableName': undefined, + 'columnOrdinal': 2, + 'columnSize': 4, + 'isAliased': undefined, + 'isAutoIncrement': false, + 'isExpression': undefined, + 'isHidden': undefined, + 'isIdentity': false, + 'isKey': undefined, + 'isReadOnly': false, + 'isUnique': false, + 'numericPrecision': 10, + 'numericScale': 255, + 'udtAssemblyQualifiedName': undefined, + 'dataType': 'System.Int32, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e', + 'dataTypeName': 'int', + 'baseSchemaName': undefined + }, + { + 'isBytes': false, + 'isChars': false, + 'isLong': false, + 'isSqlVariant': false, + 'isUdt': false, + 'isXml': false, + 'isJson': false, + 'columnName': 'schema_id', + 'allowDBundefined': false, + 'baseCatalogName': undefined, + 'baseColumnName': undefined, + 'baseServerName': undefined, + 'baseTableName': undefined, + 'columnOrdinal': 3, + 'columnSize': 4, + 'isAliased': undefined, + 'isAutoIncrement': false, + 'isExpression': undefined, + 'isHidden': undefined, + 'isIdentity': false, + 'isKey': undefined, + 'isReadOnly': false, + 'isUnique': false, + 'numericPrecision': 10, + 'numericScale': 255, + 'udtAssemblyQualifiedName': undefined, + 'dataType': 'System.Int32, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e', + 'dataTypeName': 'int', + 'baseSchemaName': undefined + }, + { + 'isBytes': false, + 'isChars': false, + 'isLong': false, + 'isSqlVariant': false, + 'isUdt': false, + 'isXml': false, + 'isJson': false, + 'columnName': 'parent_object_id', + 'allowDBundefined': false, + 'baseCatalogName': undefined, + 'baseColumnName': undefined, + 'baseServerName': undefined, + 'baseTableName': undefined, + 'columnOrdinal': 4, + 'columnSize': 4, + 'isAliased': undefined, + 'isAutoIncrement': false, + 'isExpression': undefined, + 'isHidden': undefined, + 'isIdentity': false, + 'isKey': undefined, + 'isReadOnly': false, + 'isUnique': false, + 'numericPrecision': 10, + 'numericScale': 255, + 'udtAssemblyQualifiedName': undefined, + 'dataType': 'System.Int32, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e', + 'dataTypeName': 'int', + 'baseSchemaName': undefined + }, + { + 'isBytes': false, + 'isChars': false, + 'isLong': false, + 'isSqlVariant': false, + 'isUdt': false, + 'isXml': false, + 'isJson': false, + 'columnName': 'type', + 'allowDBundefined': true, + 'baseCatalogName': undefined, + 'baseColumnName': undefined, + 'baseServerName': undefined, + 'baseTableName': undefined, + 'columnOrdinal': 5, + 'columnSize': 2, + 'isAliased': undefined, + 'isAutoIncrement': false, + 'isExpression': undefined, + 'isHidden': undefined, + 'isIdentity': false, + 'isKey': undefined, + 'isReadOnly': true, + 'isUnique': false, + 'numericPrecision': 255, + 'numericScale': 255, + 'udtAssemblyQualifiedName': undefined, + 'dataType': 'System.String, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e', + 'dataTypeName': 'char', + 'baseSchemaName': undefined + }, + { + 'isBytes': false, + 'isChars': true, + 'isLong': false, + 'isSqlVariant': false, + 'isUdt': false, + 'isXml': false, + 'isJson': false, + 'columnName': 'type_desc', + 'allowDBundefined': true, + 'baseCatalogName': undefined, + 'baseColumnName': undefined, + 'baseServerName': undefined, + 'baseTableName': undefined, + 'columnOrdinal': 6, + 'columnSize': 60, + 'isAliased': undefined, + 'isAutoIncrement': false, + 'isExpression': undefined, + 'isHidden': undefined, + 'isIdentity': false, + 'isKey': undefined, + 'isReadOnly': false, + 'isUnique': false, + 'numericPrecision': 255, + 'numericScale': 255, + 'udtAssemblyQualifiedName': undefined, + 'dataType': 'System.String, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e', + 'dataTypeName': 'nvarchar', + 'baseSchemaName': undefined + }, + { + 'isBytes': false, + 'isChars': false, + 'isLong': false, + 'isSqlVariant': false, + 'isUdt': false, + 'isXml': false, + 'isJson': false, + 'columnName': 'create_date', + 'allowDBundefined': false, + 'baseCatalogName': undefined, + 'baseColumnName': undefined, + 'baseServerName': undefined, + 'baseTableName': undefined, + 'columnOrdinal': 7, + 'columnSize': 8, + 'isAliased': undefined, + 'isAutoIncrement': false, + 'isExpression': undefined, + 'isHidden': undefined, + 'isIdentity': false, + 'isKey': undefined, + 'isReadOnly': false, + 'isUnique': false, + 'numericPrecision': 23, + 'numericScale': 3, + 'udtAssemblyQualifiedName': undefined, + 'dataType': 'System.DateTime, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e', + 'dataTypeName': 'datetime', + 'baseSchemaName': undefined + }, + { + 'isBytes': false, + 'isChars': false, + 'isLong': false, + 'isSqlVariant': false, + 'isUdt': false, + 'isXml': false, + 'isJson': false, + 'columnName': 'modify_date', + 'allowDBundefined': false, + 'baseCatalogName': undefined, + 'baseColumnName': undefined, + 'baseServerName': undefined, + 'baseTableName': undefined, + 'columnOrdinal': 8, + 'columnSize': 8, + 'isAliased': undefined, + 'isAutoIncrement': false, + 'isExpression': undefined, + 'isHidden': undefined, + 'isIdentity': false, + 'isKey': undefined, + 'isReadOnly': false, + 'isUnique': false, + 'numericPrecision': 23, + 'numericScale': 3, + 'udtAssemblyQualifiedName': undefined, + 'dataType': 'System.DateTime, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e', + 'dataTypeName': 'datetime', + 'baseSchemaName': undefined + }, + { + 'isBytes': false, + 'isChars': false, + 'isLong': false, + 'isSqlVariant': false, + 'isUdt': false, + 'isXml': false, + 'isJson': false, + 'columnName': 'is_ms_shipped', + 'allowDBundefined': false, + 'baseCatalogName': undefined, + 'baseColumnName': undefined, + 'baseServerName': undefined, + 'baseTableName': undefined, + 'columnOrdinal': 9, + 'columnSize': 1, + 'isAliased': undefined, + 'isAutoIncrement': false, + 'isExpression': undefined, + 'isHidden': undefined, + 'isIdentity': false, + 'isKey': undefined, + 'isReadOnly': true, + 'isUnique': false, + 'numericPrecision': 255, + 'numericScale': 255, + 'udtAssemblyQualifiedName': undefined, + 'dataType': 'System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e', + 'dataTypeName': 'bit', + 'baseSchemaName': undefined + }, + { + 'isBytes': false, + 'isChars': false, + 'isLong': false, + 'isSqlVariant': false, + 'isUdt': false, + 'isXml': false, + 'isJson': false, + 'columnName': 'is_published', + 'allowDBundefined': false, + 'baseCatalogName': undefined, + 'baseColumnName': undefined, + 'baseServerName': undefined, + 'baseTableName': undefined, + 'columnOrdinal': 10, + 'columnSize': 1, + 'isAliased': undefined, + 'isAutoIncrement': false, + 'isExpression': undefined, + 'isHidden': undefined, + 'isIdentity': false, + 'isKey': undefined, + 'isReadOnly': true, + 'isUnique': false, + 'numericPrecision': 255, + 'numericScale': 255, + 'udtAssemblyQualifiedName': undefined, + 'dataType': 'System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e', + 'dataTypeName': 'bit', + 'baseSchemaName': undefined + }, + { + 'isBytes': false, + 'isChars': false, + 'isLong': false, + 'isSqlVariant': false, + 'isUdt': false, + 'isXml': false, + 'isJson': false, + 'columnName': 'is_schema_published', + 'allowDBundefined': false, + 'baseCatalogName': undefined, + 'baseColumnName': undefined, + 'baseServerName': undefined, + 'baseTableName': undefined, + 'columnOrdinal': 11, + 'columnSize': 1, + 'isAliased': undefined, + 'isAutoIncrement': false, + 'isExpression': undefined, + 'isHidden': undefined, + 'isIdentity': false, + 'isKey': undefined, + 'isReadOnly': true, + 'isUnique': false, + 'numericPrecision': 255, + 'numericScale': 255, + 'udtAssemblyQualifiedName': undefined, + 'dataType': 'System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e', + 'dataTypeName': 'bit', + 'baseSchemaName': undefined + } + ] + } + ]} +}; + +export default batch; diff --git a/src/views/htmlcontent/src/js/utils.ts b/src/views/htmlcontent/src/js/utils.ts index e0dcf125cc..c697dc835b 100644 --- a/src/views/htmlcontent/src/js/utils.ts +++ b/src/views/htmlcontent/src/js/utils.ts @@ -3,17 +3,6 @@ const msInH = 3.6e6; const msInM = 60000; const msInS = 1000; -const shortcuts = { - '_comment': 'Short cuts must follow the format (ctrl)+(shift)+(alt)+(key)', - 'ctrl+alt+r': 'event.toggleResultPane', - 'ctrl+alt+y': 'event.toggleMessagePane', - 'ctrl+up': 'event.prevGrid', - 'ctrl+down': 'event.nextGrid', - 'ctrl+c': 'event.copySelection', - 'undefined': 'event.toggleMagnifyCurrent' -}; -const displayCodes = require('./displayCodes.json!'); - export function formatString(str: string, ...args: any[]): string { // This is based on code originally from https://github.com/Microsoft/vscode/blob/master/src/vs/nls.js // License: https://github.com/Microsoft/vscode/blob/master/LICENSE.txt @@ -74,43 +63,3 @@ export function parseNumAsTimeString(value: number): string { return tempVal > 0 ? rs + '.' + tempVal : rs; } - -/** - * determines the platform away shortcut string for an event for display purposes - * @param eventString The exact event string of the keycode you require (e.g event.toggleMessagePane) - */ -export function stringCodeFor(eventString: string): string { - // iterate through all the known shortcuts - for (let shortcut in shortcuts) { - if (shortcuts.hasOwnProperty(shortcut)) { - // if it matches the requested event - if (shortcuts[shortcut] === eventString && shortcut !== 'undefined') { - let keyString = shortcut; - let platString = window.navigator.platform; - - // find the current platform - if (platString.match(/win/i)) { - // iterate through the display replacement that are defined - for (let key in displayCodes['windows']) { - if (displayCodes['windows'].hasOwnProperty(key)) { - keyString = keyString.replace(key, displayCodes['windows'][key]); - } - } - } else if (platString.match(/linux/i)) { - for (let key in displayCodes['linux']) { - if (displayCodes['linux'].hasOwnProperty(key)) { - keyString = keyString.replace(key, displayCodes['linux'][key]); - } - } - } else if (platString.match(/mac/i)) { - for (let key in displayCodes['mac']) { - if (displayCodes['mac'].hasOwnProperty(key)) { - keyString = keyString.replace(key, displayCodes['mac'][key]); - } - } - } - return keyString; - } - } - } -} diff --git a/src/views/htmlcontent/systemjs.config.extras.js b/src/views/htmlcontent/systemjs.config.extras.js new file mode 100644 index 0000000000..027dfe58cf --- /dev/null +++ b/src/views/htmlcontent/systemjs.config.extras.js @@ -0,0 +1,11 @@ +/** + * Add barrels and stuff + * Adjust as necessary for your application needs. + */ +// (function (global) { +// System.config({ +// packages: { +// // add packages here +// } +// }); +// })(this); diff --git a/src/views/htmlcontent/systemjs.config.js b/src/views/htmlcontent/systemjs.config.js index 2a6866cd62..8abcaba570 100644 --- a/src/views/htmlcontent/systemjs.config.js +++ b/src/views/htmlcontent/systemjs.config.js @@ -3,44 +3,40 @@ * Adjust as necessary for your application needs. */ (function(global) { + var paths = { + 'npm:': 'lib/js/' + } // map tells the System loader where to look for things var map = { 'app': 'dist/js', // 'dist', - '@angular': 'lib/js/@angular', - 'rxjs': 'lib/js/rxjs', - 'json': 'lib/js/json.js', - 'angular2-slickgrid': 'lib/js/angular2-slickgrid' + '@angular': 'npm:@angular', + 'rxjs': 'npm:rxjs', + 'json': 'npm:json.js', + 'angular2-slickgrid': 'npm:angular2-slickgrid', + '@angular/common': 'npm:@angular/common/bundles/common.umd.js', + '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js', + '@angular/core': 'npm:@angular/core/bundles/core.umd.js', + '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js', + '@angular/http': 'npm:@angular/http/bundles/http.umd.js', + '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js', + '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js', + '@angular/router': 'npm:@angular/router/bundles/router.umd.js', + '@angular/upgrade': 'npm:@angular/upgrade/bundles/upgrade.umd.js', + 'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js' }; // packages tells the System loader how to load when no filename and/or no extension var packages = { 'app': { main: 'main.js', defaultExtension: 'js' }, '': { main: 'constants.js', defaultExtension: 'js'}, - 'rxjs': { main: 'Rx.js', defaultExtension: 'js' }, - 'angular2-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' }, 'angular2-slickgrid': { main: 'index.js', defaultExtension: 'js'} }; - var ngPackageNames = [ - '@angular/common', - '@angular/compiler', - '@angular/core', - '@angular/forms', - '@angular/http', - '@angular/platform-browser', - '@angular/platform-browser-dynamic', - '@angular/router', - '@angular/testing', - '@angular/upgrade' - ]; var meta = { '**/*.json' : { loader: 'json' } } - // add package entries for angular packages in the form '@angular/common': { main: 'index.js', defaultExtension: 'js' } - ngPackageNames.forEach(function(pkgName) { - packages[pkgName] = { main: 'index.js', defaultExtension: 'js' }; - }); var config = { + paths: paths, map: map, packages: packages, meta: meta diff --git a/src/views/htmlcontent/tsconfig.json b/src/views/htmlcontent/tsconfig.json index 8fe3338205..f42959953d 100644 --- a/src/views/htmlcontent/tsconfig.json +++ b/src/views/htmlcontent/tsconfig.json @@ -4,6 +4,7 @@ "experimentalDecorators": true, "module": "commonjs", "sourceMap": true, + "rootDir": ".", "target": "es6" } } diff --git a/src/views/htmlcontent/typings/jasmine/README.md b/src/views/htmlcontent/typings/jasmine/README.md new file mode 100644 index 0000000000..ea5e6e501d --- /dev/null +++ b/src/views/htmlcontent/typings/jasmine/README.md @@ -0,0 +1,18 @@ +# Installation +> `npm install --save @types/jasmine` + +# Summary +This package contains type definitions for Jasmine 2.5 (http://jasmine.github.io/). + +# Details +Files were exported from https://www.github.com/DefinitelyTyped/DefinitelyTyped/tree/types-2.0/jasmine + +Additional Details + * Last updated: Tue, 01 Nov 2016 12:57:25 GMT + * File structure: Global + * Library Dependencies: none + * Module Dependencies: none + * Global values: afterAll, afterEach, beforeAll, beforeEach, describe, expect, fail, fdescribe, fit, it, jasmine, pending, runs, spyOn, waits, waitsFor, xdescribe, xit + +# Credits +These definitions were written by Boris Yankov , Theodore Brown , David Pärsson . diff --git a/src/views/htmlcontent/typings/jasmine/index.d.ts b/src/views/htmlcontent/typings/jasmine/index.d.ts new file mode 100644 index 0000000000..56b50739ab --- /dev/null +++ b/src/views/htmlcontent/typings/jasmine/index.d.ts @@ -0,0 +1,537 @@ +// Type definitions for Jasmine 2.5 +// Project: http://jasmine.github.io/ +// Definitions by: Boris Yankov , Theodore Brown , David Pärsson +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + + +// For ddescribe / iit use : https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/karma-jasmine/karma-jasmine.d.ts + +declare function describe(description: string, specDefinitions: () => void): void; +declare function fdescribe(description: string, specDefinitions: () => void): void; +declare function xdescribe(description: string, specDefinitions: () => void): void; + +declare function it(expectation: string, assertion?: (done: DoneFn) => void, timeout?: number): void; +declare function fit(expectation: string, assertion?: (done: DoneFn) => void, timeout?: number): void; +declare function xit(expectation: string, assertion?: (done: DoneFn) => void, timeout?: number): void; + +/** If you call the function pending anywhere in the spec body, no matter the expectations, the spec will be marked pending. */ +declare function pending(reason?: string): void; + +declare function beforeEach(action: (done: DoneFn) => void, timeout?: number): void; +declare function afterEach(action: (done: DoneFn) => void, timeout?: number): void; + +declare function beforeAll(action: (done: DoneFn) => void, timeout?: number): void; +declare function afterAll(action: (done: DoneFn) => void, timeout?: number): void; + +declare function expect(spy: Function): jasmine.Matchers; +declare function expect(actual: any): jasmine.Matchers; + +declare function fail(e?: any): void; +/** Action method that should be called when the async work is complete */ +interface DoneFn extends Function { + (): void; + + /** fails the spec and indicates that it has completed. If the message is an Error, Error.message is used */ + fail: (message?: Error|string) => void; +} + +declare function spyOn(object: any, method: string): jasmine.Spy; + +declare function runs(asyncMethod: Function): void; +declare function waitsFor(latchMethod: () => boolean, failureMessage?: string, timeout?: number): void; +declare function waits(timeout?: number): void; + +declare namespace jasmine { + + var clock: () => Clock; + + function any(aclass: any): Any; + function anything(): Any; + function arrayContaining(sample: any[]): ArrayContaining; + function objectContaining(sample: any): ObjectContaining; + function createSpy(name: string, originalFn?: Function): Spy; + function createSpyObj(baseName: string, methodNames: any[]): any; + function createSpyObj(baseName: string, methodNames: any[]): T; + function pp(value: any): string; + function getEnv(): Env; + function addCustomEqualityTester(equalityTester: CustomEqualityTester): void; + function addMatchers(matchers: CustomMatcherFactories): void; + function stringMatching(str: string): Any; + function stringMatching(str: RegExp): Any; + function formatErrorMsg(domain: string, usage: string) : (msg: string) => string + + interface Any { + + new (expectedClass: any): any; + + jasmineMatches(other: any): boolean; + jasmineToString(): string; + } + + // taken from TypeScript lib.core.es6.d.ts, applicable to CustomMatchers.contains() + interface ArrayLike { + length: number; + [n: number]: T; + } + + interface ArrayContaining { + new (sample: any[]): any; + + asymmetricMatch(other: any): boolean; + jasmineToString(): string; + } + + interface ObjectContaining { + new (sample: any): any; + + jasmineMatches(other: any, mismatchKeys: any[], mismatchValues: any[]): boolean; + jasmineToString(): string; + } + + interface Block { + + new (env: Env, func: SpecFunction, spec: Spec): any; + + execute(onComplete: () => void): void; + } + + interface WaitsBlock extends Block { + new (env: Env, timeout: number, spec: Spec): any; + } + + interface WaitsForBlock extends Block { + new (env: Env, timeout: number, latchFunction: SpecFunction, message: string, spec: Spec): any; + } + + interface Clock { + install(): void; + uninstall(): void; + /** Calls to any registered callback are triggered when the clock is ticked forward via the jasmine.clock().tick function, which takes a number of milliseconds. */ + tick(ms: number): void; + mockDate(date?: Date): void; + withMock(func: () => void): void; + } + + interface CustomEqualityTester { + (first: any, second: any): boolean; + } + + interface CustomMatcher { + compare(actual: T, expected: T): CustomMatcherResult; + compare(actual: any, expected: any): CustomMatcherResult; + } + + interface CustomMatcherFactory { + (util: MatchersUtil, customEqualityTesters: Array): CustomMatcher; + } + + interface CustomMatcherFactories { + [index: string]: CustomMatcherFactory; + } + + interface CustomMatcherResult { + pass: boolean; + message?: string; + } + + interface MatchersUtil { + equals(a: any, b: any, customTesters?: Array): boolean; + contains(haystack: ArrayLike | string, needle: any, customTesters?: Array): boolean; + buildFailureMessage(matcherName: string, isNot: boolean, actual: any, ...expected: Array): string; + } + + interface Env { + setTimeout: any; + clearTimeout: void; + setInterval: any; + clearInterval: void; + updateInterval: number; + + currentSpec: Spec; + + matchersClass: Matchers; + + version(): any; + versionString(): string; + nextSpecId(): number; + addReporter(reporter: Reporter): void; + execute(): void; + describe(description: string, specDefinitions: () => void): Suite; + // ddescribe(description: string, specDefinitions: () => void): Suite; Not a part of jasmine. Angular team adds these + beforeEach(beforeEachFunction: () => void): void; + beforeAll(beforeAllFunction: () => void): void; + currentRunner(): Runner; + afterEach(afterEachFunction: () => void): void; + afterAll(afterAllFunction: () => void): void; + xdescribe(desc: string, specDefinitions: () => void): XSuite; + it(description: string, func: () => void): Spec; + // iit(description: string, func: () => void): Spec; Not a part of jasmine. Angular team adds these + xit(desc: string, func: () => void): XSpec; + compareRegExps_(a: RegExp, b: RegExp, mismatchKeys: string[], mismatchValues: string[]): boolean; + compareObjects_(a: any, b: any, mismatchKeys: string[], mismatchValues: string[]): boolean; + equals_(a: any, b: any, mismatchKeys: string[], mismatchValues: string[]): boolean; + contains_(haystack: any, needle: any): boolean; + addCustomEqualityTester(equalityTester: CustomEqualityTester): void; + addMatchers(matchers: CustomMatcherFactories): void; + specFilter(spec: Spec): boolean; + throwOnExpectationFailure(value: boolean): void; + seed(seed: string | number): string | number; + provideFallbackReporter(reporter: Reporter): void; + throwingExpectationFailures(): boolean; + allowRespy(allow: boolean): void; + randomTests(): boolean; + randomizeTests(b: boolean): void; + } + + interface FakeTimer { + + new (): any; + + reset(): void; + tick(millis: number): void; + runFunctionsWithinRange(oldMillis: number, nowMillis: number): void; + scheduleFunction(timeoutKey: any, funcToCall: () => void, millis: number, recurring: boolean): void; + } + + interface HtmlReporter { + new (): any; + } + + interface HtmlSpecFilter { + new (): any; + } + + interface Result { + type: string; + } + + interface NestedResults extends Result { + description: string; + + totalCount: number; + passedCount: number; + failedCount: number; + + skipped: boolean; + + rollupCounts(result: NestedResults): void; + log(values: any): void; + getItems(): Result[]; + addResult(result: Result): void; + passed(): boolean; + } + + interface MessageResult extends Result { + values: any; + trace: Trace; + } + + interface ExpectationResult extends Result { + matcherName: string; + passed(): boolean; + expected: any; + actual: any; + message: string; + trace: Trace; + } + + interface Order { + new (options: {random: boolean, seed: string}): any; + random: boolean; + seed: string; + sort(items: T[]) : T[]; + } + + namespace errors { + class ExpectationFailed extends Error { + constructor(); + stack: any; + } + } + + interface TreeProcessor { + new (attrs: any): any; + execute: (done: Function) => void; + processTree() : any; + } + + interface Trace { + name: string; + message: string; + stack: any; + } + + interface PrettyPrinter { + + new (): any; + + format(value: any): void; + iterateObject(obj: any, fn: (property: string, isGetter: boolean) => void): void; + emitScalar(value: any): void; + emitString(value: string): void; + emitArray(array: any[]): void; + emitObject(obj: any): void; + append(value: any): void; + } + + interface StringPrettyPrinter extends PrettyPrinter { + } + + interface Queue { + + new (env: any): any; + + env: Env; + ensured: boolean[]; + blocks: Block[]; + running: boolean; + index: number; + offset: number; + abort: boolean; + + addBefore(block: Block, ensure?: boolean): void; + add(block: any, ensure?: boolean): void; + insertNext(block: any, ensure?: boolean): void; + start(onComplete?: () => void): void; + isRunning(): boolean; + next_(): void; + results(): NestedResults; + } + + interface Matchers { + + new (env: Env, actual: any, spec: Env, isNot?: boolean): any; + + env: Env; + actual: any; + spec: Env; + isNot?: boolean; + message(): any; + + toBe(expected: any, expectationFailOutput?: any): boolean; + toEqual(expected: any, expectationFailOutput?: any): boolean; + toMatch(expected: string | RegExp, expectationFailOutput?: any): boolean; + toBeDefined(expectationFailOutput?: any): boolean; + toBeUndefined(expectationFailOutput?: any): boolean; + toBeNull(expectationFailOutput?: any): boolean; + toBeNaN(): boolean; + toBeTruthy(expectationFailOutput?: any): boolean; + toBeFalsy(expectationFailOutput?: any): boolean; + toHaveBeenCalled(): boolean; + toHaveBeenCalledWith(...params: any[]): boolean; + toHaveBeenCalledTimes(expected: number): boolean; + toContain(expected: any, expectationFailOutput?: any): boolean; + toBeLessThan(expected: number, expectationFailOutput?: any): boolean; + toBeLessThanOrEqual(expected: number, expectationFailOutput?: any): boolean; + toBeGreaterThan(expected: number, expectationFailOutput?: any): boolean; + toBeGreaterThanOrEqual(expected: number, expectationFailOutput?: any): boolean; + toBeCloseTo(expected: number, precision?: any, expectationFailOutput?: any): boolean; + toThrow(expected?: any): boolean; + toThrowError(message?: string | RegExp): boolean; + toThrowError(expected?: new (...args: any[]) => Error, message?: string | RegExp): boolean; + not: Matchers; + + Any: Any; + } + + interface Reporter { + reportRunnerStarting(runner: Runner): void; + reportRunnerResults(runner: Runner): void; + reportSuiteResults(suite: Suite): void; + reportSpecStarting(spec: Spec): void; + reportSpecResults(spec: Spec): void; + log(str: string): void; + } + + interface MultiReporter extends Reporter { + addReporter(reporter: Reporter): void; + } + + interface Runner { + + new (env: Env): any; + + execute(): void; + beforeEach(beforeEachFunction: SpecFunction): void; + afterEach(afterEachFunction: SpecFunction): void; + beforeAll(beforeAllFunction: SpecFunction): void; + afterAll(afterAllFunction: SpecFunction): void; + finishCallback(): void; + addSuite(suite: Suite): void; + add(block: Block): void; + specs(): Spec[]; + suites(): Suite[]; + topLevelSuites(): Suite[]; + results(): NestedResults; + } + + interface SpecFunction { + (spec?: Spec): void; + } + + interface SuiteOrSpec { + id: number; + env: Env; + description: string; + queue: Queue; + } + + interface Spec extends SuiteOrSpec { + + new (env: Env, suite: Suite, description: string): any; + + suite: Suite; + + afterCallbacks: SpecFunction[]; + spies_: Spy[]; + + results_: NestedResults; + matchersClass: Matchers; + + getFullName(): string; + results(): NestedResults; + log(arguments: any): any; + runs(func: SpecFunction): Spec; + addToQueue(block: Block): void; + addMatcherResult(result: Result): void; + getResult(): any; + expect(actual: any): any; + waits(timeout: number): Spec; + waitsFor(latchFunction: SpecFunction, timeoutMessage?: string, timeout?: number): Spec; + fail(e?: any): void; + getMatchersClass_(): Matchers; + addMatchers(matchersPrototype: CustomMatcherFactories): void; + finishCallback(): void; + finish(onComplete?: () => void): void; + after(doAfter: SpecFunction): void; + execute(onComplete?: () => void, enabled?: boolean): any; + addBeforesAndAftersToQueue(): void; + explodes(): void; + spyOn(obj: any, methodName: string, ignoreMethodDoesntExist: boolean): Spy; + removeAllSpies(): void; + throwOnExpectationFailure: boolean; + } + + interface XSpec { + id: number; + runs(): void; + } + + interface Suite extends SuiteOrSpec { + + new (env: Env, description: string, specDefinitions: () => void, parentSuite: Suite): any; + + parentSuite: Suite; + + getFullName(): string; + finish(onComplete?: () => void): void; + beforeEach(beforeEachFunction: SpecFunction): void; + afterEach(afterEachFunction: SpecFunction): void; + beforeAll(beforeAllFunction: SpecFunction): void; + afterAll(afterAllFunction: SpecFunction): void; + results(): NestedResults; + add(suiteOrSpec: SuiteOrSpec): void; + specs(): Spec[]; + suites(): Suite[]; + children(): any[]; + execute(onComplete?: () => void): void; + } + + interface XSuite { + execute(): void; + } + + interface Spy { + (...params: any[]): any; + + identity: string; + and: SpyAnd; + calls: Calls; + mostRecentCall: { args: any[]; }; + argsForCall: any[]; + wasCalled: boolean; + } + + interface SpyAnd { + /** By chaining the spy with and.callThrough, the spy will still track all calls to it but in addition it will delegate to the actual implementation. */ + callThrough(): Spy; + /** By chaining the spy with and.returnValue, all calls to the function will return a specific value. */ + returnValue(val: any): Spy; + /** By chaining the spy with and.returnValues, all calls to the function will return specific values in order until it reaches the end of the return values list. */ + returnValues(...values: any[]): Spy; + /** By chaining the spy with and.callFake, all calls to the spy will delegate to the supplied function. */ + callFake(fn: Function): Spy; + /** By chaining the spy with and.throwError, all calls to the spy will throw the specified value. */ + throwError(msg: string): Spy; + /** When a calling strategy is used for a spy, the original stubbing behavior can be returned at any time with and.stub. */ + stub(): Spy; + } + + interface Calls { + /** By chaining the spy with calls.any(), will return false if the spy has not been called at all, and then true once at least one call happens. **/ + any(): boolean; + /** By chaining the spy with calls.count(), will return the number of times the spy was called **/ + count(): number; + /** By chaining the spy with calls.argsFor(), will return the arguments passed to call number index **/ + argsFor(index: number): any[]; + /** By chaining the spy with calls.allArgs(), will return the arguments to all calls **/ + allArgs(): any[]; + /** By chaining the spy with calls.all(), will return the context (the this) and arguments passed all calls **/ + all(): CallInfo[]; + /** By chaining the spy with calls.mostRecent(), will return the context (the this) and arguments for the most recent call **/ + mostRecent(): CallInfo; + /** By chaining the spy with calls.first(), will return the context (the this) and arguments for the first call **/ + first(): CallInfo; + /** By chaining the spy with calls.reset(), will clears all tracking for a spy **/ + reset(): void; + } + + interface CallInfo { + /** The context (the this) for the call */ + object: any; + /** All arguments passed to the call */ + args: any[]; + /** The return value of the call */ + returnValue: any; + } + + interface Util { + inherit(childClass: Function, parentClass: Function): any; + formatException(e: any): any; + htmlEscape(str: string): string; + argsToArray(args: any): any; + extend(destination: any, source: any): any; + } + + interface JsApiReporter extends Reporter { + + started: boolean; + finished: boolean; + result: any; + messages: any; + runDetails: { + failedExpectations: ExpectationResult[]; + order: jasmine.Order + } + + new (): any; + + suites(): Suite[]; + summarize_(suiteOrSpec: SuiteOrSpec): any; + results(): any; + resultsForSpec(specId: any): any; + log(str: any): any; + resultsForSpecs(specIds: any): any; + summarizeResult_(result: any): any; + } + + interface Jasmine { + Spec: Spec; + clock: Clock; + util: Util; + } + + export var HtmlReporter: HtmlReporter; + export var HtmlSpecFilter: HtmlSpecFilter; + export var DEFAULT_TIMEOUT_INTERVAL: number; +} diff --git a/src/views/htmlcontent/typings/jasmine/package.json b/src/views/htmlcontent/typings/jasmine/package.json new file mode 100644 index 0000000000..df6bca3bd6 --- /dev/null +++ b/src/views/htmlcontent/typings/jasmine/package.json @@ -0,0 +1,79 @@ +{ + "_args": [ + [ + { + "raw": "@types/jasmine@^2.5.36", + "scope": "@types", + "escapedName": "@types%2fjasmine", + "name": "@types/jasmine", + "rawSpec": "^2.5.36", + "spec": ">=2.5.36 <3.0.0", + "type": "range" + }, + "/Users/anthonydresser/Documents/vscode-mssql/src/views/htmlcontent" + ] + ], + "_from": "@types/jasmine@>=2.5.36 <3.0.0", + "_id": "@types/jasmine@2.5.37", + "_inCache": true, + "_installable": true, + "_location": "/@types/jasmine", + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/jasmine-2.5.37.tgz_1478005079042_0.7982070264406502" + }, + "_npmUser": { + "name": "types", + "email": "ts-npm-types@microsoft.com" + }, + "_phantomChildren": {}, + "_requested": { + "raw": "@types/jasmine@^2.5.36", + "scope": "@types", + "escapedName": "@types%2fjasmine", + "name": "@types/jasmine", + "rawSpec": "^2.5.36", + "spec": ">=2.5.36 <3.0.0", + "type": "range" + }, + "_requiredBy": [ + "/" + ], + "_resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.5.37.tgz", + "_shasum": "15f16040b1106941ec4aeefa3cd9c55342a0dcbb", + "_shrinkwrap": null, + "_spec": "@types/jasmine@^2.5.36", + "_where": "/Users/anthonydresser/Documents/vscode-mssql/src/views/htmlcontent", + "author": { + "name": "Boris Yankov", + "email": "https://github.com/borisyankov/" + }, + "dependencies": {}, + "description": "TypeScript definitions for Jasmine 2.5", + "devDependencies": {}, + "directories": {}, + "dist": { + "shasum": "15f16040b1106941ec4aeefa3cd9c55342a0dcbb", + "tarball": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.5.37.tgz" + }, + "license": "MIT", + "main": "", + "maintainers": [ + { + "name": "types", + "email": "ryan.cavanaugh@microsoft.com" + } + ], + "name": "@types/jasmine", + "optionalDependencies": {}, + "peerDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "https://www.github.com/DefinitelyTyped/DefinitelyTyped.git" + }, + "scripts": {}, + "typesPublisherContentHash": "342ad787ae1d9085f9cb2f352460449c601a7fbda833a19bb87aa2787dbc9ec3", + "typings": "index.d.ts", + "version": "2.5.37" +} diff --git a/src/views/htmlcontent/typings/jasmine/types-metadata.json b/src/views/htmlcontent/typings/jasmine/types-metadata.json new file mode 100644 index 0000000000..8c99580636 --- /dev/null +++ b/src/views/htmlcontent/typings/jasmine/types-metadata.json @@ -0,0 +1,40 @@ +{ + "authors": "Boris Yankov , Theodore Brown , David Pärsson ", + "definitionFilename": "index.d.ts", + "libraryDependencies": [], + "moduleDependencies": [], + "libraryMajorVersion": "2", + "libraryMinorVersion": "5", + "libraryName": "Jasmine 2.5", + "typingsPackageName": "jasmine", + "projectName": "http://jasmine.github.io/", + "sourceRepoURL": "https://www.github.com/DefinitelyTyped/DefinitelyTyped", + "sourceBranch": "types-2.0", + "kind": "Global", + "globals": [ + "afterAll", + "afterEach", + "beforeAll", + "beforeEach", + "describe", + "expect", + "fail", + "fdescribe", + "fit", + "it", + "jasmine", + "pending", + "runs", + "spyOn", + "waits", + "waitsFor", + "xdescribe", + "xit" + ], + "declaredModules": [], + "files": [ + "index.d.ts" + ], + "hasPackageJson": false, + "contentHash": "342ad787ae1d9085f9cb2f352460449c601a7fbda833a19bb87aa2787dbc9ec3" +} \ No newline at end of file diff --git a/tasks/covertasks.js b/tasks/covertasks.js index 0e89d5de51..667f74b9e0 100644 --- a/tasks/covertasks.js +++ b/tasks/covertasks.js @@ -1,6 +1,8 @@ var gulp = require('gulp'); var del = require('del'); var jeditor = require("gulp-json-editor"); +var istanbulReport = require('gulp-istanbul-report'); +var cproc = require('child_process'); gulp.task('cover:clean', function (done) { return del('coverage', done); @@ -15,7 +17,7 @@ gulp.task('cover:enableconfig',() => { .pipe(gulp.dest("./out", {'overwrite':true})); }); -gulp.task('cover:enable', gulp.series('cover:clean', 'cover:enableconfig')); +gulp.task('cover:enable', gulp.series('cover:clean', 'html:test', 'cover:enableconfig')); gulp.task('cover:disable', () => { return gulp.src("./coverconfig.json") @@ -24,4 +26,20 @@ gulp.task('cover:disable', () => { return json; // must return JSON object. })) .pipe(gulp.dest("./out", {'overwrite':true})); -}); \ No newline at end of file +}); + +gulp.task('cover:combine', () => { + return gulp.src(['./coverage/coverage-final.json', './coverage/coverage-html.json']) + .pipe(istanbulReport({ + reporterOpts: { + dir: './coverage' + }, + reporters: [ + {'name': 'lcov'}, // -> ./coverage/report.txt + {'name': 'cobertura'} // -> ./jsonCov/cov.json + ] + })); +}); + +// for running on the jenkins build system +gulp.task('cover:jenkins', gulp.series('cover:clean', 'html:test', 'cover:enableconfig', 'ext:test', 'cover:combine')); \ No newline at end of file diff --git a/tasks/htmltasks.js b/tasks/htmltasks.js index 98745afe17..4d9135a865 100644 --- a/tasks/htmltasks.js +++ b/tasks/htmltasks.js @@ -1,3 +1,4 @@ +'use strict'; var gulp = require('gulp'); var tslint = require('gulp-tslint'); var ts = require('gulp-typescript'); @@ -10,6 +11,10 @@ var minifier = require('gulp-uglify/minifier'); var tsProject = ts.createProject(config.paths.html.root + '/tsconfig.json'); var sysBuilder = require('systemjs-builder'); var cleanCSS = require('gulp-clean-css'); +var argv = require('yargs').argv; +var Server = require('karma').Server; + +var min = (argv.min === undefined) ? false : true; gulp.task('html:lint', () => { return gulp.src([ @@ -22,38 +27,47 @@ gulp.task('html:lint', () => { }); // Compile TypeScript to JS -gulp.task('html:compile-src', function () { +gulp.task('html:compile-src', () => { return gulp .src([config.paths.html.root + '/src/js/**/*.ts', config.paths.html.root + '/typings/**/*']) .pipe(srcmap.init()) .pipe(ts(tsProject)) - .pipe(srcmap.write('.')) + .pipe(srcmap.write('.', { + sourceRoot: function(file){ return file.cwd + '/src/views/htmlcontent'; } + })) .pipe(gulp.dest(config.paths.html.out + '/dist/js')); }); // Generate systemjs-based builds -gulp.task('html:bundle:app', function() { - var builder = new sysBuilder('./out/src/views/htmlcontent', './src/views/htmlcontent/systemjs.config.js'); - return builder.buildStatic('app', './out/src/views/htmlcontent/dist/js/app.min.js') - .then(function () { - return del(['./out/src/views/htmlcontent/dist/js/**/*', '!' + './out/src/views/htmlcontent/dist/js/app.min.js']); - }) - .catch(function(err) { - console.error('>>> [systemjs-builder] Bundling failed'.bold.green, err); - }); +gulp.task('html:bundle:app', (done) => { + if (min) { + var builder = new sysBuilder('./out/src/views/htmlcontent', './src/views/htmlcontent/systemjs.config.js'); + return builder.buildStatic('app', './out/src/views/htmlcontent/dist/js/app.min.js') + .then(function () { + return del(['./out/src/views/htmlcontent/dist/js/**/*', '!' + './out/src/views/htmlcontent/dist/js/app.min.js']); + }) + .catch(function(err) { + console.error('>>> [systemjs-builder] Bundling failed'.bold.green, err); + }); + } else { + done(); + } }); -gulp.task('html:min-js', function() { - return gulp.src(config.paths.html.out + '/dist/js/app.min.js') - .pipe(minifier({mangle: false}, uglifyjs)) - .pipe(gulp.dest(config.paths.html.out + '/dist/js')) -}) +gulp.task('html:min-js', (done) => { + if (min) { + return gulp.src(config.paths.html.out + '/dist/js/app.min.js') + .pipe(minifier({mangle: false}, uglifyjs)) + .pipe(gulp.dest(config.paths.html.out + '/dist/js')); + } else { + done(); + } +}); gulp.task('html:bundle:css', () => { return new Promise((resolve, reject) => { gulp.src([config.paths.html.out + '/dist/css/flexbox.css', - // config.paths.html.out + '/lib/css/bootstrap.min.css', config.paths.html.out + '/dist/css/styles.css']) .pipe(cleanCSS()) .pipe(concat('styles.min.css')) @@ -61,100 +75,157 @@ gulp.task('html:bundle:css', () => { .on('end', resolve); }).then(() => { return del([config.paths.html.out + '/dist/css/flexbox.css', - // config.paths.html.out + '/lib/css/bootstrap.min.css', config.paths.html.out + '/dist/css/styles.css']); - }) -}) + }); +}); // Copy and bundle dependencies into one file (vendor/vendors.js) // system.config.js can also bundled for convenience -gulp.task('html:vendor', () => { +gulp.task('html:vendor', (done) => { gulp.src([config.paths.html.root + '/node_modules/rxjs/**/*']) .pipe(gulp.dest(config.paths.html.out + '/lib/js/rxjs')); - gulp.src([config.paths.html.root + '/src/js/libs/slickgrid/*']) - .pipe(gulp.dest(config.paths.html.out + '/lib/js/slickgrid')) - - gulp.src([config.paths.html.root + '/node_modules/angular2-in-memory-web-api/**/*']) - .pipe(gulp.dest(config.paths.html.out + '/lib/js/angular2-in-memory-web-api')); - - // concatenate non-angular2 libs, shims & systemjs-config - gulp.src([ - config.paths.html.root + '/node_modules/angular2-slickgrid/libs/SlickGrid/lib/jquery-1.7.min.js', - config.paths.html.root + '/node_modules/angular2-slickgrid/libs/SlickGrid/lib/jquery.event.drag-2.2.js', - config.paths.html.root + '/node_modules/angular2-slickgrid/libs/SlickGrid/lib/jquery-ui-1.8.16.custom.min.js', - config.paths.html.root + '/node_modules/underscore/underscore-min.js', - config.paths.html.root + '/node_modules/angular2-slickgrid/libs/SlickGrid/slick.core.js', - config.paths.html.root + '/node_modules/angular2-slickgrid/libs/SlickGrid/slick.grid.js', - config.paths.html.root + '/node_modules/angular2-slickgrid/libs/SlickGrid/slick.editors.js', - config.paths.html.root + '/node_modules/angular2-slickgrid/libs/SlickGrid/plugins/slick.dragrowselector.js', - config.paths.html.root + '/node_modules/angular2-slickgrid/libs/SlickGrid/plugins/slick.autosizecolumn.js', - config.paths.html.root + '/node_modules/core-js/client/shim.min.js', - config.paths.html.root + '/node_modules/zone.js/dist/zone.js', - config.paths.html.root + '/node_modules/reflect-metadata/Reflect.js', - config.paths.html.root + '/node_modules/systemjs/dist/system.src.js', - config.paths.html.root + '/systemjs.config.js' - ]) - .pipe(concat('vendors.min.js')) - .pipe(minifier({}, uglifyjs)) - .pipe(gulp.dest(config.paths.html.out + '/lib/js')); - - // copy source maps - gulp.src([ - // config.paths.html.root + '/node_modules/es6-shim/es6-shim.map', - config.paths.html.root + '/node_modules/reflect-metadata/Reflect.js.map', - config.paths.html.root + '/node_modules/systemjs/dist/system-polyfills.js.map', - config.paths.html.root + '/node_modules/systemjs-plugin-json/json.js' - ]).pipe(gulp.dest(config.paths.html.out + '/lib/js')); - - gulp.src([ - config.paths.html.root + '/node_modules/bootstrap/dist/css/bootstrap.*', - config.paths.html.root + '/node_modules/angular2-slickgrid/components/css/SlickGrid.css', - config.paths.html.root + '/node_modules/angular2-slickgrid/libs/SlickGrid/slick.grid.css' - ]).pipe(gulp.dest(config.paths.html.out + '/lib/css')); - - gulp.src([ - config.paths.html.root + '/node_modules/angular2-slickgrid/index.js', - config.paths.html.root + '/node_modules/angular2-slickgrid/components/**/*.js' - ], { base: config.paths.html.root + '/node_modules/angular2-slickgrid' }).pipe(gulp.dest(config.paths.html.out + '/lib/js/angular2-slickgrid')) - - return gulp.src([config.paths.html.root + '/node_modules/@angular/**/*']) - .pipe(gulp.dest(config.paths.html.out + '/lib/js/@angular')); -}); + gulp.src([config.paths.html.root + '/node_modules/angular-in-memory-web-api/**/*']) + .pipe(gulp.dest(config.paths.html.out + '/lib/js/angular-in-memory-web-api')); + + // concatenate non-angular2 libs, shims & systemjs-config + if (min) { + gulp.src([ + config.paths.html.root + '/node_modules/angular2-slickgrid/libs/SlickGrid/lib/jquery-1.7.min.js', + config.paths.html.root + '/node_modules/angular2-slickgrid/libs/SlickGrid/lib/jquery.event.drag-2.2.js', + config.paths.html.root + '/node_modules/angular2-slickgrid/libs/SlickGrid/lib/jquery-ui-1.8.16.custom.min.js', + config.paths.html.root + '/node_modules/underscore/underscore-min.js', + config.paths.html.root + '/node_modules/angular2-slickgrid/libs/SlickGrid/slick.core.js', + config.paths.html.root + '/node_modules/angular2-slickgrid/libs/SlickGrid/slick.grid.js', + config.paths.html.root + '/node_modules/angular2-slickgrid/libs/SlickGrid/slick.editors.js', + config.paths.html.root + '/node_modules/angular2-slickgrid/libs/SlickGrid/plugins/slick.dragrowselector.js', + config.paths.html.root + '/node_modules/angular2-slickgrid/libs/SlickGrid/plugins/slick.autosizecolumn.js', + config.paths.html.root + '/node_modules/core-js/client/shim.min.js', + config.paths.html.root + '/node_modules/zone.js/dist/zone.js', + config.paths.html.root + '/node_modules/reflect-metadata/Reflect.js', + config.paths.html.root + '/node_modules/systemjs/dist/system.src.js', + config.paths.html.root + '/systemjs.config.js' + ]) + .pipe(concat('vendors.min.js')) + .pipe(minifier({}, uglifyjs)) + .pipe(gulp.dest(config.paths.html.out + '/lib/js')); + } else { + gulp.src([ + config.paths.html.root + '/node_modules/angular2-slickgrid/libs/SlickGrid/lib/jquery-1.7.min.js', + config.paths.html.root + '/node_modules/angular2-slickgrid/libs/SlickGrid/lib/jquery.event.drag-2.2.js', + config.paths.html.root + '/node_modules/angular2-slickgrid/libs/SlickGrid/lib/jquery-ui-1.8.16.custom.min.js', + config.paths.html.root + '/node_modules/underscore/underscore-min.js', + config.paths.html.root + '/node_modules/angular2-slickgrid/libs/SlickGrid/slick.core.js', + config.paths.html.root + '/node_modules/angular2-slickgrid/libs/SlickGrid/slick.grid.js', + config.paths.html.root + '/node_modules/angular2-slickgrid/libs/SlickGrid/slick.editors.js', + config.paths.html.root + '/node_modules/angular2-slickgrid/libs/SlickGrid/plugins/slick.dragrowselector.js', + config.paths.html.root + '/node_modules/angular2-slickgrid/libs/SlickGrid/plugins/slick.autosizecolumn.js', + config.paths.html.root + '/node_modules/core-js/client/shim.min.js', + config.paths.html.root + '/node_modules/reflect-metadata/Reflect.js', + config.paths.html.root + '/node_modules/systemjs/dist/system.src.js', + config.paths.html.root + '/systemjs.config.extras.js', + config.paths.html.root + '/systemjs.config.js' + ]) + .pipe(gulp.dest(config.paths.html.out + '/lib/js')); + + gulp.src([config.paths.html.root + '/node_modules/zone.js/**/*']) + .pipe(gulp.dest(config.paths.html.out + '/lib/js/zone.js')); + } -gulp.task('html:copy:assets', () => { + + // copy source maps gulp.src([ - config.paths.html.root + '/src/html/*' - ]) - .pipe(gulp.dest(config.paths.html.out + '/dist/html')); + // config.paths.html.root + '/node_modules/es6-shim/es6-shim.map', + config.paths.html.root + '/node_modules/reflect-metadata/Reflect.js.map', + config.paths.html.root + '/node_modules/systemjs/dist/system-polyfills.js.map', + config.paths.html.root + '/node_modules/systemjs-plugin-json/json.js' + ]).pipe(gulp.dest(config.paths.html.out + '/lib/js')); gulp.src([ - config.paths.html.root + '/src/css/**/*' - ]) - .pipe(gulp.dest(config.paths.html.out + '/dist/css')); + config.paths.html.root + '/node_modules/angular2-slickgrid/components/css/SlickGrid.css', + config.paths.html.root + '/node_modules/angular2-slickgrid/libs/SlickGrid/slick.grid.css' + ]).pipe(gulp.dest(config.paths.html.out + '/lib/css')); gulp.src([ - config.paths.html.root + '/src/images/*' - ]) - .pipe(gulp.dest(config.paths.html.out + '/dist/images')) + config.paths.html.root + '/node_modules/angular2-slickgrid/index.js', + config.paths.html.root + '/node_modules/angular2-slickgrid/components/**/*.js' + ], { base: config.paths.html.root + '/node_modules/angular2-slickgrid' }).pipe(gulp.dest(config.paths.html.out + '/lib/js/angular2-slickgrid')); - return gulp.src([ - config.paths.html.root + '/src/js/**/*.json', - ]) - .pipe(gulp.dest(config.paths.html.out + '/dist/js')); + return gulp.src([config.paths.html.root + '/node_modules/@angular/**/*']) + .pipe(gulp.dest(config.paths.html.out + '/lib/js/@angular')); +}); + +gulp.task('html:copy:assets', (done) => { + let promises = []; + promises.push(new Promise((resolve) => { + gulp.src([ + config.paths.html.root + '/src/html/*' + ]) + .pipe(gulp.dest(config.paths.html.out + '/dist/html')) + .on('end', () => { + resolve(); + }) + }) + ); + + promises.push(new Promise((resolve) => { + gulp.src([ + config.paths.html.root + '/src/css/**/*' + ]) + .pipe(gulp.dest(config.paths.html.out + '/dist/css')) + .on('end', () => { + resolve(); + }) + }) + ); + + promises.push(new Promise((resolve) => { + gulp.src([ + config.paths.html.root + '/src/images/*' + ]) + .pipe(gulp.dest(config.paths.html.out + '/dist/images')) + .on('end', () => { + resolve(); + }) + }) + ); + + promises.push(new Promise((resolve) => { + gulp.src([ + config.paths.html.root + '/src/js/**/*.json', + ]) + .pipe(gulp.dest(config.paths.html.out + '/dist/js')) + .on('end', () => { + resolve(); + }) + }) + ); + + Promise.all(promises).then(() => done()); +}); + +gulp.task('html:test', function (done) { + new Server({ + configFile: __dirname + '/../karma.conf.js', + singleRun: true + }, done).start(); }); gulp.task('html:compile', gulp.series('html:compile-src')) gulp.task('html:app', gulp.series(['html:compile', 'html:copy:assets', 'html:bundle:app', 'html:min-js', 'html:bundle:css'])); -gulp.task('html:bundle', () => { - return gulp.src([ - config.paths.html.out + '/lib/js/vendors.min.js', - config.paths.html.out + '/dist/js/app.min.js' - ]) - .pipe(concat('app.bundle.js')) - .pipe(gulp.dest(config.paths.html.out + '/dist/js')); +gulp.task('html:bundle', (done) => { + if (min) { + return gulp.src([ + config.paths.html.out + '/lib/js/vendors.min.js', + config.paths.html.out + '/dist/js/app.min.js' + ]) + .pipe(concat('app.bundle.js')) + .pipe(gulp.dest(config.paths.html.out + '/dist/js')); + } else { + done(); + } }); gulp.task('html:build', gulp.series('html:lint', 'html:vendor', 'html:app', 'html:bundle'));