diff --git a/Gruntfile.js b/Gruntfile.js index 04bc6ab3ef35604f46c38f2db627b3afdf7e9331..7355989ff908a79ab54d209ac5e68da509bb1b79 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,6 +1,9 @@ -'use strict'; +/** + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + */ module.exports = function (grunt) { + 'use strict'; require('./spec_runner')(grunt); @@ -145,38 +148,33 @@ module.exports = function (grunt) { template: require('grunt-template-jasmine-requirejs'), ignoreEmpty: true }, - 'backend-unit-testsuite': { - options: specConfigFor('unit', 'adminhtml', 8000) - }, - 'backend-integration-testsuite': { - options: specConfigFor('integration', 'adminhtml', 8000) - }, - 'frontend-unit-testsuite': { - options: specConfigFor('unit', 'frontend', 3000) - }, - 'frontend-integration-testsuite': { - options: specConfigFor('integration', 'frontend', 3000) - } + 'backend-unit-testsuite': specConfigFor('unit', 'adminhtml', 8000), + 'backend-integration-testsuite': specConfigFor('integration', 'adminhtml', 8000), + 'frontend-unit-testsuite': specConfigFor('unit', 'frontend', 3000), + 'frontend-integration-testsuite': specConfigFor('integration', 'frontend', 3000) } }); function specConfigFor(type, dir, port) { return { - host: 'http://localhost:' + port, - specs: specPathFor(type, dir, 'Spec'), - helpers: specPathFor(type, dir, 'Helper'), - templateOptions: { - requireConfigFile: [ - 'lib/web/app-config.js', - '<%= config.path.spec %>/' + type + '/config.js' - ] + src: '<%= config.path.spec %>/env.js', + options: { + host: 'http://localhost:' + port, + specs: specPathFor(type, dir, 'Spec'), + helpers: specPathFor(type, dir, 'Helper'), + templateOptions: { + requireConfigFile: [ + 'lib/web/app-config.js', + '<%= config.path.spec %>/' + type + '/config.js/' + ] + } } } - }; + } function specPathFor(type, dir, suffix) { - return '<%= config.path.spec %>/' + type + '/**/' + dir + '/**/*' + suffix + '.js' - }; + return '<%= config.path.spec %>/' + type + '/**/' + dir + '/**/*' + suffix + '.js'; + } // Clean var & pub folders grunt.registerTask('cleanup', [ diff --git a/dev/tests/js/spec/unit/Magento/Ui/adminhtml/eventsSpec.js b/dev/tests/js/spec/unit/Magento/Ui/adminhtml/eventsSpec.js index ec222391eb5a8388af0ff5fdc7aada0ea255a0b6..3dbf1805da45d357c3e92471ec2ceda15163ae84 100644 --- a/dev/tests/js/spec/unit/Magento/Ui/adminhtml/eventsSpec.js +++ b/dev/tests/js/spec/unit/Magento/Ui/adminhtml/eventsSpec.js @@ -1,14 +1,23 @@ /** * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) */ +/* global jasmine: true, expect: true, it: true, describe: true */ define([ 'Magento_Ui/js/lib/events' ], function (EventBus) { 'use strict'; describe('EventBus', function () { - it('has <on> method', function () { - expect('on' in EventBus).toBe(true); + describe('<on> method', function () { + it('calls passed callback when event is triggered', function () { + var callback = jasmine.createSpy('callback'); + + EventBus.on('someEvent', callback); + + EventBus.trigger('someEvent'); + + expect(callback).toHaveBeenCalled(); + }); }); }); -}); \ No newline at end of file +}); diff --git a/spec_runner.js b/spec_runner.js index 6a686067dc5a70b1ccf1d94a84830b2046e731d1..faa920a556bb327e516f23cb80a2bf65b3a8b0fa 100644 --- a/spec_runner.js +++ b/spec_runner.js @@ -1,62 +1,138 @@ -'use strict'; +/** + * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) + */ + +/* global __dirname: true */ + +module.exports = function (grunt) { + 'use strict'; -module.exports = function(grunt) { var connect = require('connect'), logger = require('morgan'), serveStatic = require('serve-static'), fs = require('fs'); + /** + * Defines if passed file path exists + * + * @param {String} path + * @return {Boolean} + */ + function exists(path) { + return fs.existsSync(path); + } + + /** + * Restricts url's which lead to '/_SpecRunner.html', '/dev/tests' or '.grunt' folders from being modified + * + * @param {String} url + * @return {Boolean} + */ function canModify(url) { return url.match(/^\/(\.grunt)|(dev\/tests)|(_SpecRunner\.html)/) === null; - }; + } - grunt.registerMultiTask('specRunner', function(grunt) { + grunt.registerMultiTask('specRunner', function () { var app = connect(), options, area, + theme, share, - moduleRoot, - libPath; + middlewares; options = this.options({ port: 3000, + theme: 'blank', areaDir: 'adminhtml', shareDir: 'base', - enableLogs: false + enableLogs: false, + middleware: null }); area = options.areaDir; share = options.shareDir; - moduleRoot = '/app/code/Magento/'; - libPath = '/lib/web'; + theme = options.theme; if (options.enableLogs) { app.use(logger('dev')); } - function assembleUrl(module, area, path) { - return moduleRoot + module + '/view/' + area + '/web/' + path; - } - - app.use(function(req, res, next) { - var url = req.url, - match = url.match(/^\/Magento_([^\/]+)(\/.+)$/), + app.use(function (req, res, next) { + var url = req.url, + match = url.match(/^\/([A-Z][^\/]+)_(\w+)\/(.+)$/), + app, module, path, - exist; + getModuleUrl, + getThemeUrl; + + /** + * Returns path to theme root folder + * + * @return {String} + */ + function themeRoot() { + return [ + '/app/design', + area, + app, + theme + ].join('/'); + } + + /** + * Based on 'thematic' parameter, returnes either path to theme's lib, + * or 'lib/web'. + * + * @param {Boolean} thematic + * @return {String} + */ + function lib(thematic) { + return thematic ? themeRoot() + '/web' : '/lib/web'; + } if (match !== null) { - module = match[1]; - path = match[2]; - url = assembleUrl(module, area, path), - exist = fs.existsSync(url); + app = match[1]; + module = match[2]; + path = match[3]; + + /** + * Assembles modular path. If 'shared' flag provided and is truthy, + * will use share dir instead of area one. + * + * @param {Boolean} shared + * @return {String} + */ + getModuleUrl = function (shared) { + return [ + '/app/code', + app, + module, + 'view', + shared ? share : area, + 'web', + path + ].join('/'); + }; - if (!exist) { - url = assembleUrl(module, share, path); - } + /** + * Assembles theme modular path. + * + * @return {String} + */ + getThemeUrl = function () { + return [ + themeRoot(), + app + '_' + module, + 'web', + path + ].join('/'); + }; + + url = exists(url = getThemeUrl()) ? url : getModuleUrl(true); } else if (canModify(url)) { - url = libPath + url; + url = (exists(url = lib(true)) ? url : lib()) + req.url; } req.url = url; @@ -64,8 +140,18 @@ module.exports = function(grunt) { next(); }); + if (options.middleware && typeof options.middleware === 'function') { + middlewares = options.middleware(connect, options); + + if (Array.isArray(middlewares)) { + middlewares.forEach(function (middleware) { + app.use(middleware); + }); + } + } + app.use(serveStatic(__dirname)); app.listen(options.port); }); -} \ No newline at end of file +};