diff --git a/app/partials/progressBar.html b/app/partials/progressBar.html new file mode 100644 index 0000000..1100efa --- /dev/null +++ b/app/partials/progressBar.html @@ -0,0 +1,6 @@ +
+
+ +
+

{{processStep}}

+
diff --git a/app/scripts/controllers/index.js b/app/scripts/controllers/index.js index d3fee33..d5f80af 100644 --- a/app/scripts/controllers/index.js +++ b/app/scripts/controllers/index.js @@ -13,3 +13,4 @@ app.controller('ErrorDetailCtrl', require('./errorDetail')); app.controller('SpecialErrorDetailCtrl', require('./specialErrorDetail')); app.controller('IRSReportCtrl', require('./irsReport')); app.controller('PaginationCtrl', require('./pagination')); +app.controller('ProgressBarCtrl', require('./progressBar')); diff --git a/app/scripts/controllers/progressBar.js b/app/scripts/controllers/progressBar.js new file mode 100644 index 0000000..302089b --- /dev/null +++ b/app/scripts/controllers/progressBar.js @@ -0,0 +1,19 @@ +'use strict'; + +/** + * @ngdoc function + * @name hmdaPilotApp.controller:ProgressBarCtrl + * @description + * # ProgressBarCtrl + * Controller of the hmdaPilotApp + */ +module.exports = /*@ngInject*/ function ($scope, HMDAEngine) { + + $scope.percentageComplete = 0; + + HMDAEngine.getProgress().events.on('progressStep', function(percent) { + $scope.$apply(function(){ + $scope.percentageComplete = percent; + }); + }); +}; diff --git a/app/scripts/controllers/selectFile.js b/app/scripts/controllers/selectFile.js index 25dd92d..0895b3e 100644 --- a/app/scripts/controllers/selectFile.js +++ b/app/scripts/controllers/selectFile.js @@ -7,19 +7,20 @@ * # Select File * Controller for selecting a HMDA file and Reporting Year for verification. */ -module.exports = /*@ngInject*/ function ($scope, $location, $q, $timeout, FileReader, FileMetadata, HMDAEngine, Wizard, Session) { - var fiscalYears = HMDAEngine.getValidYears(); +module.exports = /*@ngInject*/ function ($scope, $location, $q, $timeout, FileReader, FileMetadata, HMDAEngine, Wizard, Session, ngDialog, Configuration) { + var progressDialog, + fiscalYears = HMDAEngine.getValidYears(); // Set/Reset the state of different objects on load Session.reset(); HMDAEngine.clearHmdaJson(); HMDAEngine.clearErrors(); + HMDAEngine.clearProgress(); $scope.metadata = FileMetadata.clear(); $scope.wizardSteps = Wizard.initSteps(); // Populate the $scope $scope.reportingYears = fiscalYears; - $scope.isProcessing = false; // Initialize the errors for the form fields $scope.errors = {}; @@ -45,14 +46,18 @@ module.exports = /*@ngInject*/ function ($scope, $location, $q, $timeout, FileRe $scope.submit = function(hmdaData) { // Clear out any existing errors $scope.errors.global = null; - // Toggle processing flag on so that we can notify the user - $scope.isProcessing = true; - $timeout(function() { $scope.process(hmdaData); }, 100); // Pause before starting the conversion so that the DOM can update + // Give a name to the current step in the process (shown in the progressDialog) + $scope.processStep = 'Processing HMDA file...'; + + progressDialog = ngDialog.open(angular.extend(Configuration.progressDialog, {scope: $scope})); + $timeout(function() { $scope.process(hmdaData); }, 100); // Pause before starting the conversion so that the DOM can update }; $scope.process = function(hmdaData) { + + // Enable LocalDB support? HMDAEngine.setUseLocalDB(hmdaData.local); /* istanbul ignore if debug */ @@ -63,8 +68,8 @@ module.exports = /*@ngInject*/ function ($scope, $location, $q, $timeout, FileRe // Convert the file to JSON HMDAEngine.fileToJson(hmdaData.file, hmdaData.year, function(fileErr) { if (fileErr) { - // Toggle processing flag off - $scope.isProcessing = false; + // Close the progress dialog + progressDialog.close(); $scope.errors.global = fileErr; $scope.$apply(); @@ -77,6 +82,9 @@ module.exports = /*@ngInject*/ function ($scope, $location, $q, $timeout, FileRe console.time('total time for syntactical and validity edits'); } + // Give a name to the current step in the process (shown in the progressDialog) + $scope.processStep = 'Validating Syntactical and Validity edits...'; + $q.all([HMDAEngine.runSyntactical(hmdaData.year), HMDAEngine.runValidity(hmdaData.year)]) .then(function() { @@ -94,12 +102,12 @@ module.exports = /*@ngInject*/ function ($scope, $location, $q, $timeout, FileRe // And go the summary page $location.path('/summarySyntacticalValidity'); - // Toggle processing flag off - $scope.isProcessing = false; + // Close the progress dialog + progressDialog.close(); }) .catch(function(err) { - // Toggle processing flag off - $scope.isProcessing = false; + // Close the progress dialog + progressDialog.close(); $scope.errors.global = err.message; return; diff --git a/app/scripts/controllers/summaryMSA-IRS.js b/app/scripts/controllers/summaryMSA-IRS.js index 76c78ad..88b4e28 100644 --- a/app/scripts/controllers/summaryMSA-IRS.js +++ b/app/scripts/controllers/summaryMSA-IRS.js @@ -24,10 +24,8 @@ module.exports = /*@ngInject*/ function ($scope, $location, Wizard, HMDAEngine, } // Get the list of errors from the HMDAEngine - var editErrors = HMDAEngine.getErrors(); - $scope.data = { - specialErrors: editErrors.special + specialErrors: HMDAEngine.getErrors().special }; $scope.showIRSReport = function() { diff --git a/app/scripts/controllers/summaryQualityMacro.js b/app/scripts/controllers/summaryQualityMacro.js index 9bd4422..c792cb7 100644 --- a/app/scripts/controllers/summaryQualityMacro.js +++ b/app/scripts/controllers/summaryQualityMacro.js @@ -7,7 +7,10 @@ * # SummaryQualityMacroCtrl * Controller for the Syntactical and Validity Summary view */ -module.exports = /*@ngInject*/ function ($scope, $location, $q, $timeout, HMDAEngine, Wizard, Session) { /*jshint ignore:line*/ +module.exports = /*@ngInject*/ function ($scope, $location, $q, $timeout, HMDAEngine, Wizard, Session, ngDialog, Configuration) { /*jshint ignore:line*/ + + // Set/Reset the state of different objects on load + HMDAEngine.clearProgress(); Array.prototype.diff = function(a) { return this.filter(function(i) { return a.indexOf(i) < 0; }); @@ -39,14 +42,13 @@ module.exports = /*@ngInject*/ function ($scope, $location, $q, $timeout, HMDAEn // Populate the $scope $scope.errors = {}; - $scope.isProcessing = false; // Get the list of errors from the HMDAEngine - var editErrors = HMDAEngine.getErrors(); + var progressDialog; $scope.data = { - qualityErrors: editErrors.quality, - macroErrors: editErrors.macro + qualityErrors: HMDAEngine.getErrors().quality, + macroErrors: HMDAEngine.getErrors().macro }; $scope.previous = function () { @@ -58,11 +60,13 @@ module.exports = /*@ngInject*/ function ($scope, $location, $q, $timeout, HMDAEn }; $scope.next = function() { - if (hasErrors(editErrors.special)) { + if (hasErrors(HMDAEngine.getErrors().special)) { $location.path('/summaryMSA-IRS'); } else { - // Toggle processing flag on so that we can notify the user - $scope.isProcessing = true; + // Give a name to the current step in the process (shown in the progressDialog) + $scope.processStep = 'Processing MSA/MD Data...'; + + progressDialog = ngDialog.open(angular.extend(Configuration.progressDialog, {scope: $scope})); // Pause before starting the validation so that the DOM can update $timeout(function() { $scope.process(); }, 100); @@ -91,11 +95,11 @@ module.exports = /*@ngInject*/ function ($scope, $location, $q, $timeout, HMDAEn // And go the next summary page $location.path('/summaryMSA-IRS'); - // Toggle processing flag off - $scope.isProcessing = false; + // Close the progress dialog + progressDialog.close(); }).catch(function(err) { - // Toggle processing flag off - $scope.isProcessing = false; + // Close the progress dialog + progressDialog.close(); $scope.errors.global = err.message; return; diff --git a/app/scripts/controllers/summarySyntacticalValidity.js b/app/scripts/controllers/summarySyntacticalValidity.js index b099834..7d623de 100644 --- a/app/scripts/controllers/summarySyntacticalValidity.js +++ b/app/scripts/controllers/summarySyntacticalValidity.js @@ -9,15 +9,16 @@ */ module.exports = /*@ngInject*/ function ($scope, $location, $q, $timeout, HMDAEngine, Wizard, ngDialog, Configuration) { - // Populate the $scope - $scope.errors = {}; - $scope.isProcessing = false; + // Set/Reset the state of different objects on load + HMDAEngine.clearProgress(); // Get the list of errors from the HMDAEngine - var editErrors = HMDAEngine.getErrors(); + var progressDialog; - $scope.syntacticalErrors = editErrors.syntactical || {}; - $scope.validityErrors = editErrors.validity || {}; + // Populate the $scope + $scope.errors = {}; + $scope.syntacticalErrors = HMDAEngine.getErrors().syntactical; + $scope.validityErrors = HMDAEngine.getErrors().validity; $scope.previous = function() { if (Configuration.confirmSessionReset) { @@ -34,7 +35,7 @@ module.exports = /*@ngInject*/ function ($scope, $location, $q, $timeout, HMDAEn }; $scope.hasNext = function() { - return angular.equals({}, $scope.syntacticalErrors) && angular.equals({}, $scope.validityErrors); + return angular.equals({}, HMDAEngine.getErrors().syntactical) && angular.equals({}, HMDAEngine.getErrors().validity); }; function hasErrors(obj) { @@ -42,11 +43,13 @@ module.exports = /*@ngInject*/ function ($scope, $location, $q, $timeout, HMDAEn } $scope.next = function() { - if (hasErrors(editErrors.quality) || hasErrors(editErrors.macro)) { + if (hasErrors(HMDAEngine.getErrors().quality) || hasErrors(HMDAEngine.getErrors().macro)) { $location.path('/summaryQualityMacro'); } else{ - // Toggle processing flag on so that we can notify the user - $scope.isProcessing = true; + // Give a name to the current step in the process (shown in the progressDialog) + $scope.processStep = 'Processing Quality and Macro edits...'; + + progressDialog = ngDialog.open(angular.extend(Configuration.progressDialog, {scope: $scope})); // Pause before starting the validation so that the DOM can update $timeout(function() { $scope.process(); }, 100); @@ -76,12 +79,12 @@ module.exports = /*@ngInject*/ function ($scope, $location, $q, $timeout, HMDAEn // And go the next summary page $location.path('/summaryQualityMacro'); - // Toggle processing flag off - $scope.isProcessing = false; + // Close the progress dialog + progressDialog.close(); }) .catch(function(err) { - // Toggle processing flag off - $scope.isProcessing = false; + // Close the progress dialog + progressDialog.close(); $scope.errors.global = err.message; return; diff --git a/app/scripts/directives/cfButton.js b/app/scripts/directives/cfButton.js deleted file mode 100644 index b23bd9c..0000000 --- a/app/scripts/directives/cfButton.js +++ /dev/null @@ -1,124 +0,0 @@ -'use strict'; - -/** - * @ngdoc directive - * @name hmdaPilotApp.directive:cfButton - * @description - * # Capital Framework Button directive - * Directive for displaying a button that use the Capital Framework - */ -module.exports = /*@ngInject*/ function () { - - var origBtnText; - - function disable($btn) { - $btn.prop('disabled', true); - $btn.addClass('btn__disabled'); - return $btn; - } - - function enable($btn) { - $btn.prop('disabled', false); - $btn.removeClass('btn__disabled'); - return $btn; - } - - function showProcessing($btn) { - disable($btn); - - $btn.addClass('btn-processing'); - - var text = $btn[0].getElementsByClassName('text')[0], - icon = $btn[0].getElementsByClassName('cf-icon')[0], - iconName = icon.className.match(/(^|\s)cf-icon-\S+/g)[0] || ''; - - angular.element(icon) - .removeClass(iconName) - .addClass('cf-icon-update cf-spin'); - - angular.element(text) - .text('Processing...'); - - return $btn; - } - - function hideProcessing($btn, iconName, btnText) { - enable($btn); - - $btn.removeClass('btn-processing'); - - var text = $btn[0].getElementsByClassName('text')[0], - icon = $btn[0].getElementsByClassName('cf-icon')[0]; - - angular.element(icon) - .removeClass('cf-icon-update') - .removeClass('cf-spin') - .addClass('cf-icon-' + iconName); - - angular.element(text) - .text(btnText); - - return $btn; - } - - function displayIcon($btn, name, position) { - position = position || 'right'; // default to placing the icon on the right - - var icon = ''; - - if (position === 'right') { - $btn.append(icon); - } else { - $btn.prepend(icon); - } - return $btn; - } - - function link(scope, element, attrs) { - origBtnText = element.text(); - - if (!attrs.ngClick) { - element.attr('type', 'submit'); - } - - if (attrs.iconClass) { - displayIcon(element, attrs.iconClass, attrs.iconPosition); - } - - if (scope.processing) { - showProcessing(element); - } - - if (scope.isDisabled) { - disable(element); - } - } - - function controller($scope, $element, $attrs) { - if (!$scope.isDisabled) { // If the disabled state isn't being set 'manually' - // Watch to see if the value of processing changes - $scope.$watch('processing', function(newVal) { - if (newVal) { - showProcessing($element); - } else { - hideProcessing($element, $attrs.iconClass, origBtnText); - } - }); - } - } - - return { - restrict: 'E', - replace: true, - transclude: true, - template: '', - scope: { - processing: '=', - isDisabled: '=', - iconClass: '=', - iconPosition: '=' - }, - link: link, - controller: /*@ngInject*/ controller - }; -}; diff --git a/app/scripts/directives/index.js b/app/scripts/directives/index.js index 4bb8559..ae1123c 100644 --- a/app/scripts/directives/index.js +++ b/app/scripts/directives/index.js @@ -9,7 +9,6 @@ app.directive('errorSummary', require('./errorSummary')); app.directive('errorDetail', require('./errorDetail')); app.directive('fileMetadata', require('./fileMetadata')); app.directive('wizardNav', require('./wizardNav')); -app.directive('cfButton', require('./cfButton')); app.directive('disclaimer', require('./disclaimer')); app.directive('paginationSize', require('./paginationSize')); app.directive('paginationNav', require('./paginationNav')); diff --git a/app/scripts/modules/config.js b/app/scripts/modules/config.js index 082158a..4834768 100644 --- a/app/scripts/modules/config.js +++ b/app/scripts/modules/config.js @@ -3,5 +3,13 @@ angular.module('services.config', []) .constant('Configuration', { apiUrl: 'http://localhost:8000', - confirmSessionReset: false + confirmSessionReset: false, + progressDialog: { + name: 'progress', + controller: 'ProgressBarCtrl', + template: 'partials/progressBar.html', + showClose: false, + closeByDocument: false, + closeByEscape: false, + } }); diff --git a/app/styles/hmda-pilot.less b/app/styles/hmda-pilot.less index 022b467..f7bdeaf 100644 --- a/app/styles/hmda-pilot.less +++ b/app/styles/hmda-pilot.less @@ -29,6 +29,7 @@ // HMDA Pilot components @import (less) "utils.less"; @import (less) "wizard.less"; +@import (less) "progressBar.less"; // Layouts .wrapper, .wrap { diff --git a/app/styles/progressBar.less b/app/styles/progressBar.less new file mode 100644 index 0000000..07bb9a4 --- /dev/null +++ b/app/styles/progressBar.less @@ -0,0 +1,33 @@ +.progress-bar { + + .meter { + height: 20px; + margin-bottom: 1em; + position: relative; + background: @darkgray; + -moz-border-radius: 25px; + -webkit-border-radius: 25px; + border-radius: 25px; + padding: 3px; + box-shadow: inset 0 -1px 1px rgba(255,255,255,0.3); + + & > span { + display: block; + height: 100%; + border-top-right-radius: 8px; + border-bottom-right-radius: 8px; + border-top-left-radius: 20px; + border-bottom-left-radius: 20px; + background-color: @green; + box-shadow: + inset 0 2px 9px rgba(255,255,255,0.3), + inset 0 -2px 6px rgba(0,0,0,0.4); + position: relative; + overflow: hidden; + } + } + + .description { + margin-bottom: 0; + } +} diff --git a/app/views/selectFile.html b/app/views/selectFile.html index 10b54b5..e36c61e 100644 --- a/app/views/selectFile.html +++ b/app/views/selectFile.html @@ -28,6 +28,6 @@

