From d2440f6cd77f7568fe8046fb45ad049bcd65a054 Mon Sep 17 00:00:00 2001 From: Joe Fiorini Date: Wed, 8 Jul 2015 10:13:50 -0400 Subject: [PATCH 1/7] Extract factory for generating template URLs --- awx/ui/static/js/app.js | 2 + .../counts/dashboard-counts.directive.js | 6 +- .../js/dashboard/dashboard.directive.js | 6 +- .../graphs/dashboard-graphs.directive.js | 6 +- .../host-status-graph.directive.js | 5 +- .../job-status/job-status-graph.directive.js | 5 +- .../js/dashboard/graphs/job-status/main.js | 4 +- .../job-templates-list.directive.js | 5 +- .../lists/jobs/jobs-list.directive.js | 79 ++++++++++--------- .../js/main-menu/default-menu.directive.js | 29 ++++--- .../js/main-menu/main-menu.directive.js | 79 ++++++++++--------- .../js/main-menu/menu-toggle.directive.js | 49 ++++++------ .../js/main-menu/portal-menu.directive.js | 29 ++++--- .../main-menu/web-socket-status.directive.js | 34 ++++---- .../breadcrumbs/breadcrumbs.directive.js | 49 ++++++------ .../static/js/shared/icon/icon.directive.js | 49 ++++++------ .../js/shared/multi-select-list/main.js | 3 +- .../multi-select-list/select-all.directive.js | 8 +- awx/ui/static/js/shared/template-url/main.js | 6 ++ .../template-url/template-url.factory.js | 20 +++++ .../date-picker/date-picker.directive.js | 5 +- .../fact-data-table.directive.js | 5 +- awx/ui/tests/unit/setup-browser.js | 39 +++++++++ 23 files changed, 308 insertions(+), 214 deletions(-) create mode 100644 awx/ui/static/js/shared/template-url/main.js create mode 100644 awx/ui/static/js/shared/template-url/template-url.factory.js create mode 100644 awx/ui/tests/unit/setup-browser.js diff --git a/awx/ui/static/js/app.js b/awx/ui/static/js/app.js index 41f795e625..e8f65b5a6d 100644 --- a/awx/ui/static/js/app.js +++ b/awx/ui/static/js/app.js @@ -38,6 +38,7 @@ import mainMenu from 'tower/main-menu/main'; import browserData from 'tower/browser-data/main'; import dashboard from 'tower/dashboard/main'; import moment from 'tower/shared/moment/main'; +import templateUrl from 'tower/shared/template-url/main'; import {JobDetailController} from 'tower/controllers/JobDetail'; import {JobStdoutController} from 'tower/controllers/JobStdout'; @@ -84,6 +85,7 @@ var tower = angular.module('Tower', [ mainMenu.name, dashboard.name, moment.name, + templateUrl.name, 'AuthService', 'Utilities', 'LicenseHelper', diff --git a/awx/ui/static/js/dashboard/counts/dashboard-counts.directive.js b/awx/ui/static/js/dashboard/counts/dashboard-counts.directive.js index ac0f201237..3dafe1f13e 100644 --- a/awx/ui/static/js/dashboard/counts/dashboard-counts.directive.js +++ b/awx/ui/static/js/dashboard/counts/dashboard-counts.directive.js @@ -1,14 +1,14 @@ /* jshint unused: vars */ export default - [ '$rootScope', - function() { + [ 'templateUrl', + function(templateUrl) { return { restrict: 'E', scope: { data: '=' }, replace: false, - templateUrl: '/static/js/dashboard/counts/dashboard-counts.partial.html', + templateUrl: templateUrl('dashboard/counts/dashboard-counts'), link: function(scope, element, attrs) { scope.$watch("data", function(data) { if (data && data.hosts) { diff --git a/awx/ui/static/js/dashboard/dashboard.directive.js b/awx/ui/static/js/dashboard/dashboard.directive.js index c330aeb137..243a423a67 100644 --- a/awx/ui/static/js/dashboard/dashboard.directive.js +++ b/awx/ui/static/js/dashboard/dashboard.directive.js @@ -1,11 +1,11 @@ /* jshint unused: vars */ export default - [ '$rootScope', - function() { + [ 'templateUrl', + function(templateUrl) { return { restrict: 'E', scope: true, - templateUrl: '/static/js/dashboard/dashboard.partial.html', + templateUrl: templateUrl('dashboard/dashboard'), link: function(scope, element, attrs) { } }; diff --git a/awx/ui/static/js/dashboard/graphs/dashboard-graphs.directive.js b/awx/ui/static/js/dashboard/graphs/dashboard-graphs.directive.js index b27418a94c..ce0052e132 100644 --- a/awx/ui/static/js/dashboard/graphs/dashboard-graphs.directive.js +++ b/awx/ui/static/js/dashboard/graphs/dashboard-graphs.directive.js @@ -1,11 +1,11 @@ /* jshint unused: vars */ export default - [ '$rootScope', - function() { + [ 'templateUrl', + function(templateUrl) { return { restrict: 'E', scope: true, - templateUrl: '/static/js/dashboard/graphs/dashboard-graphs.partial.html', + templateUrl: templateUrl('dashboard/graphs/dashboard-graphs'), link: function(scope, element, attrs) { function clearGraphs() { scope.jobStatusSelected = false; diff --git a/awx/ui/static/js/dashboard/graphs/host-status/host-status-graph.directive.js b/awx/ui/static/js/dashboard/graphs/host-status/host-status-graph.directive.js index 8fb44090b8..9ec11d5d46 100644 --- a/awx/ui/static/js/dashboard/graphs/host-status/host-status-graph.directive.js +++ b/awx/ui/static/js/dashboard/graphs/host-status/host-status-graph.directive.js @@ -8,14 +8,15 @@ [ '$compile', '$window', 'adjustGraphSize', + 'templateUrl', HostStatusGraph, ]; -function HostStatusGraph($compile, $window, adjustGraphSize) { +function HostStatusGraph($compile, $window, adjustGraphSize, templateUrl) { return { restrict: 'E', link: link, - templateUrl: '/static/js/dashboard/graphs/host-status/host_status_graph.partial.html' + templateUrl: templateUrl('dashboard/graphs/host-status/host_status_graph') }; function link(scope, element, attr) { diff --git a/awx/ui/static/js/dashboard/graphs/job-status/job-status-graph.directive.js b/awx/ui/static/js/dashboard/graphs/job-status/job-status-graph.directive.js index 1d233ab42f..e6c3af0095 100644 --- a/awx/ui/static/js/dashboard/graphs/job-status/job-status-graph.directive.js +++ b/awx/ui/static/js/dashboard/graphs/job-status/job-status-graph.directive.js @@ -12,16 +12,17 @@ 'Wait', 'adjustGraphSize', 'jobStatusGraphData', + 'templateUrl', JobStatusGraph ]; -function JobStatusGraph($rootScope, $compile , $location, $window, Wait, adjustGraphSize, graphDataService) { +function JobStatusGraph($rootScope, $compile , $location, $window, Wait, adjustGraphSize, graphDataService, templateUrl) { return { restrict: 'E', scope: { data: '=' }, - templateUrl: '/static/js/dashboard/graphs/job-status/job_status_graph.partial.html', + templateUrl: templateUrl('dashboard/graphs/job-status/job_status_graph'), link: link }; diff --git a/awx/ui/static/js/dashboard/graphs/job-status/main.js b/awx/ui/static/js/dashboard/graphs/job-status/main.js index 5758354a28..9c122acf3b 100644 --- a/awx/ui/static/js/dashboard/graphs/job-status/main.js +++ b/awx/ui/static/js/dashboard/graphs/job-status/main.js @@ -1,8 +1,8 @@ import JobStatusGraphDirective from 'tower/dashboard/graphs/job-status/job-status-graph.directive'; import JobStatusGraphService from 'tower/dashboard/graphs/job-status/job-status-graph.service'; import DashboardGraphHelpers from 'tower/dashboard/graphs/graph-helpers/main'; -import ApiLoader from 'tower/shared/api-loader'; +import templateUrl from 'tower/shared/template-url/main'; -export default angular.module('JobStatusGraph', [DashboardGraphHelpers.name, ApiLoader.name]) +export default angular.module('JobStatusGraph', [DashboardGraphHelpers.name, templateUrl.name]) .directive('jobStatusGraph', JobStatusGraphDirective) .service('jobStatusGraphData', JobStatusGraphService); diff --git a/awx/ui/static/js/dashboard/lists/job-templates/job-templates-list.directive.js b/awx/ui/static/js/dashboard/lists/job-templates/job-templates-list.directive.js index 6dc6f20afb..19ba322888 100644 --- a/awx/ui/static/js/dashboard/lists/job-templates/job-templates-list.directive.js +++ b/awx/ui/static/js/dashboard/lists/job-templates/job-templates-list.directive.js @@ -1,14 +1,15 @@ /* jshint unused: vars */ export default [ "PlaybookRun", - function JobTemplatesList(PlaybookRun) { + 'templateUrl', + function JobTemplatesList(PlaybookRun, templateUrl) { return { restrict: 'E', link: link, scope: { data: '=' }, - templateUrl: '/static/js/dashboard/lists/job-templates/job-templates-list.partial.html' + templateUrl: templateUrl('dashboard/lists/job-templates/job-templates-list') }; function link(scope, element, attr) { diff --git a/awx/ui/static/js/dashboard/lists/jobs/jobs-list.directive.js b/awx/ui/static/js/dashboard/lists/jobs/jobs-list.directive.js index 31a433db1a..f0c9d742e2 100644 --- a/awx/ui/static/js/dashboard/lists/jobs/jobs-list.directive.js +++ b/awx/ui/static/js/dashboard/lists/jobs/jobs-list.directive.js @@ -1,43 +1,44 @@ /* jshint unused: vars */ export default - ['moment', - function JobsList(moment) { - return { - restrict: 'E', - link: link, - scope: { - data: '=' - }, - templateUrl: '/static/js/dashboard/lists/jobs/jobs-list.partial.html' - }; - - function link(scope, element, attr) { - scope.$watch("data", function(data) { - if (data) { - if (data.length > 0) { - createList(data); - scope.noJobs = false; - } else { - scope.noJobs = true; - } - } - }); - - function createList(list) { - // detailsUrl, status, name, time - scope.jobs = _.map(list, function(job){ - return { - detailsUrl: job.url.replace("api/v1", "#"), - status: job.status, - name: job.name, - time: moment(job.finished).fromNow() - }; }); - - scope.snapRows = (list.length < 4); - } - - scope.isSuccessful = function (status) { - return (status === "successful"); + [ 'moment', + 'templateUrl', + function JobsList(moment, templateUrl) { + return { + restrict: 'E', + link: link, + scope: { + data: '=' + }, + templateUrl: templateUrl('dashboard/lists/jobs/jobs-list') }; - } + + function link(scope, element, attr) { + scope.$watch("data", function(data) { + if (data) { + if (data.length > 0) { + createList(data); + scope.noJobs = false; + } else { + scope.noJobs = true; + } + } + }); + + function createList(list) { + // detailsUrl, status, name, time + scope.jobs = _.map(list, function(job){ + return { + detailsUrl: job.url.replace("api/v1", "#"), + status: job.status, + name: job.name, + time: moment(job.finished).fromNow() + }; }); + + scope.snapRows = (list.length < 4); + } + + scope.isSuccessful = function (status) { + return (status === "successful"); + }; + } }]; diff --git a/awx/ui/static/js/main-menu/default-menu.directive.js b/awx/ui/static/js/main-menu/default-menu.directive.js index 792009307e..59e7039be5 100644 --- a/awx/ui/static/js/main-menu/default-menu.directive.js +++ b/awx/ui/static/js/main-menu/default-menu.directive.js @@ -1,15 +1,18 @@ -export default function() { - return { - restrict: 'E', - templateUrl: '/static/js/main-menu/menu-default.partial.html', - link: function(scope, element) { - var contents = element.contents(); - contents.unwrap(); +export default + [ 'templateUrl', + function(templateUrl) { + return { + restrict: 'E', + templateUrl: templateUrl('main-menu/menu-default'), + link: function(scope, element) { + var contents = element.contents(); + contents.unwrap(); - scope.$on('$destroy', function() { - contents.remove(); - $(".MenuItem--socketStatus").remove(); - }); + scope.$on('$destroy', function() { + contents.remove(); + $(".MenuItem--socketStatus").remove(); + }); + } + }; } - }; -} + ]; diff --git a/awx/ui/static/js/main-menu/main-menu.directive.js b/awx/ui/static/js/main-menu/main-menu.directive.js index 4e2eafee22..ad139cd24e 100644 --- a/awx/ui/static/js/main-menu/main-menu.directive.js +++ b/awx/ui/static/js/main-menu/main-menu.directive.js @@ -1,45 +1,48 @@ /* jshint unused: vars */ -export default function() { - return { - restrict: 'E', - controllerAs: 'mainMenu', - templateUrl: '/static/js/main-menu/main-menu.partial.html', - controller: ['$scope', function($scope) { - this.open = function() { - $scope.isOpen = true; - }; +export default + [ 'templateUrl', + function(templateUrl) { + return { + restrict: 'E', + controllerAs: 'mainMenu', + templateUrl: templateUrl('main-menu/main-menu'), + controller: ['$scope', function($scope) { + this.open = function() { + $scope.isOpen = true; + }; - this.close = function() { - $scope.isOpen = false; - }; + this.close = function() { + $scope.isOpen = false; + }; - this.toggle = function() { - $scope.isOpen = !$scope.isOpen; - }; + this.toggle = function() { + $scope.isOpen = !$scope.isOpen; + }; - $scope.isOpen = false; - }], - scope: { - menuStyle: '&menuStyle', - currentUser: '=' - }, - link: function(scope, element, attrs) { - scope.menuStyleClassName = 'blah'; - scope.$watch(function() { - return scope.$eval(scope.menuStyle); - }, function(newValue) { - scope.menuStyleClassName = 'MainMenu--' + newValue; - }); - scope.$watch('isOpen', function(isOpen) { - if (isOpen) { - element.find('.MainMenu').addClass("Menu--open"); - element.find('menu-toggle-button').addClass("MenuToggle--open"); - } else { - element.find('.MainMenu').removeClass("Menu--open"); - element.find('menu-toggle-button').removeClass("MenuToggle--open"); + $scope.isOpen = false; + }], + scope: { + menuStyle: '&menuStyle', + currentUser: '=' + }, + link: function(scope, element, attrs) { + scope.menuStyleClassName = 'blah'; + scope.$watch(function() { + return scope.$eval(scope.menuStyle); + }, function(newValue) { + scope.menuStyleClassName = 'MainMenu--' + newValue; + }); + scope.$watch('isOpen', function(isOpen) { + if (isOpen) { + element.find('.MainMenu').addClass("Menu--open"); + element.find('menu-toggle-button').addClass("MenuToggle--open"); + } else { + element.find('.MainMenu').removeClass("Menu--open"); + element.find('menu-toggle-button').removeClass("MenuToggle--open"); + } + }); } - }); + }; } - }; -} + ]; diff --git a/awx/ui/static/js/main-menu/menu-toggle.directive.js b/awx/ui/static/js/main-menu/menu-toggle.directive.js index df399bbce9..6459f3e09b 100644 --- a/awx/ui/static/js/main-menu/menu-toggle.directive.js +++ b/awx/ui/static/js/main-menu/menu-toggle.directive.js @@ -1,27 +1,30 @@ /* jshint unused: vars */ -export default function() { - return { - templateUrl: '/static/js/main-menu/menu-toggle.partial.html', - restrict: 'E', - require: '^^mainMenu', - scope: { - width: '@', - height: '@', - barHeight: '@' - }, - link: function(scope, element, attrs, mainMenuController) { - scope.$on('$destroy', function() { - element.off('click'); - }); +export default + [ 'templateUrl', + function(templateUrl) { + return { + templateUrl: templateUrl('main-menu/menu-toggle'), + restrict: 'E', + require: '^^mainMenu', + scope: { + width: '@', + height: '@', + barHeight: '@' + }, + link: function(scope, element, attrs, mainMenuController) { + scope.$on('$destroy', function() { + element.off('click'); + }); - element.on("click", function(e) { - e.preventDefault(); - e.stopPropagation(); - scope.$apply(function() { - mainMenuController.toggle(); - }); - }); + element.on("click", function(e) { + e.preventDefault(); + e.stopPropagation(); + scope.$apply(function() { + mainMenuController.toggle(); + }); + }); + } + }; } - }; -} + ]; diff --git a/awx/ui/static/js/main-menu/portal-menu.directive.js b/awx/ui/static/js/main-menu/portal-menu.directive.js index e7aeceb0e6..cd4c7b588d 100644 --- a/awx/ui/static/js/main-menu/portal-menu.directive.js +++ b/awx/ui/static/js/main-menu/portal-menu.directive.js @@ -1,15 +1,18 @@ -export default function() { - return { - restrict: 'E', - templateUrl: '/static/js/main-menu/menu-portal.partial.html', - link: function(scope, element) { - var contents = element.contents(); - contents.unwrap(); +export default + [ 'templateUrl', + function(templateUrl) { + return { + restrict: 'E', + templateUrl: templateUrl('main-menu/menu-portal'), + link: function(scope, element) { + var contents = element.contents(); + contents.unwrap(); - scope.$on('$destroy', function() { - contents.remove(); - $(".MenuItem--socketStatus").remove(); - }); + scope.$on('$destroy', function() { + contents.remove(); + $(".MenuItem--socketStatus").remove(); + }); + } + }; } - }; -} + ]; diff --git a/awx/ui/static/js/main-menu/web-socket-status.directive.js b/awx/ui/static/js/main-menu/web-socket-status.directive.js index 4f847e72f7..e7cdb5a0df 100644 --- a/awx/ui/static/js/main-menu/web-socket-status.directive.js +++ b/awx/ui/static/js/main-menu/web-socket-status.directive.js @@ -1,18 +1,22 @@ /* jshint unused: vars */ -export default ['$rootScope', function($rootScope) { - return { - restrict: 'E', - templateUrl: '/static/js/main-menu/web-socket-status.partial.html', - link: function(scope, element, attrs) { - scope.socketHelp = $rootScope.socketHelp; - scope.socketTip = $rootScope.socketTip; - $rootScope.$watch('socketStatus', function(newStatus) { - scope.socketStatus = newStatus; - }); - $rootScope.$watch('socketTip', function(newTip) { - scope.socketTip = newTip; - }); +export default + [ '$rootScope', + 'templateUrl', + function($rootScope, templateUrl) { + return { + restrict: 'E', + templateUrl: templateUrl('main-menu/web-socket-status'), + link: function(scope, element, attrs) { + scope.socketHelp = $rootScope.socketHelp; + scope.socketTip = $rootScope.socketTip; + $rootScope.$watch('socketStatus', function(newStatus) { + scope.socketStatus = newStatus; + }); + $rootScope.$watch('socketTip', function(newTip) { + scope.socketTip = newTip; + }); + } + }; } - }; -}]; + ]; diff --git a/awx/ui/static/js/shared/breadcrumbs/breadcrumbs.directive.js b/awx/ui/static/js/shared/breadcrumbs/breadcrumbs.directive.js index ae1f3fd85c..0d613d0a91 100644 --- a/awx/ui/static/js/shared/breadcrumbs/breadcrumbs.directive.js +++ b/awx/ui/static/js/shared/breadcrumbs/breadcrumbs.directive.js @@ -9,30 +9,33 @@ import controller from './breadcrumbs.controller'; import 'tower/shared/generator-helpers'; -export default function() { +export default + [ 'templateUrl', + function(templateUrl) { - return { - restrict: 'E', - controller: controller, - transclude: true, - templateUrl: '/static/js/shared/breadcrumbs/breadcrumbs.partial.html', - scope: { - }, - link: function(scope, element, attrs, controller) { - // make breadcrumbs hidden until the current - // breadcrumb has a title; this avoids - // ugly rendering when an object's title - // is fetched via ajax - // - controller.setHidden(); + return { + restrict: 'E', + controller: controller, + transclude: true, + templateUrl: templateUrl('shared/breadcrumbs/breadcrumbs'), + scope: { + }, + link: function(scope, element, attrs, controller) { + // make breadcrumbs hidden until the current + // breadcrumb has a title; this avoids + // ugly rendering when an object's title + // is fetched via ajax + // + controller.setHidden(); - scope.$watch('isHidden', function(value) { - if (value) { - element.hide(); - } else { - element.show(); + scope.$watch('isHidden', function(value) { + if (value) { + element.hide(); + } else { + element.show(); + } + }); } - }); + }; } - }; -} + ]; diff --git a/awx/ui/static/js/shared/icon/icon.directive.js b/awx/ui/static/js/shared/icon/icon.directive.js index b0735704fb..d4da46b5a6 100644 --- a/awx/ui/static/js/shared/icon/icon.directive.js +++ b/awx/ui/static/js/shared/icon/icon.directive.js @@ -1,29 +1,32 @@ -export default function() { - return { - restrict: 'E', - templateUrl: '/static/js/shared/icon/icon.partial.html', - scope: { - }, - link: function(scope, element, attrs) { - var svg = $('svg', element); - var iconPath = '#' + attrs.name; +export default + [ 'templateUrl', + function(templateUrl) { + return { + restrict: 'E', + templateUrl: templateUrl('shared/icon/icon'), + scope: { + }, + link: function(scope, element, attrs) { + var svg = $('svg', element); + var iconPath = '#' + attrs.name; - // Make a copy of the tag to insert its contents into this - // element's svg tag - var content = $(iconPath).clone(); + // Make a copy of the tag to insert its contents into this + // element's svg tag + var content = $(iconPath).clone(); - // Copy classes & viewBox off the so that we preserve any styling - // when we copy the item inline - var classes = $(iconPath).attr('class'); + // Copy classes & viewBox off the so that we preserve any styling + // when we copy the item inline + var classes = $(iconPath).attr('class'); - // viewBox needs to be access via native - // javascript's setAttribute function - var viewBox = $(iconPath)[0].getAttribute('viewBox'); + // viewBox needs to be access via native + // javascript's setAttribute function + var viewBox = $(iconPath)[0].getAttribute('viewBox'); - svg[0].setAttribute('viewBox', viewBox); - svg.attr('class', classes) - .html(content.contents()); + svg[0].setAttribute('viewBox', viewBox); + svg.attr('class', classes) + .html(content.contents()); + } + }; } - }; -} + ]; diff --git a/awx/ui/static/js/shared/multi-select-list/main.js b/awx/ui/static/js/shared/multi-select-list/main.js index 089fc7cd7b..7679b5e9d4 100644 --- a/awx/ui/static/js/shared/multi-select-list/main.js +++ b/awx/ui/static/js/shared/multi-select-list/main.js @@ -7,9 +7,10 @@ import multiSelect from './multi-select-list.directive'; import selectAll from './select-all.directive'; import selectListItem from './select-list-item.directive'; +import templateUrl from 'tower/shared/template-url/main'; export default - angular.module('multiSelectList', []) + angular.module('multiSelectList', [templateUrl.name]) .directive('multiSelectList', multiSelect) .directive('selectAll', selectAll) .directive('selectListItem', selectListItem); diff --git a/awx/ui/static/js/shared/multi-select-list/select-all.directive.js b/awx/ui/static/js/shared/multi-select-list/select-all.directive.js index 251fd6a008..4470f05e79 100644 --- a/awx/ui/static/js/shared/multi-select-list/select-all.directive.js +++ b/awx/ui/static/js/shared/multi-select-list/select-all.directive.js @@ -129,12 +129,10 @@ // // => // '/static/js/shared/multi-select-list/select-all.html // -function template(base) { - return '/static/js/' + base + '.partial.html'; -} export default - [ function() { + [ 'templateUrl', + function(templateUrl) { return { require: '^multiSelectList', restrict: 'E', @@ -145,7 +143,7 @@ export default extendedLabel: '&', isSelectionEmpty: '=selectionsEmpty' }, - templateUrl: template('shared/multi-select-list/select-all'), + templateUrl: templateUrl('shared/multi-select-list/select-all'), link: function(scope, element, attrs, controller) { scope.label = scope.label || 'All'; diff --git a/awx/ui/static/js/shared/template-url/main.js b/awx/ui/static/js/shared/template-url/main.js new file mode 100644 index 0000000000..8c1c64185e --- /dev/null +++ b/awx/ui/static/js/shared/template-url/main.js @@ -0,0 +1,6 @@ +import templateUrl from './template-url.factory'; + +export default + angular.module('templateUrl', []) + .factory('templateUrl', templateUrl); + diff --git a/awx/ui/static/js/shared/template-url/template-url.factory.js b/awx/ui/static/js/shared/template-url/template-url.factory.js new file mode 100644 index 0000000000..c3fb17fd68 --- /dev/null +++ b/awx/ui/static/js/shared/template-url/template-url.factory.js @@ -0,0 +1,20 @@ +function templateUrl($sce, path, isTrusted) { + isTrusted = isTrusted !== false; // defaults to true, can be passed in as false + var parts = ['', 'static', 'js']; + parts.push(path); + + var url = parts.join('/') + '.partial.html'; + + if (isTrusted) { + url = $sce.trustAsResourceUrl(url); + } + + return url; +} + +export default + [ '$sce', + function($sce) { + return _.partial(templateUrl, $sce); + } + ]; diff --git a/awx/ui/static/js/system-tracking/date-picker/date-picker.directive.js b/awx/ui/static/js/system-tracking/date-picker/date-picker.directive.js index 167ef8688b..211705768f 100644 --- a/awx/ui/static/js/system-tracking/date-picker/date-picker.directive.js +++ b/awx/ui/static/js/system-tracking/date-picker/date-picker.directive.js @@ -8,7 +8,8 @@ export default [ 'moment', - function(moment) { + 'templateUrl', + function(moment, templateUrl) { return { restrict: 'E', scope: { @@ -17,7 +18,7 @@ export default autoUpdate: '=?', inputClass: '&' }, - templateUrl: '/static/js/system-tracking/date-picker/date-picker.partial.html', + templateUrl: templateUrl('system-tracking/date-picker/date-picker'), link: function(scope, element, attrs) { // We need to make sure this _never_ recurses, which sometimes happens diff --git a/awx/ui/static/js/system-tracking/fact-data-table/fact-data-table.directive.js b/awx/ui/static/js/system-tracking/fact-data-table/fact-data-table.directive.js index 21f157d3ff..1c99f546a0 100644 --- a/awx/ui/static/js/system-tracking/fact-data-table/fact-data-table.directive.js +++ b/awx/ui/static/js/system-tracking/fact-data-table/fact-data-table.directive.js @@ -1,9 +1,10 @@ /* jshint unused: vars */ export default - [ function() { + [ 'templateUrl', + function(templateUrl) { return { restrict: 'E', - templateUrl: '/static/js/system-tracking/fact-data-table/fact-data-table.partial.html', + templateUrl: templateUrl('system-tracking/fact-data-table/fact-data-table'), scope: { leftHostname: '=', rightHostname: '=', diff --git a/awx/ui/tests/unit/setup-browser.js b/awx/ui/tests/unit/setup-browser.js new file mode 100644 index 0000000000..a6ed4df031 --- /dev/null +++ b/awx/ui/tests/unit/setup-browser.js @@ -0,0 +1,39 @@ +var jsdom = require('jsdom').jsdom; +var document = jsdom('tower'); +var window = document.parentWindow; +var mocha = require('mocha'); +window.mocha = mocha; +window.beforeEach = beforeEach; +window.afterEach = afterEach; + +global.document = document; +global.window = window; + +require('angular/angular'); +var jquery = require('jquery'); +require('angular-mocks/angular-mocks'); + +var chai = require('chai'); +var expect = chai.expect; +var sinonChai = require('sinon-chai'); +var chaiAsPromised = require('chai-as-promised'); +var sinon = require('sinon'); +var chaiThings = require('chai-things'); + +chai.use(sinonChai); +chai.use(chaiAsPromised); +chai.use(chaiThings); + +global.$ = window.$ = jquery; +global.angular = window.angular; +global.expect = chai.expect; + +angular.module('templates', []); +require('../../templates'); + +var lodash = require('lodash'); +global._ = lodash; + +var LocalStorage = require('node-localstorage').LocalStorage; +global.localStorage = window.localStorage = new LocalStorage('./scratch'); + From f1fe118c103a3e73a0f0d1785f1471378b004fc0 Mon Sep 17 00:00:00 2001 From: Joe Fiorini Date: Wed, 8 Jul 2015 10:27:26 -0400 Subject: [PATCH 2/7] Make front-end tests run in node --- awx/ui/static/js/shared/moment/moment.js | 6 +-- .../js/system-tracking/data-services/main.js | 3 +- awx/ui/tests/.jshintrc | 5 +++ awx/ui/tests/unit/describe-module.js | 44 ++++++++++--------- .../unit/directives/job-status-graph-test.js | 17 +++++-- .../unit/features/features.controller-test.js | 4 +- .../unit/features/features.service-test.js | 4 +- .../delete-job-template.service-test.js | 2 + .../multi-select-list.directive-test.js | 9 ++-- .../select-all.directive-test.js | 13 ++++-- awx/ui/tests/unit/rest-stub.js | 2 +- .../services/job-status-graph-data-test.js | 8 +++- awx/ui/tests/unit/setup-browser.js | 17 ++++++- .../unit/shared/lodash-as-promised_test.js | 4 +- .../compare-facts/flat-test.js | 29 ++++++------ .../compare-facts/nested-test.js | 30 +------------ .../single-host-data.service-test.js | 4 +- 17 files changed, 114 insertions(+), 87 deletions(-) create mode 100644 awx/ui/tests/.jshintrc diff --git a/awx/ui/static/js/shared/moment/moment.js b/awx/ui/static/js/shared/moment/moment.js index 9d7ba7cc91..50e8c2341f 100644 --- a/awx/ui/static/js/shared/moment/moment.js +++ b/awx/ui/static/js/shared/moment/moment.js @@ -7,9 +7,9 @@ function moment() { // lists the user's preferred languages, the first in the array // being the user's top choice. navigator.languages is currently // comptabile with chrome>v32, ffox>32, but not IE/Safari - var lang = navigator.languages ? - navigator.languages[0] : - (navigator.language || navigator.userLanguage); + var lang = window.navigator.languages ? + window.navigator.languages[0] : + (window.navigator.language || window.navigator.userLanguage); originalMoment.locale(lang); return originalMoment.apply(this, arguments); diff --git a/awx/ui/static/js/system-tracking/data-services/main.js b/awx/ui/static/js/system-tracking/data-services/main.js index cf72087b27..f76af4cc10 100644 --- a/awx/ui/static/js/system-tracking/data-services/main.js +++ b/awx/ui/static/js/system-tracking/data-services/main.js @@ -2,9 +2,10 @@ import factScanDataService from './fact-scan-data.service'; import getDataForComparison from './get-data-for-comparison.factory'; import getModuleOptions from './get-module-options.factory'; import resolveEmptyVersions from './resolve-empty-versions.factory'; +import shared from 'tower/shared/main'; export default - angular.module('systemTracking.dataServices', []) + angular.module('systemTracking.dataServices', [shared.name]) .factory('getModuleOptions', getModuleOptions) .factory('getDataForComparison', getDataForComparison) .factory('resolveEmptyVersions', resolveEmptyVersions) diff --git a/awx/ui/tests/.jshintrc b/awx/ui/tests/.jshintrc new file mode 100644 index 0000000000..f34bd39c9c --- /dev/null +++ b/awx/ui/tests/.jshintrc @@ -0,0 +1,5 @@ +{ + "expr": true, + "esnext": true, + "node": true +} diff --git a/awx/ui/tests/unit/describe-module.js b/awx/ui/tests/unit/describe-module.js index b230edb136..5a0ec240f3 100644 --- a/awx/ui/tests/unit/describe-module.js +++ b/awx/ui/tests/unit/describe-module.js @@ -1,4 +1,4 @@ -import RestStub from 'tests/unit/rest-stub'; +import RestStub from './rest-stub'; var $provide; @@ -7,7 +7,7 @@ function wrapInjected(dslFn) { // })); return function(fn) { dslFn.apply(this, - [inject( + [window.inject( [ '$injector', function($injector) { var $compile = $injector.get('$compile'); @@ -28,18 +28,19 @@ function TestModule(name, deps) { registerPreHooks: function() { var self = this; - beforeEach("tower module", module('Tower')); - beforeEach(name + " module", module(name)); - beforeEach("templates module", module('templates')); - beforeEach("mock app setup", module(['$provide', function(_provide_) { + // beforeEach("tower module", window.module('Tower')); + beforeEach(name + " module", window.module(name)); + beforeEach("templates module", window.module('templates')); + beforeEach("mock app setup", window.module(['$provide', function(_provide_) { var getBasePath = function(path) { return '/' + path + '/'; - } + }; $provide = _provide_; $provide.value('LoadBasePaths', angular.noop); $provide.value('GetBasePath', getBasePath); + $provide.value('ProcessErrors', angular.noop); for (var name in self.mockedProviders) { $provide.value(name, self.mockedProviders[name]); @@ -47,12 +48,12 @@ function TestModule(name, deps) { }])); - wrapInjected(beforeEach)(function($httpBackend) { + // wrapInjected(beforeEach)(function($httpBackend) { - $httpBackend - .expectGET('/static/js/local_config.js') - .respond({}); - }); + // $httpBackend + // .expectGET('/static/js/local_config.js') + // .respond({}); + // }); }, mockProvider: function(name, value) { this.mockedProviders[name] = value; @@ -64,7 +65,7 @@ function TestModule(name, deps) { }); }, registerPostHooks: function() { - afterEach(inject(['$httpBackend', function($httpBackend) { + afterEach(window.inject(['$httpBackend', function($httpBackend) { $httpBackend.verifyNoOutstandingExpectation(); $httpBackend.verifyNoOutstandingRequest(); }])); @@ -81,7 +82,7 @@ function TestService(name) { return { withService: function(fn) { - beforeEach(name + " service", inject([name, function() { + beforeEach(name + " service", window.inject([name, function() { var service = arguments[0]; fn(service); }])); @@ -104,7 +105,7 @@ function TestDirective(name, deps) { // by the test withScope: function(fn) { var self = this; - beforeEach("capture outer $scope", inject(['$rootScope', function($rootScope) { + beforeEach("capture outer $scope", window.inject(['$rootScope', function($rootScope) { var $scope = self.$scope = self.$scope || $rootScope.$new(); // `this` refers to mocha test suite fn.apply(this, [$scope]); @@ -112,7 +113,7 @@ function TestDirective(name, deps) { }, withIsolateScope: function(fn) { var self = this; - beforeEach("capture isolate scope", inject(['$rootScope', function($rootScope) { + beforeEach("capture isolate scope", window.inject(['$rootScope', function($rootScope) { // `this` refers to mocha test suite fn.apply(this, [self.$element.isolateScope()]); }])); @@ -165,7 +166,7 @@ function TestDirective(name, deps) { } beforeEach("compile directive element", - inject(['$compile', '$httpBackend', '$rootScope', function($compile, $httpBackend, $rootScope) { + window.inject(['$compile', '$httpBackend', '$rootScope', function($compile, $httpBackend, $rootScope) { if (!self.$scope) { self.$scope = $rootScope.$new(); @@ -176,13 +177,14 @@ function TestDirective(name, deps) { self.$scope.$digest(); - $httpBackend.flush(); + // $httpBackend.flush(); }])); afterEach("cleanup directive element", function() { - self.$element.trigger('$destroy'); + $(self.$element).trigger('$destroy'); self.$element.remove(); + delete self.$scope; }); this._compileRegistered = true; @@ -200,7 +202,7 @@ function TestDirective(name, deps) { }, provideTemplate: function(url, template) { var $scope = this.$scope; - beforeEach("mock template endpoint", inject(['$httpBackend', function($httpBackend) { + beforeEach("mock template endpoint", window.inject(['$httpBackend', function($httpBackend) { $httpBackend .whenGET(url) .respond(template); @@ -233,7 +235,7 @@ function ModuleDescriptor(name, deps) { testModule.mockProvider('$cookieStore', { get: angular.noop }); testModule.registerPreHooks(); - beforeEach("$q", inject(['$q', function($q) { + beforeEach("$q", window.inject(['$q', function($q) { testService.restStub.$q = $q; }])); diff --git a/awx/ui/tests/unit/directives/job-status-graph-test.js b/awx/ui/tests/unit/directives/job-status-graph-test.js index a7bdc72970..9af4db4909 100644 --- a/awx/ui/tests/unit/directives/job-status-graph-test.js +++ b/awx/ui/tests/unit/directives/job-status-graph-test.js @@ -1,11 +1,22 @@ -import Tower from 'tower/app'; -import {describeModule} from 'tests/unit/describe-module'; -import JobStatusGraph from 'tower/dashboard/graphs/job-status/main' +/* jshint node: true */ + +import '../setup-browser'; + +import {describeModule} from '../describe-module'; +import 'tower/shared/Utilities'; +import 'tower/shared/RestServices'; +import JobStatusGraph from 'tower/dashboard/graphs/job-status/main'; + +var sinon = require('sinon'); var resizeHandler = sinon.spy(); +window.$.fn.removeResize = angular.noop; + describeModule(JobStatusGraph.name) .mockProvider('adjustGraphSize', resizeHandler) + .mockProvider('Wait', angular.noop) + .mockProvider('Rest', angular.noop) .testDirective('jobStatusGraph', function(directive) { diff --git a/awx/ui/tests/unit/features/features.controller-test.js b/awx/ui/tests/unit/features/features.controller-test.js index ac131334a1..c607cf3d2d 100644 --- a/awx/ui/tests/unit/features/features.controller-test.js +++ b/awx/ui/tests/unit/features/features.controller-test.js @@ -1,8 +1,10 @@ +import '../setup-browser'; + import featuresController from 'tower/shared/features/features.controller'; describe('featuresController', function() { - it('checks if a feature is enabled', inject(['$rootScope', function($rootScope) { + it('checks if a feature is enabled', window.inject(['$rootScope', function($rootScope) { var actual; $rootScope.features = { diff --git a/awx/ui/tests/unit/features/features.service-test.js b/awx/ui/tests/unit/features/features.service-test.js index 26804f3254..62da79c14c 100644 --- a/awx/ui/tests/unit/features/features.service-test.js +++ b/awx/ui/tests/unit/features/features.service-test.js @@ -1,3 +1,5 @@ +import '../setup-browser'; + import features from 'tower/shared/features/main'; import {describeModule} from '../describe-module'; @@ -31,7 +33,7 @@ describeModule(features.name) }); - it('caches in rootScope', inject(['$rootScope', + it('caches in rootScope', window.inject(['$rootScope', function($rootScope){ var features = {}, result = { diff --git a/awx/ui/tests/unit/job-templates/delete-job-template.service-test.js b/awx/ui/tests/unit/job-templates/delete-job-template.service-test.js index f1fcb871fc..f30dfd1621 100644 --- a/awx/ui/tests/unit/job-templates/delete-job-template.service-test.js +++ b/awx/ui/tests/unit/job-templates/delete-job-template.service-test.js @@ -1,3 +1,5 @@ +import '../setup-browser'; + import jobTemplates from 'tower/job-templates/main'; import {describeModule} from '../describe-module'; diff --git a/awx/ui/tests/unit/multi-select-list/multi-select-list.directive-test.js b/awx/ui/tests/unit/multi-select-list/multi-select-list.directive-test.js index ed4f872c2b..c1c052dfd3 100644 --- a/awx/ui/tests/unit/multi-select-list/multi-select-list.directive-test.js +++ b/awx/ui/tests/unit/multi-select-list/multi-select-list.directive-test.js @@ -1,5 +1,8 @@ -import {describeModule} from 'tests/unit/describe-module'; +import '../setup-browser'; + +import {describeModule} from '../describe-module'; import mod from 'tower/shared/multi-select-list/main'; +var sinon = require('sinon'); describeModule(mod.name) .testDirective('multiSelectList', function(test) { @@ -18,9 +21,9 @@ describeModule(mod.name) }); it('works as an attribute on elements', function() { - inject(['$compile', function($compile) { + window.inject(['$compile', function($compile) { var node = $compile('
')($scope); - var classes = Array.prototype.slice.apply(node[0].classList) + var classes = Array.prototype.slice.apply(node.attr('class').split(' ')); expect(classes).to.contain('ng-scope'); }]); }); diff --git a/awx/ui/tests/unit/multi-select-list/select-all.directive-test.js b/awx/ui/tests/unit/multi-select-list/select-all.directive-test.js index 31f06c25e3..eef6adbd08 100644 --- a/awx/ui/tests/unit/multi-select-list/select-all.directive-test.js +++ b/awx/ui/tests/unit/multi-select-list/select-all.directive-test.js @@ -1,4 +1,9 @@ -import {describeModule} from 'tests/unit/describe-module'; +import '../setup-browser'; + +import {describeModule} from '../describe-module'; +import mod from 'tower/shared/multi-select-list/main'; + +var sinon = require('sinon'); var mockController = { selectAll: sinon.spy(), @@ -7,7 +12,7 @@ var mockController = { deselectAllExtended: sinon.spy() }; -describeModule('multiSelectList') +describeModule(mod.name) .testDirective('selectAll', function(directive) { var $scope; @@ -36,7 +41,7 @@ describeModule('multiSelectList') }); it('works as an element tag', function() { - var classes = Array.prototype.slice.apply(directive.$element[0].classList); + var classes = directive.$element.attr('class').split(' '); expect(classes).to.contain('ng-scope'); }); @@ -91,4 +96,4 @@ describeModule('multiSelectList') }); - }); +}); diff --git a/awx/ui/tests/unit/rest-stub.js b/awx/ui/tests/unit/rest-stub.js index c714096a6a..ad8789bca4 100644 --- a/awx/ui/tests/unit/rest-stub.js +++ b/awx/ui/tests/unit/rest-stub.js @@ -63,7 +63,7 @@ RestStub.prototype = inject(['$rootScope', function($rootScope) { $rootScope.$apply(); }]); - }, 1000); + }, 10); } }; diff --git a/awx/ui/tests/unit/services/job-status-graph-data-test.js b/awx/ui/tests/unit/services/job-status-graph-data-test.js index 74d4919bf6..ea4af28a69 100644 --- a/awx/ui/tests/unit/services/job-status-graph-data-test.js +++ b/awx/ui/tests/unit/services/job-status-graph-data-test.js @@ -1,5 +1,9 @@ -import {describeModule} from 'tests/unit/describe-module'; -import JobStatusGraph from 'tower/dashboard/graphs/job-status/main' +import '../setup-browser'; + +import {describeModule} from '../describe-module'; +import JobStatusGraph from 'tower/dashboard/graphs/job-status/main'; + +var sinon = require('sinon'); var processErrors = sinon.spy(); diff --git a/awx/ui/tests/unit/setup-browser.js b/awx/ui/tests/unit/setup-browser.js index a6ed4df031..a7cc84232f 100644 --- a/awx/ui/tests/unit/setup-browser.js +++ b/awx/ui/tests/unit/setup-browser.js @@ -1,3 +1,5 @@ +/* jshint node: true */ + var jsdom = require('jsdom').jsdom; var document = jsdom('tower'); var window = document.parentWindow; @@ -9,8 +11,11 @@ window.afterEach = afterEach; global.document = document; global.window = window; -require('angular/angular'); var jquery = require('jquery'); +global.$ = window.$ = global.jQuery = window.jQuery = jquery; + +require('angular/angular'); + require('angular-mocks/angular-mocks'); var chai = require('chai'); @@ -24,16 +29,24 @@ chai.use(sinonChai); chai.use(chaiAsPromised); chai.use(chaiThings); -global.$ = window.$ = jquery; global.angular = window.angular; +global.inject = window.inject; global.expect = chai.expect; angular.module('templates', []); require('../../templates'); +var d3 = require('d3'); +global.d3 = d3; + +var nv = require('nvd3'); +global.nv = nv; + var lodash = require('lodash'); global._ = lodash; var LocalStorage = require('node-localstorage').LocalStorage; global.localStorage = window.localStorage = new LocalStorage('./scratch'); +var moment = require('moment'); +window.moment = moment; diff --git a/awx/ui/tests/unit/shared/lodash-as-promised_test.js b/awx/ui/tests/unit/shared/lodash-as-promised_test.js index d0d86a4f44..d9d01759de 100644 --- a/awx/ui/tests/unit/shared/lodash-as-promised_test.js +++ b/awx/ui/tests/unit/shared/lodash-as-promised_test.js @@ -1,3 +1,5 @@ +import '../setup-browser'; + import 'tower/shared/main'; describe('LodashAsPromised', function() { @@ -17,7 +19,7 @@ describe('LodashAsPromised', function() { return memo + value; } - beforeEach(module('shared')); + beforeEach(window.module('shared')); beforeEach(inject(['lodashAsPromised', '$q', function(_lodash, _$q) { _ = _lodash; diff --git a/awx/ui/tests/unit/system-tracking/compare-facts/flat-test.js b/awx/ui/tests/unit/system-tracking/compare-facts/flat-test.js index bd72cb774a..634a3230c1 100644 --- a/awx/ui/tests/unit/system-tracking/compare-facts/flat-test.js +++ b/awx/ui/tests/unit/system-tracking/compare-facts/flat-test.js @@ -1,33 +1,32 @@ -import compareFacts from 'tower/system-tracking/compare-facts/flat'; - /* jshint node: true */ -/* globals -expect, -_ */ -var _, expect; +import '../../setup-browser'; + +import compareFacts from 'tower/system-tracking/compare-facts/flat'; // This makes this test runnable in node OR karma. The sheer // number of times I had to run this test made the karma // workflow just too dang slow for me. Maybe this can // be a pattern going forward? Not sure... // -(function(global) { - var chai = global.chai || require('chai'); +// (function(global) { +// var chai = global.chai || require('chai'); - if (typeof window === 'undefined') { - var chaiThings = global.chaiThings || require('chai-things'); - chai.use(chaiThings); - } +// if (typeof window === 'undefined') { +// var chaiThings = global.chaiThings || require('chai-things'); +// chai.use(chaiThings); +// } - _ = global._ || require('lodash'); - expect = global.expect || chai.expect; +// _ = global._ || require('lodash'); +// expect = global.expect || chai.expect; - global.expect = expect; +// global.expect = expect; - global._ = _; +// global._ = _; -})(typeof window === 'undefined' ? global : window); +// })(typeof window === 'undefined' ? global : window); describe('CompareFacts.Flat', function() { diff --git a/awx/ui/tests/unit/system-tracking/compare-facts/nested-test.js b/awx/ui/tests/unit/system-tracking/compare-facts/nested-test.js index 4014650901..5cbed586ca 100644 --- a/awx/ui/tests/unit/system-tracking/compare-facts/nested-test.js +++ b/awx/ui/tests/unit/system-tracking/compare-facts/nested-test.js @@ -1,34 +1,8 @@ -import compareFacts from 'tower/system-tracking/compare-facts/nested'; - /* jshint node: true */ -/* globals -expect, -_ */ -var _, expect; - -// This makes this test runnable in node OR karma. The sheer -// number of times I had to run this test made the karma -// workflow just too dang slow for me. Maybe this can -// be a pattern going forward? Not sure... -// -(function(global) { - var chai = global.chai || require('chai'); - - if (typeof window === 'undefined') { - var chaiThings = global.chaiThings || require('chai-things'); - chai.use(chaiThings); - } - - _ = global._ || require('lodash'); - expect = global.expect || chai.expect; - - global.expect = expect; - - - - global._ = _; - -})(typeof window === 'undefined' ? global : window); +import '../../setup-browser'; +import compareFacts from 'tower/system-tracking/compare-facts/nested'; describe('CompareFacts.Nested', function() { diff --git a/awx/ui/tests/unit/system-tracking/single-host-data.service-test.js b/awx/ui/tests/unit/system-tracking/single-host-data.service-test.js index 7579f71743..f8a07498dc 100644 --- a/awx/ui/tests/unit/system-tracking/single-host-data.service-test.js +++ b/awx/ui/tests/unit/system-tracking/single-host-data.service-test.js @@ -1,4 +1,6 @@ -import systemTracking from 'tower/system-tracking/main'; +import '../setup-browser'; + +import systemTracking from 'tower/system-tracking/data-services/main'; import {describeModule} from '../describe-module'; import moment from 'tower/shared/moment/moment'; From 572b80c7afadb348e52e6896757fb4dfec531286 Mon Sep 17 00:00:00 2001 From: Joe Fiorini Date: Wed, 8 Jul 2015 10:31:32 -0400 Subject: [PATCH 3/7] Run tests with testem in broccoli watcher --- .gitignore | 2 ++ testem.yml | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 testem.yml diff --git a/.gitignore b/.gitignore index bb1e6b97bc..cf779d87af 100644 --- a/.gitignore +++ b/.gitignore @@ -49,6 +49,8 @@ npm-debug.log coverage.xml htmlcov pep8.txt +scratch +testem.log # Mac OS X *.DS_Store diff --git a/testem.yml b/testem.yml new file mode 100644 index 0000000000..6aacbdbe1d --- /dev/null +++ b/testem.yml @@ -0,0 +1,25 @@ +--- +# before_tests: cd ../../.. && sudo make devjs +framework: mocha +cwd: awx/ui/dist/node-tests +src_files: + - tests/**.js + - static/js/**/*.js + - static/lib/**/*.js +disable_watching: true +serve_files: + - ../tower.concat.js + - tests/templates.js + - tests/test-support.js + - tests/unit/**/*.js + - tests/unit.js +unsafe_file_serving: true +routes: + /awx/ui/dist: /static +launch_in_dev: + - Mocha +launch_in_ci: + - PhantomJS +launchers: + Mocha: + command: NODE_PATH=awx/ui/dist/node-tests ./node_modules/.bin/mocha awx/ui/dist/node-tests/tests/unit/**/*.js From c6549f4aca317d8684a9999596d8825710d3aa6a Mon Sep 17 00:00:00 2001 From: Joe Fiorini Date: Wed, 8 Jul 2015 15:38:58 -0400 Subject: [PATCH 4/7] Allow tests to run in Phantom via testem for CI --- Makefile | 5 +- .../unit/directives/job-status-graph-test.js | 2 - .../multi-select-list.directive-test.js | 1 - .../select-all.directive-test.js | 2 - .../services/job-status-graph-data-test.js | 2 - awx/ui/tests/unit/setup-browser.js | 90 +++++++++++-------- testem.yml | 25 +++--- 7 files changed, 71 insertions(+), 56 deletions(-) diff --git a/Makefile b/Makefile index f3ae843b39..5f245be131 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,7 @@ SITELIB=$(shell $(PYTHON) -c "from distutils.sysconfig import get_python_lib; pr OFFICIAL ?= no PACKER ?= packer GRUNT ?= $(shell [ -t 0 ] && echo "grunt" || echo "grunt --no-color") +TESTEM ?= ./node_modules/.bin/testem BROCCOLI ?= ./node_modules/.bin/broccoli NODE ?= node @@ -293,8 +294,8 @@ reports/ui_code: node_modules clean-ui Brocfile.js bower.json Gruntfile.js $(BROCCOLI) build reports/ui_code -- --no-concat --no-tests --no-styles --no-sourcemaps # Run UI unit tests -test_ui: node_modules minjs_ci Gruntfile.js - $(GRUNT) karma:ci +test_ui: node_modules minjs_ci + $(TESTEM) ci --file testem.yml -R xunit # Run API unit tests across multiple Python/Django versions with Tox. test_tox: diff --git a/awx/ui/tests/unit/directives/job-status-graph-test.js b/awx/ui/tests/unit/directives/job-status-graph-test.js index 9af4db4909..0ea4c1265f 100644 --- a/awx/ui/tests/unit/directives/job-status-graph-test.js +++ b/awx/ui/tests/unit/directives/job-status-graph-test.js @@ -7,8 +7,6 @@ import 'tower/shared/Utilities'; import 'tower/shared/RestServices'; import JobStatusGraph from 'tower/dashboard/graphs/job-status/main'; -var sinon = require('sinon'); - var resizeHandler = sinon.spy(); window.$.fn.removeResize = angular.noop; diff --git a/awx/ui/tests/unit/multi-select-list/multi-select-list.directive-test.js b/awx/ui/tests/unit/multi-select-list/multi-select-list.directive-test.js index c1c052dfd3..debd765b1a 100644 --- a/awx/ui/tests/unit/multi-select-list/multi-select-list.directive-test.js +++ b/awx/ui/tests/unit/multi-select-list/multi-select-list.directive-test.js @@ -2,7 +2,6 @@ import '../setup-browser'; import {describeModule} from '../describe-module'; import mod from 'tower/shared/multi-select-list/main'; -var sinon = require('sinon'); describeModule(mod.name) .testDirective('multiSelectList', function(test) { diff --git a/awx/ui/tests/unit/multi-select-list/select-all.directive-test.js b/awx/ui/tests/unit/multi-select-list/select-all.directive-test.js index eef6adbd08..9f080cc494 100644 --- a/awx/ui/tests/unit/multi-select-list/select-all.directive-test.js +++ b/awx/ui/tests/unit/multi-select-list/select-all.directive-test.js @@ -3,8 +3,6 @@ import '../setup-browser'; import {describeModule} from '../describe-module'; import mod from 'tower/shared/multi-select-list/main'; -var sinon = require('sinon'); - var mockController = { selectAll: sinon.spy(), deselectAll: sinon.spy(), diff --git a/awx/ui/tests/unit/services/job-status-graph-data-test.js b/awx/ui/tests/unit/services/job-status-graph-data-test.js index ea4af28a69..d5121cbdcb 100644 --- a/awx/ui/tests/unit/services/job-status-graph-data-test.js +++ b/awx/ui/tests/unit/services/job-status-graph-data-test.js @@ -3,8 +3,6 @@ import '../setup-browser'; import {describeModule} from '../describe-module'; import JobStatusGraph from 'tower/dashboard/graphs/job-status/main'; -var sinon = require('sinon'); - var processErrors = sinon.spy(); describeModule(JobStatusGraph.name) diff --git a/awx/ui/tests/unit/setup-browser.js b/awx/ui/tests/unit/setup-browser.js index a7cc84232f..a2b3c3db85 100644 --- a/awx/ui/tests/unit/setup-browser.js +++ b/awx/ui/tests/unit/setup-browser.js @@ -1,52 +1,68 @@ /* jshint node: true */ -var jsdom = require('jsdom').jsdom; -var document = jsdom('tower'); -var window = document.parentWindow; -var mocha = require('mocha'); -window.mocha = mocha; -window.beforeEach = beforeEach; -window.afterEach = afterEach; +(function() { + var isNode = typeof window === 'undefined'; -global.document = document; -global.window = window; + if (!isNode) { + window.expect = chai.expect; + return; + } -var jquery = require('jquery'); -global.$ = window.$ = global.jQuery = window.jQuery = jquery; + setupNode(); -require('angular/angular'); + function setupNode() { -require('angular-mocks/angular-mocks'); + var jsdom = require('jsdom').jsdom; + var document = jsdom('tower'); + var window = document.parentWindow; + var mocha = require('mocha'); + window.mocha = mocha; + window.beforeEach = beforeEach; + window.afterEach = afterEach; -var chai = require('chai'); -var expect = chai.expect; -var sinonChai = require('sinon-chai'); -var chaiAsPromised = require('chai-as-promised'); -var sinon = require('sinon'); -var chaiThings = require('chai-things'); + global.document = document; + global.window = window; -chai.use(sinonChai); -chai.use(chaiAsPromised); -chai.use(chaiThings); + var jquery = require('jquery'); + global.$ = window.$ = global.jQuery = window.jQuery = jquery; -global.angular = window.angular; -global.inject = window.inject; -global.expect = chai.expect; + require('angular/angular'); -angular.module('templates', []); -require('../../templates'); + require('angular-mocks/angular-mocks'); -var d3 = require('d3'); -global.d3 = d3; + var chai = require('chai'); + var expect = chai.expect; + var sinonChai = require('sinon-chai'); + var chaiAsPromised = require('chai-as-promised'); + var sinon = require('sinon'); + var chaiThings = require('chai-things'); -var nv = require('nvd3'); -global.nv = nv; + chai.use(sinonChai); + chai.use(chaiAsPromised); + chai.use(chaiThings); -var lodash = require('lodash'); -global._ = lodash; + global.angular = window.angular; + global.inject = window.inject; + global.expect = chai.expect; + global.sinon = require('sinon'); -var LocalStorage = require('node-localstorage').LocalStorage; -global.localStorage = window.localStorage = new LocalStorage('./scratch'); + angular.module('templates', []); + require('../../templates'); -var moment = require('moment'); -window.moment = moment; + var d3 = require('d3'); + global.d3 = d3; + + var nv = require('nvd3'); + global.nv = nv; + + var lodash = require('lodash'); + global._ = lodash; + + var LocalStorage = require('node-localstorage').LocalStorage; + global.localStorage = window.localStorage = new LocalStorage('./scratch'); + + var moment = require('moment'); + window.moment = moment; + } + +})(); diff --git a/testem.yml b/testem.yml index 6aacbdbe1d..0c74994e1d 100644 --- a/testem.yml +++ b/testem.yml @@ -1,25 +1,30 @@ --- -# before_tests: cd ../../.. && sudo make devjs framework: mocha -cwd: awx/ui/dist/node-tests +cwd: awx/ui/ +port: 7358 src_files: - - tests/**.js - static/js/**/*.js - static/lib/**/*.js -disable_watching: true + - tests/**/*.js serve_files: - - ../tower.concat.js - - tests/templates.js - - tests/test-support.js - - tests/unit/**/*.js - - tests/unit.js + - dist/tower.concat.js + - dist/tests/**/*.js + - dist/tests/unit.js unsafe_file_serving: true +test_page: tests.html +disable_watching: true routes: /awx/ui/dist: /static + /tests.html: ../../packaging/grunt/testem.mustache + /test-loader.js: static/lib/ember-cli-test-loader/test-loader.js + /vendor: ../../node_modules + /angular-mocks.js: dist/lib/angular-mocks/angular-mocks.js + /templates.js: dist/node-tests/templates.js +reporter: xunit launch_in_dev: - Mocha launch_in_ci: - PhantomJS launchers: Mocha: - command: NODE_PATH=awx/ui/dist/node-tests ./node_modules/.bin/mocha awx/ui/dist/node-tests/tests/unit/**/*.js + command: NODE_PATH=awx/ui/dist/node-tests ./node_modules/.bin/mocha $(find awx/ui/dist/node-tests/tests/ -name '*-test.js') From 1f118467b949e63a94993e1a224e9044f51ade76 Mon Sep 17 00:00:00 2001 From: Joe Fiorini Date: Thu, 9 Jul 2015 11:10:08 -0400 Subject: [PATCH 5/7] Remove karma and unused testing files --- awx/ui/tests/e2e/CheckLicense.js | 30 ----------- awx/ui/tests/karma-unit.conf | 22 -------- awx/ui/tests/karma.conf.js | 88 -------------------------------- awx/ui/tests/protractor-e2e.conf | 4 -- 4 files changed, 144 deletions(-) delete mode 100644 awx/ui/tests/e2e/CheckLicense.js delete mode 100644 awx/ui/tests/karma-unit.conf delete mode 100644 awx/ui/tests/karma.conf.js delete mode 100644 awx/ui/tests/protractor-e2e.conf diff --git a/awx/ui/tests/e2e/CheckLicense.js b/awx/ui/tests/e2e/CheckLicense.js deleted file mode 100644 index f2e148c1dc..0000000000 --- a/awx/ui/tests/e2e/CheckLicense.js +++ /dev/null @@ -1,30 +0,0 @@ -/********************************** - * Copyright (c) 2015 Ansible, Inc. - * - * CheckLicense.js - * - * Tests the CheckLicense service- helpers/CheckLicense.js - * - */ - - /* global describe, it, expect, by, browser, element, beforeEach */ - - -describe('E2E:CheckLicense', function() { - beforeEach(function() { - browser.get('http://localhost:8013'); - }); - - it('should present login dialog', function() { - var labels = element.all(by.css('#login-modal .modal-body label')); - expect(labels.get(0).getText()).toMatch(/Username/); - }); - - it('should login', function() { - element(by.model('login_username')).sendKeys('admin'); - element(by.model('login_password')).sendKeys('password01!'); - element(by.id('login-button')).click(); - var user = element(by.css('#account-menu [ng-bind="current_user.username"]')); - expect(user.getText()).toMatch(/admin/); - }); -}); \ No newline at end of file diff --git a/awx/ui/tests/karma-unit.conf b/awx/ui/tests/karma-unit.conf deleted file mode 100644 index eae72dd9e0..0000000000 --- a/awx/ui/tests/karma-unit.conf +++ /dev/null @@ -1,22 +0,0 @@ -// Karma configuration -// Generated on Mon Aug 04 2014 21:17:04 GMT-0400 (EDT) - -var sharedConfig = require('./karma-shared.conf'); - -module.exports = function(config) { - var conf = sharedConfig(); - - // list of files / patterns to load in the browser - conf.files = conf.files.concat([ - '../static/lib/angular-mocks/angular-mocks.js', - '../../../node_modules/ng-midway-tester/src/ngMidwayTester.js', - './unit/*', - './unit/**/*' - ]); - - // level of logging - // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG - conf.logLevel = config.LOG_INFO, - - config.set(conf); -}; diff --git a/awx/ui/tests/karma.conf.js b/awx/ui/tests/karma.conf.js deleted file mode 100644 index a6f42aa4a6..0000000000 --- a/awx/ui/tests/karma.conf.js +++ /dev/null @@ -1,88 +0,0 @@ -// Karma configuration -// Generated on Mon Aug 04 2014 21:17:04 GMT-0400 (EDT) - -var path = require('path'); - -module.exports = function(config) { - config.set({ - - // base path that will be used to resolve all patterns (eg. files, exclude) - basePath: '', - - autoWatchBatchDelay: 2000, - - // frameworks to use - // available frameworks: https://npmjs.org/browse/keyword/karma-adapter - - frameworks: - [ 'mocha', - 'chai', - 'sinon-chai', - 'chai-as-promised', - 'chai-things' - ], - - preprocessors: - { '../dist/**/*.html': ['ng-html2js'] - }, - - // list of files / patterns to load in the browser - files: [ - '../tests/phantomjs-polyfill.js', - '../dist/tower.concat.js', - '../static/lib/angular-mocks/angular-mocks.js', - '../static/lib/ember-cli-test-loader/test-loader.js', - '../dist/tests/**/*.js', - '../tests/unit.js', - '../dist/partials/**/*.html', - '../dist/js/**/*.html' - ], - - ngHtml2JsPreprocessor: { - stripPrefix: path.join(process.cwd(), 'awx/ui/dist'), - prependPrefix: '/static', - moduleName: 'templates' - }, - - - // list of files to exclude - exclude: [ - '../static/js/awx.min.js' - ], - - - // test results reporter to use - // possible values: 'dots', 'progress' - // available reporters: https://npmjs.org/browse/keyword/karma-reporter - reporters: ['dots', 'progress'], - - client: { - mocha: { - ui: 'bdd' - } - }, - - - // web server port - port: 9876, - - - // enable / disable colors in the output (reporters and logs) - colors: true, - - - // enable / disable watching file and executing tests whenever any file changes - autoWatch: true, - - - // start these browsers - // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher - browsers: ['Chrome'], - - - // Continuous Integration mode - // if true, Karma captures browsers, runs the tests and exits - singleRun: false - - }); -}; diff --git a/awx/ui/tests/protractor-e2e.conf b/awx/ui/tests/protractor-e2e.conf deleted file mode 100644 index c4df53799e..0000000000 --- a/awx/ui/tests/protractor-e2e.conf +++ /dev/null @@ -1,4 +0,0 @@ -exports.config = { - seleniumAddress: 'http://localhost:4444/wd/hub', - specs: ['e2e/*.js'] -} From 8d4e8f11648e4bcd4c91ca1e4b9d7f1e042a0dea Mon Sep 17 00:00:00 2001 From: Joe Fiorini Date: Thu, 9 Jul 2015 11:55:29 -0400 Subject: [PATCH 6/7] Reorganize test directory structure --- awx/ui/static/lib/loader.js/loader.js | 6 +- .../directives/job-status-graph-test.js | 4 +- .../features/features.controller-test.js | 2 +- .../features/features.service-test.js | 4 +- .../delete-job-template.service-test.js | 4 +- .../multi-select-list.controller-test.js | 0 .../multi-select-list.directive-test.js | 4 +- .../select-all.directive-test.js | 4 +- awx/ui/tests/phantomjs-polyfill.js | 28 -------- .../services/job-status-graph-data-test.js | 4 +- .../lodash-as-promised-test.js} | 2 +- .../{unit.js => support/browser/index.js} | 0 .../{unit => support}/describe-module.js | 0 awx/ui/tests/support/node/export-global.js | 4 ++ awx/ui/tests/support/node/index.js | 26 +++++++ .../tests/support/node/setup/angular-mocks.js | 5 ++ .../support/node/setup/angular-templates.js | 2 + awx/ui/tests/support/node/setup/angular.js | 5 ++ .../tests/support/node/setup/chai-plugins.js | 8 +++ awx/ui/tests/support/node/setup/chai.js | 5 ++ awx/ui/tests/support/node/setup/d3.js | 6 ++ awx/ui/tests/support/node/setup/jquery.js | 7 ++ awx/ui/tests/support/node/setup/jsdom.js | 6 ++ .../tests/support/node/setup/local-storage.js | 7 ++ awx/ui/tests/support/node/setup/lodash.js | 4 ++ awx/ui/tests/support/node/setup/mocha.js | 7 ++ awx/ui/tests/support/node/setup/moment.js | 5 ++ awx/ui/tests/support/node/setup/nv.js | 6 ++ awx/ui/tests/support/node/setup/sinon.js | 4 ++ awx/ui/tests/{unit => support}/rest-stub.js | 0 .../compare-facts/flat-test.js | 2 +- .../compare-facts/nested-test.js | 2 +- .../single-host-data.service-test.js | 4 +- awx/ui/tests/unit/setup-browser.js | 68 ------------------- 34 files changed, 130 insertions(+), 115 deletions(-) rename awx/ui/tests/{unit => }/directives/job-status-graph-test.js (96%) rename awx/ui/tests/{unit => }/features/features.controller-test.js (96%) rename awx/ui/tests/{unit => }/features/features.service-test.js (94%) rename awx/ui/tests/{unit => }/job-templates/delete-job-template.service-test.js (86%) rename awx/ui/tests/{unit => }/multi-select-list/multi-select-list.controller-test.js (100%) rename awx/ui/tests/{unit => }/multi-select-list/multi-select-list.directive-test.js (98%) rename awx/ui/tests/{unit => }/multi-select-list/select-all.directive-test.js (97%) delete mode 100644 awx/ui/tests/phantomjs-polyfill.js rename awx/ui/tests/{unit => }/services/job-status-graph-data-test.js (96%) rename awx/ui/tests/{unit/shared/lodash-as-promised_test.js => shared/lodash-as-promised-test.js} (98%) rename awx/ui/tests/{unit.js => support/browser/index.js} (100%) rename awx/ui/tests/{unit => support}/describe-module.js (100%) create mode 100644 awx/ui/tests/support/node/export-global.js create mode 100644 awx/ui/tests/support/node/index.js create mode 100644 awx/ui/tests/support/node/setup/angular-mocks.js create mode 100644 awx/ui/tests/support/node/setup/angular-templates.js create mode 100644 awx/ui/tests/support/node/setup/angular.js create mode 100644 awx/ui/tests/support/node/setup/chai-plugins.js create mode 100644 awx/ui/tests/support/node/setup/chai.js create mode 100644 awx/ui/tests/support/node/setup/d3.js create mode 100644 awx/ui/tests/support/node/setup/jquery.js create mode 100644 awx/ui/tests/support/node/setup/jsdom.js create mode 100644 awx/ui/tests/support/node/setup/local-storage.js create mode 100644 awx/ui/tests/support/node/setup/lodash.js create mode 100644 awx/ui/tests/support/node/setup/mocha.js create mode 100644 awx/ui/tests/support/node/setup/moment.js create mode 100644 awx/ui/tests/support/node/setup/nv.js create mode 100644 awx/ui/tests/support/node/setup/sinon.js rename awx/ui/tests/{unit => support}/rest-stub.js (100%) rename awx/ui/tests/{unit => }/system-tracking/compare-facts/flat-test.js (99%) rename awx/ui/tests/{unit => }/system-tracking/compare-facts/nested-test.js (99%) rename awx/ui/tests/{unit => }/system-tracking/single-host-data.service-test.js (96%) delete mode 100644 awx/ui/tests/unit/setup-browser.js diff --git a/awx/ui/static/lib/loader.js/loader.js b/awx/ui/static/lib/loader.js/loader.js index 0c9559c39b..4f3f7f6e38 100644 --- a/awx/ui/static/lib/loader.js/loader.js +++ b/awx/ui/static/lib/loader.js/loader.js @@ -55,7 +55,11 @@ var define, requireModule, require, requirejs; } if (!registry[name]) { - throw new Error('Could not find module ' + name); + name = name + '/index'; + + if (!registry[name]) { + throw new Error('Could not find module ' + name); + } } var mod = registry[name]; diff --git a/awx/ui/tests/unit/directives/job-status-graph-test.js b/awx/ui/tests/directives/job-status-graph-test.js similarity index 96% rename from awx/ui/tests/unit/directives/job-status-graph-test.js rename to awx/ui/tests/directives/job-status-graph-test.js index 0ea4c1265f..f0c49d1ef0 100644 --- a/awx/ui/tests/unit/directives/job-status-graph-test.js +++ b/awx/ui/tests/directives/job-status-graph-test.js @@ -1,8 +1,8 @@ /* jshint node: true */ -import '../setup-browser'; +import '../support/node'; -import {describeModule} from '../describe-module'; +import {describeModule} from '../support/describe-module'; import 'tower/shared/Utilities'; import 'tower/shared/RestServices'; import JobStatusGraph from 'tower/dashboard/graphs/job-status/main'; diff --git a/awx/ui/tests/unit/features/features.controller-test.js b/awx/ui/tests/features/features.controller-test.js similarity index 96% rename from awx/ui/tests/unit/features/features.controller-test.js rename to awx/ui/tests/features/features.controller-test.js index c607cf3d2d..08c159a881 100644 --- a/awx/ui/tests/unit/features/features.controller-test.js +++ b/awx/ui/tests/features/features.controller-test.js @@ -1,4 +1,4 @@ -import '../setup-browser'; +import '../support/node'; import featuresController from 'tower/shared/features/features.controller'; diff --git a/awx/ui/tests/unit/features/features.service-test.js b/awx/ui/tests/features/features.service-test.js similarity index 94% rename from awx/ui/tests/unit/features/features.service-test.js rename to awx/ui/tests/features/features.service-test.js index 62da79c14c..320ed0fd46 100644 --- a/awx/ui/tests/unit/features/features.service-test.js +++ b/awx/ui/tests/features/features.service-test.js @@ -1,7 +1,7 @@ -import '../setup-browser'; +import '../support/node'; import features from 'tower/shared/features/main'; -import {describeModule} from '../describe-module'; +import {describeModule} from '../support/describe-module'; //test that it returns features, as well as test that it is returned in rootScope diff --git a/awx/ui/tests/unit/job-templates/delete-job-template.service-test.js b/awx/ui/tests/job-templates/delete-job-template.service-test.js similarity index 86% rename from awx/ui/tests/unit/job-templates/delete-job-template.service-test.js rename to awx/ui/tests/job-templates/delete-job-template.service-test.js index f30dfd1621..5766287f51 100644 --- a/awx/ui/tests/unit/job-templates/delete-job-template.service-test.js +++ b/awx/ui/tests/job-templates/delete-job-template.service-test.js @@ -1,7 +1,7 @@ -import '../setup-browser'; +import '../support/node'; import jobTemplates from 'tower/job-templates/main'; -import {describeModule} from '../describe-module'; +import {describeModule} from '../support/describe-module'; describeModule(jobTemplates.name) .testService('deleteJobTemplate', function(test, restStub) { diff --git a/awx/ui/tests/unit/multi-select-list/multi-select-list.controller-test.js b/awx/ui/tests/multi-select-list/multi-select-list.controller-test.js similarity index 100% rename from awx/ui/tests/unit/multi-select-list/multi-select-list.controller-test.js rename to awx/ui/tests/multi-select-list/multi-select-list.controller-test.js diff --git a/awx/ui/tests/unit/multi-select-list/multi-select-list.directive-test.js b/awx/ui/tests/multi-select-list/multi-select-list.directive-test.js similarity index 98% rename from awx/ui/tests/unit/multi-select-list/multi-select-list.directive-test.js rename to awx/ui/tests/multi-select-list/multi-select-list.directive-test.js index debd765b1a..5af5770cb2 100644 --- a/awx/ui/tests/unit/multi-select-list/multi-select-list.directive-test.js +++ b/awx/ui/tests/multi-select-list/multi-select-list.directive-test.js @@ -1,6 +1,6 @@ -import '../setup-browser'; +import '../support/node'; -import {describeModule} from '../describe-module'; +import {describeModule} from '../support/describe-module'; import mod from 'tower/shared/multi-select-list/main'; describeModule(mod.name) diff --git a/awx/ui/tests/unit/multi-select-list/select-all.directive-test.js b/awx/ui/tests/multi-select-list/select-all.directive-test.js similarity index 97% rename from awx/ui/tests/unit/multi-select-list/select-all.directive-test.js rename to awx/ui/tests/multi-select-list/select-all.directive-test.js index 9f080cc494..8bdf295111 100644 --- a/awx/ui/tests/unit/multi-select-list/select-all.directive-test.js +++ b/awx/ui/tests/multi-select-list/select-all.directive-test.js @@ -1,6 +1,6 @@ -import '../setup-browser'; +import '../support/node'; -import {describeModule} from '../describe-module'; +import {describeModule} from '../support/describe-module'; import mod from 'tower/shared/multi-select-list/main'; var mockController = { diff --git a/awx/ui/tests/phantomjs-polyfill.js b/awx/ui/tests/phantomjs-polyfill.js deleted file mode 100644 index 46c4204283..0000000000 --- a/awx/ui/tests/phantomjs-polyfill.js +++ /dev/null @@ -1,28 +0,0 @@ -// Phantom.js is missing the standard Function.prototype.bind -// function. See https://code.google.com/p/phantomjs/issues/detail?id=522 -// for more details. -// -if (!Function.prototype.bind) { - Function.prototype.bind = function(oThis) { - if (typeof this !== 'function') { - // closest thing possible to the ECMAScript 5 - // internal IsCallable function - throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); - } - - var aArgs = Array.prototype.slice.call(arguments, 1), - fToBind = this, - fNOP = function() {}, - fBound = function() { - return fToBind.apply(this instanceof fNOP - ? this - : oThis, - aArgs.concat(Array.prototype.slice.call(arguments))); - }; - - fNOP.prototype = this.prototype; - fBound.prototype = new fNOP(); - - return fBound; - }; -} diff --git a/awx/ui/tests/unit/services/job-status-graph-data-test.js b/awx/ui/tests/services/job-status-graph-data-test.js similarity index 96% rename from awx/ui/tests/unit/services/job-status-graph-data-test.js rename to awx/ui/tests/services/job-status-graph-data-test.js index d5121cbdcb..e810b7e708 100644 --- a/awx/ui/tests/unit/services/job-status-graph-data-test.js +++ b/awx/ui/tests/services/job-status-graph-data-test.js @@ -1,6 +1,6 @@ -import '../setup-browser'; +import '../support/node'; -import {describeModule} from '../describe-module'; +import {describeModule} from '../support/describe-module'; import JobStatusGraph from 'tower/dashboard/graphs/job-status/main'; var processErrors = sinon.spy(); diff --git a/awx/ui/tests/unit/shared/lodash-as-promised_test.js b/awx/ui/tests/shared/lodash-as-promised-test.js similarity index 98% rename from awx/ui/tests/unit/shared/lodash-as-promised_test.js rename to awx/ui/tests/shared/lodash-as-promised-test.js index d9d01759de..80105306bc 100644 --- a/awx/ui/tests/unit/shared/lodash-as-promised_test.js +++ b/awx/ui/tests/shared/lodash-as-promised-test.js @@ -1,4 +1,4 @@ -import '../setup-browser'; +import '../support/node'; import 'tower/shared/main'; diff --git a/awx/ui/tests/unit.js b/awx/ui/tests/support/browser/index.js similarity index 100% rename from awx/ui/tests/unit.js rename to awx/ui/tests/support/browser/index.js diff --git a/awx/ui/tests/unit/describe-module.js b/awx/ui/tests/support/describe-module.js similarity index 100% rename from awx/ui/tests/unit/describe-module.js rename to awx/ui/tests/support/describe-module.js diff --git a/awx/ui/tests/support/node/export-global.js b/awx/ui/tests/support/node/export-global.js new file mode 100644 index 0000000000..c1fccb23a1 --- /dev/null +++ b/awx/ui/tests/support/node/export-global.js @@ -0,0 +1,4 @@ +module.exports = + function exportGlobal(varName, value) { + global[varName] = global.window[varName] = value; + }; diff --git a/awx/ui/tests/support/node/index.js b/awx/ui/tests/support/node/index.js new file mode 100644 index 0000000000..91ef218cf6 --- /dev/null +++ b/awx/ui/tests/support/node/index.js @@ -0,0 +1,26 @@ +/* jshint node: true */ + +(function() { + var isNode = typeof window === 'undefined'; + + if (!isNode) { + window.expect = chai.expect; + return; + } + + require('./setup/jsdom'); + require('./setup/mocha'); + require('./setup/jquery'); + require('./setup/angular'); + require('./setup/angular-mocks'); + require('./setup/angular-templates'); + require('./setup/sinon'); + require('./setup/chai'); + require('./setup/chai-plugins'); + require('./setup/d3'); + require('./setup/nv'); + require('./setup/lodash'); + require('./setup/local-storage'); + require('./setup/moment'); + +})(); diff --git a/awx/ui/tests/support/node/setup/angular-mocks.js b/awx/ui/tests/support/node/setup/angular-mocks.js new file mode 100644 index 0000000000..fbf1a88ac4 --- /dev/null +++ b/awx/ui/tests/support/node/setup/angular-mocks.js @@ -0,0 +1,5 @@ +var exportGlobal = require('../export-global'); +require('angular-mocks/angular-mocks'); + +exportGlobal('inject', window.inject); + diff --git a/awx/ui/tests/support/node/setup/angular-templates.js b/awx/ui/tests/support/node/setup/angular-templates.js new file mode 100644 index 0000000000..75837d0ad8 --- /dev/null +++ b/awx/ui/tests/support/node/setup/angular-templates.js @@ -0,0 +1,2 @@ +angular.module('templates', []); +require('../../../../templates'); diff --git a/awx/ui/tests/support/node/setup/angular.js b/awx/ui/tests/support/node/setup/angular.js new file mode 100644 index 0000000000..90749a49bc --- /dev/null +++ b/awx/ui/tests/support/node/setup/angular.js @@ -0,0 +1,5 @@ +var exportGlobal = require('../export-global'); +require('angular/angular'); + +exportGlobal('angular', window.angular); + diff --git a/awx/ui/tests/support/node/setup/chai-plugins.js b/awx/ui/tests/support/node/setup/chai-plugins.js new file mode 100644 index 0000000000..dde64dd10c --- /dev/null +++ b/awx/ui/tests/support/node/setup/chai-plugins.js @@ -0,0 +1,8 @@ +var sinonChai = require('sinon-chai'); +var chaiAsPromised = require('chai-as-promised'); +var chaiThings = require('chai-things'); + +chai.use(sinonChai); +chai.use(chaiAsPromised); +chai.use(chaiThings); + diff --git a/awx/ui/tests/support/node/setup/chai.js b/awx/ui/tests/support/node/setup/chai.js new file mode 100644 index 0000000000..570b230185 --- /dev/null +++ b/awx/ui/tests/support/node/setup/chai.js @@ -0,0 +1,5 @@ +var exportGlobal = require('../export-global'); +var chai = require('chai'); + +exportGlobal('chai', chai); +exportGlobal('expect', chai.expect); diff --git a/awx/ui/tests/support/node/setup/d3.js b/awx/ui/tests/support/node/setup/d3.js new file mode 100644 index 0000000000..ec8f384ccb --- /dev/null +++ b/awx/ui/tests/support/node/setup/d3.js @@ -0,0 +1,6 @@ +var exportGlobal = require('../export-global'); +var d3 = require('d3'); + +exportGlobal('d3', d3); + + diff --git a/awx/ui/tests/support/node/setup/jquery.js b/awx/ui/tests/support/node/setup/jquery.js new file mode 100644 index 0000000000..d10af4298c --- /dev/null +++ b/awx/ui/tests/support/node/setup/jquery.js @@ -0,0 +1,7 @@ +var exportGlobal = require('../export-global'); +var jquery = require('jquery'); + +exportGlobal('$', jquery); +exportGlobal('jQuery', jquery); + + diff --git a/awx/ui/tests/support/node/setup/jsdom.js b/awx/ui/tests/support/node/setup/jsdom.js new file mode 100644 index 0000000000..5a5a7b68e5 --- /dev/null +++ b/awx/ui/tests/support/node/setup/jsdom.js @@ -0,0 +1,6 @@ +var jsdom = require('jsdom').jsdom; +var document = jsdom('tower'); +var window = document.parentWindow; + +global.document = document; +global.window = window; diff --git a/awx/ui/tests/support/node/setup/local-storage.js b/awx/ui/tests/support/node/setup/local-storage.js new file mode 100644 index 0000000000..fff3ab7861 --- /dev/null +++ b/awx/ui/tests/support/node/setup/local-storage.js @@ -0,0 +1,7 @@ +var exportGlobal = require('../export-global'); +var LocalStorage = require('node-localstorage').LocalStorage; + +exportGlobal('localStorage', + new LocalStorage('./scratch')); + + diff --git a/awx/ui/tests/support/node/setup/lodash.js b/awx/ui/tests/support/node/setup/lodash.js new file mode 100644 index 0000000000..8af57a2da5 --- /dev/null +++ b/awx/ui/tests/support/node/setup/lodash.js @@ -0,0 +1,4 @@ +var exportGlobal = require('../export-global'); +var lodash = require('lodash'); + +exportGlobal('_', lodash); diff --git a/awx/ui/tests/support/node/setup/mocha.js b/awx/ui/tests/support/node/setup/mocha.js new file mode 100644 index 0000000000..b7d366a4b7 --- /dev/null +++ b/awx/ui/tests/support/node/setup/mocha.js @@ -0,0 +1,7 @@ +var exportGlobal = require('../export-global'); +var mocha = require('mocha'); + +exportGlobal('mocha', mocha); +exportGlobal('beforeEach', beforeEach); +exportGlobal('afterEach', afterEach); + diff --git a/awx/ui/tests/support/node/setup/moment.js b/awx/ui/tests/support/node/setup/moment.js new file mode 100644 index 0000000000..28822e411c --- /dev/null +++ b/awx/ui/tests/support/node/setup/moment.js @@ -0,0 +1,5 @@ +var exportGlobal = require('../export-global'); +var moment = require('moment'); + +exportGlobal('moment', moment); + diff --git a/awx/ui/tests/support/node/setup/nv.js b/awx/ui/tests/support/node/setup/nv.js new file mode 100644 index 0000000000..733b7dbad6 --- /dev/null +++ b/awx/ui/tests/support/node/setup/nv.js @@ -0,0 +1,6 @@ +var exportGlobal = require('../export-global'); +var nv = require('nvd3'); + +exportGlobal('nv', nv); + + diff --git a/awx/ui/tests/support/node/setup/sinon.js b/awx/ui/tests/support/node/setup/sinon.js new file mode 100644 index 0000000000..bfaf5cacec --- /dev/null +++ b/awx/ui/tests/support/node/setup/sinon.js @@ -0,0 +1,4 @@ +var exportGlobal = require('../export-global'); +var sinon = require('sinon'); + +exportGlobal('sinon', sinon); diff --git a/awx/ui/tests/unit/rest-stub.js b/awx/ui/tests/support/rest-stub.js similarity index 100% rename from awx/ui/tests/unit/rest-stub.js rename to awx/ui/tests/support/rest-stub.js diff --git a/awx/ui/tests/unit/system-tracking/compare-facts/flat-test.js b/awx/ui/tests/system-tracking/compare-facts/flat-test.js similarity index 99% rename from awx/ui/tests/unit/system-tracking/compare-facts/flat-test.js rename to awx/ui/tests/system-tracking/compare-facts/flat-test.js index 634a3230c1..c277a19641 100644 --- a/awx/ui/tests/unit/system-tracking/compare-facts/flat-test.js +++ b/awx/ui/tests/system-tracking/compare-facts/flat-test.js @@ -1,6 +1,6 @@ /* jshint node: true */ -import '../../setup-browser'; +import '../../support/node'; import compareFacts from 'tower/system-tracking/compare-facts/flat'; diff --git a/awx/ui/tests/unit/system-tracking/compare-facts/nested-test.js b/awx/ui/tests/system-tracking/compare-facts/nested-test.js similarity index 99% rename from awx/ui/tests/unit/system-tracking/compare-facts/nested-test.js rename to awx/ui/tests/system-tracking/compare-facts/nested-test.js index 5cbed586ca..a7ff98452b 100644 --- a/awx/ui/tests/unit/system-tracking/compare-facts/nested-test.js +++ b/awx/ui/tests/system-tracking/compare-facts/nested-test.js @@ -1,6 +1,6 @@ /* jshint node: true */ -import '../../setup-browser'; +import '../../support/node'; import compareFacts from 'tower/system-tracking/compare-facts/nested'; diff --git a/awx/ui/tests/unit/system-tracking/single-host-data.service-test.js b/awx/ui/tests/system-tracking/single-host-data.service-test.js similarity index 96% rename from awx/ui/tests/unit/system-tracking/single-host-data.service-test.js rename to awx/ui/tests/system-tracking/single-host-data.service-test.js index f8a07498dc..f9da3c2770 100644 --- a/awx/ui/tests/unit/system-tracking/single-host-data.service-test.js +++ b/awx/ui/tests/system-tracking/single-host-data.service-test.js @@ -1,7 +1,7 @@ -import '../setup-browser'; +import '../support/node'; import systemTracking from 'tower/system-tracking/data-services/main'; -import {describeModule} from '../describe-module'; +import {describeModule} from '../support/describe-module'; import moment from 'tower/shared/moment/moment'; describeModule(systemTracking.name) diff --git a/awx/ui/tests/unit/setup-browser.js b/awx/ui/tests/unit/setup-browser.js deleted file mode 100644 index a2b3c3db85..0000000000 --- a/awx/ui/tests/unit/setup-browser.js +++ /dev/null @@ -1,68 +0,0 @@ -/* jshint node: true */ - -(function() { - var isNode = typeof window === 'undefined'; - - if (!isNode) { - window.expect = chai.expect; - return; - } - - setupNode(); - - function setupNode() { - - var jsdom = require('jsdom').jsdom; - var document = jsdom('tower'); - var window = document.parentWindow; - var mocha = require('mocha'); - window.mocha = mocha; - window.beforeEach = beforeEach; - window.afterEach = afterEach; - - global.document = document; - global.window = window; - - var jquery = require('jquery'); - global.$ = window.$ = global.jQuery = window.jQuery = jquery; - - require('angular/angular'); - - require('angular-mocks/angular-mocks'); - - var chai = require('chai'); - var expect = chai.expect; - var sinonChai = require('sinon-chai'); - var chaiAsPromised = require('chai-as-promised'); - var sinon = require('sinon'); - var chaiThings = require('chai-things'); - - chai.use(sinonChai); - chai.use(chaiAsPromised); - chai.use(chaiThings); - - global.angular = window.angular; - global.inject = window.inject; - global.expect = chai.expect; - global.sinon = require('sinon'); - - angular.module('templates', []); - require('../../templates'); - - var d3 = require('d3'); - global.d3 = d3; - - var nv = require('nvd3'); - global.nv = nv; - - var lodash = require('lodash'); - global._ = lodash; - - var LocalStorage = require('node-localstorage').LocalStorage; - global.localStorage = window.localStorage = new LocalStorage('./scratch'); - - var moment = require('moment'); - window.moment = moment; - } - -})(); From 42eff20c4fcfd1db3ada640bed15ae63d28d3b4c Mon Sep 17 00:00:00 2001 From: Joe Fiorini Date: Thu, 9 Jul 2015 12:51:47 -0400 Subject: [PATCH 7/7] Use npm test for running tests --- testem.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testem.yml b/testem.yml index 0c74994e1d..913cd51282 100644 --- a/testem.yml +++ b/testem.yml @@ -27,4 +27,4 @@ launch_in_ci: - PhantomJS launchers: Mocha: - command: NODE_PATH=awx/ui/dist/node-tests ./node_modules/.bin/mocha $(find awx/ui/dist/node-tests/tests/ -name '*-test.js') + command: npm test