From d298d3ab036f419d885bc50cec567b647d18901d Mon Sep 17 00:00:00 2001 From: Juan Pinilla Date: Tue, 13 Dec 2016 23:02:51 -0500 Subject: [PATCH 1/2] Add '--suite' option to 'ng e2e' command --- packages/angular-cli/commands/e2e.ts | 17 +++++-- packages/angular-cli/tasks/e2e.ts | 14 ++++-- tests/helpers/mock-project.js | 59 ++++++++++++++++++++++++ tests/runner.js | 2 +- tests/unit/commands/e2e.spec.ts | 48 +++++++++++++++++++ tests/{ => unit}/models/config.spec.ts | 0 tests/{ => unit}/models/spec-schema.d.ts | 0 tests/{ => unit}/models/spec-schema.json | 0 8 files changed, 131 insertions(+), 9 deletions(-) create mode 100644 tests/helpers/mock-project.js create mode 100644 tests/unit/commands/e2e.spec.ts rename tests/{ => unit}/models/config.spec.ts (100%) rename tests/{ => unit}/models/spec-schema.d.ts (100%) rename tests/{ => unit}/models/spec-schema.json (100%) diff --git a/packages/angular-cli/commands/e2e.ts b/packages/angular-cli/commands/e2e.ts index c3074afb649d..3f0248cc64eb 100644 --- a/packages/angular-cli/commands/e2e.ts +++ b/packages/angular-cli/commands/e2e.ts @@ -1,12 +1,21 @@ const Command = require('../ember-cli/lib/models/command'); -import {E2eTask} from '../tasks/e2e'; -import {CliConfig} from '../models/config'; +import { E2eTask } from '../tasks/e2e'; +import { CliConfig } from '../models/config'; + +export interface E2eOptions { + suite?: string; +} const E2eCommand = Command.extend({ name: 'e2e', description: 'Run e2e tests in existing project', works: 'insideProject', - run: function () { + + availableOptions: [ + { name: 'suite', type: String, default: null }, + ], + + run: function (commandOptions: E2eOptions) { this.project.ngConfig = this.project.ngConfig || CliConfig.fromProject(); const e2eTask = new E2eTask({ @@ -15,7 +24,7 @@ const E2eCommand = Command.extend({ project: this.project }); - return e2eTask.run(); + return e2eTask.run(commandOptions); } }); diff --git a/packages/angular-cli/tasks/e2e.ts b/packages/angular-cli/tasks/e2e.ts index 4de5cbac8fc7..bea5ff7c9f71 100644 --- a/packages/angular-cli/tasks/e2e.ts +++ b/packages/angular-cli/tasks/e2e.ts @@ -1,15 +1,21 @@ const Task = require('../ember-cli/lib/models/task'); import * as chalk from 'chalk'; -import {exec} from 'child_process'; - +import { exec } from 'child_process'; +import { E2eOptions } from '../commands/e2e'; export const E2eTask = Task.extend({ - run: function () { + run: function (options: E2eOptions) { + const commandArgs: string[] = []; const ui = this.ui; let exitCode = 0; + if (options.suite) { + commandArgs.push(`--suite=${options.suite}`); + } + return new Promise((resolve) => { - exec(`npm run e2e -- ${this.project.ngConfig.config.e2e.protractor.config}`, + const protractorConfig = this.project.ngConfig.config.e2e.protractor.config; + exec(`npm run e2e -- ${protractorConfig} ${commandArgs.join(' ')}`, (err: NodeJS.ErrnoException, stdout: string, stderr: string) => { ui.writeLine(stdout); if (err) { diff --git a/tests/helpers/mock-project.js b/tests/helpers/mock-project.js new file mode 100644 index 000000000000..de1b1daca590 --- /dev/null +++ b/tests/helpers/mock-project.js @@ -0,0 +1,59 @@ +'use strict'; + +var Project = require('angular-cli/ember-cli/lib/models/project'); +var MockUI = require('./mock-ui'); + +function MockProject() { + var root = process.cwd(); + var pkg = {}; + var ui = new MockUI(); + Project.apply(this, [root, pkg, ui]); +} + +MockProject.prototype.require = function(file) { + if (file === './server') { + return function() { + return { + listen: function() { + arguments[arguments.length - 1](); + } + }; + }; + } +}; + +MockProject.prototype.config = function() { + return this._config || { + baseURL: '/', + locationType: 'auto' + }; +}; + +MockProject.prototype.has = function(key) { + return (/server/.test(key)); +}; + +MockProject.prototype.name = function() { + return 'mock-project'; +}; + +MockProject.prototype.initializeAddons = Project.prototype.initializeAddons; +MockProject.prototype.hasDependencies = function() { + return true; +}; +MockProject.prototype.discoverAddons = Project.prototype.discoverAddons; +MockProject.prototype.addIfAddon = Project.prototype.addIfAddon; +MockProject.prototype.supportedInternalAddonPaths = Project.prototype.supportedInternalAddonPaths; +MockProject.prototype.setupBowerDirectory = Project.prototype.setupBowerDirectory; +MockProject.prototype.setupNodeModulesPath = Project.prototype.setupNodeModulesPath; +MockProject.prototype.isEmberCLIProject = Project.prototype.isEmberCLIProject; +MockProject.prototype.isEmberCLIAddon = Project.prototype.isEmberCLIAddon; +MockProject.prototype.findAddonByName = Project.prototype.findAddonByName; +MockProject.prototype.dependencies = function() { + return []; +}; +MockProject.prototype.isEmberCLIAddon = function() { + return false; +}; + +module.exports = MockProject; diff --git a/tests/runner.js b/tests/runner.js index ab9a4e1f4955..06a11838fb03 100644 --- a/tests/runner.js +++ b/tests/runner.js @@ -7,7 +7,7 @@ var Mocha = require('mocha'); var glob = require('glob'); var path = require('path'); -var root = 'tests/{acceptance,models}'; +var root = 'tests/{acceptance,unit}'; var specFiles = glob.sync(root + '/**/*.spec.*'); var mocha = new Mocha({ timeout: 5000, reporter: 'spec' }); diff --git a/tests/unit/commands/e2e.spec.ts b/tests/unit/commands/e2e.spec.ts new file mode 100644 index 000000000000..2a17473a7966 --- /dev/null +++ b/tests/unit/commands/e2e.spec.ts @@ -0,0 +1,48 @@ +import E2eCommand from 'angular-cli/commands/e2e'; +import { CliConfig } from 'angular-cli/models/config/config'; +import { stub } from 'sinon'; +import { expect } from 'chai'; +import * as proc from 'child_process'; + +const MockUI = require('../../helpers/mock-ui'); +const MockAnalytics = require('../../helpers/mock-analytics'); +const MockProject = require('../../helpers/mock-project'); + +function createProject() { + const project = new MockProject(); + project.isEmberCLIProject = () => true; + project.ngConfig = CliConfig.fromJson({ + e2e: { + protractor: { + config: 'some-config' + } + } + }); + + return project; +} + +describe('e2e command', () => { + let command: E2eCommand; + + beforeEach(() => { + command = new E2eCommand({ + settings: {}, + project: createProject(), + ui: new MockUI(), + analytics: new MockAnalytics(), + }); + }); + + beforeEach(() => { + stub(proc, 'exec').callsArg(1); + }); + + it('passes through the suite option', () => { + const commandOption = '--suite=suiteA'; + return command.validateAndRun([commandOption]).then(() => { + expect(proc.exec.calledOnce).to.be.true; + expect(proc.exec.firstCall.args[0]).to.have.string(` ${commandOption}`); + }); + }); +}); diff --git a/tests/models/config.spec.ts b/tests/unit/models/config.spec.ts similarity index 100% rename from tests/models/config.spec.ts rename to tests/unit/models/config.spec.ts diff --git a/tests/models/spec-schema.d.ts b/tests/unit/models/spec-schema.d.ts similarity index 100% rename from tests/models/spec-schema.d.ts rename to tests/unit/models/spec-schema.d.ts diff --git a/tests/models/spec-schema.json b/tests/unit/models/spec-schema.json similarity index 100% rename from tests/models/spec-schema.json rename to tests/unit/models/spec-schema.json From 4c6bfd827046711fdf318c13b963718318bc94c7 Mon Sep 17 00:00:00 2001 From: Juan Pinilla Date: Fri, 23 Dec 2016 20:00:58 -0500 Subject: [PATCH 2/2] Add double quotes to e2e command passed through option - Remove analytics from spec #3688 - Fix sinon types --- package.json | 3 ++- packages/angular-cli/tasks/e2e.ts | 2 +- tests/unit/commands/e2e.spec.ts | 20 +++++++++++--------- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 17cda0eb34e8..d0e16ef37fec 100644 --- a/package.json +++ b/package.json @@ -145,6 +145,7 @@ "@types/node": "^6.0.36", "@types/request": "0.0.30", "@types/rimraf": "0.0.25-alpha", + "@types/sinon": "^1.16.33", "@types/source-map": "^0.5.0", "@types/webpack": "^1.12.22-alpha", "chai": "^3.5.0", @@ -165,7 +166,7 @@ "request": "^2.74.0", "resolve-bin": "^0.4.0", "rewire": "^2.5.1", - "sinon": "^1.17.3", + "sinon": "^1.17.6", "through": "^2.3.8", "tree-kill": "^1.0.0", "ts-node": "^1.3.0", diff --git a/packages/angular-cli/tasks/e2e.ts b/packages/angular-cli/tasks/e2e.ts index bea5ff7c9f71..1e85721b17f8 100644 --- a/packages/angular-cli/tasks/e2e.ts +++ b/packages/angular-cli/tasks/e2e.ts @@ -10,7 +10,7 @@ export const E2eTask = Task.extend({ let exitCode = 0; if (options.suite) { - commandArgs.push(`--suite=${options.suite}`); + commandArgs.push(`--suite="${options.suite}"`); } return new Promise((resolve) => { diff --git a/tests/unit/commands/e2e.spec.ts b/tests/unit/commands/e2e.spec.ts index 2a17473a7966..cb755aae8083 100644 --- a/tests/unit/commands/e2e.spec.ts +++ b/tests/unit/commands/e2e.spec.ts @@ -1,11 +1,10 @@ import E2eCommand from 'angular-cli/commands/e2e'; import { CliConfig } from 'angular-cli/models/config/config'; -import { stub } from 'sinon'; +import { stub, SinonStub } from 'sinon'; import { expect } from 'chai'; import * as proc from 'child_process'; const MockUI = require('../../helpers/mock-ui'); -const MockAnalytics = require('../../helpers/mock-analytics'); const MockProject = require('../../helpers/mock-project'); function createProject() { @@ -23,26 +22,29 @@ function createProject() { } describe('e2e command', () => { - let command: E2eCommand; + let command: any; + let exec: SinonStub; beforeEach(() => { command = new E2eCommand({ settings: {}, project: createProject(), ui: new MockUI(), - analytics: new MockAnalytics(), }); }); beforeEach(() => { - stub(proc, 'exec').callsArg(1); + exec = stub(proc, 'exec').callsArg(1); + }); + + afterEach(() => { + exec.restore(); }); it('passes through the suite option', () => { - const commandOption = '--suite=suiteA'; - return command.validateAndRun([commandOption]).then(() => { - expect(proc.exec.calledOnce).to.be.true; - expect(proc.exec.firstCall.args[0]).to.have.string(` ${commandOption}`); + return command.validateAndRun(['--suite', 'suiteA,suite B']).then(() => { + expect(exec.calledOnce).to.be.true; + expect(exec.firstCall.args[0]).to.have.string(' --suite="suiteA,suite B"'); }); }); });