Skip to content

Commit

Permalink
feat: implement gui for hermione
Browse files Browse the repository at this point in the history
  • Loading branch information
DudaGod committed Mar 22, 2018
1 parent 4dbb809 commit c55d126
Show file tree
Hide file tree
Showing 35 changed files with 1,204 additions and 769 deletions.
49 changes: 9 additions & 40 deletions gemini.js
Original file line number Diff line number Diff line change
@@ -1,54 +1,23 @@
'use strict';

const _ = require('lodash');
const Promise = require('bluebird');

const PluginAdapter = require('./lib/plugin-adapter');
const utils = require('./lib/server-utils');
const {saveTestImages} = require('./lib/reporter-helpers');
const ReportBuilderFactory = require('./lib/report-builder-factory');
const parseConfig = require('./lib/config');
const gui = require('./lib/gui');

Promise.promisifyAll(require('fs-extra'));

const GUI_COMMAND = 'gui';
let reportBuilder;

module.exports = (gemini, opts) => {
const pluginConfig = parseConfig(opts);
const plugin = PluginAdapter.create(gemini, opts, 'gemini');

if (!pluginConfig.enabled) {
if (!plugin.isEnabled()) {
return;
}

let runHtmlReporter = initHtmlReporter;

gemini.on(gemini.events.CLI, (commander) => {
gui(commander, gemini, pluginConfig);

commander.on(`command:${GUI_COMMAND}`, () => runHtmlReporter = _.noop);
});

gemini.on(gemini.events.INIT, () => {
runHtmlReporter(gemini, pluginConfig);
});
plugin
.extendCliByGuiCommand()
.init(prepareData, prepareImages);
};

function initHtmlReporter(gemini, pluginConfig) {
reportBuilder = ReportBuilderFactory.create('gemini', gemini.config, pluginConfig);
const generateReportPromise = Promise
.all([
prepareData(gemini),
prepareImages(gemini, pluginConfig)
])
.spread((reportBuilder) => reportBuilder.save())
.then(utils.logPathToHtmlReport)
.catch(utils.logError);

gemini.on(gemini.events.END_RUNNER, () => generateReportPromise);
}

function prepareData(gemini) {
function prepareData(gemini, reportBuilder) {
return new Promise((resolve) => {
gemini.on(gemini.events.SKIP_STATE, (result) => reportBuilder.addSkipped(result));

Expand All @@ -66,7 +35,7 @@ function prepareData(gemini) {
});
}

function prepareImages(gemini, pluginConfig) {
function prepareImages(gemini, pluginConfig, reportBuilder) {
const {path: reportPath} = pluginConfig;
function handleErrorEvent(result) {
var src = result.imagePath || result.currentPath;
Expand Down Expand Up @@ -96,7 +65,7 @@ function prepareImages(gemini, pluginConfig) {
});

gemini.on(gemini.events.UPDATE_RESULT, (testResult) => {
testResult = _.extend(testResult, {
testResult = Object.assign(testResult, {
referencePath: testResult.imagePath,
equal: true
});
Expand Down
48 changes: 12 additions & 36 deletions hermione.js
Original file line number Diff line number Diff line change
@@ -1,47 +1,23 @@
'use strict';

const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs-extra'));

const PluginAdapter = require('./lib/plugin-adapter');
const utils = require('./lib/server-utils');
const {saveTestImages} = require('./lib/reporter-helpers');
const ReportBuilderFactory = require('./lib/report-builder-factory');
const parseConfig = require('./lib/config');

let reportBuilder;
const {saveTestImages, saveBase64Screenshot} = require('./lib/reporter-helpers');

module.exports = (hermione, opts) => {
const pluginConfig = parseConfig(opts);
const plugin = PluginAdapter.create(hermione, opts, 'hermione');

if (!pluginConfig.enabled) {
if (!plugin.isEnabled()) {
return;
}

reportBuilder = ReportBuilderFactory.create('hermione', hermione.config, pluginConfig);
const generateReportPromise = Promise
.all([
prepareData(hermione, pluginConfig),
prepareImages(hermione, pluginConfig)
])
.spread((reportBuilder) => reportBuilder.save())
.then(utils.logPathToHtmlReport)
.catch(utils.logError);

hermione.on(hermione.events.RUNNER_END, () => generateReportPromise);
plugin
.extendCliByGuiCommand()
.init(prepareData, prepareImages);
};

function saveScreenshot(imageData, destPath) {
if (!imageData) {
utils.logger.warn('Cannot save screenshot on reject');

return Promise.resolve();
}

return utils.makeDirFor(destPath)
.then(() => fs.writeFileAsync(destPath, new Buffer(imageData, 'base64'), 'base64'));
}

function prepareData(hermione) {
function prepareData(hermione, reportBuilder) {
return new Promise((resolve) => {
hermione.on(hermione.events.TEST_PENDING, (testResult) => reportBuilder.addSkipped(testResult));

Expand All @@ -57,23 +33,23 @@ function prepareData(hermione) {
function failHandler(testResult) {
const wrapped = reportBuilder.format(testResult);

return wrapped.hasDiff ? reportBuilder.addFail(testResult) : reportBuilder.addError(testResult);
return wrapped.hasDiff() ? reportBuilder.addFail(testResult) : reportBuilder.addError(testResult);
}
}

function prepareImages(hermione, pluginConfig) {
function prepareImages(hermione, pluginConfig, reportBuilder) {
function handleErrorEvent(testResult) {
const src = testResult.currentPath;

return src
? utils.copyImageAsync(src, utils.getCurrentAbsolutePath(testResult, pluginConfig.path))
: saveScreenshot(testResult.screenshot, utils.getCurrentAbsolutePath(testResult, pluginConfig.path));
: saveBase64Screenshot(testResult, pluginConfig.path);
}

function failHandler(testResult) {
const wrapped = reportBuilder.format(testResult);

return wrapped.hasDiff ? saveTestImages(wrapped, pluginConfig.path) : handleErrorEvent(wrapped);
return wrapped.hasDiff() ? saveTestImages(wrapped, pluginConfig.path) : handleErrorEvent(wrapped);
}

return new Promise((resolve, reject) => {
Expand Down
8 changes: 7 additions & 1 deletion lib/constants/errors.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
'use strict';

module.exports = {
exports.getCommonErrors = () => ({
NO_REF_IMAGE_ERROR: 'NoRefImageError'
});

exports.getHermioneErrors = () => {
return Object.assign({
IMAGE_DIFF_ERROR: 'ImageDiffError'
}, exports.getCommonErrors());
};
2 changes: 1 addition & 1 deletion lib/gui/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ module.exports = class App {
}

get data() {
return this._tool.getTree();
return this._tool.tree;
}
};
14 changes: 14 additions & 0 deletions lib/gui/constants/client-events.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
'use strict';

module.exports = {
BEGIN_SUITE: 'beginSuite',
BEGIN_STATE: 'beginState',

TEST_RESULT: 'testResult',
UPDATE_RESULT: 'updateResult',

RETRY: 'retry',
ERROR: 'err',

END: 'end'
};
35 changes: 25 additions & 10 deletions lib/gui/tool-runner-factory/base-tool-runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,38 @@
const path = require('path');
const _ = require('lodash');
const chalk = require('chalk');
const temp = require('temp');
const ReportBuilderFactory = require('../../report-builder-factory');
const EventSource = require('../event-source');
const utils = require('../../server-utils');
const {findNode} = require('../../../lib/static/modules/utils');

temp.track();

module.exports = class ToolRunner {
constructor(paths) {
static create(paths, tool, configs) {
return new this(paths, tool, configs);
}

constructor(paths, tool, {program: globalOpts, pluginConfig, options: guiOpts}) {
const toolName = globalOpts.name();

this._testFiles = [].concat(paths);
this._tool = tool;
this._tree = null;

this._globalOpts = globalOpts;
this._guiOpts = guiOpts;
this._reportPath = pluginConfig.path;

this._eventSource = new EventSource();
this.diffDir = temp.path('gemini-gui-diff');
this.currentDir = temp.path('gemini-gui-curr');
this._reportBuilder = ReportBuilderFactory.create(toolName, tool.config, pluginConfig);
}

get tree() {
return this._tree;
}

initialize() {
return this._readTests()
.then(() => this._subscribeOnEvents());
}

addClient(connection) {
Expand All @@ -26,10 +45,6 @@ module.exports = class ToolRunner {
this._eventSource.emit(event, data);
}

getTree() {
return this.tree;
}

_loadReuseData() {
try {
return utils.require(path.resolve(this._reportPath, 'data'));
Expand Down
Loading

0 comments on commit c55d126

Please sign in to comment.