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

Commit

Permalink
fix up sets logic
Browse files Browse the repository at this point in the history
  • Loading branch information
rostik404 committed Aug 30, 2016
1 parent a73ca63 commit d82ccbe
Show file tree
Hide file tree
Showing 11 changed files with 156 additions and 54 deletions.
5 changes: 1 addition & 4 deletions lib/config/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ module.exports = root(

sets: map(section({
files: option({
defaultValue: 'gemini',
validate: function(value) {
if (!_.isArray(value) && !_.isString(value)) {
throw new GeminiError('"sets.files" must be an array or string');
Expand Down Expand Up @@ -116,9 +115,7 @@ module.exports = root(
}
}
})
}), {
all: {} // Use `all` set with default values if no set specified in config
}),
})),

browsers: map(section(browserOptions.getPerBrowser()))
}))
Expand Down
9 changes: 9 additions & 0 deletions lib/test-reader/files-filter/identity-filter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
'use strict';

const FilesFilter = require('./');

module.exports = class IdentityFilter extends FilesFilter {
filter(filesToFilter) {
return filesToFilter;
}
};
7 changes: 7 additions & 0 deletions lib/test-reader/files-filter/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'use strict';

module.exports = class FilesFilter {
filter() {
throw new Error('Cannot call method of the base class');
}
};
19 changes: 19 additions & 0 deletions lib/test-reader/files-filter/intersection-filter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
'use strict';

const _ = require('lodash');

const FilesFilter = require('./');

module.exports = class IntersectionFilter extends FilesFilter {
constructor(files) {
super();

this._files = files;
}

filter(filesToFilter) {
return _.isEmpty(filesToFilter)
? this._files
: _.intersection(filesToFilter, this._files);
}
};
19 changes: 17 additions & 2 deletions lib/test-reader/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
'use strict';

const q = require('q');
const path = require('path');

const _ = require('lodash');
const globExtra = require('glob-extra');
const q = require('q');

const SetCollection = require('./set-collection');
const Suite = require('../suite');
const testsApi = require('../tests-api');
Expand All @@ -24,10 +27,22 @@ const loadSuites = (sets, emitter) => {
return rootSuite;
};

const filesExist = (configSets, cliPaths) => {
return !_.isEmpty(configSets) || !_.isEmpty(cliPaths);
};

const getGeminiPath = (projectRoot) => {
return path.resolve(projectRoot, 'gemini');
};