Select File and Validate

- Start validation +
diff --git a/app/views/summaryQualityMacro.html b/app/views/summaryQualityMacro.html index ed56400..09dda31 100644 --- a/app/views/summaryQualityMacro.html +++ b/app/views/summaryQualityMacro.html @@ -13,6 +13,6 @@

Macro Edit Report

- Continue +
diff --git a/app/views/summarySyntacticalValidity.html b/app/views/summarySyntacticalValidity.html index 1c655eb..dcf3b55 100644 --- a/app/views/summarySyntacticalValidity.html +++ b/app/views/summarySyntacticalValidity.html @@ -13,6 +13,6 @@

Validity Edit Report

- Continue +
diff --git a/config/config.js b/config/config.js index 3acfbc2..20030bc 100644 --- a/config/config.js +++ b/config/config.js @@ -3,5 +3,13 @@ angular.module('services.config', []) .constant('Configuration', { apiUrl: '@@apiUrl', - confirmSessionReset: @@confirmSessionReset + confirmSessionReset: @@confirmSessionReset, + progressDialog: { + name: 'progress', + controller: 'ProgressBarCtrl', + template: 'partials/progressBar.html', + showClose: false, + closeByDocument: false, + closeByEscape: false, + } }); diff --git a/package.json b/package.json index 7e8b829..4e4d85f 100644 --- a/package.json +++ b/package.json @@ -14,15 +14,15 @@ "url": "https://github.com/cfpb/hmda-pilot/issues" }, "dependencies": { - "angular": "1.3.13", - "angular-animate": "1.3.13", - "angular-aria": "1.3.13", - "angular-cookies": "1.3.13", + "angular": "1.3.15", + "angular-animate": "1.3.15", + "angular-aria": "1.3.15", + "angular-cookies": "1.3.15", "angular-filereader": "matteosuppo/angular-filereader#v1.0.2", - "angular-resource": "1.3.13", - "angular-route": "1.3.13", - "angular-sanitize": "1.3.13", - "angular-touch": "1.3.13", + "angular-resource": "1.3.15", + "angular-route": "1.3.15", + "angular-sanitize": "1.3.15", + "angular-touch": "1.3.15", "hmda-rule-engine": "cfpb/hmda-rule-engine#milestone9", "ng-dialog": "^0.3.12", "normalize-css": "^2.3.1" @@ -38,7 +38,7 @@ "cf-layout": "cfpb/cf-layout#0.2.2" }, "devDependencies": { - "angular-mocks": "1.3.13", + "angular-mocks": "1.3.15", "browserify-istanbul": "^0.1.2", "browserify-shim": "^3.8.3", "chai": "^2.2.0", diff --git a/test/spec/controllers/progressBar.js b/test/spec/controllers/progressBar.js new file mode 100644 index 0000000..d2ab057 --- /dev/null +++ b/test/spec/controllers/progressBar.js @@ -0,0 +1,33 @@ +'use strict'; + +require('angular'); +require('angular-mocks'); + +describe('Controller: ProgressBarCtrl', function () { + + var scope, + mockEngine = { + getProgress: function() { + return { events: { on: function() {} } }; + } + }; + + beforeEach(angular.mock.module('hmdaPilotApp')); + + beforeEach(inject(function ($rootScope, $controller) { + scope = $rootScope.$new(); + + // spyOn(mockEngine.getProgress().events, 'on').and.returnValue(100); + + $controller('ProgressBarCtrl', { + $scope: scope, + HMDAEngine: mockEngine + }); + })); + + describe('initial scope', function() { + it('should set the percentageComplete to 0', function() { + expect(scope.percentageComplete).toBe(0); + }); + }); +}); diff --git a/test/spec/controllers/selectFile.js b/test/spec/controllers/selectFile.js index a1b3200..c070324 100644 --- a/test/spec/controllers/selectFile.js +++ b/test/spec/controllers/selectFile.js @@ -8,6 +8,7 @@ describe('Controller: SelectFileCtrl', function () { var controller, scope, location, + timeout, Q, Wizard, FileMetadata, @@ -17,6 +18,7 @@ describe('Controller: SelectFileCtrl', function () { getValidYears: function() { return ['2013', '2014']; }, clearHmdaJson: function () { return {}; }, clearErrors: function () { return {}; }, + clearProgress: function () { return {}; }, fileToJson: function(file, year, next) { return next(null); }, runSyntactical: function() { return; }, runValidity: function() { return; }, @@ -27,11 +29,24 @@ describe('Controller: SelectFileCtrl', function () { beforeEach(angular.mock.module('hmdaPilotApp')); - beforeEach(inject(function ($rootScope, $location, $controller, $q, _Wizard_, _FileMetadata_, _FileReader_) { + beforeEach(inject(function($templateCache) { + var directiveTemplate = null; + var templateId = 'partials/progressBar.html'; + var req = new XMLHttpRequest(); + req.onload = function() { + directiveTemplate = this.responseText; + }; + req.open('get', '/base/app/'+templateId, false); + req.send(); + $templateCache.put(templateId, directiveTemplate); + })); + + beforeEach(inject(function ($rootScope, $location, $controller, $q, $timeout, _Wizard_, _FileMetadata_, _FileReader_, _Configuration_, _ngDialog_) { scope = $rootScope.$new(); controller = $controller; location = $location; Q = $q; + timeout = $timeout; Wizard = _Wizard_; FileMetadata = _FileMetadata_; FileReader = _FileReader_; @@ -41,10 +56,13 @@ describe('Controller: SelectFileCtrl', function () { $scope: scope, $location: location, $q: Q, + $timeout: timeout, Wizard: _Wizard_, FileMetadata: _FileMetadata_, FileReader: _FileReader_, - HMDAEngine: mockEngine + HMDAEngine: mockEngine, + ngDialog: _ngDialog_, + Configuration: _Configuration_ }); })); @@ -61,10 +79,6 @@ describe('Controller: SelectFileCtrl', function () { expect(scope.errors).toBeDefined(); expect(scope.errors).toEqual({}); }); - - it('should set the isProcessing flag to false', function () { - expect(scope.isProcessing).toBeFalsy(); - }); }); describe('getFile()', function() { @@ -82,7 +96,7 @@ describe('Controller: SelectFileCtrl', function () { }); }); - describe('process()', function() { + describe('submit()', function() { var hmdaData = { file: 'test.dat', @@ -100,7 +114,8 @@ describe('Controller: SelectFileCtrl', function () { $q: Q, HMDAEngine: mockEngine }); - scope.process(hmdaData); + scope.submit(hmdaData); + timeout.flush(); scope.$digest(); expect(scope.errors.global).toBe('error'); @@ -118,7 +133,8 @@ describe('Controller: SelectFileCtrl', function () { $q: Q, HMDAEngine: mockEngine }); - scope.process(hmdaData); + scope.submit(hmdaData); + timeout.flush(); scope.$digest(); expect(scope.errors.global).toBe('error'); @@ -136,7 +152,8 @@ describe('Controller: SelectFileCtrl', function () { $q: Q, HMDAEngine: mockEngine }); - scope.process(hmdaData); + scope.submit(hmdaData); + timeout.flush(); scope.$digest(); expect(scope.errors.global).toBe('error'); @@ -153,7 +170,8 @@ describe('Controller: SelectFileCtrl', function () { $q: Q, HMDAEngine: mockEngine }); - scope.process(hmdaData); + scope.submit(hmdaData); + timeout.flush(); scope.$digest(); }); diff --git a/test/spec/controllers/summaryQualityMacro.js b/test/spec/controllers/summaryQualityMacro.js index b2109b1..293ed1e 100644 --- a/test/spec/controllers/summaryQualityMacro.js +++ b/test/spec/controllers/summaryQualityMacro.js @@ -21,12 +21,25 @@ describe('Controller: SummaryQualityMacroCtrl', function () { getErrors: function() { return mockErrors; }, getRuleYear: function() { return '2015'; }, runSpecial: function(year, next) { return next(null); }, - getDebug: function() { return false; } + getDebug: function() { return false; }, + clearProgress: function () { return {}; } }; beforeEach(angular.mock.module('hmdaPilotApp')); - beforeEach(inject(function ($rootScope, $location, $controller, $q, $timeout, _Wizard_, _Session_) { + beforeEach(inject(function($templateCache) { + var directiveTemplate = null; + var templateId = 'partials/progressBar.html'; + var req = new XMLHttpRequest(); + req.onload = function() { + directiveTemplate = this.responseText; + }; + req.open('get', '/base/app/'+templateId, false); + req.send(); + $templateCache.put(templateId, directiveTemplate); + })); + + beforeEach(inject(function ($rootScope, $location, $controller, $q, $timeout, _Wizard_, _Session_, _ngDialog_, _Configuration_) { scope = $rootScope.$new(); location = $location; controller = $controller; @@ -34,14 +47,18 @@ describe('Controller: SummaryQualityMacroCtrl', function () { Q = $q; Wizard = _Wizard_; Session = _Session_; + Wizard.initSteps(); + $controller('SummaryQualityMacroCtrl', { $scope: scope, $location: location, $timeout: timeout, HMDAEngine: mockEngine, Wizard: _Wizard_, - Session: _Session_ + Session: _Session_, + ngDialog: _ngDialog_, + Configuration: _Configuration_ }); })); @@ -133,39 +150,18 @@ describe('Controller: SummaryQualityMacroCtrl', function () { }); }); - describe('when special edit checks have not been run', function() { - beforeEach(function() { - mockErrors.special = {}; - controller('SummaryQualityMacroCtrl', { - $scope: scope, - $location: location, - $timeout: timeout, - HMDAEngine: mockEngine, - Session: Session - }); - }); - - it('should run the process() function', function() { - spyOn(scope, 'process'); - scope.next(); - scope.$digest(); - timeout.flush(); - expect(scope.process).toHaveBeenCalled(); - }); - }); - }); - - describe('process()', function() { describe('when runSpecial has a runtime error', function() { it('should display a global error', function() { mockEngine.runSpecial = function() { return Q.reject(new Error('error')); }; + mockErrors.special = {}; controller('SummaryQualityMacroCtrl', { $scope: scope, $location: location, $q: Q, HMDAEngine: mockEngine }); - scope.process(); + scope.next(); + timeout.flush(); scope.$digest(); expect(scope.errors.global).toBe('error'); @@ -175,13 +171,15 @@ describe('Controller: SummaryQualityMacroCtrl', function () { describe('when runSpecial has no runtime errors', function() { beforeEach(function() { mockEngine.runSpecial = function() { return; }; + mockErrors.special = {}; controller('SummaryQualityMacroCtrl', { $scope: scope, $location: location, $q: Q, HMDAEngine: mockEngine }); - scope.process(); + scope.next(); + timeout.flush(); scope.$digest(); }); diff --git a/test/spec/controllers/summarySyntacticalValidity.js b/test/spec/controllers/summarySyntacticalValidity.js index 9add049..7016c53 100644 --- a/test/spec/controllers/summarySyntacticalValidity.js +++ b/test/spec/controllers/summarySyntacticalValidity.js @@ -24,11 +24,24 @@ describe('Controller: SummarySyntacticalValidityCtrl', function () { getRuleYear: function() { return '2015'; }, runQuality: function(year, next) { return next(null); }, runMacro: function(year, next) { return next(null); }, - getDebug: function() { return false; } + getDebug: function() { return false; }, + clearProgress: function () { return {}; } }; beforeEach(angular.mock.module('hmdaPilotApp')); + beforeEach(inject(function($templateCache) { + var directiveTemplate = null; + var templateId = 'partials/progressBar.html'; + var req = new XMLHttpRequest(); + req.onload = function() { + directiveTemplate = this.responseText; + }; + req.open('get', '/base/app/'+templateId, false); + req.send(); + $templateCache.put(templateId, directiveTemplate); + })); + beforeEach(inject(function ($rootScope, $location, $controller, $q, $timeout, _Wizard_, _Configuration_) { scope = $rootScope.$new(); location = $location; @@ -42,7 +55,9 @@ describe('Controller: SummarySyntacticalValidityCtrl', function () { } }; mockNgDialog = { - openConfirm: function() { } + open: function() {}, + openConfirm: function() {}, + close: function() {} }; spyOn(mockNgDialog, 'openConfirm').and.returnValue(mockNgDialogPromise); @@ -169,9 +184,7 @@ describe('Controller: SummarySyntacticalValidityCtrl', function () { expect(scope.process).toHaveBeenCalled(); }); }); - }); - describe('process()', function() { describe('when runQuality has a runtime error', function() { it('should display a global error', function() { mockEngine.runQuality = function() { return Q.reject(new Error('error')); }; @@ -182,8 +195,9 @@ describe('Controller: SummarySyntacticalValidityCtrl', function () { $q: Q, HMDAEngine: mockEngine }); - scope.process(); + scope.next(); scope.$digest(); + timeout.flush(); expect(scope.errors.global).toBe('error'); }); @@ -199,7 +213,8 @@ describe('Controller: SummarySyntacticalValidityCtrl', function () { $q: Q, HMDAEngine: mockEngine }); - scope.process(); + scope.next(); + timeout.flush(); scope.$digest(); expect(scope.errors.global).toBe('error'); @@ -216,7 +231,8 @@ describe('Controller: SummarySyntacticalValidityCtrl', function () { $q: Q, HMDAEngine: mockEngine }); - scope.process(); + scope.next(); + timeout.flush(); scope.$digest(); }); diff --git a/test/spec/directives/cfButton.js b/test/spec/directives/cfButton.js deleted file mode 100644 index 5abfb6d..0000000 --- a/test/spec/directives/cfButton.js +++ /dev/null @@ -1,180 +0,0 @@ -/*global jQuery:true*/ - -'use strict'; - -require('angular'); -require('angular-mocks'); - -describe('Directive: cfButton', function () { - - var element, - scope; - - beforeEach(angular.mock.module('hmdaPilotApp')); - - beforeEach(inject(function ($rootScope) { - scope = $rootScope.$new(); - })); - - describe('by default', function() { - beforeEach(inject(function ($compile) { - element = angular.element('A Button'); - element = $compile(element)(scope); - scope.$digest(); - })); - - it('should have type="submit", if not specified', function() { - expect(element.attr('type')).toBeDefined(); - expect(element.attr('type')).toBe('submit'); - }); - - it('should have the "btn" class', function() { - expect(element.hasClass('btn')).toBeTruthy(); - }); - - it('should not have the disabled property', function() { - expect(element.prop('disabled')).toBeFalsy(); - }); - - it('should not have the disabled class', function() { - expect(element.hasClass('btn__disabled')).toBeFalsy(); - }); - - it('should display the button text', function() { - expect(jQuery('.text', element).text()).toBe('A Button'); - }); - - it('should not display "Processing..." text', function() { - expect(jQuery('.text', element).text()).not.toBe('Processing...'); - }); - }); - - describe('icon-class', function() { - beforeEach(inject(function ($compile) { - element = angular.element('A Button'); - element = $compile(element)(scope); - scope.$digest(); - })); - - it('should display the named icon on the right by default', function() { - var el = jQuery('.cf-icon-test', element).parent(); - expect(el.hasClass('btn_icon__right')).toBeTruthy(); - }); - }); - - describe('icon-position', function() { - beforeEach(inject(function ($compile) { - element = angular.element('A Button'); - element = $compile(element)(scope); - scope.$digest(); - })); - - it('should display the icon on the left when specified', function() { - var el = jQuery('.cf-icon-test', element).parent(); - expect(el.hasClass('btn_icon__left')).toBeTruthy(); - }); - }); - - describe('if processing', function() { - beforeEach(inject(function ($compile) { - scope.isProcessing = true; - element = angular.element('A Button'); - element = $compile(element)(scope); - scope.$digest(); - })); - - it('should disable the button', function() { - expect(element.prop('disabled')).toBeTruthy(); - expect(element.hasClass('btn__disabled')).toBeTruthy(); - }); - - it('should change the button text to "Processing..."', function() { - var el = jQuery('span.text', element); - expect(el.text()).toBe('Processing...'); - expect(element.hasClass('btn-processing')).toBeTruthy(); - }); - - it('should display a spinning update icon', function() { - var el = jQuery('span.cf-icon', element); - expect(el.hasClass('cf-icon-update')).toBeTruthy(); - expect(el.hasClass('cf-spin')).toBeTruthy(); - }); - }); - - describe('if processing turns off', function() { - beforeEach(inject(function ($compile) { - scope.isProcessing = true; - element = angular.element('A Button'); - element = $compile(element)(scope); - scope.$digest(); - // Make sure that the processing is being triggered - expect(element.prop('disabled')).toBeTruthy(); - expect(element.hasClass('btn__disabled')).toBeTruthy(); - // Turn off processing - scope.isProcessing = false; - scope.$digest(); - })); - - it('should enable the button', function() { - expect(element.prop('disabled')).toBeFalsy(); - expect(element.hasClass('btn__disabled')).toBeFalsy(); - }); - - it('should reset the button text to "A Button"', function() { - var el = jQuery('span.text', element); - expect(el.text()).toBe('A Button'); - expect(element.hasClass('btn-processing')).toBeFalsy(); - }); - - it('should reset to the initial icon', function() { - var el = jQuery('span.cf-icon', element); - expect(el.hasClass('cf-icon-test')).toBeTruthy(); - expect(el.hasClass('cf-icon-update')).toBeFalsy(); - expect(el.hasClass('cf-spin')).toBeFalsy(); - }); - }); - - describe('when isDisabled evals to true', function() { - beforeEach(inject(function ($compile) { - scope.hasNext = function() { return true; }; - element = angular.element('A Button'); - element = $compile(element)(scope); - scope.$digest(); - })); - - it('should disable the button', function() { - expect(element.prop('disabled')).toBeTruthy(); - expect(element.hasClass('btn__disabled')).toBeTruthy(); - }); - }); - - describe('when the button has type="submit"', function() { - beforeEach(inject(function ($compile) { - element = angular.element('A Button'); - element = $compile(element)(scope); - scope.$digest(); - })); - - it('should pass through type="submit"', function() { - expect(element.attr('type')).toBeDefined(); - expect(element.attr('type')).toBe('submit'); - }); - }); - - describe('when the button has ngClick', function() { - beforeEach(inject(function ($compile) { - element = angular.element('A Button'); - element = $compile(element)(scope); - scope.$digest(); - })); - - it('should pass through the ngClick attr', function() { - expect(element.attr('ng-click')).toBeDefined(); - expect(element.attr('ng-click')).toBe('action()'); - }); - - it('should not include type="submit"', function() { - expect(element.attr('type')).toBeUndefined(); - }); - }); -});