diff --git a/Makefile b/Makefile index 8db882e36db..eef81042fd9 100644 --- a/Makefile +++ b/Makefile @@ -160,8 +160,13 @@ client-format: node-deps ## Reformat client code client-watch: node-deps ## A useful target for parallel development building. cd client && yarn run watch -client-test: client ## Run qunit tests via Karma - cd client && yarn run test +_client-test-mocha: ## Run mocha tests via karma + cd client && GALAXY_TEST_FRAMEWORK=mocha yarn run test + +_client-test-qunit: ## Run qunit tests via karma + cd client && GALAXY_TEST_FRAMEWORK=qunit yarn run test + +client-test: client _client-test-mocha _client-test-qunit ## Run JS unit tests via Karma client-test-watch: client ## Watch and run qunit tests on changes via Karma cd client && yarn run test-watch diff --git a/client/galaxy/scripts/mocha/test.js b/client/galaxy/scripts/mocha/test.js new file mode 100644 index 00000000000..685c4593442 --- /dev/null +++ b/client/galaxy/scripts/mocha/test.js @@ -0,0 +1 @@ +import rules from "mocha/tests/rules_tests"; diff --git a/client/galaxy/scripts/mocha/tests/rules_dsl_spec.yml b/client/galaxy/scripts/mocha/tests/rules_dsl_spec.yml new file mode 120000 index 00000000000..801fe01b06f --- /dev/null +++ b/client/galaxy/scripts/mocha/tests/rules_dsl_spec.yml @@ -0,0 +1 @@ +../../../../../test/base/data/rules_dsl_spec.yml \ No newline at end of file diff --git a/client/galaxy/scripts/mocha/tests/rules_tests.js b/client/galaxy/scripts/mocha/tests/rules_tests.js new file mode 100644 index 00000000000..3d0efc8b6c4 --- /dev/null +++ b/client/galaxy/scripts/mocha/tests/rules_tests.js @@ -0,0 +1,58 @@ +import chai from "chai"; +import RuleDefs from "mvc/rules/rule-definitions"; +import SPEC_TEST_CASES from "json-loader!yaml-loader!./rules_dsl_spec.yml"; + +const RULES = RuleDefs.RULES; + +function applyRules(rules, data, sources) { + let columns = []; + if (data[0]) { + for (const index in data[0]) { + columns.push("new"); + } + } + for (var ruleIndex in rules) { + const rule = rules[ruleIndex]; + rule.error = null; + rule.warn = null; + + var ruleType = rule.type; + const ruleDef = RULES[ruleType]; + const res = ruleDef.apply(rule, data, sources, columns); + if (res.error) { + throw res.error; + } else { + if (res.warn) { + rule.warn = res.warn; + } + data = res.data || data; + sources = res.sources || sources; + columns = res.columns || columns; + } + } + return { data, sources, columns }; +} + +function itShouldConform(specTestCase, i) { + it("should pass conformance test case " + i, function() { + chai.assert.property(specTestCase, "rules"); + chai.assert.property(specTestCase, "initial"); + chai.assert.property(specTestCase, "final"); + + const rules = specTestCase.rules; + const initial = specTestCase.initial; + const expectedFinal = specTestCase.final; + + const final = applyRules(rules, initial.data, initial.sources); + const finalData = final.data; + const finalSources = final.sources; + chai.assert.deepEqual(finalData, expectedFinal.data); + if (expectedFinal.sources !== undefined) { + chai.assert.deepEqual(finalSources, expectedFinal.sources); + } + }); +} + +describe("Rules DSL Spec", function() { + SPEC_TEST_CASES.forEach(itShouldConform); +}); diff --git a/client/karma.config.js b/client/karma.config.js index a5fa1756f6f..acfe996d489 100644 --- a/client/karma.config.js +++ b/client/karma.config.js @@ -14,7 +14,11 @@ var single_pack_mode = function(){ return process.env.GALAXY_TEST_AS_SINGLE_PACK || false; }; -var TESTS_SEPARATE_PACKS = [ +var test_framework = function() { + return process.env.GALAXY_TEST_FRAMEWORK || "qunit"; +} + +var QUNIT_TESTS_SEPARATE_PACKS = [ {pattern: 'galaxy/scripts/qunit/tests/galaxy_app_base_tests.js', watched: false}, // Something is funky with form_tests.js - needs to come before all other tests. {pattern: 'galaxy/scripts/qunit/tests/form_tests.js', watched: false}, @@ -41,22 +45,31 @@ var TESTS_SEPARATE_PACKS = [ // {pattern: 'galaxy/scripts/qunit/tests/ui_tests.js', watched: false}, ]; -var TESTS_AS_SINGLE_PACK = [ +var QUNIT_TESTS_AS_SINGLE_PACK = [ {pattern: 'galaxy/scripts/qunit/test.js', watched: false}, ]; + +QUNIT_TEST_FILES = single_pack_mode() ? QUNIT_TESTS_AS_SINGLE_PACK : QUNIT_TESTS_SEPARATE_PACKS; +MOCHA_TEST_FILES = [ + {pattern: 'galaxy/scripts/mocha/test.js', watched: false}, +]; +TEST_FILES = test_framework() == "qunit" ? QUNIT_TEST_FILES : MOCHA_TEST_FILES; +FRAMEWORK_PLUGIN = test_framework() == "qunit" ? "karma-qunit" : "karma-mocha"; + // karma.conf.js module.exports = function(config) { config.set({ basepath: '.', - files: (single_pack_mode() ? TESTS_AS_SINGLE_PACK : TESTS_SEPARATE_PACKS).concat([ + files: TEST_FILES.concat([ // Non-test assets that will be served by web server. // CSS needed by tests. 'galaxy/scripts/qunit/assets/*.css', ]), plugins: [ 'karma-webpack', - 'karma-qunit', + FRAMEWORK_PLUGIN, + 'karma-mocha', 'karma-polyfill', 'karma-phantomjs-launcher', ], @@ -69,10 +82,11 @@ module.exports = function(config) { // that we have a working setup. preprocessors: { // add webpack as preprocessor - 'galaxy/scripts/qunit/**/*.js': ['webpack'] + 'galaxy/scripts/qunit/**/*.js': ['webpack'], + 'galaxy/scripts/mocha/**/*.js': ['webpack'] }, - frameworks: ['polyfill', 'qunit'], + frameworks: ['polyfill', test_framework()], webpack: webpackConfig, webpackMiddleware: { noInfo: false } diff --git a/client/package.json b/client/package.json index 6151ec4686e..121a4b374d3 100644 --- a/client/package.json +++ b/client/package.json @@ -58,6 +58,7 @@ "babel-loader": "^7.1.1", "babel-plugin-transform-vue-template": "^0.3.1", "babel-preset-env": "^1.6.1", + "chai": "^4.1.2", "concurrently": "^3.5.1", "css-loader": "^0.28.7", "del": "^3.0.0", @@ -83,10 +84,12 @@ "gulp-watch": "^4.3.11", "jshint": "^2.9.4", "karma": "^1.7.1", + "karma-mocha": "^1.3.0", "karma-phantomjs-launcher": "^1.0.4", "karma-polyfill": "^1.0.0", "karma-qunit": "^1.2.1", "karma-webpack": "^2.0.6", + "mocha": "^5.0.5", "phantomjs-polyfill": "0.0.2", "phantomjs-prebuilt": "^2.1.7", "prettier": "^1.10.1", @@ -94,6 +97,7 @@ "sinon": "^4.1.2", "vue-loader": "^13.5.0", "vue-template-compiler": "^2.5.13", - "webpack": "^3.10.0" + "webpack": "^3.10.0", + "yaml-loader": "^0.5.0" } } diff --git a/test/base/data/rules_dsl_spec.yml b/test/base/data/rules_dsl_spec.yml new file mode 100644 index 00000000000..4dd6653191b --- /dev/null +++ b/test/base/data/rules_dsl_spec.yml @@ -0,0 +1,359 @@ +- rules: + - type: add_column_basename + target_column: 0 + initial: + data: [['/path/to/moo.txt'], ['moo.txt']] + sources: [1, 2] + final: + data: + - [/path/to/moo.txt, moo.txt] + - [moo.txt, moo.txt] +- rules: + - type: add_column_regex + target_column: 0 + expression: '(o)+' + initial: + data: [[foo], [cow]] + sources: [1,2] + final: + data: [[foo, oo], [cow, o]] +- rules: + - type: add_column_regex + target_column: 0 + expression: '(o+)' + replacement: 'the os \1' + initial: + data: [[foo], [cow]] + sources: [1,2] + final: + data: [["foo", "the os oo"], ["cow", "the os o"]] +- rules: + - type: add_column_substr + target_column: 0 + substr_type: keep_prefix + length: 2 + initial: + data: [[foo], [cow], [ba], [d]] + sources: [1, 2] + final: + data: [[foo, fo], [cow, co], [ba, ba], [d, d]] +- rules: + - type: add_column_substr + target_column: 0 + substr_type: keep_suffix + length: 2 + initial: + data: [[foo], [cow], [ba], [d]] + sources: [1, 2] + final: + data: [[foo, oo], [cow, ow], [ba, ba], [d, d]] +- rules: + - type: add_column_substr + target_column: 0 + substr_type: drop_prefix + length: 2 + initial: + data: [[foo], [cow], [ba], [d]] + sources: [1, 2] + final: + data: [[foo, o], [cow, w], [ba, ""], [d, ""]] +- rules: + - type: add_column_substr + target_column: 0 + substr_type: drop_suffix + length: 2 + initial: + data: [[foo], [cow], [ba], [d]] + sources: [1, 2] + final: + data: [[foo, f], [cow, c], [ba, ""], [d, ""]] +- rules: + - type: add_column_rownum + start: 1 + initial: + data: [[foo], [cow], [ba], [d]] + sources: [1, 2, 3, 4] + final: + data: [[foo, "1"], [cow, "2"], [ba, "3"], [d, "4"]] +- rules: + - type: add_column_rownum + start: 0 + initial: + data: [[foo], [cow], [ba], [d]] + sources: [1, 2, 3, 4] + final: + data: [[foo, "0"], [cow, "1"], [ba, "2"], [d, "3"]] +- rules: + - type: add_column_value + value: "moo" + initial: + data: [[foo], [cow]] + sources: [1, 2] + final: + data: [[foo, moo], [cow, moo]] +- rules: + - type: remove_columns + target_columns: [0, 1] + initial: + data: [[a, b, c], [e, f, g]] + sources: [1, 2] + final: + data: [[c], [g]] +- rules: + - type: remove_columns + target_columns: [2] + initial: + data: [[a, b, c], [e, f, g]] + sources: [1, 2] + final: + data: [[a, b], [e, f]] +- rules: + - type: add_filter_regex + target_column: 0 + expression: '(a+)' + invert: false + initial: + data: [[a, b, c], [e, f, g]] + sources: [1, 2] + final: + data: [[a, b, c]] +- rules: + - type: add_filter_regex + target_column: 2 + expression: '(c+)' + invert: true + initial: + data: [[a, b, c], [e, f, g]] + sources: [1, 2] + final: + data: [[e, f, g]] + sources: [2] +- rules: + - type: add_filter_count + count: 1 + which: first + invert: false + initial: + data: [[a, b, c], [e, f, g], [h, i, j]] + sources: [1, 2, 3] + final: + data: [[e, f, g], [h, i, j]] + sources: [2, 3] +- rules: + - type: add_filter_count + count: 0 + which: first + invert: false + initial: + data: [[a, b, c], [e, f, g], [h, i, j]] + sources: [1, 2, 3] + final: + data: [[a, b, c], [e, f, g], [h, i, j]] + sources: [1, 2, 3] +- rules: + - type: add_filter_count + count: 1 + which: last + invert: false + initial: + data: [[a, b, c], [e, f, g], [h, i, j]] + sources: [1, 2, 3] + final: + data: [[a, b, c], [e, f, g]] + sources: [1, 2] +- rules: + - type: add_filter_count + count: 1 + which: last + invert: true + initial: + data: [[a, b, c], [e, f, g], [h, i, j]] + sources: [1, 2, 3] + final: + data: [[h, i, j]] + sources: [3] +- rules: + - type: add_filter_empty + target_column: 0 + invert: false + initial: + data: [["", "b", "c"], ["a", "b", "c"]] + sources: [1, 2] + final: + data: [["a", "b", "c"]] + sources: [2] +- rules: + - type: add_filter_empty + target_column: 0 + invert: true + initial: + data: [["", "b", "c"], ["a", "b", "c"]] + sources: [moo, cow] + final: + data: [["", "b", "c"]] + sources: [moo] + +- rules: + - type: add_filter_matches + value: a + target_column: 0 + invert: false + initial: + data: [[a, b, c], + [e, f, g], + [h, i, j]] + sources: [1, 2, 3] + final: + data: [[a, b, c]] + sources: [1] + +- rules: + - type: add_filter_matches + value: a + target_column: 0 + invert: true + initial: + data: [[a, b, c], + [e, f, g], + [h, i, j]] + sources: [1, 2, 3] + final: + data: [[e, f, g], + [h, i, j]] + sources: [2, 3] + +- rules: + - type: add_filter_matches + value: p + target_column: 1 + invert: false + initial: + data: [[a, b, c], + [e, f, g], + [h, i, j]] + sources: [1, 2, 3] + final: + data: [] + sources: [] + +- rules: + - type: add_filter_matches + value: a + target_column: 1 + invert: false + initial: + data: [['a ', b, c], + [e, f, g], + [h, i, j]] + sources: [1, 2, 3] + final: + data: [] + sources: [] + +- rules: + - type: add_filter_matches + value: 'a ' + target_column: 1 + invert: false + initial: + data: [[a, b, c], + [e, f, g], + [h, i, j]] + sources: [1, 2, 3] + final: + data: [] + sources: [] + +- rules: + - type: add_filter_matches + value: p + target_column: 1 + invert: true + initial: + data: [[a, b, c], + [e, f, g], + [h, i, j]] + sources: [1, 2, 3] + final: + data: [[a, b, c], + [e, f, g], + [h, i, j]] + sources: [1, 2, 3] + +- rules: + - type: add_filter_compare + target_column: 0 + value: 13 + compare_type: less_than + initial: + data: [["1", "moo"], ["10", "cow"], ["13", "rat"], ["20", "dog"], ["30", "cat"]] + sources: [1, 2, 3, 4, 5] + final: + data: [["1", "moo"], ["10", "cow"]] + sources: [1, 2] + +- rules: + - type: add_filter_compare + target_column: 0 + value: 13 + compare_type: less_than_equal + initial: + data: [["1", "moo"], ["10", "cow"], ["13", "rat"], ["20", "dog"], ["30", "cat"]] + sources: [1, 2, 3, 4, 5] + final: + data: [["1", "moo"], ["10", "cow"], ["13", "rat"]] + sources: [1, 2, 3] + +- rules: + - type: add_filter_compare + target_column: 0 + value: 13 + compare_type: greater_than + initial: + data: [["1", "moo"], ["10", "cow"], ["13", "rat"], ["20", "dog"], ["30", "cat"]] + sources: [1, 2, 3, 4, 5] + final: + data: [["20", "dog"], ["30", "cat"]] + sources: [4, 5] +- rules: + - type: add_filter_compare + target_column: 0 + value: 13 + compare_type: greater_than_equal + initial: + data: [["1", "moo"], ["10", "cow"], ["13", "rat"], ["20", "dog"], ["30", "cat"]] + sources: [1, 2, 3, 4, 5] + final: + data: [["13", "rat"], ["20", "dog"], ["30", "cat"]] + sources: [3, 4, 5] +- rules: + - type: sort + numeric: false + target_column: 0 + initial: + data: [["moo", "cow"], ["meow", "cat"], ["bark", "dog"]] + sources: [1, 2, 3] + final: + data: [["bark", "dog"], ["meow", "cat"], ["moo", "cow"]] + sources: [3, 2, 1] +- rules: + - type: sort + numeric: false + target_column: 1 + initial: + data: [["moo", "cow"], ["meow", "cat"], ["bark", "dog"]] + sources: [1, 2, 3] + final: + data: [["meow", "cat"], ["moo", "cow"], ["bark", "dog"]] + sources: [2, 1, 3] +- rules: + - type: sort + numeric: false + target_column: 1 + initial: + data: [["moo", "cow"], ["meow", "cat"], ["bark", "Dog"]] + sources: [1, 2, 3] + final: + data: [["bark", "Dog"], ["meow", "cat"], ["moo", "cow"]] + sources: [3, 2, 1] +