Skip to content
This repository has been archived by the owner on Jul 29, 2024. It is now read-only.

chore(launcher): reorganize launcher #1485

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/referenceConf.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,10 @@ exports.config = {
}
},

// If set, protractor will save the test output in json format at this path.
// The path is relative to the location of this config.
resultJsonOutputFile: null,

// ---------------------------------------------------------------------------
// ----- The test framework --------------------------------------------------
// ---------------------------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions lib/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ var optimist = require('optimist').
describe('stackTrace', 'Print stack trace on error').
describe('params', 'Param object to be passed to the tests').
describe('framework', 'Test framework to use: jasmine, cucumber or mocha').
describe('resultJsonOutputFile', 'Path to save JSON test result').
alias('browser', 'capabilities.browserName').
alias('name', 'capabilities.name').
alias('platform', 'capabilities.platform').
Expand Down
15 changes: 13 additions & 2 deletions lib/frameworks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,16 @@ Requirements

- `runner.getConfig().onComplete` must be called when tests are finished.

- The returned promise must be resolved when tests are finished and it should return a results object.
This object must have a `failedCount` property.
- The returned promise must be resolved when tests are finished and it should return a results object. This object must have a `failedCount` property and optionally a `specResults`
object of the following structure:
```
specResults = [{
description: string,
assertions: [{
passed: boolean,
errorMsg: string,
stackTrace: string
}],
duration: integer
}]
```
62 changes: 55 additions & 7 deletions lib/frameworks/cucumber.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,65 @@ exports.run = function(runner, specs) {
}
global.cucumber = Cucumber.Cli(execOptions);

return runner.runTestPreparer().then(function () {
return q.promise(function (resolve, reject) {
global.cucumber.run(function (succeeded) {
var testResult = [];
var failedCount = 0;
// Add a listener into cucumber so that protractor can find out which
// steps passed/failed
var addResultListener = function(formatter) {
var originalHandleStepResultEvent = formatter.handleStepResultEvent;
formatter.handleStepResultEvent = function(event, callback) {

var stepResult = event.getPayloadItem('stepResult');
if (stepResult.isSuccessful()) {
runner.emit('testPass');
testResult.push({
description: stepResult.getStep().getName(),
assertions: [{
passed: true
}],
duration: stepResult.getDuration()
});
}
else if (stepResult.isFailed()) {
runner.emit('testFail');
++failedCount;
var failureMessage = stepResult.getFailureException();
testResult.push({
description: stepResult.getStep().getName(),
assertions: [{
passed: false,
errorMsg: failureMessage.message,
stackTrace: failureMessage.stack
}],
duration: stepResult.getDuration()
});
}

if (originalHandleStepResultEvent
&& typeof(originalHandleStepResultEvent) === 'function') {
originalHandleStepResultEvent(event, callback);
} else {
callback();
}
}
};

return runner.runTestPreparer().then(function() {
return q.promise(function(resolve, reject) {
var cucumberConf = Cucumber.Cli.Configuration(execOptions);
var runtime = Cucumber.Runtime(cucumberConf);
var formatter = cucumberConf.getFormatter();
addResultListener(formatter);
runtime.attachListener(formatter);
runtime.start(function(succeeded) {
try {
if (runner.getConfig().onComplete) {
runner.getConfig().onComplete();
}
var resolvedObj = {
failedCount: succeeded ? 0 : 1
};
resolve(resolvedObj);
resolve({
failedCount: failedCount,
specResults: testResult
});
} catch (err) {
reject(err);
}
Expand Down
25 changes: 23 additions & 2 deletions lib/frameworks/jasmine.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,38 @@ exports.run = function(runner, specs) {
require('jasminewd');
/* global jasmine */

var testResult = [];

var RunnerReporter = function(emitter) {
this.emitter = emitter;
};

RunnerReporter.prototype.reportRunnerStarting = function() {};
RunnerReporter.prototype.reportRunnerResults = function() {};
RunnerReporter.prototype.reportSuiteResults = function() {};
RunnerReporter.prototype.reportSpecStarting = function() {};
RunnerReporter.prototype.reportSpecStarting = function() {
this.startTime = new Date();
};
RunnerReporter.prototype.reportSpecResults = function(spec) {
if (spec.results().passed()) {
this.emitter.emit('testPass');
} else {
this.emitter.emit('testFail');
}

var entry = {
description: spec.results().description,
assertions: [],
duration: new Date().getTime() - this.startTime.getTime()
};
spec.results().getItems().forEach(function(item) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we find information about the rumored output format that javascript frameworks were supposedly discussing? Would be great to use something compatible with that.

entry.assertions.push({
passed: item.passed(),
errorMsg: item.passed() ? undefined : item.message,
stackTrace: item.passed() ? undefined : item.trace.stack
});
});
testResult.push(entry);
};
RunnerReporter.prototype.log = function() {};

Expand All @@ -47,7 +65,10 @@ exports.run = function(runner, specs) {
if (originalOnComplete) {
originalOnComplete(jasmineRunner, log);
}
resolve(jasmineRunner.results());
resolve({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to update frameworks/README with more info about the changes to the resolved object.

failedCount: jasmineRunner.results().failedCount,
specResults: testResult
});
} catch(err) {
reject(err);
}
Expand Down
51 changes: 34 additions & 17 deletions lib/frameworks/mocha.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,11 @@ exports.run = function(runner, specs) {
global.it.only = global.iit = originalOnly;

global.it.skip = global.xit = mochaAdapters.xit;
}catch(err){
} catch(err) {
deferred.reject(err);
}
});

mocha.suite.on('pass', function() {
runner.emit('testPass');
});

mocha.suite.on('fail', function() {
runner.emit('testFail');
});

mocha.loadFiles();

runner.runTestPreparer().then(function() {
Expand All @@ -56,21 +48,46 @@ exports.run = function(runner, specs) {
mocha.addFile(file);
});

mocha.run(function(failures) {
var testResult = [];

var mochaRunner = mocha.run(function(failures) {
try {
if (runner.getConfig().onComplete) {
runner.getConfig().onComplete();
}
var resolvedObj = {
failedCount: failures
};

deferred.resolve(resolvedObj);
}catch(err){
deferred.resolve({
failedCount: failures,
specResults: testResult
});
} catch(err) {
deferred.reject(err);
}
});
}).catch(function(reason){

mochaRunner.on('pass', function(test) {
runner.emit('testPass');
testResult.push({
description: test.title,
assertions: [{
passed: true
}],
duration: test.duration
});
});

mochaRunner.on('fail', function(test) {
runner.emit('testFail');
testResult.push({
description: test.title,
assertions: [{
passed: false,
errorMsg: test.err.message,
stackTrace: test.err.stack
}],
duration: test.duration
});
});
}).catch(function(reason) {
deferred.reject(reason);
});

Expand Down
Loading