module.exports = (cli, config, emitter) => {
const files = filesExist(config.sets, cli.paths)
? cli.paths
: [getGeminiPath(config.system.projectRoot)];

return q.all([
SetCollection.create(config, cli.sets),
globExtra.expandPaths(cli.paths, {formats: ['.js']})
globExtra.expandPaths(files, {formats: ['.js']})
])
.spread((sets, paths) => {
sets.filterFiles(paths);
Expand Down
17 changes: 12 additions & 5 deletions lib/test-reader/set-collection.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ const Set = require('./set');

module.exports = class SetCollection {
static create(config, sets) {
const filteredSets = SetCollection._filter(config.sets, sets);
let filteredSets = SetCollection._filter(config.sets, sets);

if (_.isEmpty(filteredSets)) {
filteredSets = [{files: {}, browsers: config.getBrowserIds()}];
}

return SetCollection._expand(filteredSets, config.system.projectRoot)
.then((sets) => new SetCollection(sets));
Expand All @@ -29,10 +33,13 @@ module.exports = class SetCollection {
const unknownSets = _.difference(setsToUse, _.keys(sets));

if (!_.isEmpty(unknownSets)) {
throw new GeminiError(
`No such sets: ${unknownSets.join(', ')}. Use one of the sets, specified ` +
`in config file: ${_.keys(sets).join(', ')}`
);
let error = `No such sets: ${unknownSets.join(', ')}.`;

if (!_.isEmpty(sets)) {
error += ` Use one of the sets, specified in config file: ${_.keys(sets).join(', ')}`;
}

throw new GeminiError(error);
}
}

Expand Down
11 changes: 8 additions & 3 deletions lib/test-reader/set.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,20 @@

const _ = require('lodash');

const IdentityFilter = require('./files-filter/identity-filter');
const IntersectionFilter = require('./files-filter/intersection-filter');

module.exports = class Set {
static create(set) {
return new Set(set);
}

constructor(set) {
this._set = set;

this._filesFilter = _.isEmpty(this._set.files)
? new IdentityFilter()
: new IntersectionFilter(this._set.files);
}

getFiles() {
Expand All @@ -20,8 +27,6 @@ module.exports = class Set {
}

filterFiles(files) {
if (!_.isEmpty(files)) {
this._set.files = _.intersection(files, this._set.files);
}
this._set.files = this._filesFilter.filter(files);
}
};
83 changes: 45 additions & 38 deletions test/unit/config-options/sets.test.js
Original file line number Diff line number Diff line change
@@ -1,41 +1,43 @@
'use strict';
var parser = require('lib/config/options'),
GeminiError = require('lib/errors/gemini-error'),
_ = require('lodash');

describe('config.sets', function() {
///
function createConfig(opts) {
var REQUIRED_OPTIONS = {

const MissingOptionError = require('gemini-configparser').MissingOptionError;
const _ = require('lodash');

const parser = require('lib/config/options');
const GeminiError = require('lib/errors/gemini-error');

describe('config.sets', () => {
const createConfig = (opts) => {
const REQUIRED_OPTIONS = {
system: {
projectRoot: '/some/path'
},
rootUrl: 'http://example.com/root',
desiredCapabilities: {}
};

var options = _.extend({}, REQUIRED_OPTIONS, opts);
const options = _.extend({}, REQUIRED_OPTIONS, opts);

return parser({
options: options,
env: {},
argv: []
});
}
};

describe('files', function() {
it('should be `gemini` by default', function() {
var config = createConfig({
sets: {
someSet: {}
}
});

assert.deepEqual(config.sets.someSet.files, ['gemini']);
describe('files', () => {
it('should throw an error if files are not specified', () => {
assert.throws(() => {
createConfig({
sets: {
someSet: {}
}
});
}, MissingOptionError);
});

it('should convert string to array of strings', function() {
var config = createConfig({
it('should convert string to array of strings', () => {
const config = createConfig({
sets: {
someSet: {
files: 'some/path'
Expand All @@ -46,8 +48,8 @@ describe('config.sets', function() {
assert.deepEqual(config.sets.someSet.files, ['some/path']);
});

it('should not accept non-string arrays', function() {
assert.throws(function() {
it('should not accept non-string arrays', () => {
assert.throws(() => {
createConfig({
sets: {
someSet: {
Expand All @@ -58,8 +60,8 @@ describe('config.sets', function() {
}, GeminiError);
});

it('should accept array with strings', function() {
var config = createConfig({
it('should accept array with strings', () => {
const config = createConfig({
sets: {
someSet: {
files: [
Expand All @@ -77,60 +79,66 @@ describe('config.sets', function() {
});
});

describe('browsers', function() {
it('should contain all browsers by default', function() {
describe('browsers', () => {
it('should contain all browsers by default', () => {
var config = createConfig({
browsers: {
b1: {},
b2: {}
},
sets: {
someSet: {}
someSet: {
files: ['some/path']
}
}
});

assert.deepEqual(config.sets.someSet.browsers, ['b1', 'b2']);
});

it('should not accept non-arrays', function() {
assert.throws(function() {
it('should not accept non-arrays', () => {
assert.throws(() => {
createConfig({
sets: {
someSet: {
files: ['some/path'],
browsers: 'something'
}
}
});
}, GeminiError);
});

it('should not accept unknown browsers', function() {
assert.throws(function() {
it('should not accept unknown browsers', () => {
assert.throws(() => {
createConfig({
browsers: {
b1: {},
b2: {}
},
sets: {
someSet: {
files: ['some/path'],
browsers: ['b3']
}
}
});
}, GeminiError);
});

it('should accept configured browsers', function() {
var config = createConfig({
it('should accept configured browsers', () => {
const config = createConfig({
browsers: {
b1: {},
b2: {}
},
sets: {
set1: {
files: ['some/path'],
browsers: ['b1']
},
set2: {
files: ['other/path'],
browsers: ['b2']
}
}
Expand All @@ -141,15 +149,14 @@ describe('config.sets', function() {
});
});

it('should have `all` set with default values if no set specified', function() {
var config = createConfig({
it('should not have default set if sets are not specified', () => {
const config = createConfig({
browsers: {
b1: {},
b2: {}
}
});

assert.deepEqual(config.sets.all.files, ['gemini']);
assert.deepEqual(config.sets.all.browsers, ['b1', 'b2']);
assert.deepEqual(config.sets, {});
});
});
11 changes: 11 additions & 0 deletions test/unit/test-reader/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,17 @@ describe('test-reader', () => {
});
});

it('should use gemini folder if sets are not specified in config and paths are not passed', () => {
const config = {
getBrowserIds: () => []
};

globExtra.expandPaths.withArgs(['/root/gemini']).returns(q(['/root/gemini/file.js']));

return readTests_({config})
.then(() => assert.calledWith(utils.requireWithNoCache, '/root/gemini/file.js'));
});

it('should load suites related to sets from config', () => {
const config = {
sets: {
Expand Down
20 changes: 18 additions & 2 deletions test/unit/test-reader/set-collection.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ describe('set-collection', () => {
const mkConfigStub = (opts) => {
return _.defaults(opts || {}, {
sets: opts.sets || {},
getBrowserIds: opts.getBrowserIds,
system: {
projectRoot: '/root'
}
Expand All @@ -32,6 +33,21 @@ describe('set-collection', () => {

afterEach(() => sandbox.restore());

describe('sets are not specified in config', () => {
it('should throw an error if an unknown set was passed', () => {
assert.throws(() => SetCollection.create(mkConfigStub(), ['unknown-set'], /unknown-set/));
});

it('should create new set with empty files and browsers from config', () => {
sandbox.stub(Set, 'create').returns(mkSetStub());

const getBrowserIds = sandbox.stub().returns(['b1', 'b2']);

return SetCollection.create(mkConfigStub({getBrowserIds}))
.then(() => assert.calledWith(Set.create, {files: [], browsers: ['b1', 'b2']}));
});
});

it('should create collection for specified sets', () => {
const config = mkConfigStub({
sets: {
Expand Down Expand Up @@ -94,10 +110,10 @@ describe('set-collection', () => {
}
});

assert.throws(() => SetCollection.create(config, ['set3']), /set3(.+) set1, set2/);
assert.throws(() => SetCollection.create(config, ['unknown-set']), /unknown-set(.+) set1, set2/);
});

it('should filter sets files by passed files', () => {
it('should filter passed files if sets are specified in config', () => {
const sets = {
set1: mkSetStub(),
set2: mkSetStub()
Expand Down
Loading

0 comments on commit d82ccbe

Please sign in to comment.