From 9e8b4ed3fecbf5631a3b74ee1fa94eaa8239394c Mon Sep 17 00:00:00 2001 From: Bradley Maier Date: Mon, 9 Jan 2017 01:33:04 -0500 Subject: [PATCH 01/21] Add initial code - need to update tests --- .gitignore | 13 ++ .travis.yml | 20 +++ Gruntfile.js | 34 +++++ LICENSE | 28 ++++ codecov.yml | 4 + package.json | 52 +++++++ src/dirname.ts | 1 + src/intern/intern-local.js | 15 +++ src/intern/intern-saucelabs.js | 30 +++++ src/intern/intern.js | 75 +++++++++++ src/main.ts | 64 +++++++++ src/runTests.ts | 49 +++++++ tests/intern.ts | 47 +++++++ tests/support/MockModule.ts | 83 ++++++++++++ tests/support/Reporter.ts | 238 +++++++++++++++++++++++++++++++++ tests/support/util.ts | 18 +++ tests/unit/all.ts | 1 + tests/unit/main.ts | 96 +++++++++++++ tsconfig.json | 20 +++ tslint.json | 69 ++++++++++ typings.json | 12 ++ 21 files changed, 969 insertions(+) create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 Gruntfile.js create mode 100644 LICENSE create mode 100644 codecov.yml create mode 100644 package.json create mode 100644 src/dirname.ts create mode 100644 src/intern/intern-local.js create mode 100644 src/intern/intern-saucelabs.js create mode 100644 src/intern/intern.js create mode 100644 src/main.ts create mode 100644 src/runTests.ts create mode 100644 tests/intern.ts create mode 100644 tests/support/MockModule.ts create mode 100644 tests/support/Reporter.ts create mode 100644 tests/support/util.ts create mode 100644 tests/unit/all.ts create mode 100644 tests/unit/main.ts create mode 100644 tsconfig.json create mode 100644 tslint.json create mode 100644 typings.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bd0a505 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +*.js.map +!/*.js +!/tasks/*.js +/_build +/bower_components +/dist +/html-report +/node_modules +/typings +.baseDir.ts +.tscache +coverage-unmapped.json +npm-debug.log diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..23bf167 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,20 @@ +sudo: false +language: node_js +node_js: +- '6' +env: + global: + - SAUCE_USERNAME: dojo2-ts-ci + - SAUCE_ACCESS_KEY: e92610e3-834e-4bec-a3b5-6f7b9d874601 +install: +- travis_retry npm install grunt cli +- travis_retry npm install +script: +- grunt +- grunt intern:node --combined +- grunt remapIstanbul:ci +- grunt uploadCoverage +notifications: + slack: + secure: O9m3cCkl3H8VXRIuKLFfx91C01n9yLlehem9K3snnBMiyrtGWR2aXo+t1eeZYGfFWIl8UBEaSPlDurI1KspIcW/JbszuYAVje21rbl+ptkp008f5gDVfFCFpqdM9S5+lrVJLlx1mrikWKBRsjYqZHYV9EJx/ss+P86JsQ0utC7zgBFYId+UCMybAemzi1FPfeULFWpoi8QavoN8fNr4yHBayrqOlqnnIhlYLoTiGL6yY8L/meUrmWVxSY3JMDxLeIYNppt4puvTGUD1hU2LZgFZp1y6jGMcAlZI5amGV+iyTl/h2w1wiB6q5tolJ1JslosFvh53y7+1Crbm8wQDkX42+z7Rn3/jXRUBFwLZBGZQ99FcE0Yz+XBaQA3GuCgPNd0rcHmJxeYAKMm7jg2B8Nzd6It3q5mjdp9ITA5kR2G7g+iH8R4y112FXCpvt4/RUvHuyhl7w8lFlHK+LslH3DBjDi3fKUuwiGtU8oD3xpCunJ4JUgQmAWIOy3mpFIOX4QPcBKqByp10fNw3G73JDsJ9DXrFGb/+WnA2OgpDnKOnjoporwufRZLeioRwCJAWM0DbFDvRc1mbnECwcKiedzKdTxSWUGyJ6sxKydZtC11tF356BkzIsf3x7cKSed2LI8VXYNiPOJu9P+/s5/jRf/7kZ+i2ETfuKZC2awhgkBGo= + on_success: change diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 0000000..87b9f4f --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,34 @@ +module.exports = function (grunt) { + var staticFiles = [ 'intern/**' ]; + require('grunt-dojo2').initConfig(grunt, { + ts: { + dist: { + exclude: [ + './src/intern', + "./tests/**/*.ts" + ] + } + }, + copy: { + staticDistFiles: { + expand: true, + cwd: 'src', + src: staticFiles, + dest: '<%= distDirectory %>' + }, + staticDevFiles: { + expand: true, + cwd: 'src', + src: staticFiles, + dest: '<%= devDirectory %>/src' + } + } + }); + + grunt.registerTask('ci', [ + 'intern:node' + ]); + + grunt.registerTask('dist', grunt.config.get('distTasks').concat(['copy:staticDistFiles'])); + grunt.registerTask('dev', grunt.config.get('devTasks').concat(['copy:staticDevFiles'])); +}; diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..08f88a1 --- /dev/null +++ b/LICENSE @@ -0,0 +1,28 @@ +The "New" BSD License +********************* + +Copyright (c) 2015 - 2016, The Dojo Foundation +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the Dojo Foundation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000..97e007a --- /dev/null +++ b/codecov.yml @@ -0,0 +1,4 @@ +comment: + branches: + - master + - feature/* diff --git a/package.json b/package.json new file mode 100644 index 0000000..fc206fc --- /dev/null +++ b/package.json @@ -0,0 +1,52 @@ +{ + "name": "dojo-cli-test-intern", + "version": "2.0.0-pre", + "description": "build a dojo 2 application", + "private": true, + "homepage": "http://dojotoolkit.org", + "bugs": { + "url": "https://github.com/maier49/cli-test-intern/issues" + }, + "license": "BSD-3-Clause", + "main": "main.js", + "repository": { + "type": "git", + "url": "https://github.com/maier49/cli-test-intern.git" + }, + "scripts": { + "test": "grunt test" + }, + "devDependencies": { + "codecov.io": "0.1.6", + "@types/node": "^6.0.49", + "@types/chalk": "^0.4.31", + "@types/ejs": "^2.3.33", + "@types/chai": "^3.4.34", + "@types/fs-extra": "0.0.34", + "@types/glob": "^5.0.30", + "@types/grunt": "~0.4.0", + "@types/mockery": "^1.4.29", + "@types/sinon": "^1.16.32", + "dojo-cli": "^2.0.0-alpha.3", + "dojo-loader": ">=2.0.0-beta.7", + "dts-generator": "~1.7.0", + "glob": "^7.0.3", + "grunt": "~1.0.1", + "grunt-tslint": "^3.0.0", + "grunt-dojo2": "^2.0.0-beta.18", + "intern": "~3.3.2", + "istanbul": "^0.4.3", + "mockery": "^1.7.0", + "remap-istanbul": "^0.6.4", + "sinon": "^1.17.5", + "tslint": "^3.15.1", + "typescript": "~2.1.4", + "yargs": "^5.0.0" + }, + "dependencies": { + "ora": "^0.3.0", + "chalk": "^1.1.3", + "cross-spawn": "^4.0.0", + "pkg-dir": "^1.0.0" + } +} diff --git a/src/dirname.ts b/src/dirname.ts new file mode 100644 index 0000000..1ba7c63 --- /dev/null +++ b/src/dirname.ts @@ -0,0 +1 @@ +export default __dirname; diff --git a/src/intern/intern-local.js b/src/intern/intern-local.js new file mode 100644 index 0000000..b2fd589 --- /dev/null +++ b/src/intern/intern-local.js @@ -0,0 +1,15 @@ +define([ + './intern' +], function (intern) { + intern.tunnel = 'NullTunnel'; + intern.tunnelOptions = { + hostname: 'localhost', + port: '4444' + }; + + intern.environments = [ + { browserName: 'chrome' } + ]; + + return intern; +}); diff --git a/src/intern/intern-saucelabs.js b/src/intern/intern-saucelabs.js new file mode 100644 index 0000000..662a8fb --- /dev/null +++ b/src/intern/intern-saucelabs.js @@ -0,0 +1,30 @@ +define([ + './intern' +], function (intern) { + + intern.capabilities = { + project: '<%- appName %>', + name: '<%- appName %>', + fixSessionCapabilities: false + }; + + intern.environments = [ + { browserName: 'internet explorer', version: [ '10.0', '11.0' ], platform: 'Windows 7' }, + // { browserName: 'microsoftedge', platform: 'Windows 10' }, + { browserName: 'firefox', version: '43', platform: 'Windows 10' }, + { browserName: 'chrome', platform: 'Windows 10' }, + // { browserName: 'safari', version: '9', platform: 'OS X 10.11' }, + { browserName: 'android', platform: 'Linux', version: '4.4', deviceName: 'Google Nexus 7 HD Emulator' }// , + // { browserName: 'iphone', version: '9.1', deviceName: 'iPhone 6' } + ]; + + /* SauceLabs supports more max concurrency */ + intern.maxConcurrency = 4; + + /* SauceLabs combined with Travis often causes functional tests to fail with too short a timeout */ + intern.defaultTimeout = 10000; + + intern.tunnel = 'SauceLabsTunnel'; + + return intern; +}); diff --git a/src/intern/intern.js b/src/intern/intern.js new file mode 100644 index 0000000..15c7e3d --- /dev/null +++ b/src/intern/intern.js @@ -0,0 +1,75 @@ +define({ + proxyPort: 9000, + + // A fully qualified URL to the Intern proxy + proxyUrl: 'http://localhost:9000/', + + // Default desired capabilities for all environments. Individual capabilities can be overridden by any of the + // specified browser environments in the `environments` array below as well. See + // https://code.google.com/p/selenium/wiki/DesiredCapabilities for standard Selenium capabilities and + // https://saucelabs.com/docs/additional-config#desired-capabilities for Sauce Labs capabilities. + // Note that the `build` capability will be filled in with the current commit ID from the Travis CI environment + // automatically + capabilities: { + 'browserstack.debug': false, + project: '<%- appName %>', + name: '<%- appName %>', + fixSessionCapabilities: false + }, + + // Browsers to run integration testing against. Note that version numbers must be strings if used with Sauce + // OnDemand. Options that will be permutated are browserName, version, platform, and platformVersion; any other + // capabilities options specified for an environment will be copied as-is + environments: [ + { browserName: 'internet explorer', version: [ '10', '11' ], platform: 'WINDOWS' }, + { browserName: 'firefox', platform: 'WINDOWS' }, + { browserName: 'chrome', platform: 'WINDOWS' }/*, + { browserName: 'Safari', version: '9', platform: 'OS X' }*/ + ], + + // Maximum number of simultaneous integration tests that should be executed on the remote WebDriver service + maxConcurrency: 2, + + // Name of the tunnel class to use for WebDriver tests + tunnel: 'BrowserStackTunnel', + + // Support running unit tests from a web server that isn't the intern proxy + initialBaseUrl: (function () { + if (typeof location !== 'undefined' && location.pathname.indexOf('__intern/') > -1) { + return '/'; + } + return null; + })(), + + // The desired AMD loader to use when running unit tests (client.html/client.js). Omit to use the default Dojo + // loader + loaders: { + 'host-browser': 'node_modules/dojo-loader/loader.js', + 'host-node': 'dojo-loader' + }, + + // Configuration options for the module loader; any AMD configuration options supported by the specified AMD loader + // can be used here + loaderOptions: { + // Packages that should be registered with the loader in each testing environment + packages: [ + { name: 'src', location: '_build/src' }, + { name: 'tests', location: '_build/tests' }, + { name: 'dojo', location: 'node_modules/intern/browser_modules/dojo' }, + { name: 'dojo-has', location: 'node_modules/dojo-has' }, + { name: 'dojo-shim', location: 'node_modules/dojo-shim' }, + { name: 'sinon', location: 'node_modules/sinon/pkg', main: 'sinon' } + ] + }, + + // Non-functional test suite(s) to run in each browser + suites: [ 'tests/unit/all' ], + + // Functional test suite(s) to run in each browser once non-functional tests are completed + functionalSuites: [ 'tests/functional/all' ], + + // A regular expression matching URLs to files that should not be included in code coverage analysis + excludeInstrumentation: /(?:node_modules|bower_components|tests)[\/]/, + + defaultTimeout: 5000 +}); diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..08c6ccb --- /dev/null +++ b/src/main.ts @@ -0,0 +1,64 @@ +import { Command, Helper } from 'dojo-cli/interfaces'; +import { Argv } from 'yargs'; +import runTests from './runTests'; + +export interface TestArgs extends Argv { + environments: string; + config: string; + unit: boolean; + functional: boolean; + reporters: string; + coverage: boolean; +} + +const command: Command = { + description: 'test your application', + register(helper: Helper) { + helper.yargs.option('c', { + alias: 'config', + describe: 'Specifies what configuration to test with: browserstack(default), \'saucelabs\', or \'local\'ly.', + type: 'string' + }); + + helper.yargs.options('e', { + alias: 'environments', + describe: 'Comma separated list of browsers to run tests in', + type: 'string' + }); + + helper.yargs.option('r', { + alias: 'reporters', + describe: 'Comma separated list of reporters to use, defaults to Console', + type: 'string' + }); + + helper.yargs.option('u', { + alias: 'unit', + describe: 'Indicates that only unit tests should be run. By default functional tests and unit tests are run' + }); + + helper.yargs.option('f', { + alias: 'functional', + describe: 'Indicates that only functional tests should be run. By default functional tests and unit tests are run' + }); + + helper.yargs.option('cov', { + alias: 'coverage', + describe: 'If specified coverage will be included. This is the same as adding the LcovHtml reporter' + }); + + return helper.yargs; + }, + run(helper: Helper, args: TestArgs) { + return new Promise((resolve, reject) => { + if (!helper.command.exists('build')) { + reject(Error('Required command: \'build\', does not exist')); + } + helper.command.run('build', '', { withTests: true }).then( + () => runTests(args).then(resolve, reject), + reject + ); + }); + } +}; +export default command; diff --git a/src/runTests.ts b/src/runTests.ts new file mode 100644 index 0000000..8d50409 --- /dev/null +++ b/src/runTests.ts @@ -0,0 +1,49 @@ +import { red, green } from 'chalk'; +import * as path from 'path'; +import dirname from './dirname'; +import { TestArgs } from './main'; + +const cs: any = require('cross-spawn'); +const ora: any = require('ora'); +const pkgDir: any = require('pkg-dir'); +const packagePath = pkgDir.sync(dirname); + +function parseArguments({ unit, functional, environments, config, coverage, reporters }: TestArgs) { + config = config ? `-${config}` : ''; + const args = [ `config=${path.relative('.', path.join(packagePath, 'intern', 'intern' + config))}` ]; + if (unit) { + args.push('functionalSuites='); + } + else if (functional) { + args.push('suites='); + } + + const environmentArgs = environments ? environments.split(',').map( + (environment) => `environments={ "browserName": "${environment}" }` + ) : []; + + const reporterArgs = reporters ? reporters.split(',').map((reporter) => `reporters=${reporter}`) : []; + if (coverage && reporterArgs.every((reporter) => reporter.indexOf('LcovHtml') < 0)) { + reporterArgs.push('reporters=LcovHtml'); + } + return [ ...args, ...environmentArgs, ...reporterArgs ]; +} + +export default async function (testArgs: TestArgs) { + return new Promise((resolve, reject) => { + const spinner = ora({ + spinner: 'dots', + color: 'white', + text: 'Running tests' + }).start(); + cs.spawn(path.resolve('node_modules/.bin/intern-runner'), parseArguments(testArgs), { stdio: 'inherit' }) + .on('close', () => { + spinner.stopAndPersist(green.bold(' completed')); + resolve(); + }) + .on('error', (err: Error) => { + spinner.stopAndPersist(red.bold(' failed')); + reject(err); + }); + }); +} diff --git a/tests/intern.ts b/tests/intern.ts new file mode 100644 index 0000000..e6649db --- /dev/null +++ b/tests/intern.ts @@ -0,0 +1,47 @@ +export const proxyPort = 9000; + +// A fully qualified URL to the Intern proxy +export const proxyUrl = 'http://localhost:9000/'; + +// Default desired capabilities for all environments. Individual capabilities can be overridden by any of the +// specified browser environments in the `environments` array below as well. See +// https://code.google.com/p/selenium/wiki/DesiredCapabilities for standard Selenium capabilities and +// https://saucelabs.com/docs/additional-config#desired-capabilities for Sauce Labs capabilities. +// Note that the `build` capability will be filled in with the current commit ID from the Travis CI environment +// automatically +export const capabilities = { + project: 'Dojo 2', + name: 'dojo-cli-test-intern' +}; + +// Support running unit tests from a web server that isn't the intern proxy +export const initialBaseUrl: string = (function () { + if (typeof location !== 'undefined' && location.pathname.indexOf('__intern/') > -1) { + return '/'; + } + return ''; +})(); + +// The desired AMD loader to use when running unit tests (client.html/client.js). Omit to use the default Dojo +// loader +export const loaders = { + 'host-browser': 'node_modules/dojo-loader/loader.js', + 'host-node': 'dojo-loader' +}; + +// Configuration options for the module loader; any AMD configuration options supported by the specified AMD loader +// can be used here +export const loaderOptions = { + // Packages that should be registered with the loader in each testing environment + packages: [ + { name: 'src', location: '_build/src' }, + { name: 'tests', location: '_build/tests' }, + { name: 'dojo', location: 'node_modules/intern/node_modules/dojo' } + ] +}; + +// Non-functional test suite(s) to run in each browser +export const suites = [ 'tests/unit/all' ]; + +// A regular expression matching URLs to files that should not be included in code coverage analysis +export const excludeInstrumentation = /(?:node_modules|bower_components|tests)[\/\\]|webpack\.config/; diff --git a/tests/support/MockModule.ts b/tests/support/MockModule.ts new file mode 100644 index 0000000..3511ac3 --- /dev/null +++ b/tests/support/MockModule.ts @@ -0,0 +1,83 @@ +import * as mockery from 'mockery'; +import * as sinon from 'sinon'; + +const dojoNodePlugin = 'intern/dojo/node'; + +function load(modulePath: string): any { + const mid = `${dojoNodePlugin}!${modulePath}`; + return require(mid); +} + +function unload(modulePath: string): void { + const abs = require.toUrl(modulePath); + const plugin = require.toAbsMid(dojoNodePlugin); + require.undef(`${plugin}!${abs}`); +} + +function resolvePath(basePath: string, modulePath: string): string { + return modulePath.replace('./', `${basePath}/`); +} + +function getBasePath(modulePath: string): string { + const chunks = modulePath.split('/'); + chunks.pop(); + return chunks.join('/'); +} + +export default class MockModule { + private basePath: string; + private moduleUnderTestPath: string; + private mocks: any; + private sandbox: sinon.SinonSandbox; + + constructor(moduleUnderTestPath: string) { + this.basePath = getBasePath(moduleUnderTestPath); + this.moduleUnderTestPath = moduleUnderTestPath; + this.sandbox = sinon.sandbox.create(); + this.mocks = {}; + } + + dependencies(dependencies: string[]): void { + dependencies.forEach((dependencyName) => { + let dependency = load(resolvePath(this.basePath, dependencyName)); + const mock: any = {}; + + for (let prop in dependency) { + if (typeof dependency[prop] === 'function') { + mock[prop] = function () {}; + this.sandbox.stub(mock, prop); + } else { + mock[prop] = dependency[prop]; + } + } + + if (typeof dependency === 'function') { + const ctor = this.sandbox.stub().returns(mock); + mockery.registerMock(dependencyName, ctor); + mock.ctor = ctor; + } + else { + mockery.registerMock(dependencyName, mock); + } + this.mocks[dependencyName] = mock; + }); + } + + getMock(dependencyName: string): any { + return this.mocks[dependencyName]; + } + + getModuleUnderTest(): any { + mockery.enable({ warnOnUnregistered: false }); + const allowable = require.toUrl(this.moduleUnderTestPath) + '.js'; + mockery.registerAllowable(allowable, true); + return load(this.moduleUnderTestPath); + } + + destroy(): void { + unload(this.moduleUnderTestPath); + this.sandbox.restore(); + mockery.deregisterAll(); + mockery.disable(); + } +} diff --git a/tests/support/Reporter.ts b/tests/support/Reporter.ts new file mode 100644 index 0000000..bd66452 --- /dev/null +++ b/tests/support/Reporter.ts @@ -0,0 +1,238 @@ +import * as fs from 'fs'; +import * as nodeUtil from 'util'; +import * as path from 'path'; +import * as intern from 'intern'; +import Collector = require('istanbul/lib/collector'); +import glob = require('glob'); +import JsonReporter = require('istanbul/lib/report/json'); +import Instrumenter = require('istanbul/lib/instrumenter'); +import 'istanbul/index'; + +import Runner = require('intern/lib/reporters/Runner'); +import util = require('intern/lib/util'); + +const LIGHT_RED = '\x1b[91m'; +const LIGHT_GREEN = '\x1b[92m'; +const LIGHT_MAGENTA = '\x1b[95m'; + +class Reporter extends Runner { + private _filename: string; + private _collector: Collector; + private _reporter: JsonReporter; + private reporter: any; + private _errors: { [sessionId: string ]: any[] } = {}; + + constructor(config: any = {}) { + super(config); + + this._filename = config.file || 'coverage-final.json'; + this._collector = new Collector(); + this.reporter = { + writeReport: function () {} + }; + this._reporter = new JsonReporter({ + file: this._filename, + watermarks: config.watermarks + }); + } + + coverage(sessionId: string, coverage: any) { + if (intern.mode === 'client' || sessionId) { + const session = this.sessions[sessionId || '']; + session.coverage = true; + this._collector.add(coverage); + } + } + + runEnd() { + let numEnvironments = 0; + let numTests = 0; + let numFailedTests = 0; + let numSkippedTests = 0; + + for (const sessionId in this.sessions) { + const session = this.sessions[sessionId]; + ++numEnvironments; + numTests += session.suite.numTests; + numFailedTests += session.suite.numFailedTests; + numSkippedTests += session.suite.numSkippedTests; + } + + this.charm.write('\n'); + + if (intern.mode === 'client') { + for (let sid in this._errors) { + this._errors[sid].forEach((test) => { + this.charm + .write(LIGHT_RED) + .write('× ' + test.id) + .foreground('white') + .write(' (' + (test.timeElapsed / 1000) + 's)') + .write('\n') + .foreground('red') + .write(test.error) + .display('reset') + .write('\n\n'); + }); + } + } + + let message = `TOTAL: tested ${numEnvironments} platforms, ${numFailedTests}/${numTests} failed`; + + if (numSkippedTests) { + message += ` (${numSkippedTests} skipped)`; + } + if (this.hasErrors && !numFailedTests) { + message += '; fatal error occurred'; + } + + this.charm + .foreground(numFailedTests > 0 || this.hasErrors ? 'red' : 'green') + .write(message) + .display('reset') + .write('\n'); + + this._writeCoverage(); + } + + suiteStart(suite: any): void { + if (!suite.hasParent) { + this.sessions[suite.sessionId || ''] = { suite: suite }; + if (suite.sessionId) { + this.charm.write('\n‣ Created session ' + suite.name + ' (' + suite.sessionId + ')\n'); + } + } + } + + suiteEnd(suite: any): void { + if (!suite.hasParent) { + // runEnd will report all of this information, so do not repeat it + if (intern.mode === 'client') { + return; + } + + // Runner mode test with no sessionId was some failed test, not a bug + if (!suite.sessionId) { + return; + } + + const session = this.sessions[suite.sessionId]; + + if (session.coverage) { + this.reporter.writeReport(session.coverage); + } + else { + this.charm + .write('No unit test coverage for ' + suite.name) + .display('reset') + .write('\n'); + } + + this.charm + .write('\n\n'); + + if (this._errors[suite.sessionId]) { + this._errors[suite.sessionId].forEach((test) => { + this.charm + .write(LIGHT_RED) + .write('× ' + test.id) + .foreground('white') + .write(' (' + (test.timeElapsed / 1000) + 's)') + .write('\n') + .foreground('red') + .write(test.error) + .display('reset') + .write('\n\n'); + }); + } + + const name = suite.name; + const hasError = (function hasError(suite: any) { + return suite.tests ? (suite.error || suite.tests.some(hasError)) : false; + })(suite); + const numFailedTests = suite.numFailedTests; + const numTests = suite.numTests; + const numSkippedTests = suite.numSkippedTests; + + let summary = nodeUtil.format('%s: %d/%d tests failed', name, numFailedTests, numTests); + if (numSkippedTests) { + summary += ' (' + numSkippedTests + ' skipped)'; + } + + if (hasError) { + summary += '; fatal error occurred'; + } + + this.charm + .write(numFailedTests || hasError > 0 ? LIGHT_RED : LIGHT_GREEN) + .write(summary) + .display('reset') + .write('\n\n'); + } + } + + testFail(test: any): void { + if (!this._errors[test.sessionId]) { + this._errors[test.sessionId] = []; + } + + this._errors[test.sessionId].push({ + id: test.id, + timeElapsed: test.timeElapsed, + error: util.getErrorMessage(test.error) + }); + + this.charm + .write(LIGHT_RED) + .write('×') + .display('reset'); + } + + testPass(test: any): void { + this.charm + .write(LIGHT_GREEN) + .write('✓') + .display('reset'); + } + + testSkip(test: any): void { + this.charm + .write(LIGHT_MAGENTA) + .write('~') + .display('reset'); + } + + _writeCoverage(): void { + let coverage: any; + if (fs.existsSync(this._filename)) { + coverage = JSON.parse(fs.readFileSync(this._filename, { encoding: 'utf8' })); + } + else { + coverage = {}; + const coveredFiles = this._collector.files(); + const instrumenter = new Instrumenter({ + noCompact: true, + noAutoWrap: true + }); + glob.sync('_build/**/*.js').filter(function (filepath) { + return !( intern.executor).config.excludeInstrumentation.test(filepath) && coveredFiles.indexOf(path.resolve(filepath)) === -1; + }).forEach(function (filepath) { + try { + const wholename = path.resolve(filepath); + instrumenter.instrumentSync(fs.readFileSync(wholename, 'utf8'), wholename); + coverage[wholename] = instrumenter.lastFileCoverage(); + for (let i in coverage[wholename].s) { + coverage[wholename].s[i] = 0; + } + } + catch (error) { + console.error(filepath + ': ' + error); + } + }); + } + this._collector.add(coverage); + this._reporter.writeReport(this._collector, true); + } +} + +export = Reporter; diff --git a/tests/support/util.ts b/tests/support/util.ts new file mode 100644 index 0000000..e5cc4b7 --- /dev/null +++ b/tests/support/util.ts @@ -0,0 +1,18 @@ +/** + * Thenable represents any object with a callable `then` property. + */ +export interface Thenable { + then(onFulfilled?: (value?: T) => U | Thenable, onRejected?: (error?: any) => U | Thenable): Thenable; +} + +export function isEventuallyRejected(promise: Thenable): Thenable { + return promise.then(function () { + throw new Error('unexpected code path'); + }, function () { + return true; // expect rejection + }); +} + +export function throwImmediatly() { + throw new Error('unexpected code path'); +} diff --git a/tests/unit/all.ts b/tests/unit/all.ts new file mode 100644 index 0000000..ce89878 --- /dev/null +++ b/tests/unit/all.ts @@ -0,0 +1 @@ +import './main'; diff --git a/tests/unit/main.ts b/tests/unit/main.ts new file mode 100644 index 0000000..6ffbb54 --- /dev/null +++ b/tests/unit/main.ts @@ -0,0 +1,96 @@ +import { beforeEach, afterEach, describe, it } from 'intern!bdd'; +import * as assert from 'intern/chai!assert'; +import MockModule from '../support/MockModule'; +import { throwImmediatly } from '../support/util'; +import * as sinon from 'sinon'; + +describe('main', () => { + + let moduleUnderTest: any; + let mockModule: MockModule; + let mockWebpack: any; + let mockWebpackConfig: any; + let sandbox: sinon.SinonSandbox; + + beforeEach(() => { + sandbox = sinon.sandbox.create(); + mockModule = new MockModule('../../src/main'); + mockModule.dependencies(['./webpack.config', 'webpack', 'webpack-dev-server']); + mockWebpack = mockModule.getMock('webpack'); + const mockWebpackConfigModule = mockModule.getMock('./webpack.config'); + mockWebpackConfig = { + entry: { + 'src/main': [ + 'src/main.styl', + 'src/main.ts' + ] + } + }; + mockWebpackConfigModule.ctor.returns(mockWebpackConfig); + moduleUnderTest = mockModule.getModuleUnderTest().default; + sandbox.stub(console, 'log'); + }); + + afterEach(() => { + sandbox.restore(); + mockModule.destroy(); + }); + + it('should register supported arguments', () => { + const helper = { yargs: { option: sandbox.stub() } }; + moduleUnderTest.register(helper); + assert.deepEqual( + helper.yargs.option.firstCall.args, + [ 'w', { alias: 'watch', describe: 'watch and serve' } ] + ); + assert.deepEqual( + helper.yargs.option.secondCall.args, + [ 'p', { alias: 'port', describe: 'port to serve on when using --watch', type: 'number' }], + ); + }); + + it('should run compile and log results on success', () => { + mockWebpack.run = sandbox.stub().yields(false, 'some stats'); + return moduleUnderTest.run({}, {}).then(() => { + assert.isTrue(mockWebpack.run.calledOnce); + assert.isTrue(( console.log).calledWith('some stats')); + }); + }); + + it('should run compile and reject on failure', () => { + const compilerError = new Error('compiler error'); + mockWebpack.run = sandbox.stub().yields(compilerError, null); + return moduleUnderTest.run({}, {}).then( + throwImmediatly, + (e: Error) => { + assert.isTrue(mockWebpack.run.calledOnce); + assert.equal(e, compilerError); + } + ); + }); + + it('should run watch, setting appropriate webpack options', () => { + const mockWebpackDevServer = mockModule.getMock('webpack-dev-server'); + mockWebpackDevServer.listen = sandbox.stub().yields(); + moduleUnderTest.run({}, { watch: true }); + return new Promise((resolve) => setTimeout(resolve, 10)).then(() => { + assert.isTrue(mockWebpackDevServer.listen.calledOnce); + assert.isTrue(( console.log).firstCall.calledWith('Starting server on http://localhost:9999')); + assert.equal(mockWebpackConfig.devtool, 'eval-source-map'); + assert.equal(mockWebpackConfig.entry['src/main'][0], 'webpack-dev-server/client?'); + }); + }); + + it('should run watch and reject on failure', () => { + const compilerError = new Error('compiler error'); + const mockWebpackDevServer = mockModule.getMock('webpack-dev-server'); + mockWebpackDevServer.listen = sandbox.stub().yields(compilerError); + return moduleUnderTest.run({}, { watch: true }).then( + throwImmediatly, + (e: Error) => { + assert.isTrue(mockWebpackDevServer.listen.calledOnce); + assert.equal(e, compilerError); + } + ); + }); +}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..a8962d0 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,20 @@ +{ + "version": "2.0.3", + "compilerOptions": { + "declaration": false, + "module": "umd", + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "outDir": "_build/", + "removeComments": false, + "sourceMap": true, + "target": "es6", + "moduleResolution": "node" + }, + "include": [ + "./typings/index.d.ts", + "./src/**/*.ts", + "./tests/**/*.ts" + ] +} diff --git a/tslint.json b/tslint.json new file mode 100644 index 0000000..1e9c0fc --- /dev/null +++ b/tslint.json @@ -0,0 +1,69 @@ +{ + "rules": { + "align": false, + "ban": [], + "class-name": true, + "comment-format": [ true, "check-space" ], + "curly": true, + "eofline": true, + "forin": false, + "indent": [ true, "tabs" ], + "interface-name": [ true, "never-prefix" ], + "jsdoc-format": true, + "label-position": true, + "label-undefined": true, + "max-line-length": 120, + "member-access": false, + "member-ordering": false, + "no-any": false, + "no-arg": true, + "no-bitwise": false, + "no-consecutive-blank-lines": true, + "no-console": false, + "no-construct": false, + "no-constructor-vars": true, + "no-debugger": true, + "no-duplicate-key": true, + "no-duplicate-variable": true, + "no-empty": false, + "no-eval": true, + "no-inferrable-types": [ true, "ignore-params" ], + "no-shadowed-variable": false, + "no-string-literal": false, + "no-switch-case-fall-through": false, + "no-trailing-whitespace": true, + "no-unreachable": true, + "no-unused-expression": false, + "no-unused-variable": true, + "no-use-before-declare": false, + "no-var-keyword": true, + "no-var-requires": false, + "object-literal-sort-keys": false, + "one-line": [ true, "check-open-brace", "check-whitespace" ], + "quotemark": [ true, "single" ], + "radix": true, + "semicolon": [ true, "always" ], + "trailing-comma": [ true, { + "multiline": "never", + "singleline": "never" + } ], + "triple-equals": [ true, "allow-null-check" ], + "typedef": false, + "typedef-whitespace": [ true, { + "call-signature": "nospace", + "index-signature": "nospace", + "parameter": "nospace", + "property-declaration": "nospace", + "variable-declaration": "nospace" + }, { + "call-signature": "onespace", + "index-signature": "onespace", + "parameter": "onespace", + "property-declaration": "onespace", + "variable-declaration": "onespace" + } ], + "use-strict": false, + "variable-name": [ true, "check-format", "allow-pascal-case", "allow-leading-underscore", "ban-keywords" ], + "whitespace": [ true, "check-branch", "check-decl", "check-operator", "check-module", "check-separator", "check-type", "check-typecast" ] + } +} diff --git a/typings.json b/typings.json new file mode 100644 index 0000000..c725fab --- /dev/null +++ b/typings.json @@ -0,0 +1,12 @@ +{ + "name": "dojo-cli-test-intern", + "dependencies": { + "yargs": "registry:npm/yargs#5.0.0+20160907000723" + }, + "globalDevDependencies": { + "dojo2": "github:dojo/typings/custom/dojo2/dojo.d.ts#a62873258aa1deed48f9882c193c335436100d4b", + "dojo2-dev": "github:dojo/typings/custom/dev/dev.d.ts#288d3a9868194f0e1ad6687371dffd1d96cb39a1", + "intern": "github:dojo/typings/custom/intern/intern.d.ts#92fcf688c0982c1107fca278de52e4bfe23bd8af", + "leadfoot": "github:dojo/typings/custom/leadfoot/leadfoot.d.ts#8f3dfe6cafd04dfa78068785551552a5cfd88db1" + } +} From a4c042cfbe72d1dcf70218b5c0107823452c0f50 Mon Sep 17 00:00:00 2001 From: Bradley Maier Date: Wed, 11 Jan 2017 04:06:38 -0500 Subject: [PATCH 02/21] Add tests and typings --- package.json | 10 +-- src/main.ts | 9 ++- src/runTests.ts | 2 +- tests/intern.ts | 6 +- tests/support/MockModule.ts | 2 +- tests/unit/all.ts | 1 + tests/unit/main.ts | 113 ++++++++++++++++++++------------- tests/unit/runTests.ts | 122 ++++++++++++++++++++++++++++++++++++ typings.json | 14 ++++- 9 files changed, 215 insertions(+), 64 deletions(-) create mode 100644 tests/unit/runTests.ts diff --git a/package.json b/package.json index fc206fc..c38ad31 100644 --- a/package.json +++ b/package.json @@ -17,16 +17,8 @@ "test": "grunt test" }, "devDependencies": { - "codecov.io": "0.1.6", - "@types/node": "^6.0.49", "@types/chalk": "^0.4.31", - "@types/ejs": "^2.3.33", - "@types/chai": "^3.4.34", - "@types/fs-extra": "0.0.34", - "@types/glob": "^5.0.30", - "@types/grunt": "~0.4.0", - "@types/mockery": "^1.4.29", - "@types/sinon": "^1.16.32", + "codecov.io": "0.1.6", "dojo-cli": "^2.0.0-alpha.3", "dojo-loader": ">=2.0.0-beta.7", "dts-generator": "~1.7.0", diff --git a/src/main.ts b/src/main.ts index 08c6ccb..abf2972 100644 --- a/src/main.ts +++ b/src/main.ts @@ -20,7 +20,7 @@ const command: Command = { type: 'string' }); - helper.yargs.options('e', { + helper.yargs.option('e', { alias: 'environments', describe: 'Comma separated list of browsers to run tests in', type: 'string' @@ -54,8 +54,11 @@ const command: Command = { if (!helper.command.exists('build')) { reject(Error('Required command: \'build\', does not exist')); } - helper.command.run('build', '', { withTests: true }).then( - () => runTests(args).then(resolve, reject), + const result = helper.command.run('build', '', { withTests: true }); + result.then( + () => { + runTests(args).then(resolve, reject); + }, reject ); }); diff --git a/src/runTests.ts b/src/runTests.ts index 8d50409..71ca92a 100644 --- a/src/runTests.ts +++ b/src/runTests.ts @@ -8,7 +8,7 @@ const ora: any = require('ora'); const pkgDir: any = require('pkg-dir'); const packagePath = pkgDir.sync(dirname); -function parseArguments({ unit, functional, environments, config, coverage, reporters }: TestArgs) { +export function parseArguments({ unit, functional, environments, config, coverage, reporters }: TestArgs) { config = config ? `-${config}` : ''; const args = [ `config=${path.relative('.', path.join(packagePath, 'intern', 'intern' + config))}` ]; if (unit) { diff --git a/tests/intern.ts b/tests/intern.ts index e6649db..3c2f5ee 100644 --- a/tests/intern.ts +++ b/tests/intern.ts @@ -25,7 +25,6 @@ export const initialBaseUrl: string = (function () { // The desired AMD loader to use when running unit tests (client.html/client.js). Omit to use the default Dojo // loader export const loaders = { - 'host-browser': 'node_modules/dojo-loader/loader.js', 'host-node': 'dojo-loader' }; @@ -35,8 +34,7 @@ export const loaderOptions = { // Packages that should be registered with the loader in each testing environment packages: [ { name: 'src', location: '_build/src' }, - { name: 'tests', location: '_build/tests' }, - { name: 'dojo', location: 'node_modules/intern/node_modules/dojo' } + { name: 'tests', location: '_build/tests' } ] }; @@ -44,4 +42,4 @@ export const loaderOptions = { export const suites = [ 'tests/unit/all' ]; // A regular expression matching URLs to files that should not be included in code coverage analysis -export const excludeInstrumentation = /(?:node_modules|bower_components|tests)[\/\\]|webpack\.config/; +export const excludeInstrumentation = /(?:node_modules|bower_components|tests)[\/\\]|intern\.js|intern-local\.js|intern-saucelabs\.js|dirname/; diff --git a/tests/support/MockModule.ts b/tests/support/MockModule.ts index 3511ac3..c0186d0 100644 --- a/tests/support/MockModule.ts +++ b/tests/support/MockModule.ts @@ -68,7 +68,7 @@ export default class MockModule { } getModuleUnderTest(): any { - mockery.enable({ warnOnUnregistered: false }); + mockery.enable({ warnOnUnregistered: false, useCleanCache: true }); const allowable = require.toUrl(this.moduleUnderTestPath) + '.js'; mockery.registerAllowable(allowable, true); return load(this.moduleUnderTestPath); diff --git a/tests/unit/all.ts b/tests/unit/all.ts index ce89878..29a5054 100644 --- a/tests/unit/all.ts +++ b/tests/unit/all.ts @@ -1 +1,2 @@ import './main'; +import './runTests'; diff --git a/tests/unit/main.ts b/tests/unit/main.ts index 6ffbb54..773991b 100644 --- a/tests/unit/main.ts +++ b/tests/unit/main.ts @@ -1,5 +1,6 @@ import { beforeEach, afterEach, describe, it } from 'intern!bdd'; import * as assert from 'intern/chai!assert'; +import * as mockery from 'mockery'; import MockModule from '../support/MockModule'; import { throwImmediatly } from '../support/util'; import * as sinon from 'sinon'; @@ -8,25 +9,16 @@ describe('main', () => { let moduleUnderTest: any; let mockModule: MockModule; - let mockWebpack: any; - let mockWebpackConfig: any; + let mockRunTests: any; let sandbox: sinon.SinonSandbox; beforeEach(() => { sandbox = sinon.sandbox.create(); mockModule = new MockModule('../../src/main'); - mockModule.dependencies(['./webpack.config', 'webpack', 'webpack-dev-server']); - mockWebpack = mockModule.getMock('webpack'); - const mockWebpackConfigModule = mockModule.getMock('./webpack.config'); - mockWebpackConfig = { - entry: { - 'src/main': [ - 'src/main.styl', - 'src/main.ts' - ] - } + mockRunTests = { + default: sandbox.stub().returns(Promise.resolve()) }; - mockWebpackConfigModule.ctor.returns(mockWebpackConfig); + mockery.registerMock('./runTests', mockRunTests); moduleUnderTest = mockModule.getModuleUnderTest().default; sandbox.stub(console, 'log'); }); @@ -41,56 +33,87 @@ describe('main', () => { moduleUnderTest.register(helper); assert.deepEqual( helper.yargs.option.firstCall.args, - [ 'w', { alias: 'watch', describe: 'watch and serve' } ] + [ 'c', { alias: 'config', describe: 'Specifies what configuration to test with: browserstack(default), \'saucelabs\', or \'local\'ly.', type: 'string' } ], + 'First argument' ); assert.deepEqual( helper.yargs.option.secondCall.args, - [ 'p', { alias: 'port', describe: 'port to serve on when using --watch', type: 'number' }], + [ 'e', { alias: 'environments', describe: 'Comma separated list of browsers to run tests in', type: 'string' }], + 'Second argument' ); - }); - it('should run compile and log results on success', () => { - mockWebpack.run = sandbox.stub().yields(false, 'some stats'); - return moduleUnderTest.run({}, {}).then(() => { - assert.isTrue(mockWebpack.run.calledOnce); - assert.isTrue(( console.log).calledWith('some stats')); - }); + assert.deepEqual( + helper.yargs.option.thirdCall.args, + [ 'r', { alias: 'reporters', describe: 'Comma separated list of reporters to use, defaults to Console', type: 'string' }], + 'Third argument' + ); + + assert.deepEqual( + helper.yargs.option.getCall(3).args, + [ 'u', { alias: 'unit', describe: 'Indicates that only unit tests should be run. By default functional tests and unit tests are run' }], + 'Fourth argument' + ); + + assert.deepEqual( + helper.yargs.option.getCall(4).args, + [ 'f', { alias: 'functional', describe: 'Indicates that only functional tests should be run. By default functional tests and unit tests are run' }], + 'Fifth argument' + ); + + assert.deepEqual( + helper.yargs.option.getCall(5).args, + [ 'cov', { alias: 'coverage', describe: 'If specified coverage will be included. This is the same as adding the LcovHtml reporter' }], + 'Sixth argument' + ); }); - it('should run compile and reject on failure', () => { - const compilerError = new Error('compiler error'); - mockWebpack.run = sandbox.stub().yields(compilerError, null); - return moduleUnderTest.run({}, {}).then( + it('should check for build command and fail if it doesn\'t exist', () => { + const helper = { + command: { + exists: sandbox.stub().returns(false) + } + }; + return moduleUnderTest.run(helper, {}).then( throwImmediatly, (e: Error) => { - assert.isTrue(mockWebpack.run.calledOnce); - assert.equal(e, compilerError); + assert.isTrue(helper.command.exists.calledOnce); + assert.equal(e.message, 'Required command: \'build\', does not exist'); } ); }); - it('should run watch, setting appropriate webpack options', () => { - const mockWebpackDevServer = mockModule.getMock('webpack-dev-server'); - mockWebpackDevServer.listen = sandbox.stub().yields(); - moduleUnderTest.run({}, { watch: true }); - return new Promise((resolve) => setTimeout(resolve, 10)).then(() => { - assert.isTrue(mockWebpackDevServer.listen.calledOnce); - assert.isTrue(( console.log).firstCall.calledWith('Starting server on http://localhost:9999')); - assert.equal(mockWebpackConfig.devtool, 'eval-source-map'); - assert.equal(mockWebpackConfig.entry['src/main'][0], 'webpack-dev-server/client?'); + it('should run the build command with appropriate arguments', () => { + const helper = { + command: { + exists: sandbox.stub().returns(true), + run: sandbox.stub().returns(Promise.resolve()) + } + }; + const runTestArgs = { testArg: 'value' }; + return moduleUnderTest.run(helper, runTestArgs).then(() => { + assert.isTrue(helper.command.run.calledOnce, 'Should have called run'); + assert.deepEqual(helper.command.run.firstCall.args, [ 'build', '', { withTests: true } ], 'Didn\'t call with proper arguments'); + assert.isTrue(mockRunTests.default.calledOnce, 'Should have called the runTests module'); + assert.deepEqual(mockRunTests.default.firstCall.args, [ runTestArgs ], 'Didn\'t run tests with provided arguments'); }); }); - it('should run watch and reject on failure', () => { - const compilerError = new Error('compiler error'); - const mockWebpackDevServer = mockModule.getMock('webpack-dev-server'); - mockWebpackDevServer.listen = sandbox.stub().yields(compilerError); - return moduleUnderTest.run({}, { watch: true }).then( + it('should reject on failure', () => { + const buildError = Error('Failed to build'); + const helper = { + command: { + exists: sandbox.stub().returns(true), + run: sandbox.stub().throws(buildError) + } + }; + return moduleUnderTest.run(helper, {}).then( throwImmediatly, - (e: Error) => { - assert.isTrue(mockWebpackDevServer.listen.calledOnce); - assert.equal(e, compilerError); + (error: any) => { + assert.isTrue(helper.command.run.calledOnce, 'Should have called run'); + assert.deepEqual(helper.command.run.firstCall.args, [ 'build', '', { withTests: true } ], 'Didn\'t call with proper arguments'); + assert.equal('Failed to build', error.message, 'Wrong error message'); } ); + }); }); diff --git a/tests/unit/runTests.ts b/tests/unit/runTests.ts new file mode 100644 index 0000000..d0754bd --- /dev/null +++ b/tests/unit/runTests.ts @@ -0,0 +1,122 @@ +import { before, beforeEach, after, afterEach, describe, it } from 'intern!bdd'; +import * as assert from 'intern/chai!assert'; +import * as mockery from 'mockery'; + +import { stub, SinonStub } from 'sinon'; +const cs: any = require('cross-spawn'); +let spawnStub: SinonStub; +let spawnOnStub: SinonStub; +const stopAndPersistStub: SinonStub = stub(); +const startStub: SinonStub = stub().returns({ + stopAndPersist: stopAndPersistStub +}); +let runTests: any; + +describe('runTests', () => { + before(() => { + mockery.enable({ + warnOnUnregistered: false + }); + + mockery.registerMock('ora', () => { + return { + start: startStub + }; + }); + + runTests = require('intern/dojo/node!./../../src/runTests'); + }); + after(() => { + mockery.deregisterAll(); + mockery.disable(); + }); + beforeEach(() => { + spawnOnStub = stub(); + const spawnOnResponse = { + 'on': spawnOnStub + }; + + startStub.reset(); + stopAndPersistStub.reset(); + spawnOnStub.returns(spawnOnResponse); + spawnStub = stub(cs, 'spawn').returns(spawnOnResponse); + }); + afterEach(() => { + spawnStub.restore(); + }); + it('Should call spawn to run intern', async () => { + spawnOnStub.onFirstCall().callsArg(1); + await runTests.default({}); + assert.isTrue(spawnStub.calledOnce); + }); + it('Should use a loading spinner', async () => { + spawnOnStub.onFirstCall().callsArg(1); + await runTests.default({}); + assert.isTrue(startStub.calledOnce, 'Should call start on the spinner'); + assert.isTrue(stopAndPersistStub.calledOnce, 'Should stop the spinner'); + assert.isTrue(stopAndPersistStub.firstCall.calledWithMatch('completed'), + 'Should persist completed message'); + }); + it('Should reject with an error when spawn throws an error', async () => { + const errorMessage = 'test error message'; + spawnOnStub.onSecondCall().callsArgWith(1, new Error(errorMessage)); + try { + await runTests.default({}); + assert.fail(null, null, 'Should not get here'); + } + catch (error) { + assert.equal(errorMessage, error.message); + assert.isTrue(stopAndPersistStub.calledOnce, 'Should stop the spinner'); + assert.isTrue(stopAndPersistStub.firstCall.calledWithMatch('failed'), + 'Should persis the failed message'); + } + }); + + describe('Should parse arguments', () => { + it('Should use config to set intern file if provided', () => { + assert.equal('config=intern\\intern-test', runTests.parseArguments({config: 'test'})[0]); + }); + + it('Should have a default for intern config', () => { + assert.equal('config=intern\\intern', runTests.parseArguments({})[0]); + }); + + it('Should push an empty functionalSuites arg if unit is provided', () => { + assert.equal('functionalSuites=', runTests.parseArguments({ unit: true })[1]); + }); + + it('Should push an empty suites arg if functional is provided', () => { + assert.equal('suites=', runTests.parseArguments({ functional: true })[1]); + }); + + it('Should add environments if provided', () => { + const args = runTests.parseArguments({ + environments: 'one,two' + }); + assert.equal('environments={ "browserName": "one" }', args[1]); + assert.equal('environments={ "browserName": "two" }', args[2]); + }); + + it('Should add reporters if provided', () => { + const args = runTests.parseArguments({ + reporters: 'one,two' + }); + + assert.equal('reporters=one', args[1]); + assert.equal('reporters=two', args[2]); + }); + + it('Should add LcovHtml reporter if coverage argument is provided', () => { + assert.equal('reporters=LcovHtml', runTests.parseArguments({ coverage: true })[1]); + }); + + it('Should not duplicate the LcovHtml reporter', () => { + const args = runTests.parseArguments({ + reporters: 'LcovHtml', + coverage: true + }); + assert.equal('reporters=LcovHtml', args[1]); + assert.equal(2, args.length); + }); + }); +}); diff --git a/typings.json b/typings.json index c725fab..877a2fe 100644 --- a/typings.json +++ b/typings.json @@ -3,10 +3,22 @@ "dependencies": { "yargs": "registry:npm/yargs#5.0.0+20160907000723" }, + "devDependencies": { + "chai": "registry:npm/chai#3.5.0+20160415060238", + "glob": "registry:npm/glob#6.0.0+20160211003958", + "sinon": "registry:npm/sinon#1.16.0+20160723033700" + }, "globalDevDependencies": { + "digdug": "github:dojo/typings/custom/digdug/digdug.d.ts#a62873258aa1deed48f9882c193c335436100d4b", "dojo2": "github:dojo/typings/custom/dojo2/dojo.d.ts#a62873258aa1deed48f9882c193c335436100d4b", "dojo2-dev": "github:dojo/typings/custom/dev/dev.d.ts#288d3a9868194f0e1ad6687371dffd1d96cb39a1", + "gruntjs": "registry:dt/gruntjs#0.4.0+20160316171810", "intern": "github:dojo/typings/custom/intern/intern.d.ts#92fcf688c0982c1107fca278de52e4bfe23bd8af", - "leadfoot": "github:dojo/typings/custom/leadfoot/leadfoot.d.ts#8f3dfe6cafd04dfa78068785551552a5cfd88db1" + "leadfoot": "github:dojo/typings/custom/leadfoot/leadfoot.d.ts#8f3dfe6cafd04dfa78068785551552a5cfd88db1", + "mockery": "registry:dt/mockery#1.4.0+20160316155526", + "node": "github:dojo/typings/custom/node/node.d.ts#a62873258aa1deed48f9882c193c335436100d4b" + }, + "globalDependencies": { + "dojo-loader": "npm:dojo-loader" } } From 3957028ec88e9f322e4ac0a0f6c9a26c39992c8f Mon Sep 17 00:00:00 2001 From: Bradley Maier Date: Wed, 11 Jan 2017 04:12:33 -0500 Subject: [PATCH 03/21] Fix indentation --- Gruntfile.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 87b9f4f..357877e 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,11 +1,11 @@ module.exports = function (grunt) { var staticFiles = [ 'intern/**' ]; require('grunt-dojo2').initConfig(grunt, { - ts: { - dist: { - exclude: [ - './src/intern', - "./tests/**/*.ts" + ts: { + dist: { + exclude: [ + './src/intern', + './tests/**/*.ts' ] } }, @@ -16,12 +16,12 @@ module.exports = function (grunt) { src: staticFiles, dest: '<%= distDirectory %>' }, - staticDevFiles: { - expand: true, + staticDevFiles: { + expand: true, cwd: 'src', - src: staticFiles, - dest: '<%= devDirectory %>/src' - } + src: staticFiles, + dest: '<%= devDirectory %>/src' + } } }); From e35235bf92379594a3e3c1b300c5ec7f9963f588 Mon Sep 17 00:00:00 2001 From: Bradley Maier Date: Wed, 11 Jan 2017 04:15:12 -0500 Subject: [PATCH 04/21] Update readme and package.json description --- README.md | 41 ++++++++++++++++++++++++++++++++++++++++- package.json | 2 +- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 34e5531..c72d9e3 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,41 @@ # cli-test-intern -The Dojo 2 cli command for testing applications + + + +The official dojo 2 test command. + +## Features + +TODO: Add sections on features of this package + +## How do I use this package? + +TODO: Add appropriate usage and instruction guidelines + +## How do I contribute? + +We appreciate your interest! Please see the [Dojo 2 Meta Repository](https://github.com/dojo/meta#readme) for the +Contributing Guidelines and Style Guide. + +## Testing + +Test cases MUST be written using [Intern](https://theintern.github.io) using the Object test interface and Assert assertion interface. + +90% branch coverage MUST be provided for all code submitted to this repository, as reported by istanbul’s combined coverage results for all supported platforms. + +To test locally in node run: + +`grunt test` + +## Licensing information + +TODO: If third-party code was used to write this library, make a list of project names and licenses here + +* [Third-party lib one](https//github.com/foo/bar) ([New BSD](http://opensource.org/licenses/BSD-3-Clause)) + +© 2004–2016 Dojo Foundation & contributors. [New BSD](http://opensource.org/licenses/BSD-3-Clause) license. + diff --git a/package.json b/package.json index c38ad31..a12e756 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "dojo-cli-test-intern", "version": "2.0.0-pre", - "description": "build a dojo 2 application", + "description": "test a dojo 2 application", "private": true, "homepage": "http://dojotoolkit.org", "bugs": { From 1f60128dc05595ad23fa391ce8096b1a0e343e91 Mon Sep 17 00:00:00 2001 From: Bradley Maier Date: Wed, 11 Jan 2017 12:19:59 -0500 Subject: [PATCH 05/21] PR cleanup --- LICENSE | 2 +- README.md | 23 ++++++++++++++++------- package.json | 6 +++--- src/intern/intern-saucelabs.js | 4 ++-- tsconfig.json | 2 +- 5 files changed, 23 insertions(+), 14 deletions(-) diff --git a/LICENSE b/LICENSE index 08f88a1..a9f3e56 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,7 @@ The "New" BSD License ********************* -Copyright (c) 2015 - 2016, The Dojo Foundation +Copyright (c) 2015 - 2017, The JS Foundation All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/README.md b/README.md index c72d9e3..41090d7 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![npm version](https://badge.fury.io/js/dojo-cli-test-intern.svg)](http://badge.fury.io/js/dojo-cli-test-intern) --> -The official dojo 2 test command. +The official Dojo 2 test command. ## Features @@ -25,7 +25,7 @@ Contributing Guidelines and Style Guide. Test cases MUST be written using [Intern](https://theintern.github.io) using the Object test interface and Assert assertion interface. -90% branch coverage MUST be provided for all code submitted to this repository, as reported by istanbul’s combined coverage results for all supported platforms. +90% branch coverage MUST be provided for all code submitted to this repository, as reported by Istanbul’s combined coverage results for all supported platforms. To test locally in node run: @@ -33,9 +33,18 @@ To test locally in node run: ## Licensing information -TODO: If third-party code was used to write this library, make a list of project names and licenses here - -* [Third-party lib one](https//github.com/foo/bar) ([New BSD](http://opensource.org/licenses/BSD-3-Clause)) - -© 2004–2016 Dojo Foundation & contributors. [New BSD](http://opensource.org/licenses/BSD-3-Clause) license. +* [ora](https://github.com/sindresorhus/ora) ([MIT](https://opensource.org/licenses/MIT)) +* [Chalk](https://github.com/chalk/chalk)([MIT](https://opensource.org/licenses/MIT)) +* [cross-spawn](https://github.com/IndigoUnited/node-cross-spawn)([MIT](https://opensource.org/licenses/MIT)) +* [pkg-dir](https://github.com/sindresorhus/pkg-dir)([MIT](https://opensource.org/licenses/MIT)) +* [Istanbul](https://github.com/gotwarlost/istanbul)([New BSD](http://opensource.org/licenses/BSD-3-Clause)) +* [Mockery](https://github.com/mfncooper/mockery)([MIT](https://opensource.org/licenses/MIT)) +* [codecov.io](https://github.com/cainus/codecov.io)([MIT](https://opensource.org/licenses/MIT)) +* [Glob](https://github.com/isaacs/node-glob)([ISC](https://opensource.org/licenses/ISC)) +* [grunt-tslint](https://github.com/palantir/grunt-tslint)([Apache 2.0](https://opensource.org/licenses/Apache-2.0)) +* [Sinon.JS](https://github.com/sinonjs/sinon)([New BSD](http://opensource.org/licenses/BSD-3-Clause)) +* [TSLint](https://github.com/palantir/tslint)([Apache 2.0](https://opensource.org/licenses/Apache-2.0)) +* [yargs](https://github.com/yargs/yargs)([MIT](https://opensource.org/licenses/MIT)) + +© 2004–2017 JS Foundation & contributors. [New BSD](LICENSE) license. diff --git a/package.json b/package.json index a12e756..d9d00f7 100644 --- a/package.json +++ b/package.json @@ -1,17 +1,17 @@ { "name": "dojo-cli-test-intern", "version": "2.0.0-pre", - "description": "test a dojo 2 application", + "description": "Test a Dojo 2 application", "private": true, "homepage": "http://dojotoolkit.org", "bugs": { - "url": "https://github.com/maier49/cli-test-intern/issues" + "url": "https://github.com/dojo/cli-test-intern/issues" }, "license": "BSD-3-Clause", "main": "main.js", "repository": { "type": "git", - "url": "https://github.com/maier49/cli-test-intern.git" + "url": "https://github.com/dojo/cli-test-intern.git" }, "scripts": { "test": "grunt test" diff --git a/src/intern/intern-saucelabs.js b/src/intern/intern-saucelabs.js index 662a8fb..b37ea5b 100644 --- a/src/intern/intern-saucelabs.js +++ b/src/intern/intern-saucelabs.js @@ -11,10 +11,10 @@ define([ intern.environments = [ { browserName: 'internet explorer', version: [ '10.0', '11.0' ], platform: 'Windows 7' }, // { browserName: 'microsoftedge', platform: 'Windows 10' }, - { browserName: 'firefox', version: '43', platform: 'Windows 10' }, + { browserName: 'firefox', version: '50', platform: 'Windows 10' }, { browserName: 'chrome', platform: 'Windows 10' }, // { browserName: 'safari', version: '9', platform: 'OS X 10.11' }, - { browserName: 'android', platform: 'Linux', version: '4.4', deviceName: 'Google Nexus 7 HD Emulator' }// , + // { browserName: 'android', platform: 'Linux', version: '4.4', deviceName: 'Google Nexus 7 HD Emulator' }// , // { browserName: 'iphone', version: '9.1', deviceName: 'iPhone 6' } ]; diff --git a/tsconfig.json b/tsconfig.json index a8962d0..7baccf4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,5 +1,5 @@ { - "version": "2.0.3", + "version": "2.1.4", "compilerOptions": { "declaration": false, "module": "umd", From f066ede74d89d93e69a4d1c79a824fbbd1abe710 Mon Sep 17 00:00:00 2001 From: Bradley Maier Date: Wed, 11 Jan 2017 12:21:33 -0500 Subject: [PATCH 06/21] Move node typings to global dependencies so grunt dist works --- typings.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/typings.json b/typings.json index 877a2fe..d8a4ce6 100644 --- a/typings.json +++ b/typings.json @@ -15,10 +15,10 @@ "gruntjs": "registry:dt/gruntjs#0.4.0+20160316171810", "intern": "github:dojo/typings/custom/intern/intern.d.ts#92fcf688c0982c1107fca278de52e4bfe23bd8af", "leadfoot": "github:dojo/typings/custom/leadfoot/leadfoot.d.ts#8f3dfe6cafd04dfa78068785551552a5cfd88db1", - "mockery": "registry:dt/mockery#1.4.0+20160316155526", - "node": "github:dojo/typings/custom/node/node.d.ts#a62873258aa1deed48f9882c193c335436100d4b" + "mockery": "registry:dt/mockery#1.4.0+20160316155526" }, "globalDependencies": { - "dojo-loader": "npm:dojo-loader" + "dojo-loader": "npm:dojo-loader", + "node": "github:dojo/typings/custom/node/node.d.ts#a62873258aa1deed48f9882c193c335436100d4b" } } From c84c3acf8fc9aeb6b1f3f4e426ef23a4359e6d48 Mon Sep 17 00:00:00 2001 From: Bradley Maier Date: Wed, 11 Jan 2017 16:08:25 -0500 Subject: [PATCH 07/21] Update intern and add testingbot configuration --- package.json | 2 +- src/intern/intern-saucelabs.js | 2 +- src/intern/intern-testingbot.js | 38 +++++++++++++++++++++++++++++++++ src/main.ts | 21 ++++++++++++++++++ src/runTests.ts | 15 ++++++++++--- tests/intern.ts | 2 +- tests/support/MockModule.ts | 1 + typings.json | 9 -------- 8 files changed, 75 insertions(+), 15 deletions(-) create mode 100644 src/intern/intern-testingbot.js diff --git a/package.json b/package.json index d9d00f7..cbc6477 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "grunt": "~1.0.1", "grunt-tslint": "^3.0.0", "grunt-dojo2": "^2.0.0-beta.18", - "intern": "~3.3.2", + "intern": "~3.4.2", "istanbul": "^0.4.3", "mockery": "^1.7.0", "remap-istanbul": "^0.6.4", diff --git a/src/intern/intern-saucelabs.js b/src/intern/intern-saucelabs.js index b37ea5b..f8e8274 100644 --- a/src/intern/intern-saucelabs.js +++ b/src/intern/intern-saucelabs.js @@ -11,7 +11,7 @@ define([ intern.environments = [ { browserName: 'internet explorer', version: [ '10.0', '11.0' ], platform: 'Windows 7' }, // { browserName: 'microsoftedge', platform: 'Windows 10' }, - { browserName: 'firefox', version: '50', platform: 'Windows 10' }, + { browserName: 'firefox', version: '49', platform: 'Windows 10' }, { browserName: 'chrome', platform: 'Windows 10' }, // { browserName: 'safari', version: '9', platform: 'OS X 10.11' }, // { browserName: 'android', platform: 'Linux', version: '4.4', deviceName: 'Google Nexus 7 HD Emulator' }// , diff --git a/src/intern/intern-testingbot.js b/src/intern/intern-testingbot.js new file mode 100644 index 0000000..b0c2ed5 --- /dev/null +++ b/src/intern/intern-testingbot.js @@ -0,0 +1,38 @@ +define([ + './intern' +], function (intern) { + + intern.capabilities = { + project: '<%- appName %>', + name: '<%- appName %>' + }; + + intern.environments = [ + { browserName: 'internet explorer', version: [ '10', '11' ], platform: 'WIN8' }, + // { browserName: 'microsoftedge', platform: 'WIN10' }, + { browserName: 'firefox', version: '49', platform: 'WIN10' }, + { browserName: 'chrome', platform: 'WIN10' }, + // { browserName: 'safari', version: '9', platform: 'CAPITAN' }, + // { browserName: 'chrome', version: '55', platform: 'SIERRA' }, + // { browserName: 'browser', platform: 'ANDROID', version: '6.0', deviceName: 'Galaxy S6', platformName: 'Android' }// , + // { browserName: 'safari', platform: 'CAPITAN', version: '9.3', deviceName: 'iPhone 6s Plus', platformName: 'iOS' } + ]; + + /* Testingbot supports more max concurrency */ + intern.maxConcurrency = 3; + intern.tunnel = 'TestingBotTunnel'; + intern.webdriver = { + host: 'http://hub.testingbot.com/wd/hub', + username: 'key', + accessKey: 'secret' + }; + + intern.tunnelOptions = { + verbose: true, + apiKey: 'key', + apiSecret: 'secret' + }; + intern.useSauceConnect = false; + + return intern; +}); diff --git a/src/main.ts b/src/main.ts index abf2972..cff925e 100644 --- a/src/main.ts +++ b/src/main.ts @@ -9,6 +9,9 @@ export interface TestArgs extends Argv { functional: boolean; reporters: string; coverage: boolean; + testingKey: string; + secret: string; + userName: string; } const command: Command = { @@ -47,6 +50,24 @@ const command: Command = { describe: 'If specified coverage will be included. This is the same as adding the LcovHtml reporter' }); + helper.yargs.option('k', { + alias: 'testingKey', + describe: 'API key for testingbot or crossbrowsertesting or accesskey for saucelabs or browserstack', + type: 'string' + }); + + helper.yargs.option('n', { + alias: 'userName', + describe: 'User name for testing platform', + type: 'string' + }); + + helper.yargs.option('s', { + alias: 'secret', + describe: 'API secret for testingbot', + type: 'string' + }); + return helper.yargs; }, run(helper: Helper, args: TestArgs) { diff --git a/src/runTests.ts b/src/runTests.ts index 71ca92a..a38c437 100644 --- a/src/runTests.ts +++ b/src/runTests.ts @@ -8,9 +8,9 @@ const ora: any = require('ora'); const pkgDir: any = require('pkg-dir'); const packagePath = pkgDir.sync(dirname); -export function parseArguments({ unit, functional, environments, config, coverage, reporters }: TestArgs) { - config = config ? `-${config}` : ''; - const args = [ `config=${path.relative('.', path.join(packagePath, 'intern', 'intern' + config))}` ]; +export function parseArguments({ unit, functional, environments, config, coverage, reporters, testingKey, secret, userName }: TestArgs) { + const configArg = config ? `-${config}` : ''; + const args = [ `config=${path.relative('.', path.join(packagePath, 'intern', 'intern' + configArg))}` ]; if (unit) { args.push('functionalSuites='); } @@ -26,6 +26,15 @@ export function parseArguments({ unit, functional, environments, config, coverag if (coverage && reporterArgs.every((reporter) => reporter.indexOf('LcovHtml') < 0)) { reporterArgs.push('reporters=LcovHtml'); } + + if (config === 'testingbot' && testingKey && secret) { + args.push(`tunnelOptions={ "verbose": "true", "apiKey": "${testingKey}", "apiSecret": "${secret}" }`); + args.push(`webdriver={ "host": "http://hub.testingbot.com/wd/hub", "username": "${testingKey}", "accessKey": "${secret}" }`); + } + else if (userName && testingKey) { + args.push(`tunnelOptions={ "username": "${userName}", "accessKey": "${testingKey}" }`); + } + return [ ...args, ...environmentArgs, ...reporterArgs ]; } diff --git a/tests/intern.ts b/tests/intern.ts index 3c2f5ee..6f8e653 100644 --- a/tests/intern.ts +++ b/tests/intern.ts @@ -42,4 +42,4 @@ export const loaderOptions = { export const suites = [ 'tests/unit/all' ]; // A regular expression matching URLs to files that should not be included in code coverage analysis -export const excludeInstrumentation = /(?:node_modules|bower_components|tests)[\/\\]|intern\.js|intern-local\.js|intern-saucelabs\.js|dirname/; +export const excludeInstrumentation = /(?:node_modules|bower_components|tests)[\/\\]|intern\.js|intern-local\.js|intern-saucelabs\.js|intern-testingbot\.js|dirname/; diff --git a/tests/support/MockModule.ts b/tests/support/MockModule.ts index c0186d0..6b6450e 100644 --- a/tests/support/MockModule.ts +++ b/tests/support/MockModule.ts @@ -1,5 +1,6 @@ import * as mockery from 'mockery'; import * as sinon from 'sinon'; +import { IRootRequire } from 'dojo/loader'; declare const require: IRootRequire; const dojoNodePlugin = 'intern/dojo/node'; diff --git a/typings.json b/typings.json index d8a4ce6..a53920a 100644 --- a/typings.json +++ b/typings.json @@ -4,21 +4,12 @@ "yargs": "registry:npm/yargs#5.0.0+20160907000723" }, "devDependencies": { - "chai": "registry:npm/chai#3.5.0+20160415060238", "glob": "registry:npm/glob#6.0.0+20160211003958", "sinon": "registry:npm/sinon#1.16.0+20160723033700" }, "globalDevDependencies": { - "digdug": "github:dojo/typings/custom/digdug/digdug.d.ts#a62873258aa1deed48f9882c193c335436100d4b", - "dojo2": "github:dojo/typings/custom/dojo2/dojo.d.ts#a62873258aa1deed48f9882c193c335436100d4b", "dojo2-dev": "github:dojo/typings/custom/dev/dev.d.ts#288d3a9868194f0e1ad6687371dffd1d96cb39a1", "gruntjs": "registry:dt/gruntjs#0.4.0+20160316171810", - "intern": "github:dojo/typings/custom/intern/intern.d.ts#92fcf688c0982c1107fca278de52e4bfe23bd8af", - "leadfoot": "github:dojo/typings/custom/leadfoot/leadfoot.d.ts#8f3dfe6cafd04dfa78068785551552a5cfd88db1", "mockery": "registry:dt/mockery#1.4.0+20160316155526" - }, - "globalDependencies": { - "dojo-loader": "npm:dojo-loader", - "node": "github:dojo/typings/custom/node/node.d.ts#a62873258aa1deed48f9882c193c335436100d4b" } } From 2298656764064a71414f07c0d5a28766909b608a Mon Sep 17 00:00:00 2001 From: Bradley Maier Date: Wed, 11 Jan 2017 16:19:27 -0500 Subject: [PATCH 08/21] Use tabs consistently --- src/intern/intern-local.js | 18 ++--- src/intern/intern-saucelabs.js | 36 +++++----- src/intern/intern-testingbot.js | 60 ++++++++--------- src/intern/intern.js | 112 ++++++++++++++++---------------- 4 files changed, 113 insertions(+), 113 deletions(-) diff --git a/src/intern/intern-local.js b/src/intern/intern-local.js index b2fd589..831090a 100644 --- a/src/intern/intern-local.js +++ b/src/intern/intern-local.js @@ -1,15 +1,15 @@ define([ './intern' ], function (intern) { - intern.tunnel = 'NullTunnel'; - intern.tunnelOptions = { - hostname: 'localhost', - port: '4444' - }; + intern.tunnel = 'NullTunnel'; + intern.tunnelOptions = { + hostname: 'localhost', + port: '4444' + }; - intern.environments = [ - { browserName: 'chrome' } - ]; + intern.environments = [ + { browserName: 'chrome' } + ]; - return intern; + return intern; }); diff --git a/src/intern/intern-saucelabs.js b/src/intern/intern-saucelabs.js index f8e8274..6840448 100644 --- a/src/intern/intern-saucelabs.js +++ b/src/intern/intern-saucelabs.js @@ -2,29 +2,29 @@ define([ './intern' ], function (intern) { - intern.capabilities = { - project: '<%- appName %>', - name: '<%- appName %>', - fixSessionCapabilities: false - }; + intern.capabilities = { + project: '<%- appName %>', + name: '<%- appName %>', + fixSessionCapabilities: false + }; - intern.environments = [ - { browserName: 'internet explorer', version: [ '10.0', '11.0' ], platform: 'Windows 7' }, - // { browserName: 'microsoftedge', platform: 'Windows 10' }, - { browserName: 'firefox', version: '49', platform: 'Windows 10' }, - { browserName: 'chrome', platform: 'Windows 10' }, - // { browserName: 'safari', version: '9', platform: 'OS X 10.11' }, - // { browserName: 'android', platform: 'Linux', version: '4.4', deviceName: 'Google Nexus 7 HD Emulator' }// , - // { browserName: 'iphone', version: '9.1', deviceName: 'iPhone 6' } - ]; + intern.environments = [ + { browserName: 'internet explorer', version: [ '10.0', '11.0' ], platform: 'Windows 7' }, + // { browserName: 'microsoftedge', platform: 'Windows 10' }, + { browserName: 'firefox', version: '49', platform: 'Windows 10' }, + { browserName: 'chrome', platform: 'Windows 10' }, + // { browserName: 'safari', version: '9', platform: 'OS X 10.11' }, + // { browserName: 'android', platform: 'Linux', version: '4.4', deviceName: 'Google Nexus 7 HD Emulator' }// , + // { browserName: 'iphone', version: '9.1', deviceName: 'iPhone 6' } + ]; /* SauceLabs supports more max concurrency */ - intern.maxConcurrency = 4; + intern.maxConcurrency = 4; /* SauceLabs combined with Travis often causes functional tests to fail with too short a timeout */ - intern.defaultTimeout = 10000; + intern.defaultTimeout = 10000; - intern.tunnel = 'SauceLabsTunnel'; + intern.tunnel = 'SauceLabsTunnel'; - return intern; + return intern; }); diff --git a/src/intern/intern-testingbot.js b/src/intern/intern-testingbot.js index b0c2ed5..6df29b9 100644 --- a/src/intern/intern-testingbot.js +++ b/src/intern/intern-testingbot.js @@ -1,38 +1,38 @@ define([ - './intern' + './intern' ], function (intern) { - intern.capabilities = { - project: '<%- appName %>', - name: '<%- appName %>' - }; + intern.capabilities = { + project: '<%- appName %>', + name: '<%- appName %>' + }; - intern.environments = [ - { browserName: 'internet explorer', version: [ '10', '11' ], platform: 'WIN8' }, - // { browserName: 'microsoftedge', platform: 'WIN10' }, - { browserName: 'firefox', version: '49', platform: 'WIN10' }, - { browserName: 'chrome', platform: 'WIN10' }, - // { browserName: 'safari', version: '9', platform: 'CAPITAN' }, - // { browserName: 'chrome', version: '55', platform: 'SIERRA' }, - // { browserName: 'browser', platform: 'ANDROID', version: '6.0', deviceName: 'Galaxy S6', platformName: 'Android' }// , - // { browserName: 'safari', platform: 'CAPITAN', version: '9.3', deviceName: 'iPhone 6s Plus', platformName: 'iOS' } - ]; + intern.environments = [ + { browserName: 'internet explorer', version: [ '10', '11' ], platform: 'WIN8' }, + // { browserName: 'microsoftedge', platform: 'WIN10' }, + { browserName: 'firefox', version: '49', platform: 'WIN10' }, + { browserName: 'chrome', platform: 'WIN10' }, + // { browserName: 'safari', version: '9', platform: 'CAPITAN' }, + // { browserName: 'chrome', version: '55', platform: 'SIERRA' }, + // { browserName: 'browser', platform: 'ANDROID', version: '6.0', deviceName: 'Galaxy S6', platformName: 'Android' }// , + // { browserName: 'safari', platform: 'CAPITAN', version: '9.3', deviceName: 'iPhone 6s Plus', platformName: 'iOS' } + ]; - /* Testingbot supports more max concurrency */ - intern.maxConcurrency = 3; - intern.tunnel = 'TestingBotTunnel'; - intern.webdriver = { - host: 'http://hub.testingbot.com/wd/hub', - username: 'key', - accessKey: 'secret' - }; + /* Testingbot supports more max concurrency */ + intern.maxConcurrency = 3; + intern.tunnel = 'TestingBotTunnel'; + intern.webdriver = { + host: 'http://hub.testingbot.com/wd/hub', + username: 'key', + accessKey: 'secret' + }; - intern.tunnelOptions = { - verbose: true, - apiKey: 'key', - apiSecret: 'secret' - }; - intern.useSauceConnect = false; + intern.tunnelOptions = { + verbose: true, + apiKey: 'key', + apiSecret: 'secret' + }; + intern.useSauceConnect = false; - return intern; + return intern; }); diff --git a/src/intern/intern.js b/src/intern/intern.js index 15c7e3d..262efb0 100644 --- a/src/intern/intern.js +++ b/src/intern/intern.js @@ -2,74 +2,74 @@ define({ proxyPort: 9000, // A fully qualified URL to the Intern proxy - proxyUrl: 'http://localhost:9000/', + proxyUrl: 'http://localhost:9000/', - // Default desired capabilities for all environments. Individual capabilities can be overridden by any of the - // specified browser environments in the `environments` array below as well. See - // https://code.google.com/p/selenium/wiki/DesiredCapabilities for standard Selenium capabilities and - // https://saucelabs.com/docs/additional-config#desired-capabilities for Sauce Labs capabilities. - // Note that the `build` capability will be filled in with the current commit ID from the Travis CI environment - // automatically - capabilities: { - 'browserstack.debug': false, - project: '<%- appName %>', - name: '<%- appName %>', - fixSessionCapabilities: false - }, + // Default desired capabilities for all environments. Individual capabilities can be overridden by any of the + // specified browser environments in the `environments` array below as well. See + // https://code.google.com/p/selenium/wiki/DesiredCapabilities for standard Selenium capabilities and + // https://saucelabs.com/docs/additional-config#desired-capabilities for Sauce Labs capabilities. + // Note that the `build` capability will be filled in with the current commit ID from the Travis CI environment + // automatically + capabilities: { + 'browserstack.debug': false, + project: '<%- appName %>', + name: '<%- appName %>', + fixSessionCapabilities: false + }, - // Browsers to run integration testing against. Note that version numbers must be strings if used with Sauce - // OnDemand. Options that will be permutated are browserName, version, platform, and platformVersion; any other - // capabilities options specified for an environment will be copied as-is - environments: [ - { browserName: 'internet explorer', version: [ '10', '11' ], platform: 'WINDOWS' }, - { browserName: 'firefox', platform: 'WINDOWS' }, - { browserName: 'chrome', platform: 'WINDOWS' }/*, + // Browsers to run integration testing against. Note that version numbers must be strings if used with Sauce + // OnDemand. Options that will be permutated are browserName, version, platform, and platformVersion; any other + // capabilities options specified for an environment will be copied as-is + environments: [ + { browserName: 'internet explorer', version: [ '10', '11' ], platform: 'WINDOWS' }, + { browserName: 'firefox', platform: 'WINDOWS' }, + { browserName: 'chrome', platform: 'WINDOWS' }/*, { browserName: 'Safari', version: '9', platform: 'OS X' }*/ - ], + ], // Maximum number of simultaneous integration tests that should be executed on the remote WebDriver service - maxConcurrency: 2, + maxConcurrency: 2, // Name of the tunnel class to use for WebDriver tests - tunnel: 'BrowserStackTunnel', + tunnel: 'BrowserStackTunnel', - // Support running unit tests from a web server that isn't the intern proxy - initialBaseUrl: (function () { - if (typeof location !== 'undefined' && location.pathname.indexOf('__intern/') > -1) { - return '/'; - } - return null; - })(), + // Support running unit tests from a web server that isn't the intern proxy + initialBaseUrl: (function () { + if (typeof location !== 'undefined' && location.pathname.indexOf('__intern/') > -1) { + return '/'; + } + return null; + })(), - // The desired AMD loader to use when running unit tests (client.html/client.js). Omit to use the default Dojo - // loader - loaders: { - 'host-browser': 'node_modules/dojo-loader/loader.js', - 'host-node': 'dojo-loader' - }, + // The desired AMD loader to use when running unit tests (client.html/client.js). Omit to use the default Dojo + // loader + loaders: { + 'host-browser': 'node_modules/dojo-loader/loader.js', + 'host-node': 'dojo-loader' + }, - // Configuration options for the module loader; any AMD configuration options supported by the specified AMD loader - // can be used here - loaderOptions: { - // Packages that should be registered with the loader in each testing environment - packages: [ - { name: 'src', location: '_build/src' }, - { name: 'tests', location: '_build/tests' }, - { name: 'dojo', location: 'node_modules/intern/browser_modules/dojo' }, - { name: 'dojo-has', location: 'node_modules/dojo-has' }, - { name: 'dojo-shim', location: 'node_modules/dojo-shim' }, - { name: 'sinon', location: 'node_modules/sinon/pkg', main: 'sinon' } - ] - }, + // Configuration options for the module loader; any AMD configuration options supported by the specified AMD loader + // can be used here + loaderOptions: { + // Packages that should be registered with the loader in each testing environment + packages: [ + { name: 'src', location: '_build/src' }, + { name: 'tests', location: '_build/tests' }, + { name: 'dojo', location: 'node_modules/intern/browser_modules/dojo' }, + { name: 'dojo-has', location: 'node_modules/dojo-has' }, + { name: 'dojo-shim', location: 'node_modules/dojo-shim' }, + { name: 'sinon', location: 'node_modules/sinon/pkg', main: 'sinon' } + ] + }, - // Non-functional test suite(s) to run in each browser - suites: [ 'tests/unit/all' ], + // Non-functional test suite(s) to run in each browser + suites: [ 'tests/unit/all' ], - // Functional test suite(s) to run in each browser once non-functional tests are completed - functionalSuites: [ 'tests/functional/all' ], + // Functional test suite(s) to run in each browser once non-functional tests are completed + functionalSuites: [ 'tests/functional/all' ], - // A regular expression matching URLs to files that should not be included in code coverage analysis - excludeInstrumentation: /(?:node_modules|bower_components|tests)[\/]/, + // A regular expression matching URLs to files that should not be included in code coverage analysis + excludeInstrumentation: /(?:node_modules|bower_components|tests)[\/]/, - defaultTimeout: 5000 + defaultTimeout: 5000 }); From 5274c599d2c2bdc960ecce96fbd53048a1483f09 Mon Sep 17 00:00:00 2001 From: Bradley Maier Date: Wed, 11 Jan 2017 16:21:50 -0500 Subject: [PATCH 09/21] Use selenium tunnel for local intern config --- src/intern/intern-local.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/intern/intern-local.js b/src/intern/intern-local.js index 831090a..1fa843e 100644 --- a/src/intern/intern-local.js +++ b/src/intern/intern-local.js @@ -1,7 +1,7 @@ define([ './intern' ], function (intern) { - intern.tunnel = 'NullTunnel'; + intern.tunnel = 'SeleniumTunnel'; intern.tunnelOptions = { hostname: 'localhost', port: '4444' From 6d7a03f978d5410b6fd6d90215135dd0a040faff Mon Sep 17 00:00:00 2001 From: Bradley Maier Date: Wed, 11 Jan 2017 23:55:05 -0500 Subject: [PATCH 10/21] Add more saucelabs browser examples --- src/intern/intern-saucelabs.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/intern/intern-saucelabs.js b/src/intern/intern-saucelabs.js index 6840448..42315d2 100644 --- a/src/intern/intern-saucelabs.js +++ b/src/intern/intern-saucelabs.js @@ -14,8 +14,10 @@ define([ { browserName: 'firefox', version: '49', platform: 'Windows 10' }, { browserName: 'chrome', platform: 'Windows 10' }, // { browserName: 'safari', version: '9', platform: 'OS X 10.11' }, + // { browserName: 'chrome', version: '54.0', platform: 'macOS 10.12' }, // { browserName: 'android', platform: 'Linux', version: '4.4', deviceName: 'Google Nexus 7 HD Emulator' }// , - // { browserName: 'iphone', version: '9.1', deviceName: 'iPhone 6' } + // { browserName: 'opera', version: '12.15', platform: 'Linux' }, + // { browserName: 'iphone', version: '9.1', deviceName: 'iPhone 6' }, ]; /* SauceLabs supports more max concurrency */ From dd659e1dae7802805efd64ebdda9a0601dd7c02d Mon Sep 17 00:00:00 2001 From: Bradley Maier Date: Wed, 11 Jan 2017 23:58:30 -0500 Subject: [PATCH 11/21] Add more examples --- src/intern/intern-saucelabs.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/intern/intern-saucelabs.js b/src/intern/intern-saucelabs.js index 42315d2..82b59a1 100644 --- a/src/intern/intern-saucelabs.js +++ b/src/intern/intern-saucelabs.js @@ -15,8 +15,10 @@ define([ { browserName: 'chrome', platform: 'Windows 10' }, // { browserName: 'safari', version: '9', platform: 'OS X 10.11' }, // { browserName: 'chrome', version: '54.0', platform: 'macOS 10.12' }, + // { browserName: 'firefox', version: '49.0', platform: 'macOS 10.12' }, // { browserName: 'android', platform: 'Linux', version: '4.4', deviceName: 'Google Nexus 7 HD Emulator' }// , // { browserName: 'opera', version: '12.15', platform: 'Linux' }, + // { browserName: 'chrome', version: '48.0', platform: 'Linux' }, // { browserName: 'iphone', version: '9.1', deviceName: 'iPhone 6' }, ]; From 924430677624548ab38222fdacf8d8ede7b5cbb5 Mon Sep 17 00:00:00 2001 From: Bradley Maier Date: Thu, 12 Jan 2017 11:23:11 -0500 Subject: [PATCH 12/21] Update tests for new config options, and add testingbot to config description --- src/main.ts | 4 ++-- tests/unit/main.ts | 20 +++++++++++++++++++- tests/unit/runTests.ts | 18 ++++++++++++++++++ 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/main.ts b/src/main.ts index cff925e..6bc0282 100644 --- a/src/main.ts +++ b/src/main.ts @@ -19,7 +19,7 @@ const command: Command = { register(helper: Helper) { helper.yargs.option('c', { alias: 'config', - describe: 'Specifies what configuration to test with: browserstack(default), \'saucelabs\', or \'local\'ly.', + describe: 'Specifies what configuration to test with: browserstack(default), \'testingbot\', \'saucelabs\', or \'local\'ly.', type: 'string' }); @@ -52,7 +52,7 @@ const command: Command = { helper.yargs.option('k', { alias: 'testingKey', - describe: 'API key for testingbot or crossbrowsertesting or accesskey for saucelabs or browserstack', + describe: 'API key for testingbot or accesskey for saucelabs or browserstack', type: 'string' }); diff --git a/tests/unit/main.ts b/tests/unit/main.ts index 773991b..2ddfd28 100644 --- a/tests/unit/main.ts +++ b/tests/unit/main.ts @@ -33,7 +33,7 @@ describe('main', () => { moduleUnderTest.register(helper); assert.deepEqual( helper.yargs.option.firstCall.args, - [ 'c', { alias: 'config', describe: 'Specifies what configuration to test with: browserstack(default), \'saucelabs\', or \'local\'ly.', type: 'string' } ], + [ 'c', { alias: 'config', describe: 'Specifies what configuration to test with: browserstack(default), \'testingbot\', \'saucelabs\', or \'local\'ly.', type: 'string' } ], 'First argument' ); assert.deepEqual( @@ -65,6 +65,24 @@ describe('main', () => { [ 'cov', { alias: 'coverage', describe: 'If specified coverage will be included. This is the same as adding the LcovHtml reporter' }], 'Sixth argument' ); + + assert.deepEqual( + helper.yargs.option.getCall(6).args, + [ 'k', { alias: 'testingKey', describe: 'API key for testingbot or accesskey for saucelabs or browserstack', type: 'string' }], + 'Seventh Argument' + ); + + assert.deepEqual( + helper.yargs.option.getCall(7).args, + [ 'n', { alias: 'userName', describe: 'User name for testing platform', type: 'string' }], + 'Eigth Argument' + ); + + assert.deepEqual( + helper.yargs.option.getCall(8).args, + [ 's', { alias: 'secret', describe: 'API secret for testingbot', type: 'string' }], + 'Ninth Argument' + ); }); it('should check for build command and fail if it doesn\'t exist', () => { diff --git a/tests/unit/runTests.ts b/tests/unit/runTests.ts index d0754bd..93c3b07 100644 --- a/tests/unit/runTests.ts +++ b/tests/unit/runTests.ts @@ -118,5 +118,23 @@ describe('runTests', () => { assert.equal('reporters=LcovHtml', args[1]); assert.equal(2, args.length); }); + + it('Should set testingbot tunnel config if provided', () => { + const args = runTests.parseArguments({ + config: 'testingbot', + testingKey: 'key', + secret: 'secret' + }); + assert.equal('tunnelOptions={ "verbose": "true", "apiKey": "key", "apiSecret": "secret" }', args[1]); + + assert.equal('webdriver={ "host": "http://hub.testingbot.com/wd/hub", "username": "key", "accessKey": "secret" }', args[2]); + }); + + it('Should set normal tunnel config if provided', () => { + assert.equal('tunnelOptions={ "username": "user", "accessKey": "key" }', runTests.parseArguments({ + testingKey: 'key', + userName: 'user' + })[1]); + }); }); }); From 4550eb76708f4a69454165bb1f03ea061cdce8b4 Mon Sep 17 00:00:00 2001 From: Bradley Maier Date: Mon, 16 Jan 2017 11:46:29 -0500 Subject: [PATCH 13/21] Move to scoped packages and pin dojo dependencies --- package.json | 6 +++--- src/main.ts | 2 +- tests/intern.ts | 5 +++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index cbc6477..cfc2762 100644 --- a/package.json +++ b/package.json @@ -19,13 +19,13 @@ "devDependencies": { "@types/chalk": "^0.4.31", "codecov.io": "0.1.6", - "dojo-cli": "^2.0.0-alpha.3", - "dojo-loader": ">=2.0.0-beta.7", + "@dojo/cli": "2.0.0-alpha.8", + "@dojo/loader": "2.0.0-beta.9", "dts-generator": "~1.7.0", "glob": "^7.0.3", "grunt": "~1.0.1", "grunt-tslint": "^3.0.0", - "grunt-dojo2": "^2.0.0-beta.18", + "grunt-dojo2": "2.0.0-beta.23", "intern": "~3.4.2", "istanbul": "^0.4.3", "mockery": "^1.7.0", diff --git a/src/main.ts b/src/main.ts index 6bc0282..014cffa 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,4 +1,4 @@ -import { Command, Helper } from 'dojo-cli/interfaces'; +import { Command, Helper } from '@dojo/cli/interfaces'; import { Argv } from 'yargs'; import runTests from './runTests'; diff --git a/tests/intern.ts b/tests/intern.ts index 6f8e653..f7b84e5 100644 --- a/tests/intern.ts +++ b/tests/intern.ts @@ -25,7 +25,7 @@ export const initialBaseUrl: string = (function () { // The desired AMD loader to use when running unit tests (client.html/client.js). Omit to use the default Dojo // loader export const loaders = { - 'host-node': 'dojo-loader' + 'host-node': '@dojo/loader' }; // Configuration options for the module loader; any AMD configuration options supported by the specified AMD loader @@ -34,7 +34,8 @@ export const loaderOptions = { // Packages that should be registered with the loader in each testing environment packages: [ { name: 'src', location: '_build/src' }, - { name: 'tests', location: '_build/tests' } + { name: 'tests', location: '_build/tests' }, + { name: '@dojo', location: 'node_modules/@dojo' } ] }; From 6cdf27d8162f98458f84a559144c9383ef3f1e7c Mon Sep 17 00:00:00 2001 From: Bradley Maier Date: Mon, 16 Jan 2017 11:59:21 -0500 Subject: [PATCH 14/21] Update intenr files for apps using cli to use scoped packages --- src/intern/intern.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/intern/intern.js b/src/intern/intern.js index 262efb0..1e5af48 100644 --- a/src/intern/intern.js +++ b/src/intern/intern.js @@ -44,8 +44,8 @@ define({ // The desired AMD loader to use when running unit tests (client.html/client.js). Omit to use the default Dojo // loader loaders: { - 'host-browser': 'node_modules/dojo-loader/loader.js', - 'host-node': 'dojo-loader' + 'host-browser': 'node_modules/@dojo/loader/loader.js', + 'host-node': '@dojo/loader' }, // Configuration options for the module loader; any AMD configuration options supported by the specified AMD loader @@ -56,9 +56,8 @@ define({ { name: 'src', location: '_build/src' }, { name: 'tests', location: '_build/tests' }, { name: 'dojo', location: 'node_modules/intern/browser_modules/dojo' }, - { name: 'dojo-has', location: 'node_modules/dojo-has' }, - { name: 'dojo-shim', location: 'node_modules/dojo-shim' }, - { name: 'sinon', location: 'node_modules/sinon/pkg', main: 'sinon' } + { name: 'sinon', location: 'node_modules/sinon/pkg', main: 'sinon' }, + { name: '@dojo', location: 'node_modules/@dojo' } ] }, From 4ab0441f437fe73d54a7630d8faa28e852f48aa3 Mon Sep 17 00:00:00 2001 From: Bradley Maier Date: Mon, 16 Jan 2017 12:14:53 -0500 Subject: [PATCH 15/21] Use path.join in tests --- tests/unit/runTests.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/unit/runTests.ts b/tests/unit/runTests.ts index 93c3b07..45f59d3 100644 --- a/tests/unit/runTests.ts +++ b/tests/unit/runTests.ts @@ -1,6 +1,7 @@ import { before, beforeEach, after, afterEach, describe, it } from 'intern!bdd'; import * as assert from 'intern/chai!assert'; import * as mockery from 'mockery'; +import * as path from 'path'; import { stub, SinonStub } from 'sinon'; const cs: any = require('cross-spawn'); @@ -74,11 +75,11 @@ describe('runTests', () => { describe('Should parse arguments', () => { it('Should use config to set intern file if provided', () => { - assert.equal('config=intern\\intern-test', runTests.parseArguments({config: 'test'})[0]); + assert.equal(path.join('config=intern', 'intern-test'), runTests.parseArguments({config: 'test'})[0]); }); it('Should have a default for intern config', () => { - assert.equal('config=intern\\intern', runTests.parseArguments({})[0]); + assert.equal(path.join('config=intern', 'intern'), runTests.parseArguments({})[0]); }); it('Should push an empty functionalSuites arg if unit is provided', () => { From 1cc8225dd9e5a4057305f66c4cf625e227194320 Mon Sep 17 00:00:00 2001 From: Bradley Maier Date: Wed, 18 Jan 2017 01:59:39 -0500 Subject: [PATCH 16/21] Fix various issues * Moved to scoped packages * Make local tests the default * Specify capabilities at run time so the project name can be read from package.json --- package.json | 2 +- src/intern/intern-browserstack.js | 16 ++++++++++++++++ src/intern/intern-local.js | 15 --------------- src/intern/intern-saucelabs.js | 7 +------ src/intern/intern-testingbot.js | 5 ----- src/intern/intern.js | 27 +++++++-------------------- src/main.ts | 4 ++-- src/runTests.ts | 25 ++++++++++++++++++------- tests/intern.ts | 4 ++-- tests/unit/main.ts | 4 ++-- tests/unit/runTests.ts | 29 ++++++++++++++++++++++++++++- 11 files changed, 77 insertions(+), 61 deletions(-) create mode 100644 src/intern/intern-browserstack.js delete mode 100644 src/intern/intern-local.js diff --git a/package.json b/package.json index cfc2762..81f8447 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "dojo-cli-test-intern", + "name": "@dojo/cli-test-intern", "version": "2.0.0-pre", "description": "Test a Dojo 2 application", "private": true, diff --git a/src/intern/intern-browserstack.js b/src/intern/intern-browserstack.js new file mode 100644 index 0000000..29fabb7 --- /dev/null +++ b/src/intern/intern-browserstack.js @@ -0,0 +1,16 @@ +define([ + './intern' +], function (intern) { + intern.tunnel = 'BrowserstackTunnel'; + intern.tunnelOptions = {}; + intern.maxConcurrency = 2; + + intern.environments = [ + { browserName: 'internet explorer', version: [ '10', '11' ], platform: 'WINDOWS' }, + { browserName: 'firefox', platform: 'WINDOWS' }, + { browserName: 'chrome', platform: 'WINDOWS' }/*, + { browserName: 'Safari', version: '9', platform: 'OS X' }*/ + ]; + + return intern; +}); diff --git a/src/intern/intern-local.js b/src/intern/intern-local.js deleted file mode 100644 index 1fa843e..0000000 --- a/src/intern/intern-local.js +++ /dev/null @@ -1,15 +0,0 @@ -define([ - './intern' -], function (intern) { - intern.tunnel = 'SeleniumTunnel'; - intern.tunnelOptions = { - hostname: 'localhost', - port: '4444' - }; - - intern.environments = [ - { browserName: 'chrome' } - ]; - - return intern; -}); diff --git a/src/intern/intern-saucelabs.js b/src/intern/intern-saucelabs.js index 82b59a1..c9cf862 100644 --- a/src/intern/intern-saucelabs.js +++ b/src/intern/intern-saucelabs.js @@ -2,12 +2,6 @@ define([ './intern' ], function (intern) { - intern.capabilities = { - project: '<%- appName %>', - name: '<%- appName %>', - fixSessionCapabilities: false - }; - intern.environments = [ { browserName: 'internet explorer', version: [ '10.0', '11.0' ], platform: 'Windows 7' }, // { browserName: 'microsoftedge', platform: 'Windows 10' }, @@ -29,6 +23,7 @@ define([ intern.defaultTimeout = 10000; intern.tunnel = 'SauceLabsTunnel'; + intern.tunnelOptions = {}; return intern; }); diff --git a/src/intern/intern-testingbot.js b/src/intern/intern-testingbot.js index 6df29b9..a8f8a02 100644 --- a/src/intern/intern-testingbot.js +++ b/src/intern/intern-testingbot.js @@ -2,11 +2,6 @@ define([ './intern' ], function (intern) { - intern.capabilities = { - project: '<%- appName %>', - name: '<%- appName %>' - }; - intern.environments = [ { browserName: 'internet explorer', version: [ '10', '11' ], platform: 'WIN8' }, // { browserName: 'microsoftedge', platform: 'WIN10' }, diff --git a/src/intern/intern.js b/src/intern/intern.js index 1e5af48..3f0ce05 100644 --- a/src/intern/intern.js +++ b/src/intern/intern.js @@ -4,35 +4,22 @@ define({ // A fully qualified URL to the Intern proxy proxyUrl: 'http://localhost:9000/', - // Default desired capabilities for all environments. Individual capabilities can be overridden by any of the - // specified browser environments in the `environments` array below as well. See - // https://code.google.com/p/selenium/wiki/DesiredCapabilities for standard Selenium capabilities and - // https://saucelabs.com/docs/additional-config#desired-capabilities for Sauce Labs capabilities. - // Note that the `build` capability will be filled in with the current commit ID from the Travis CI environment - // automatically - capabilities: { - 'browserstack.debug': false, - project: '<%- appName %>', - name: '<%- appName %>', - fixSessionCapabilities: false - }, - // Browsers to run integration testing against. Note that version numbers must be strings if used with Sauce // OnDemand. Options that will be permutated are browserName, version, platform, and platformVersion; any other // capabilities options specified for an environment will be copied as-is environments: [ - { browserName: 'internet explorer', version: [ '10', '11' ], platform: 'WINDOWS' }, - { browserName: 'firefox', platform: 'WINDOWS' }, - { browserName: 'chrome', platform: 'WINDOWS' }/*, - { browserName: 'Safari', version: '9', platform: 'OS X' }*/ + { browserName: 'chrome' } ], // Maximum number of simultaneous integration tests that should be executed on the remote WebDriver service maxConcurrency: 2, // Name of the tunnel class to use for WebDriver tests - tunnel: 'BrowserStackTunnel', - + tunnel: 'SeleniumTunnel', + tunnelOptions: { + hostname: 'localhost', + port: '4444' + }, // Support running unit tests from a web server that isn't the intern proxy initialBaseUrl: (function () { if (typeof location !== 'undefined' && location.pathname.indexOf('__intern/') > -1) { @@ -55,7 +42,7 @@ define({ packages: [ { name: 'src', location: '_build/src' }, { name: 'tests', location: '_build/tests' }, - { name: 'dojo', location: 'node_modules/intern/browser_modules/dojo' }, + { name: 'dojo', location: 'node_modules/intern/node_modules/dojo' }, { name: 'sinon', location: 'node_modules/sinon/pkg', main: 'sinon' }, { name: '@dojo', location: 'node_modules/@dojo' } ] diff --git a/src/main.ts b/src/main.ts index 014cffa..63f16a7 100644 --- a/src/main.ts +++ b/src/main.ts @@ -19,7 +19,7 @@ const command: Command = { register(helper: Helper) { helper.yargs.option('c', { alias: 'config', - describe: 'Specifies what configuration to test with: browserstack(default), \'testingbot\', \'saucelabs\', or \'local\'ly.', + describe: 'Specifies what configuration to test with: \'local\'(default), \'browserstack\', \'testingbot\', or \'saucelabs\'.', type: 'string' }); @@ -73,7 +73,7 @@ const command: Command = { run(helper: Helper, args: TestArgs) { return new Promise((resolve, reject) => { if (!helper.command.exists('build')) { - reject(Error('Required command: \'build\', does not exist')); + reject(Error('Required command: \'build\', does not exist. Have you run npm install @dojo/cli-build?')); } const result = helper.command.run('build', '', { withTests: true }); result.then( diff --git a/src/runTests.ts b/src/runTests.ts index a38c437..ffac279 100644 --- a/src/runTests.ts +++ b/src/runTests.ts @@ -7,6 +7,7 @@ const cs: any = require('cross-spawn'); const ora: any = require('ora'); const pkgDir: any = require('pkg-dir'); const packagePath = pkgDir.sync(dirname); +const projectName = require(path.join(packagePath, 'package.json')).name; export function parseArguments({ unit, functional, environments, config, coverage, reporters, testingKey, secret, userName }: TestArgs) { const configArg = config ? `-${config}` : ''; @@ -18,13 +19,13 @@ export function parseArguments({ unit, functional, environments, config, coverag args.push('suites='); } - const environmentArgs = environments ? environments.split(',').map( - (environment) => `environments={ "browserName": "${environment}" }` - ) : []; + args.push(...(environments ? environments.split(',').map( + (environment) => `environments={ "browserName": "${environment}" }` + ) : [])); - const reporterArgs = reporters ? reporters.split(',').map((reporter) => `reporters=${reporter}`) : []; - if (coverage && reporterArgs.every((reporter) => reporter.indexOf('LcovHtml') < 0)) { - reporterArgs.push('reporters=LcovHtml'); + args.push(...(reporters ? reporters.split(',').map((reporter) => `reporters=${reporter}`) : [])); + if (coverage && args.every((reporter) => reporter.indexOf('LcovHtml') < 0)) { + args.push('reporters=LcovHtml'); } if (config === 'testingbot' && testingKey && secret) { @@ -35,7 +36,17 @@ export function parseArguments({ unit, functional, environments, config, coverag args.push(`tunnelOptions={ "username": "${userName}", "accessKey": "${testingKey}" }`); } - return [ ...args, ...environmentArgs, ...reporterArgs ]; + const capabilitiesBase = `capabilities={ "name": "${projectName}", "project": "${projectName}"`; + if (config === 'browserstack') { + args.push(capabilitiesBase + ', "fixSessionCapabilities": "false", "browserstack.debug": "false" }'); + } + else if (config === 'saucelabs') { + args.push(capabilitiesBase + ', "fixSessionCapabilities": "false" }'); + } + else { + args.push(capabilitiesBase + ' }'); + } + return [ ...args ]; } export default async function (testArgs: TestArgs) { diff --git a/tests/intern.ts b/tests/intern.ts index f7b84e5..8726dd0 100644 --- a/tests/intern.ts +++ b/tests/intern.ts @@ -11,7 +11,7 @@ export const proxyUrl = 'http://localhost:9000/'; // automatically export const capabilities = { project: 'Dojo 2', - name: 'dojo-cli-test-intern' + name: '@dojo/cli-test-intern' }; // Support running unit tests from a web server that isn't the intern proxy @@ -43,4 +43,4 @@ export const loaderOptions = { export const suites = [ 'tests/unit/all' ]; // A regular expression matching URLs to files that should not be included in code coverage analysis -export const excludeInstrumentation = /(?:node_modules|bower_components|tests)[\/\\]|intern\.js|intern-local\.js|intern-saucelabs\.js|intern-testingbot\.js|dirname/; +export const excludeInstrumentation = /(?:node_modules|bower_components|tests)[\/\\]|intern\.js|intern-browserstack\.js|intern-saucelabs\.js|intern-testingbot\.js|dirname/; diff --git a/tests/unit/main.ts b/tests/unit/main.ts index 2ddfd28..9789915 100644 --- a/tests/unit/main.ts +++ b/tests/unit/main.ts @@ -33,7 +33,7 @@ describe('main', () => { moduleUnderTest.register(helper); assert.deepEqual( helper.yargs.option.firstCall.args, - [ 'c', { alias: 'config', describe: 'Specifies what configuration to test with: browserstack(default), \'testingbot\', \'saucelabs\', or \'local\'ly.', type: 'string' } ], + [ 'c', { alias: 'config', describe: 'Specifies what configuration to test with: \'local\'(default), \'browserstack\', \'testingbot\', or \'saucelabs\'.', type: 'string' } ], 'First argument' ); assert.deepEqual( @@ -95,7 +95,7 @@ describe('main', () => { throwImmediatly, (e: Error) => { assert.isTrue(helper.command.exists.calledOnce); - assert.equal(e.message, 'Required command: \'build\', does not exist'); + assert.equal(e.message, 'Required command: \'build\', does not exist. Have you run npm install @dojo/cli-build?'); } ); }); diff --git a/tests/unit/runTests.ts b/tests/unit/runTests.ts index 45f59d3..1a46b02 100644 --- a/tests/unit/runTests.ts +++ b/tests/unit/runTests.ts @@ -117,7 +117,7 @@ describe('runTests', () => { coverage: true }); assert.equal('reporters=LcovHtml', args[1]); - assert.equal(2, args.length); + assert.equal(3, args.length); }); it('Should set testingbot tunnel config if provided', () => { @@ -137,5 +137,32 @@ describe('runTests', () => { userName: 'user' })[1]); }); + + it('Should set capabilities based on project name and according to config', () => { + const capabilitiesBase = 'capabilities={ "name": "@dojo/cli-test-intern", "project": "@dojo/cli-test-intern"'; + assert.equal( + capabilitiesBase + ', "fixSessionCapabilities": "false", "browserstack.debug": "false" }', + runTests.parseArguments({ + config: 'browserstack' + })[1], + 'Didn\'t add browserstack config' + ); + + assert.equal( + capabilitiesBase + ', "fixSessionCapabilities": "false" }', + runTests.parseArguments({ + config: 'saucelabs' + })[1], + 'Didn\'t add saucelabs config' + ); + + assert.equal( + capabilitiesBase + ' }', + runTests.parseArguments({ + config: 'anything else' + })[1], + 'Didn\'t add default config config' + ); + }); }); }); From fb5c440c1afaacb42ed17aa1f037d5eadd475f50 Mon Sep 17 00:00:00 2001 From: Bradley Maier Date: Wed, 18 Jan 2017 02:11:43 -0500 Subject: [PATCH 17/21] Fix path to package.json and order of arguments --- src/runTests.ts | 3 ++- tests/unit/runTests.ts | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/runTests.ts b/src/runTests.ts index ffac279..a8786bb 100644 --- a/src/runTests.ts +++ b/src/runTests.ts @@ -7,7 +7,8 @@ const cs: any = require('cross-spawn'); const ora: any = require('ora'); const pkgDir: any = require('pkg-dir'); const packagePath = pkgDir.sync(dirname); -const projectName = require(path.join(packagePath, 'package.json')).name; +const process = require('process'); +const projectName = require(path.join(process.cwd(), './package.json')).name; export function parseArguments({ unit, functional, environments, config, coverage, reporters, testingKey, secret, userName }: TestArgs) { const configArg = config ? `-${config}` : ''; diff --git a/tests/unit/runTests.ts b/tests/unit/runTests.ts index 1a46b02..10c5374 100644 --- a/tests/unit/runTests.ts +++ b/tests/unit/runTests.ts @@ -141,18 +141,18 @@ describe('runTests', () => { it('Should set capabilities based on project name and according to config', () => { const capabilitiesBase = 'capabilities={ "name": "@dojo/cli-test-intern", "project": "@dojo/cli-test-intern"'; assert.equal( - capabilitiesBase + ', "fixSessionCapabilities": "false", "browserstack.debug": "false" }', runTests.parseArguments({ config: 'browserstack' })[1], + capabilitiesBase + ', "fixSessionCapabilities": "false", "browserstack.debug": "false" }', 'Didn\'t add browserstack config' ); assert.equal( - capabilitiesBase + ', "fixSessionCapabilities": "false" }', runTests.parseArguments({ config: 'saucelabs' })[1], + capabilitiesBase + ', "fixSessionCapabilities": "false" }', 'Didn\'t add saucelabs config' ); From 4a386b3a1dfdfaa81567e2c32aadda88f6ea7900 Mon Sep 17 00:00:00 2001 From: Bradley Maier Date: Wed, 18 Jan 2017 02:15:52 -0500 Subject: [PATCH 18/21] Fix order of all the arguments --- tests/unit/runTests.ts | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/tests/unit/runTests.ts b/tests/unit/runTests.ts index 10c5374..a56a80b 100644 --- a/tests/unit/runTests.ts +++ b/tests/unit/runTests.ts @@ -66,7 +66,7 @@ describe('runTests', () => { assert.fail(null, null, 'Should not get here'); } catch (error) { - assert.equal(errorMessage, error.message); + assert.equal(error.message, errorMessage); assert.isTrue(stopAndPersistStub.calledOnce, 'Should stop the spinner'); assert.isTrue(stopAndPersistStub.firstCall.calledWithMatch('failed'), 'Should persis the failed message'); @@ -75,27 +75,27 @@ describe('runTests', () => { describe('Should parse arguments', () => { it('Should use config to set intern file if provided', () => { - assert.equal(path.join('config=intern', 'intern-test'), runTests.parseArguments({config: 'test'})[0]); + assert.equal(runTests.parseArguments({config: 'test'})[0], path.join('config=intern', 'intern-test')); }); it('Should have a default for intern config', () => { - assert.equal(path.join('config=intern', 'intern'), runTests.parseArguments({})[0]); + assert.equal(runTests.parseArguments({})[0], path.join('config=intern', 'intern')); }); it('Should push an empty functionalSuites arg if unit is provided', () => { - assert.equal('functionalSuites=', runTests.parseArguments({ unit: true })[1]); + assert.equal(runTests.parseArguments({ unit: true })[1], 'functionalSuites='); }); it('Should push an empty suites arg if functional is provided', () => { - assert.equal('suites=', runTests.parseArguments({ functional: true })[1]); + assert.equal(runTests.parseArguments({ functional: true })[1], 'suites='); }); it('Should add environments if provided', () => { const args = runTests.parseArguments({ environments: 'one,two' }); - assert.equal('environments={ "browserName": "one" }', args[1]); - assert.equal('environments={ "browserName": "two" }', args[2]); + assert.equal(args[1], 'environments={ "browserName": "one" }'); + assert.equal(args[2], 'environments={ "browserName": "two" }'); }); it('Should add reporters if provided', () => { @@ -103,12 +103,12 @@ describe('runTests', () => { reporters: 'one,two' }); - assert.equal('reporters=one', args[1]); - assert.equal('reporters=two', args[2]); + assert.equal(args[1], 'reporters=one'); + assert.equal(args[2], 'reporters=two'); }); it('Should add LcovHtml reporter if coverage argument is provided', () => { - assert.equal('reporters=LcovHtml', runTests.parseArguments({ coverage: true })[1]); + assert.equal(runTests.parseArguments({ coverage: true })[1], 'reporters=LcovHtml'); }); it('Should not duplicate the LcovHtml reporter', () => { @@ -116,8 +116,8 @@ describe('runTests', () => { reporters: 'LcovHtml', coverage: true }); - assert.equal('reporters=LcovHtml', args[1]); - assert.equal(3, args.length); + assert.equal(args[1], 'reporters=LcovHtml'); + assert.equal(args.length, 3); }); it('Should set testingbot tunnel config if provided', () => { @@ -126,16 +126,21 @@ describe('runTests', () => { testingKey: 'key', secret: 'secret' }); - assert.equal('tunnelOptions={ "verbose": "true", "apiKey": "key", "apiSecret": "secret" }', args[1]); + assert.equal(args[1], 'tunnelOptions={ "verbose": "true", "apiKey": "key", "apiSecret": "secret" }'); - assert.equal('webdriver={ "host": "http://hub.testingbot.com/wd/hub", "username": "key", "accessKey": "secret" }', args[2]); + assert.equal( + args[2], + 'webdriver={ "host": "http://hub.testingbot.com/wd/hub", "username": "key", "accessKey": "secret" }' + ); }); it('Should set normal tunnel config if provided', () => { - assert.equal('tunnelOptions={ "username": "user", "accessKey": "key" }', runTests.parseArguments({ - testingKey: 'key', - userName: 'user' - })[1]); + assert.equal( + runTests.parseArguments({ + testingKey: 'key', + userName: 'user' + })[1], + 'tunnelOptions={ "username": "user", "accessKey": "key" }'); }); it('Should set capabilities based on project name and according to config', () => { From 14b91976003ba7bb4c22cfae4cf4d326425eacc3 Mon Sep 17 00:00:00 2001 From: Bradley Maier Date: Wed, 18 Jan 2017 02:22:50 -0500 Subject: [PATCH 19/21] Add more to readme --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 41090d7..85ce194 100644 --- a/README.md +++ b/README.md @@ -10,11 +10,14 @@ The official Dojo 2 test command. ## Features -TODO: Add sections on features of this package +Builds and runs test cases for a Dojo 2 application. This module assumes that your project is structured +as it would be if created by `dojo create`. Specifically, `src` and `tests` should be in the root of the project directory, +and `tests` should have `functional` and `unit` folders with `all.ts` files in each that import other tests. ## How do I use this package? -TODO: Add appropriate usage and instruction guidelines +To build and run tests locally, just execute `dojo test` in your project. There are several configuration options, to see what +options are available run `dojo test -h` ## How do I contribute? From 7ccfc39dfe3a0fb4c9f3dd8472798ecc3ee5ddec Mon Sep 17 00:00:00 2001 From: Bradley Maier Date: Wed, 18 Jan 2017 11:18:54 -0500 Subject: [PATCH 20/21] Remove commented out browsers in environments config --- src/intern/intern-browserstack.js | 3 +-- src/intern/intern-saucelabs.js | 10 +--------- src/intern/intern-testingbot.js | 7 +------ 3 files changed, 3 insertions(+), 17 deletions(-) diff --git a/src/intern/intern-browserstack.js b/src/intern/intern-browserstack.js index 29fabb7..66d8162 100644 --- a/src/intern/intern-browserstack.js +++ b/src/intern/intern-browserstack.js @@ -8,8 +8,7 @@ define([ intern.environments = [ { browserName: 'internet explorer', version: [ '10', '11' ], platform: 'WINDOWS' }, { browserName: 'firefox', platform: 'WINDOWS' }, - { browserName: 'chrome', platform: 'WINDOWS' }/*, - { browserName: 'Safari', version: '9', platform: 'OS X' }*/ + { browserName: 'chrome', platform: 'WINDOWS' } ]; return intern; diff --git a/src/intern/intern-saucelabs.js b/src/intern/intern-saucelabs.js index c9cf862..d080ff0 100644 --- a/src/intern/intern-saucelabs.js +++ b/src/intern/intern-saucelabs.js @@ -4,16 +4,8 @@ define([ intern.environments = [ { browserName: 'internet explorer', version: [ '10.0', '11.0' ], platform: 'Windows 7' }, - // { browserName: 'microsoftedge', platform: 'Windows 10' }, { browserName: 'firefox', version: '49', platform: 'Windows 10' }, - { browserName: 'chrome', platform: 'Windows 10' }, - // { browserName: 'safari', version: '9', platform: 'OS X 10.11' }, - // { browserName: 'chrome', version: '54.0', platform: 'macOS 10.12' }, - // { browserName: 'firefox', version: '49.0', platform: 'macOS 10.12' }, - // { browserName: 'android', platform: 'Linux', version: '4.4', deviceName: 'Google Nexus 7 HD Emulator' }// , - // { browserName: 'opera', version: '12.15', platform: 'Linux' }, - // { browserName: 'chrome', version: '48.0', platform: 'Linux' }, - // { browserName: 'iphone', version: '9.1', deviceName: 'iPhone 6' }, + { browserName: 'chrome', platform: 'Windows 10' } ]; /* SauceLabs supports more max concurrency */ diff --git a/src/intern/intern-testingbot.js b/src/intern/intern-testingbot.js index a8f8a02..8bb35ba 100644 --- a/src/intern/intern-testingbot.js +++ b/src/intern/intern-testingbot.js @@ -4,13 +4,8 @@ define([ intern.environments = [ { browserName: 'internet explorer', version: [ '10', '11' ], platform: 'WIN8' }, - // { browserName: 'microsoftedge', platform: 'WIN10' }, { browserName: 'firefox', version: '49', platform: 'WIN10' }, - { browserName: 'chrome', platform: 'WIN10' }, - // { browserName: 'safari', version: '9', platform: 'CAPITAN' }, - // { browserName: 'chrome', version: '55', platform: 'SIERRA' }, - // { browserName: 'browser', platform: 'ANDROID', version: '6.0', deviceName: 'Galaxy S6', platformName: 'Android' }// , - // { browserName: 'safari', platform: 'CAPITAN', version: '9.3', deviceName: 'iPhone 6s Plus', platformName: 'iOS' } + { browserName: 'chrome', platform: 'WIN10' } ]; /* Testingbot supports more max concurrency */ From 8f328412f4224a4b7999602a50eb8489c5fc7a09 Mon Sep 17 00:00:00 2001 From: Bradley Maier Date: Wed, 18 Jan 2017 14:18:13 -0500 Subject: [PATCH 21/21] Remove environments config variable --- src/main.ts | 7 ------- src/runTests.ts | 6 +----- tests/unit/main.ts | 19 +++++++------------ tests/unit/runTests.ts | 8 -------- 4 files changed, 8 insertions(+), 32 deletions(-) diff --git a/src/main.ts b/src/main.ts index 63f16a7..e39e301 100644 --- a/src/main.ts +++ b/src/main.ts @@ -3,7 +3,6 @@ import { Argv } from 'yargs'; import runTests from './runTests'; export interface TestArgs extends Argv { - environments: string; config: string; unit: boolean; functional: boolean; @@ -23,12 +22,6 @@ const command: Command = { type: 'string' }); - helper.yargs.option('e', { - alias: 'environments', - describe: 'Comma separated list of browsers to run tests in', - type: 'string' - }); - helper.yargs.option('r', { alias: 'reporters', describe: 'Comma separated list of reporters to use, defaults to Console', diff --git a/src/runTests.ts b/src/runTests.ts index a8786bb..af61ca9 100644 --- a/src/runTests.ts +++ b/src/runTests.ts @@ -10,7 +10,7 @@ const packagePath = pkgDir.sync(dirname); const process = require('process'); const projectName = require(path.join(process.cwd(), './package.json')).name; -export function parseArguments({ unit, functional, environments, config, coverage, reporters, testingKey, secret, userName }: TestArgs) { +export function parseArguments({ unit, functional, config, coverage, reporters, testingKey, secret, userName }: TestArgs) { const configArg = config ? `-${config}` : ''; const args = [ `config=${path.relative('.', path.join(packagePath, 'intern', 'intern' + configArg))}` ]; if (unit) { @@ -20,10 +20,6 @@ export function parseArguments({ unit, functional, environments, config, coverag args.push('suites='); } - args.push(...(environments ? environments.split(',').map( - (environment) => `environments={ "browserName": "${environment}" }` - ) : [])); - args.push(...(reporters ? reporters.split(',').map((reporter) => `reporters=${reporter}`) : [])); if (coverage && args.every((reporter) => reporter.indexOf('LcovHtml') < 0)) { args.push('reporters=LcovHtml'); diff --git a/tests/unit/main.ts b/tests/unit/main.ts index 9789915..62e42ea 100644 --- a/tests/unit/main.ts +++ b/tests/unit/main.ts @@ -36,50 +36,45 @@ describe('main', () => { [ 'c', { alias: 'config', describe: 'Specifies what configuration to test with: \'local\'(default), \'browserstack\', \'testingbot\', or \'saucelabs\'.', type: 'string' } ], 'First argument' ); - assert.deepEqual( - helper.yargs.option.secondCall.args, - [ 'e', { alias: 'environments', describe: 'Comma separated list of browsers to run tests in', type: 'string' }], - 'Second argument' - ); assert.deepEqual( - helper.yargs.option.thirdCall.args, + helper.yargs.option.secondCall.args, [ 'r', { alias: 'reporters', describe: 'Comma separated list of reporters to use, defaults to Console', type: 'string' }], 'Third argument' ); assert.deepEqual( - helper.yargs.option.getCall(3).args, + helper.yargs.option.thirdCall.args, [ 'u', { alias: 'unit', describe: 'Indicates that only unit tests should be run. By default functional tests and unit tests are run' }], 'Fourth argument' ); assert.deepEqual( - helper.yargs.option.getCall(4).args, + helper.yargs.option.getCall(3).args, [ 'f', { alias: 'functional', describe: 'Indicates that only functional tests should be run. By default functional tests and unit tests are run' }], 'Fifth argument' ); assert.deepEqual( - helper.yargs.option.getCall(5).args, + helper.yargs.option.getCall(4).args, [ 'cov', { alias: 'coverage', describe: 'If specified coverage will be included. This is the same as adding the LcovHtml reporter' }], 'Sixth argument' ); assert.deepEqual( - helper.yargs.option.getCall(6).args, + helper.yargs.option.getCall(5).args, [ 'k', { alias: 'testingKey', describe: 'API key for testingbot or accesskey for saucelabs or browserstack', type: 'string' }], 'Seventh Argument' ); assert.deepEqual( - helper.yargs.option.getCall(7).args, + helper.yargs.option.getCall(6).args, [ 'n', { alias: 'userName', describe: 'User name for testing platform', type: 'string' }], 'Eigth Argument' ); assert.deepEqual( - helper.yargs.option.getCall(8).args, + helper.yargs.option.getCall(7).args, [ 's', { alias: 'secret', describe: 'API secret for testingbot', type: 'string' }], 'Ninth Argument' ); diff --git a/tests/unit/runTests.ts b/tests/unit/runTests.ts index a56a80b..5d0a9a2 100644 --- a/tests/unit/runTests.ts +++ b/tests/unit/runTests.ts @@ -90,14 +90,6 @@ describe('runTests', () => { assert.equal(runTests.parseArguments({ functional: true })[1], 'suites='); }); - it('Should add environments if provided', () => { - const args = runTests.parseArguments({ - environments: 'one,two' - }); - assert.equal(args[1], 'environments={ "browserName": "one" }'); - assert.equal(args[2], 'environments={ "browserName": "two" }'); - }); - it('Should add reporters if provided', () => { const args = runTests.parseArguments({ reporters: 'one,two'