Skip to content
This repository has been archived by the owner on Sep 21, 2022. It is now read-only.

Commit

Permalink
Showing 7 changed files with 183 additions and 100 deletions.
1 change: 1 addition & 0 deletions lib/reporters/html/view-model.js
Original file line number Diff line number Diff line change
@@ -123,6 +123,7 @@ module.exports = class ViewModel {
const suite = result.suite;
const metaInfo = suite ? suite.metaInfo : {};
metaInfo.sessionId = result.sessionId || 'unknown session id';
metaInfo.file = suite.file;

const testResult = _.assign({
suiteUrl: rootUrl + suite.url,
1 change: 1 addition & 0 deletions lib/suite.js
Original file line number Diff line number Diff line change
@@ -24,6 +24,7 @@ module.exports = class Suite {
this.afterActions = [];
this.browsers = [];
this.context = {};
this.file = null;
definePrivate(this);
}

17 changes: 10 additions & 7 deletions lib/test-reader.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const _ = require('lodash');
const path = require('path');
const SetsBuilder = require('gemini-core').SetsBuilder;
const Suite = require('./suite');
const Events = require('./constants/events');
@@ -9,15 +10,17 @@ const utils = require('./utils');

const DEFAULT_DIR = require('../package').name;

const loadSuites = (sets, emitter) => {
const loadSuites = (sets, emitter, projectRoot) => {
const rootSuite = Suite.create('');

_.forEach(sets.groupByFile(), (browsers, path) => {
global.gemini = testsApi(rootSuite, browsers);
_.forEach(sets.groupByFile(), (browsers, filePath) => {
const relativeFilePath = path.relative(projectRoot, filePath);

emitter.emit(Events.BEFORE_FILE_READ, path);
utils.requireWithNoCache(path);
emitter.emit(Events.AFTER_FILE_READ, path);
global.gemini = testsApi(rootSuite, browsers, relativeFilePath);

emitter.emit(Events.BEFORE_FILE_READ, filePath);
utils.requireWithNoCache(filePath);
emitter.emit(Events.AFTER_FILE_READ, filePath);

delete global.gemini;
});
@@ -32,5 +35,5 @@ module.exports = (emitter, config, opts) => {
.useFiles(opts.paths)
.useBrowsers(opts.browsers)
.build(config.system.projectRoot, {ignore: config.system.exclude})
.then((setCollection) => loadSuites(setCollection, emitter));
.then((setCollection) => loadSuites(setCollection, emitter, config.system.projectRoot));
};
14 changes: 11 additions & 3 deletions lib/tests-api/index.js
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ const Suite = require('../suite');
const SuiteBuilder = require('./suite-builder');
const keysCodes = require('./keys-codes');

module.exports = (suite, browsers) => {
module.exports = (suite, browsers, file) => {
let suiteId = 1;
const testsAPI = keysCodes;

@@ -25,9 +25,17 @@ module.exports = (suite, browsers) => {
suite = Suite.create(name, parent);
parent.addChild(suite);
suite.id = suiteId++;
if (browsers && suite.parent.isRoot) {
suite.browsers = browsers;

if (suite.parent.isRoot) {
if (browsers) {
suite.browsers = browsers;
}

if (file) {
suite.file = file;
}
}

callback(new SuiteBuilder(suite));
if (suite.hasStates) {
if (!suite.url) {
38 changes: 38 additions & 0 deletions test/unit/reporters/html/view-model.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
'use strict';

const _ = require('lodash');

const ViewModel = require('lib/reporters/html/view-model');

describe('ViewModel', () => {
const sandbox = sinon.sandbox.create();
const stubTest_ = (opts) => {
opts = opts || {};

return _.defaultsDeep(opts, {
state: {name: 'name-default'},
suite: {
path: ['suite'],
metaInfo: {sessionId: 'sessionId-default'},
file: 'default/path/file.js'
}
});
};
const getResult_ = (model) => model.getResult().suites[0].children[0].browsers[0].result;
const createViewModel_ = () =>{
const config = {forBrowser: sandbox.stub().returns({})};
return new ViewModel(config);
};

it('should contain "file" in "metaInfo"', () => {
const model = createViewModel_();

model.addSuccess(stubTest_({
suite: {file: '/path/file.js'}
}));

const metaInfo = JSON.parse(getResult_(model).metaInfo);

assert.equal(metaInfo.file, '/path/file.js');
});
});
13 changes: 13 additions & 0 deletions test/unit/test-reader.js
Original file line number Diff line number Diff line change
@@ -135,6 +135,19 @@ describe('test-reader', () => {
);
});
});

it('should call "testsApi" with relative file path', () => {
const groupByFile = () => ({'/project/root/path/file1.js': []});

const config = mkConfigStub({
system: {projectRoot: '/project/root'}
});

SetsBuilder.prototype.build.returns(Promise.resolve({groupByFile}));

return readTests_({config})
.then(() => assert.calledWith(testsApi, sinon.match.any, sinon.match.any, 'path/file1.js'));
});
});

describe('global "gemini" variable', () => {
199 changes: 109 additions & 90 deletions test/unit/tests-api/index.js
Original file line number Diff line number Diff line change
@@ -1,58 +1,54 @@
'use strict';

var testsAPI = require('lib/tests-api'),
Suite = require('lib/suite');
const testsAPI = require('lib/tests-api');
const Suite = require('lib/suite');

describe('tests-api', function() {
beforeEach(function() {
this.suite = Suite.create('');
describe('tests-api', () => {
let rootSuite;

beforeEach(() => {
rootSuite = Suite.create('');
});

describe('.suite method', function() {
var gemini;
describe('.suite method', () => {
let gemini;

beforeEach(function() {
gemini = testsAPI(this.suite);
beforeEach(() => {
gemini = testsAPI(rootSuite);
});

it('should throw an error if first argument is not a string', function() {
assert.throws(function() {
gemini.suite(123, function() {});
}, TypeError);
it('should throw an error if first argument is not a string', () => {
assert.throws(() => gemini.suite(123, () => {}), TypeError);
});

it('should throw an error if second argument is not a function', function() {
assert.throws(function() {
gemini.suite('name');
}, TypeError);
it('should throw an error if second argument is not a function', () => {
assert.throws(() => gemini.suite('name'), TypeError);
});

it('should create new suite with corresponding name', function() {
gemini.suite('name', function() {});
it('should create new suite with corresponding name', () => {
gemini.suite('name', () => {});

assert.equal(this.suite.children[0].name, 'name');
assert.equal(rootSuite.children[0].name, 'name');
});

it('should call callback', function() {
var spy = sinon.spy();
it('should call callback', () => {
const spy = sinon.spy();
gemini.suite('name', spy);
assert.called(spy);
});

it('should created nested suites when called nestedly', function() {
gemini.suite('name', function() {
gemini.suite('child', function() {});
});
it('should created nested suites when called nestedly', () => {
gemini.suite('name', () => gemini.suite('child', () => {}));

assert.equal(this.suite.children[0].children[0].name, 'child');
assert.equal(rootSuite.children[0].children[0].name, 'child');
});

describe('child suites of the same name', () => {
beforeEach(function() {
gemini = testsAPI(this.suite, ['browser1']);
beforeEach(() => {
gemini = testsAPI(rootSuite, ['browser1']);
});

it('should not allow to create with intersect browsers', function() {
it('should not allow to create with intersect browsers', () => {
assert.throws(() => {
gemini.suite('name', () => {
gemini.suite('child', () => {});
@@ -61,12 +57,10 @@ describe('tests-api', function() {
});
});

it('should allow to create with not intersecting browser sets', function() {
gemini.suite('name', () => {
gemini.suite('child', () => {});
});
it('should allow to create with not intersecting browser sets', () => {
gemini.suite('name', () => gemini.suite('child', () => {}));

gemini = testsAPI(this.suite, ['browser2']);
gemini = testsAPI(rootSuite, ['browser2']);

assert.doesNotThrow(() => {
gemini.suite('name', () => {
@@ -76,123 +70,148 @@ describe('tests-api', function() {
});
});

it('should create non-nested suite at the root level', function() {
gemini.suite('first', function() {});
gemini.suite('second', function() {});
it('should create non-nested suite at the root level', () => {
gemini.suite('first', () => {});
gemini.suite('second', () => {});

assert.equal(this.suite.children[1].name, 'second');
assert.equal(rootSuite.children[1].name, 'second');
});

it('should throw when suite has states but does not has URL', function() {
assert.throws(function() {
gemini.suite('first', function(suite) {
it('should throw when suite has states but does not has URL', () => {
assert.throws(() => {
gemini.suite('first', (suite) => {
suite.setCaptureElements('.element')
.capture('plain');
});
});
});

it('should throw when suite has no states nor URL', function() {
assert.doesNotThrow(function() {
gemini.suite('first', function(suite) {
it('should throw when suite has no states nor URL', () => {
assert.doesNotThrow(() => {
gemini.suite('first', (suite) => {
suite.setCaptureElements('.element');
});
});
});

it('should not throw when suite has states and url is inherited from parent', function() {
assert.doesNotThrow(function() {
gemini.suite('first', function(suite) {
it('should not throw when suite has states and url is inherited from parent', () => {
assert.doesNotThrow(() => {
gemini.suite('first', (suite) => {
suite.setUrl('/url');
gemini.suite('child', function(suite) {
gemini.suite('child', (suite) => {
suite.setCaptureElements('.element')
.capture('plain');
});
});
});
});

it('should throw if suite has states but does not has captureSelectors', function() {
assert.throws(function() {
gemini.suite('first', function(suite) {
it('should throw if suite has states but does not has captureSelectors', () => {
assert.throws(() => {
gemini.suite('first', (suite) => {
suite.setUrl('/url')
.capture('plain');
});
});
});

it('should not throw if suite has no states nor captureSelectors', function() {
assert.doesNotThrow(function() {
gemini.suite('first', function(suite) {
it('should not throw if suite has no states nor captureSelectors', () => {
assert.doesNotThrow(() => {
gemini.suite('first', (suite) => {
suite.setUrl('/url');
});
});
});

it('should not throw when suite has states and captureSelectors are inherited from parent', function() {
assert.doesNotThrow(function() {
gemini.suite('first', function(suite) {
it('should not throw when suite has states and captureSelectors are inherited from parent', () => {
assert.doesNotThrow(() => {
gemini.suite('first', (suite) => {
suite.setCaptureElements('.element');
gemini.suite('child', function(suite) {
gemini.suite('child', (suite) => {
suite.setUrl('/url')
.capture('plain');
});
});
});
});

it('should assign suite ids', function() {
gemini.suite('suite', function() {});
assert.equal(this.suite.children[0].id, 1);
it('should assign suite ids', () => {
gemini.suite('suite', () => {});
assert.equal(rootSuite.children[0].id, 1);
});

it('should assign incrementing suite ids for following suites', function() {
gemini.suite('suite', function() {});
gemini.suite('suite2', function() {});
assert.equal(this.suite.children[1].id, 2);
it('should assign incrementing suite ids for following suites', () => {
gemini.suite('suite', () => {});
gemini.suite('suite2', () => {});
assert.equal(rootSuite.children[1].id, 2);
});

it('should assign incrementing suite ids for child suites', function() {
gemini.suite('suite', function() {
gemini.suite('suite2', function() {});
it('should assign incrementing suite ids for child suites', () => {
gemini.suite('suite', () => {
gemini.suite('suite2', () => {});
});
assert.equal(this.suite.children[0].children[0].id, 2);
assert.equal(rootSuite.children[0].children[0].id, 2);
});

it('should assign child suite ids before siblings', function() {
gemini.suite('suite', function() {
gemini.suite('suite2', function() {});
it('should assign child suite ids before siblings', () => {
gemini.suite('suite', () => {
gemini.suite('suite2', () => {});
});

gemini.suite('suite3', function() {});
gemini.suite('suite3', () => {});

assert.equal(rootSuite.children[0].children[0].id, 2);
assert.equal(rootSuite.children[1].id, 3);
});
});

describe('browsers', () => {
const browsers = ['some-browser', 'other-browser'];
let gemini;

beforeEach(() => {
gemini = testsAPI(rootSuite, browsers);
});

it('should be set for top level suite', () => {
gemini.suite('suite', () => {});

assert.equal(rootSuite.children[0].browsers, browsers);
assert.isTrue(rootSuite.children[0].hasOwnProperty('browsers'));
});

it('should not be set for not top level suite', () => {
gemini.suite('suite', () => {
gemini.suite('child', () => {});
});

assert.equal(this.suite.children[0].children[0].id, 2);
assert.equal(this.suite.children[1].id, 3);
assert.equal(rootSuite.children[0].children[0].browsers, browsers);
assert.isFalse(rootSuite.children[0].children[0].hasOwnProperty('browsers'));
});
});

describe('browsers', function() {
var browsers = ['some-browser', 'other-browser'],
gemini;
describe('file path', () => {
const file = 'path/file.js';
let gemini;

beforeEach(function() {
gemini = testsAPI(this.suite, browsers);
beforeEach(() => {
gemini = testsAPI(rootSuite, [], file);
});

it('should be set for top level suite', function() {
gemini.suite('suite', function() {});
it('should be set for suite', () => {
gemini.suite('suite', () => {});

assert.equal(this.suite.children[0].browsers, browsers);
assert.isTrue(this.suite.children[0].hasOwnProperty('browsers'));
assert.equal(rootSuite.children[0].file, file);
assert.isTrue(rootSuite.children[0].hasOwnProperty('file'));
});

it('should not be set for not top level suite', function() {
gemini.suite('suite', function() {
gemini.suite('child', function() {});
it('should not be set for not top level suite', () => {
gemini.suite('suite', () => {
gemini.suite('child', () => {});
});

assert.equal(this.suite.children[0].children[0].browsers, browsers);
assert.isFalse(this.suite.children[0].children[0].hasOwnProperty('browsers'));
assert.equal(rootSuite.children[0].children[0].file, file);
assert.isFalse(rootSuite.children[0].children[0].hasOwnProperty('file'));
});
});
});

0 comments on commit 0311f6d

Please sign in to comment.