diff --git a/README.md b/README.md index 2966f0a..718b0f8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Build Status](https://travis-ci.org/TAMULib/ProjectManagementUI.svg?branch=master)](https://travis-ci.org/TAMULib/ProjectManagementUI) -[![Coverage Status](https://coveralls.io/repos/github/TAMULib/ProjectManagementUI/badge.svg?branch=master)](https://coveralls.io/github/TAMULib/ProjectManagementUI?branch=master) +[![Build Status](https://travis-ci.org/TAMULib/ProductManagementUI.svg?branch=master)](https://travis-ci.org/TAMULib/ProductManagementUI) +[![Coverage Status](https://coveralls.io/repos/github/TAMULib/ProductManagementUI/badge.svg?branch=master)](https://coveralls.io/github/TAMULib/ProductManagementUI?branch=master) -# Project Management UI +# Product Management UI diff --git a/app/.htaccess b/app/.htaccess index a58e764..78fc7d0 100644 --- a/app/.htaccess +++ b/app/.htaccess @@ -1,7 +1,7 @@ RewriteEngine On - RewriteBase /projects/ + RewriteBase /products/ RewriteCond %{HTTP:X-Requested-With} !XMLHttpRequest$ RewriteCond %{REQUEST_FILENAME} !-f RewriteRule . index.html [L] - \ No newline at end of file + diff --git a/app/config/apiMapping.js b/app/config/apiMapping.js index 45ec0dc..eb0bcb5 100644 --- a/app/config/apiMapping.js +++ b/app/config/apiMapping.js @@ -1,166 +1,233 @@ // CONVENTION: must match model name, case sensitive var apiMapping = { - Project: { - validations: true, - lazy: true, - channel: '/channel/projects', - all: { - 'endpoint': '/private/queue', - 'controller': 'projects', - 'method': '', - 'httpMethod': 'GET' - }, - create: { - 'endpoint': '/private/queue', - 'controller': 'projects', - 'method': '', - 'httpMethod': 'POST' - }, - update: { - 'endpoint': '/private/queue', - 'controller': 'projects', - 'method': '', - 'httpMethod': 'PUT' - }, - remove: { - 'endpoint': '/private/queue', - 'controller': 'projects', - 'method': '', - 'httpMethod': 'DELETE' - }, - listen: { - 'endpoint': '/channel', - 'controller': 'projects' - } - }, - User: { - lazy: true, - channel: '/channel/users', - instantiate: { - 'endpoint': '/private/queue', - 'controller': 'users', - 'method': 'credentials' - }, - all: { - 'endpoint': '/private/queue', - 'controller': 'users' - }, - listen: { - 'endpoint': '/channel', - 'controller': 'users' - }, - update: { - 'endpoint': '/private/queue', - 'controller': 'users', - 'method': 'update' - } - }, - RemoteProjectManager: { - validations: true, - lazy: true, - channel: '/channel/remote-project-manager', - all: { - 'endpoint': '/private/queue', - 'controller': 'remote-project-manager', - 'method': '', - 'httpMethod': 'GET' - }, - create: { - 'endpoint': '/private/queue', - 'controller': 'remote-project-manager', - 'method': '', - 'httpMethod': 'POST' - }, - update: { - 'endpoint': '/private/queue', - 'controller': 'remote-project-manager', - 'method': '', - 'httpMethod': 'PUT' - }, - remove: { - 'endpoint': '/private/queue', - 'controller': 'remote-project-manager', - 'method': '', - 'httpMethod': 'DELETE' - }, - listen: { - 'endpoint': '/channel', - 'controller': 'remote-project-manager' - }, - types: { - 'endpoint': '/channel', - 'controller': 'remote-project-manager', - 'method': 'types/', - 'httpMethod': 'GET' - }, - scaffolding: { - 'endpoint': '/channel', - 'controller': 'remote-project-manager', - 'method': 'scaffolding/:type/', - 'httpMethod': 'GET' - } - }, - Status: { - validations: true, - lazy: true, - channel: '/channel/status', - all: { - 'endpoint': '/private/queue', - 'controller': 'status', - 'method': '', - 'httpMethod': 'GET' - }, - create: { - 'endpoint': '/private/queue', - 'controller': 'status', - 'method': '', - 'httpMethod': 'POST' - }, - update: { - 'endpoint': '/private/queue', - 'controller': 'status', - 'method': '', - 'httpMethod': 'PUT' - }, - remove: { - 'endpoint': '/private/queue', - 'controller': 'status', - 'method': '', - 'httpMethod': 'DELETE' - }, - listen: { - 'endpoint': '/channel', - 'controller': 'status' - } - }, - RemoteProjects: { - all: { - 'endpoint': '/private/queue', - 'controller': 'projects/remote' - }, - listen: { - 'endpoint': '/channel', - 'controller': 'projects/remote' - } - }, - ProjectsStats: { - all: { - 'endpoint': '/private/queue', - 'controller': 'projects/stats' - }, - listen: { - 'endpoint': '/channel', - 'controller': 'projects/stats' - } - }, - ActiveSprints: { - all: { - 'endpoint': '/private/queue', - 'controller': 'sprints/active' - }, - listen: { - 'endpoint': '/channel', - 'controller': 'sprints/active' - } + Product: { + validations: true, + lazy: true, + channel: '/channel/products', + all: { + 'endpoint': '/private/queue', + 'controller': 'products', + 'method': '', + 'httpMethod': 'GET' + }, + create: { + 'endpoint': '/private/queue', + 'controller': 'products', + 'method': '', + 'httpMethod': 'POST' + }, + update: { + 'endpoint': '/private/queue', + 'controller': 'products', + 'method': '', + 'httpMethod': 'PUT' + }, + remove: { + 'endpoint': '/private/queue', + 'controller': 'products', + 'method': '', + 'httpMethod': 'DELETE' + }, + listen: { + 'endpoint': '/channel', + 'controller': 'products' + } + }, + FeatureRequest: { + validations: false, + channel: '/channel/internal/request', + push: { + 'endpoint': '/private/queue', + 'controller': 'internal/request', + 'method': 'push/:requestId/:productId/:rpmId', + 'httpMethod': 'PUT' + }, + stats: { + 'endpoint': '/private/queue', + 'controller': 'internal/request', + 'method': 'stats', + 'httpMethod': 'GET' + }, + listen: { + 'endpoint': '/channel', + 'controller': 'internal/request' + } + }, + InternalRequest: { + validations: true, + lazy: true, + channel: '/channel/internal/request', + all: { + 'endpoint': '/private/queue', + 'controller': 'internal/request', + 'method': '', + 'httpMethod': 'GET' + }, + create: { + 'endpoint': '/private/queue', + 'controller': 'internal/request', + 'method': '', + 'httpMethod': 'POST' + }, + update: { + 'endpoint': '/private/queue', + 'controller': 'internal/request', + 'method': '', + 'httpMethod': 'PUT' + }, + submitFeatureProposal: { + 'endpoint': '/private/queue', + 'controller': 'internal/request', + 'method': '', + 'httpMethod': 'PUT' + }, + remove: { + 'endpoint': '/private/queue', + 'controller': 'internal/request', + 'method': '', + 'httpMethod': 'DELETE' + }, + listen: { + 'endpoint': '/channel', + 'controller': 'internal/request', + 'method': '' + } + }, + User: { + lazy: true, + channel: '/channel/users', + instantiate: { + 'endpoint': '/private/queue', + 'controller': 'users', + 'method': 'credentials' + }, + all: { + 'endpoint': '/private/queue', + 'controller': 'users' + }, + listen: { + 'endpoint': '/channel', + 'controller': 'users' + }, + update: { + 'endpoint': '/private/queue', + 'controller': 'users', + 'method': 'update' + } + }, + RemoteProjectManager: { + validations: true, + lazy: true, + channel: '/channel/remote-project-manager', + all: { + 'endpoint': '/private/queue', + 'controller': 'remote-project-manager', + 'method': '', + 'httpMethod': 'GET' + }, + create: { + 'endpoint': '/private/queue', + 'controller': 'remote-project-manager', + 'method': '', + 'httpMethod': 'POST' + }, + update: { + 'endpoint': '/private/queue', + 'controller': 'remote-project-manager', + 'method': '', + 'httpMethod': 'PUT' + }, + remove: { + 'endpoint': '/private/queue', + 'controller': 'remote-project-manager', + 'method': '', + 'httpMethod': 'DELETE' + }, + listen: { + 'endpoint': '/channel', + 'controller': 'remote-project-manager' + }, + types: { + 'endpoint': '/channel', + 'controller': 'remote-project-manager', + 'method': 'types/', + 'httpMethod': 'GET' + }, + scaffolding: { + 'endpoint': '/channel', + 'controller': 'remote-project-manager', + 'method': 'scaffolding/:type/', + 'httpMethod': 'GET' + } + }, + Status: { + validations: true, + lazy: true, + channel: '/channel/status', + all: { + 'endpoint': '/private/queue', + 'controller': 'status', + 'method': '', + 'httpMethod': 'GET' + }, + create: { + 'endpoint': '/private/queue', + 'controller': 'status', + 'method': '', + 'httpMethod': 'POST' + }, + update: { + 'endpoint': '/private/queue', + 'controller': 'status', + 'method': '', + 'httpMethod': 'PUT' + }, + remove: { + 'endpoint': '/private/queue', + 'controller': 'status', + 'method': '', + 'httpMethod': 'DELETE' + }, + listen: { + 'endpoint': '/channel', + 'controller': 'status' + } + }, + RemoteProjects: { + lazy: true, + all: { + 'endpoint': '/private/queue', + 'controller': 'projects/remote' + }, + byProduct: { + 'endpoint': '/private/queue', + 'controller': 'products', + 'method': 'remote-projects/:productId', + 'httpMethod': 'GET' + }, + listen: { + 'endpoint': '/channel', + 'controller': 'projects/remote' + } + }, + ProductsStats: { + all: { + 'endpoint': '/private/queue', + 'controller': 'products/stats' + }, + listen: { + 'endpoint': '/channel', + 'controller': 'products/stats' + } + }, + ActiveSprints: { + all: { + 'endpoint': '/private/queue', + 'controller': 'sprints/active' + }, + listen: { + 'endpoint': '/channel', + 'controller': 'sprints/active' } -}; \ No newline at end of file + } +}; diff --git a/app/config/routes.js b/app/config/routes.js index 612db6b..7e15694 100644 --- a/app/config/routes.js +++ b/app/config/routes.js @@ -1,7 +1,7 @@ app.config(function ($routeProvider) { $routeProvider. when('/management', { - redirectTo: '/management/projects' + redirectTo: '/management/products' }). when('/management/:tab', { templateUrl: 'views/management.html', @@ -31,4 +31,4 @@ app.config(function ($routeProvider) { otherwise({ redirectTo: '/error/404' }); -}); \ No newline at end of file +}); diff --git a/app/controllers/activeSprintsController.js b/app/controllers/activeSprintsController.js index d32855c..bd9fc41 100644 --- a/app/controllers/activeSprintsController.js +++ b/app/controllers/activeSprintsController.js @@ -19,7 +19,7 @@ app.controller('ActiveSprintsController', function ($controller, $sce, $scope, A }; $scope.kanbanHeader = function () { - return $scope.getSelectedSprint() ? $scope.getSelectedSprint().project + ": " + $scope.getSelectedSprint().name : "Select Sprint Above"; + return $scope.getSelectedSprint() ? $scope.getSelectedSprint().product + ": " + $scope.getSelectedSprint().name : "Select Sprint Above"; }; $scope.getSprintEstimateTotal = function (sprint) { @@ -76,4 +76,4 @@ app.controller('ActiveSprintsController', function ($controller, $sce, $scope, A } }); -}); \ No newline at end of file +}); diff --git a/app/controllers/internalRequestController.js b/app/controllers/internalRequestController.js new file mode 100644 index 0000000..f80dc31 --- /dev/null +++ b/app/controllers/internalRequestController.js @@ -0,0 +1,171 @@ +app.controller('InternalRequestController', function ($controller, $scope, ApiResponseActions, InternalRequestRepo, InternalRequestsService, ProductRepo, ProductsService, WsApi) { + + angular.extend(this, $controller('AbstractController', { + $scope: $scope + })); + + if ($scope.isManager() || $scope.isAdmin()) { + $scope.internalRequests = InternalRequestRepo.getAll(); + + $scope.internalRequestToCreate = InternalRequestRepo.getScaffold(); + $scope.internalRequestToEdit = {}; + $scope.internalRequestToDelete = {}; + + $scope.featureRequestToPush = {}; + + $scope.resetInternalRequestForms = function () { + InternalRequestRepo.clearValidationResults(); + + for (var key in $scope.internalRequestForms) { + if ($scope.internalRequestForms[key] !== undefined && !$scope.internalRequestForms[key].$pristine && $scope.internalRequestForms[key].$setPristine) { + $scope.internalRequestForms[key].$setPristine(); + } + } + + $scope.closeModal(); + }; + + $scope.resetInternalRequestForms(); + + $scope.selectRemoteProjects = function () { + if ($scope.featureRequestToPush.product && $scope.featureRequestToPush.product.id) { + if (!$scope.remoteProjects[$scope.featureRequestToPush.product.id]) { + $scope.refreshRemoteProjectsForProduct($scope.featureRequestToPush.product.id); + } + } + }; + + $scope.refreshRemoteProjectsForProduct = function (productId) { + if (productId && !$scope.remoteProjectsLoading[productId]) { + ProductsService.refreshRemoteProjectsForProduct(productId); + } + }; + + $scope.addInternalRequest = function () { + if (!$scope.productsLoading) { + ProductsService.refreshProducts(); + } + + $scope.openModal('#addInternalRequestModal'); + }; + + $scope.createInternalRequest = function () { + $scope.internalRequestToCreate.createdOn = new Date().getTime(); + + if (!$scope.productsLoading) { + ProductsService.refreshProducts(); + } + + InternalRequestRepo.create($scope.internalRequestToCreate).then(function (res) { + if (angular.fromJson(res.body).meta.status === 'SUCCESS') { + $scope.resetCreateInternalRequest(); + } + }); + }; + + $scope.resetCreateInternalRequest = function () { + angular.extend($scope.internalRequestToCreate, InternalRequestRepo.getScaffold()); + $scope.resetInternalRequestForms(); + }; + + $scope.pushInternalRequest = function (internalRequest) { + $scope.featureRequestToPush = { + id: internalRequest.id, + title: internalRequest.title, + description: internalRequest.description, + rpmId: null, + product: internalRequest.product, + scopeId: null + }; + + if (!$scope.productsLoading) { + ProductsService.refreshProducts(); + } + + $scope.openModal('#pushInternalRequestModal'); + }; + + $scope.pushFeatureRequest = function () { + for (var key in $scope.products) { + if ($scope.products[key].id == $scope.featureRequestToPush.product.id) { + for (var k in $scope.products[key].remoteProjectInfo) { + if ($scope.products[key].remoteProjectInfo[k].scopeId == $scope.featureRequestToPush.scopeId) { + $scope.featureRequestToPush.rpmId = $scope.products[key].remoteProjectInfo[k].remoteProjectManager.id; + break; + } + } + + break; + } + } + + InternalRequestsService.pushFeatureRequest($scope.featureRequestToPush).then(function (res) { + $scope.cancelPushFeatureRequest(); + }).catch(function() { + $scope.cancelPushFeatureRequest(); + }); + }; + + $scope.cancelPushFeatureRequest = function () { + $scope.featureRequestToPush = {}; + $scope.resetInternalRequestForms(); + }; + + $scope.editInternalRequest = function (internalRequest) { + $scope.internalRequestToEdit = angular.copy(internalRequest); + + if (!$scope.productsLoading) { + ProductsService.refreshProducts(); + } + + $scope.openModal('#editInternalRequestModal'); + }; + + $scope.updateInternalRequest = function () { + $scope.internalRequestToEdit.dirty(true); + $scope.internalRequestToEdit.save().then(function () { + $scope.cancelEditInternalRequest(); + }); + }; + + $scope.cancelEditInternalRequest = function () { + $scope.internalRequestToEdit.refresh(); + $scope.resetInternalRequestForms(); + }; + + $scope.confirmDeleteInternalRequest = function (internalRequest) { + $scope.internalRequestToDelete = angular.copy(internalRequest); + $scope.openModal('#deleteInternalRequestModal'); + }; + + $scope.cancelDeleteInternalRequest = function () { + $scope.internalRequestToDelete = {}; + $scope.closeModal(); + }; + + $scope.deleteInternalRequest = function (internalRequest) { + InternalRequestRepo.delete(internalRequest).then(function (res) { + if (angular.fromJson(res.body).meta.status === "SUCCESS") { + $scope.cancelDeleteInternalRequest(); + } + }); + }; + + ProductsService.ready.then(null, null, function () { + $scope.products = ProductsService.getProducts(); + $scope.productsLoading = ProductsService.getProductsLoading(); + $scope.remoteProjects = ProductsService.getRemoteProjects(); + $scope.remoteProjectsLoading = ProductsService.getRemoteProjectsLoading(); + }); + + InternalRequestRepo.listen([ApiResponseActions.CREATE, ApiResponseActions.DELETE, ApiResponseActions.UPDATE], function () { + $scope.internalRequests.length = 0; + + var internalRequests = InternalRequestRepo.getAll(); + for (var i in internalRequests) { + $scope.internalRequests.push(internalRequests[i]); + } + }); + } + +}); diff --git a/app/controllers/internalStatsController.js b/app/controllers/internalStatsController.js new file mode 100644 index 0000000..5a902b5 --- /dev/null +++ b/app/controllers/internalStatsController.js @@ -0,0 +1,9 @@ +app.controller('InternalStatsController', function ($controller, $scope, ApiResponseActions, InternalRequestRepo, InternalStatsService) { + + angular.extend(this, $controller('AbstractController', { + $scope: $scope + })); + + $scope.stats = InternalStatsService.getStats(); + +}); diff --git a/app/controllers/productController.js b/app/controllers/productController.js new file mode 100644 index 0000000..0a8cfea --- /dev/null +++ b/app/controllers/productController.js @@ -0,0 +1,148 @@ +app.controller('ProductController', function ($controller, $scope, ApiResponseActions, ProductRepo, RemoteProjectManagerRepo, RemoteProjectsService) { + + angular.extend(this, $controller('AbstractController', { + $scope: $scope + })); + + $scope.products = ProductRepo.getAll(); + + $scope.productToCreate = ProductRepo.getScaffold(); + + $scope.productToDelete = {}; + + $scope.addingRemoteProjectInfo = false; + $scope.remoteProjectInfoChanged = false; + + $scope.remoteProjectInfoToAdd = { + remoteProjectManager: null, + scopeId: null + }; + + $scope.productForms = { + validations: ProductRepo.getValidations(), + getResults: ProductRepo.getValidationResults + }; + + $scope.closeAddRemoteProjectInfo = function() { + $scope.addingRemoteProjectInfo = false; + $scope.remoteProjectInfoToAdd = { + remoteProjectManager: null, + scopeId: null + }; + }; + + $scope.resetProductForms = function () { + ProductRepo.clearValidationResults(); + for (var key in $scope.productForms) { + if ($scope.productForms[key] !== undefined && !$scope.productForms[key].$pristine && $scope.productForms[key].$setPristine) { + $scope.productForms[key].$setPristine(); + } + } + $scope.closeAddRemoteProjectInfo(); + $scope.remoteProjectInfoChanged = false; + $scope.closeModal(); + }; + + $scope.resetProductForms(); + + $scope.createProduct = function () { + ProductRepo.create($scope.productToCreate).then(function (res) { + if (angular.fromJson(res.body).meta.status === 'SUCCESS') { + $scope.resetCreateProduct(); + } + }); + }; + + $scope.resetCreateProduct = function () { + angular.extend($scope.productToCreate, ProductRepo.getScaffold()); + $scope.resetProductForms(); + }; + + $scope.editProduct = function (product) { + $scope.productToEdit = product; + $scope.openModal('#editProductModal'); + }; + + $scope.updateProduct = function () { + $scope.productToEdit.dirty(true); + $scope.productToEdit.save().then(function () { + $scope.cancelEditProduct(); + }); + }; + + $scope.cancelEditProduct = function () { + $scope.productToEdit.refresh(); + $scope.productToEdit = {}; + $scope.resetProductForms(); + }; + + $scope.confirmDeleteProduct = function (product) { + $scope.productToDelete = product; + $scope.openModal('#deleteProductModal'); + }; + + $scope.cancelDeleteProduct = function () { + $scope.productToDelete = {}; + $scope.closeModal(); + }; + + $scope.deleteProduct = function (product) { + ProductRepo.delete(product).then(function (res) { + if (angular.fromJson(res.body).meta.status === "SUCCESS") { + $scope.cancelDeleteProduct(); + } + }); + }; + + $scope.openAddRemoteProjectInfo = function() { + $scope.addingRemoteProjectInfo = true; + }; + + $scope.addRemoteProjectInfo = function(remoteProjectInfo, remoteProject) { + remoteProjectInfo.push(remoteProject); + $scope.remoteProjectInfoChanged = true; + $scope.closeAddRemoteProjectInfo(); + }; + + $scope.removeRemoteProjectInfo = function(remoteProjectInfo, remoteProject) { + remoteProjectInfo.splice(remoteProjectInfo.indexOf(remoteProject), 1); + $scope.remoteProjectInfoChanged = true; + }; + + if ($scope.isManager() || $scope.isAdmin()) { + $scope.remoteProjectManagers = RemoteProjectManagerRepo.getAll(); + + $scope.remoteProjectInfo = RemoteProjectsService.getRemoteProjectInfo(); + + $scope.getRemoteProjectManagerRemoteProjects = function (remoteProjectManagerId) { + return $scope.remoteProjectInfo[remoteProjectManagerId]; + }; + + $scope.getRemoteProjectByRemoteProjectInfo = function(remoteProjectInfo) { + if (angular.isDefined(remoteProjectInfo.remoteProjectManager.id)) { + if (angular.isDefined($scope.remoteProjectInfo[remoteProjectInfo.remoteProjectManager.id])) { + return $scope.remoteProjectInfo[remoteProjectInfo.remoteProjectManager.id].filter(function(rp) { + return rp.id === remoteProjectInfo.scopeId; + })[0]; + } + } + }; + + RemoteProjectManagerRepo.listen([ApiResponseActions.CREATE, ApiResponseActions.DELETE, ApiResponseActions.UPDATE], function () { + $scope.remoteProjectManagers.length = 0; + var remoteProjectManagers = RemoteProjectManagerRepo.getAll(); + for (var i in remoteProjectManagers) { + $scope.remoteProjectManagers.push(remoteProjectManagers[i]); + } + }); + } + + ProductRepo.listen([ApiResponseActions.CREATE, ApiResponseActions.DELETE, ApiResponseActions.UPDATE], function () { + $scope.products.length = 0; + var products = ProductRepo.getAll(); + for (var i in products) { + $scope.products.push(products[i]); + } + }); + +}); diff --git a/app/controllers/projectController.js b/app/controllers/projectController.js deleted file mode 100644 index e37d08c..0000000 --- a/app/controllers/projectController.js +++ /dev/null @@ -1,105 +0,0 @@ -app.controller('ProjectController', function ($controller, $scope, ApiResponseActions, ProjectRepo, RemoteProjectManagerRepo, RemoteProjectsService) { - - angular.extend(this, $controller('AbstractController', { - $scope: $scope - })); - - $scope.projects = ProjectRepo.getAll(); - - $scope.projectToCreate = ProjectRepo.getScaffold(); - - $scope.projectToDelete = {}; - - $scope.projectForms = { - validations: ProjectRepo.getValidations(), - getResults: ProjectRepo.getValidationResults - }; - - $scope.resetProjectForms = function () { - ProjectRepo.clearValidationResults(); - for (var key in $scope.projectForms) { - if ($scope.projectForms[key] !== undefined && !$scope.projectForms[key].$pristine && $scope.projectForms[key].$setPristine) { - $scope.projectForms[key].$setPristine(); - } - } - $scope.closeModal(); - }; - - $scope.resetProjectForms(); - - $scope.createProject = function () { - ProjectRepo.create($scope.projectToCreate).then(function (res) { - if (angular.fromJson(res.body).meta.status === 'SUCCESS') { - $scope.resetCreateProject(); - } - }); - }; - - $scope.resetCreateProject = function () { - angular.extend($scope.projectToCreate, ProjectRepo.getScaffold()); - $scope.resetProjectForms(); - }; - - $scope.editProject = function (project) { - $scope.projectToEdit = project; - $scope.openModal('#editProjectModal'); - }; - - $scope.updateProject = function () { - $scope.projectToEdit.dirty(true); - $scope.projectToEdit.save().then(function () { - $scope.cancelEditProject(); - }); - }; - - $scope.cancelEditProject = function () { - $scope.projectToEdit.refresh(); - $scope.projectToEdit = {}; - $scope.resetProjectForms(); - }; - - $scope.confirmDeleteProject = function (project) { - $scope.projectToDelete = project; - $scope.openModal('#deleteProjectModal'); - }; - - $scope.cancelDeleteProject = function () { - $scope.projectToDelete = {}; - $scope.closeModal(); - }; - - $scope.deleteProject = function (project) { - ProjectRepo.delete(project).then(function (res) { - if (angular.fromJson(res.body).meta.status === "SUCCESS") { - $scope.cancelDeleteProject(); - } - }); - }; - - if ($scope.isManager() || $scope.isAdmin()) { - $scope.remoteProjectManagers = RemoteProjectManagerRepo.getAll(); - - $scope.remoteProjects = RemoteProjectsService.getRemoteProjects(); - - $scope.getRemoteProjectManagerRemoteProjects = function (remoteProjectManagerId) { - return $scope.remoteProjects[remoteProjectManagerId]; - }; - - RemoteProjectManagerRepo.listen([ApiResponseActions.CREATE, ApiResponseActions.DELETE, ApiResponseActions.UPDATE], function () { - $scope.remoteProjectManagers.length = 0; - var remoteProjectManagers = RemoteProjectManagerRepo.getAll(); - for (var i in remoteProjectManagers) { - $scope.remoteProjectManagers.push(remoteProjectManagers[i]); - } - }); - } - - ProjectRepo.listen([ApiResponseActions.CREATE, ApiResponseActions.DELETE, ApiResponseActions.UPDATE], function () { - $scope.projects.length = 0; - var projects = ProjectRepo.getAll(); - for (var i in projects) { - $scope.projects.push(projects[i]); - } - }); - -}); \ No newline at end of file diff --git a/app/controllers/remoteProjectManagerController.js b/app/controllers/remoteProjectManagerController.js index affc44a..39cb559 100644 --- a/app/controllers/remoteProjectManagerController.js +++ b/app/controllers/remoteProjectManagerController.js @@ -31,6 +31,11 @@ app.controller('RemoteProjectManagerController', function ($controller, $scope, $scope.closeModal(); }; + $scope.addRemoteProjectManager = function () { + $scope.resetCreateRemoteProjectManager(); + $scope.openModal('#addRemoteProjectManagerModal'); + }; + $scope.createRemoteProjectManager = function () { RemoteProjectManagerRepo.create($scope.remoteProjectManagerToCreate).then(function (res) { if (angular.fromJson(res.body).meta.status === 'SUCCESS') { @@ -98,4 +103,4 @@ app.controller('RemoteProjectManagerController', function ($controller, $scope, } }); -}); \ No newline at end of file +}); diff --git a/app/directives/remoteProjectManagerFormDirective.js b/app/directives/remoteProjectManagerFormDirective.js index 7cdf011..771b4a5 100644 --- a/app/directives/remoteProjectManagerFormDirective.js +++ b/app/directives/remoteProjectManagerFormDirective.js @@ -55,4 +55,4 @@ app.directive('remoteProjectManagerForm', function () { }; } }; -}); \ No newline at end of file +}); diff --git a/app/filters/availableRemoteProjectFilter.js b/app/filters/availableRemoteProjectFilter.js new file mode 100644 index 0000000..5af75f3 --- /dev/null +++ b/app/filters/availableRemoteProjectFilter.js @@ -0,0 +1,14 @@ +app.filter('availableRemoteProject', function() { + return function(input, usedRPs) { + if (!input) return false; + return input.filter(function(val) { + if (usedRPs) { + return !usedRPs.some(function(rp) { + return rp.scopeId === val.id; + }); + } else { + return true; + } + }); + }; +}); diff --git a/app/index.html b/app/index.html index 7782293..d3155db 100644 --- a/app/index.html +++ b/app/index.html @@ -7,7 +7,7 @@ - + @@ -15,7 +15,7 @@ - Project Management :: Texas A&M Libraries + Product Management :: Texas A&M Libraries @@ -38,7 +38,7 @@
- + @@ -196,29 +196,37 @@ - - + + + + + + - + + - + + - + + + @@ -246,4 +254,4 @@ - \ No newline at end of file + diff --git a/app/model/internalRequest.js b/app/model/internalRequest.js new file mode 100644 index 0000000..ba2db67 --- /dev/null +++ b/app/model/internalRequest.js @@ -0,0 +1,7 @@ +app.model("InternalRequest", function InternalRequest() { + return function InternalRequest() { + var internalRequest = this; + + return internalRequest; + }; +}); diff --git a/app/model/product.js b/app/model/product.js new file mode 100644 index 0000000..e51e68b --- /dev/null +++ b/app/model/product.js @@ -0,0 +1,15 @@ +app.model("Product", function Product(ProductsStatsService, RemoteProjectsService) { + return function Product() { + var product = this; + + product.before(function () { + ProductsStatsService.getById(product.id).then(function (productStats) { + angular.extend(product, { + stats: productStats + }); + }); + }); + + return product; + }; +}); diff --git a/app/model/project.js b/app/model/project.js deleted file mode 100644 index 88755e9..0000000 --- a/app/model/project.js +++ /dev/null @@ -1,28 +0,0 @@ -app.model("Project", function Project(ProjectsStatsService, RemoteProjectsService) { - return function Project() { - - var project = this; - - project.before(function () { - if (project.remoteProjectManager && project.scopeId) { - ProjectsStatsService.getById(project.id).then(function (projectStats) { - angular.extend(project, { - stats: projectStats - }); - }); - } - }); - - project.before(function () { - if (project.remoteProjectManager && project.scopeId) { - RemoteProjectsService.getByScopeId(project.remoteProjectManager.id, project.scopeId).then(function (remoteProject) { - angular.extend(project, { - remoteProject: remoteProject - }); - }); - } - }); - - return project; - }; -}); \ No newline at end of file diff --git a/app/model/remoteProjectManager.js b/app/model/remoteProjectManager.js index 694a7c6..676bd1e 100644 --- a/app/model/remoteProjectManager.js +++ b/app/model/remoteProjectManager.js @@ -2,4 +2,4 @@ app.model("RemoteProjectManager", function RemoteProjectManager() { return function RemoteProjectManager() { return this; }; -}); \ No newline at end of file +}); diff --git a/app/repo/internalRequestRepo.js b/app/repo/internalRequestRepo.js new file mode 100644 index 0000000..d9cb074 --- /dev/null +++ b/app/repo/internalRequestRepo.js @@ -0,0 +1,12 @@ +app.repo("InternalRequestRepo", function InternalRequestRepo() { + var internalRequestRepo = this; + + internalRequestRepo.scaffold = { + title: '', + description: '', + product: null, + createdOn: null + }; + + return internalRequestRepo; +}); diff --git a/app/repo/productRepo.js b/app/repo/productRepo.js new file mode 100644 index 0000000..6d3c026 --- /dev/null +++ b/app/repo/productRepo.js @@ -0,0 +1,10 @@ +app.repo("ProductRepo", function ProductRepo() { + + this.scaffold = { + name: '', + remoteProjectInfo: [] + }; + + return this; + +}); diff --git a/app/repo/projectRepo.js b/app/repo/projectRepo.js deleted file mode 100644 index e4e42ec..0000000 --- a/app/repo/projectRepo.js +++ /dev/null @@ -1,9 +0,0 @@ -app.repo("ProjectRepo", function ProjectRepo() { - - this.scaffold = { - name: '' - }; - - return this; - -}); \ No newline at end of file diff --git a/app/repo/remoteProjectManagerRepo.js b/app/repo/remoteProjectManagerRepo.js index 3819d51..7a9e6ee 100644 --- a/app/repo/remoteProjectManagerRepo.js +++ b/app/repo/remoteProjectManagerRepo.js @@ -39,4 +39,4 @@ app.repo("RemoteProjectManagerRepo", function RemoteProjectManagerRepo($q, WsApi return this; -}); \ No newline at end of file +}); diff --git a/app/resources/styles/sass/management/_all.scss b/app/resources/styles/sass/management/_all.scss index 8113eef..e729d27 100644 --- a/app/resources/styles/sass/management/_all.scss +++ b/app/resources/styles/sass/management/_all.scss @@ -1,3 +1,5 @@ +@import "products"; + .management-table { table { .glyphicon { @@ -5,4 +7,4 @@ cursor: pointer; } } -} \ No newline at end of file +} diff --git a/app/resources/styles/sass/management/_products.scss b/app/resources/styles/sass/management/_products.scss new file mode 100644 index 0000000..1b541b6 --- /dev/null +++ b/app/resources/styles/sass/management/_products.scss @@ -0,0 +1,23 @@ +.clickable:hover { + cursor: pointer; +} + +.remote-product-panel { + margin-top: 20px; + + .panel-heading { + min-height: 54px; + + label { + margin-top: 5px; + } + + .form-group { + margin-top: 20px; + } + } + + ul { + margin-bottom: 0; + } +} \ No newline at end of file diff --git a/app/services/internalRequestsService.js b/app/services/internalRequestsService.js new file mode 100644 index 0000000..7366068 --- /dev/null +++ b/app/services/internalRequestsService.js @@ -0,0 +1,30 @@ +app.service('InternalRequestsService', function ($q, WsApi) { + var service = this; + + service.pushFeatureRequest = function(featureRequest) { + var options = { + data: featureRequest.scopeId, + pathValues: { + requestId: featureRequest.id, + productId: featureRequest.product ? featureRequest.product.id : null, + rpmId: featureRequest.rpmId, + } + }; + + return $q(function (resolve, reject) { + WsApi.fetch(apiMapping.FeatureRequest.push, options).then(function (response) { + var apiRes = angular.fromJson(response.body); + + if (apiRes.meta.status === 'SUCCESS') { + resolve(); + } else { + reject('Push failed!'); + } + }, function error(error) { + console.error(error); + reject(error); + }); + }); + }; + +}); diff --git a/app/services/internalStatsService.js b/app/services/internalStatsService.js new file mode 100644 index 0000000..98dd64f --- /dev/null +++ b/app/services/internalStatsService.js @@ -0,0 +1,50 @@ +app.service('InternalStatsService', function ($q, InternalRequestRepo, WsApi) { + var service = this; + + var defer = $q.defer(); + + var stats = { + internalCount: 0 + }; + + var refreshable = true; + + var process = function (response) { + var apiRes = angular.fromJson(response.body); + + if (apiRes.meta.status === 'SUCCESS') { + for (var key in stats) { + stats[key] = undefined; + } + + angular.extend(stats, apiRes.payload.InternalStats); + defer.notify(); + } else { + console.error(apiRes.meta); + throw "Unable to retrieve internal stats"; + } + }; + + WsApi.listen(apiMapping.FeatureRequest.listen).then(null, null, function (response) { + service.refreshStats(); + }); + + service.refreshStats = function () { + if (refreshable) { + refreshable = false; + WsApi.fetch(apiMapping.FeatureRequest.stats).then(function (response) { + process(response); + refreshable = true; + }); + } + }; + + service.getStats = function () { + return stats; + }; + + this.refreshStats(); + + this.ready = defer.promise; + +}); diff --git a/app/services/productsService.js b/app/services/productsService.js new file mode 100644 index 0000000..0e16918 --- /dev/null +++ b/app/services/productsService.js @@ -0,0 +1,130 @@ +app.service('ProductsService', function ($q, ProductRepo, WsApi) { + var service = this; + + var products = []; + var productsLoading = false; + var remoteProjects = {}; + var remoteProjectsLoading = []; + + var defer = $q.defer(); + + var process = function (res) { + var apiRes = angular.fromJson(res.body); + + if (apiRes.meta.status === 'SUCCESS') { + products.length = 0; + + angular.extend(products, apiRes.payload['ArrayList']); + defer.notify(); + productsLoading = false; + + var toRemove = {}; + for (var productId in remoteProjects) { + toRemove[productId] = productId; + } + + for (var key in products) { + toRemove[products[key].id] = undefined; + + if (!remoteProjectsLoading[products[key].id]) { + service.refreshRemoteProjectsForProduct(products[key].id); + } + } + + for (var id in toRemove) { + remoteProjects[id] = undefined; + } + } else { + console.error(apiRes.meta); + throw "Unable to retrieve products"; + } + }; + + var processRemoteProject = function (res, productId) { + var apiRes = angular.fromJson(res.body); + + if (apiRes.meta.status === 'SUCCESS') { + if (angular.isDefined(remoteProjects[productId])) { + for (var key in remoteProjects[productId]) { + remoteProjects[productId][key] = undefined; + } + } else { + remoteProjects[productId] = {}; + } + + angular.extend(remoteProjects[productId], apiRes.payload.HashMap); + remoteProjectsLoading[productId] = false; + } else { + throw "Unable to retrieve remote projects for product " + productId; + } + }; + + WsApi.listen(apiMapping.Product.listen).then(null, null, function (res) { + service.refreshProducts(); + }); + + service.refreshProducts = function () { + if (productsLoading === false) { + productsLoading = true; + + WsApi.fetch(apiMapping.Product.all).then(function (res) { + process(res); + }); + } + }; + + service.refreshRemoteProjectsForProduct = function (productId) { + if (productsLoading === false) { + var productFound = false; + for (var key in products) { + if (products[key].id === productId) { + productFound = true; + break; + } + } + + if (productFound) { + var options = { + pathValues: { + productId: productId + } + }; + + remoteProjectsLoading[productId] = true; + + WsApi.fetch(apiMapping.RemoteProjects.byProduct, options).then(function (res) { + processRemoteProject(res, productId); + }); + } + } + }; + + service.getProducts = function () { + return products; + }; + + service.getProductsLoading = function () { + return productsLoading; + }; + + service.getRemoteProjects = function () { + return remoteProjects; + }; + + service.getRemoteProjectsLoading = function () { + return remoteProjectsLoading; + }; + + service.getRemoteProjectInfo = function (productId) { + for (var i in products) { + if (products[i].id == productId) { + return products[i].remoteProjectInfo; + } + } + }; + + service.refreshProducts(); + + service.ready = defer.promise; + +}); diff --git a/app/services/projectsStatsService.js b/app/services/productsStatsService.js similarity index 52% rename from app/services/projectsStatsService.js rename to app/services/productsStatsService.js index 93aa278..94f0b1d 100644 --- a/app/services/projectsStatsService.js +++ b/app/services/productsStatsService.js @@ -1,49 +1,49 @@ -app.service('ProjectsStatsService', function ($q, ProjectRepo, WsApi) { +app.service('ProductsStatsService', function ($q, ProductRepo, WsApi) { - var projectsStats = []; + var productsStats = []; var defer = $q.defer(); var process = function (response) { var apiRes = angular.fromJson(response.body); if (apiRes.meta.status === 'SUCCESS') { - angular.extend(projectsStats, apiRes.payload['ArrayList']); + angular.extend(productsStats, apiRes.payload['ArrayList']); defer.resolve(); - ProjectRepo.reset(); + ProductRepo.reset(); } else { console.error(apiRes.meta); throw "Unable to retrieve remote projects"; } }; - WsApi.listen(apiMapping.ProjectsStats.listen).then(null, null, function (response) { + WsApi.listen(apiMapping.ProductsStats.listen).then(null, null, function (response) { process(response); }); - this.refreshProjectsStats = function () { - WsApi.fetch(apiMapping.ProjectsStats.all).then(function (response) { + this.refreshProductsStats = function () { + WsApi.fetch(apiMapping.ProductsStats.all).then(function (response) { process(response); }); }; - this.getProjectsStats = function () { - return projectsStats; + this.getProductsStats = function () { + return productsStats; }; this.getById = function (id) { return $q(function (resolve, reject) { this.ready.then(function () { - for (var i in projectsStats) { - if (projectsStats[i].id == id) { - resolve(projectsStats[i]); + for (var i in productsStats) { + if (productsStats[i].id == id) { + resolve(productsStats[i]); } } }); }.bind(this)); }; - this.refreshProjectsStats(); + this.refreshProductsStats(); this.ready = defer.promise; -}); \ No newline at end of file +}); diff --git a/app/services/remoteProjectsService.js b/app/services/remoteProjectsService.js index 11b259c..6619ba5 100644 --- a/app/services/remoteProjectsService.js +++ b/app/services/remoteProjectsService.js @@ -1,52 +1,40 @@ -app.service('RemoteProjectsService', function ($q, ProjectRepo, WsApi) { - - var remoteProjects = {}; - - var defer = $q.defer(); - - var process = function (response) { - var apiRes = angular.fromJson(response.body); - if (apiRes.meta.status === 'SUCCESS') { - for (var key in remoteProjects) { - remoteProjects[key] = undefined; - } - angular.extend(remoteProjects, apiRes.payload.HashMap); - defer.resolve(); - ProjectRepo.reset(); - } else { - console.error(apiRes.meta); - throw "Unable to retrieve remote projects"; - } - }; - - WsApi.listen(apiMapping.RemoteProjects.listen).then(null, null, function (response) { - process(response); +app.service('RemoteProjectsService', function ($q, ProductRepo, WsApi) { + + var remoteProjectInfo = {}; + + var defer = $q.defer(); + + var process = function (response) { + var apiRes = angular.fromJson(response.body); + if (apiRes.meta.status === 'SUCCESS') { + for (var key in remoteProjectInfo) { + remoteProjectInfo[key] = undefined; + } + angular.extend(remoteProjectInfo, apiRes.payload.HashMap); + defer.resolve(); + ProductRepo.reset(); + } else { + console.error(apiRes.meta); + throw "Unable to retrieve remote project information"; + } + }; + + WsApi.listen(apiMapping.RemoteProjects.listen).then(null, null, function (response) { + process(response); + }); + + this.refreshRemoteProjectInfo = function () { + WsApi.fetch(apiMapping.RemoteProjects.all).then(function (response) { + process(response); }); + }; - this.refreshRemoteProjects = function () { - WsApi.fetch(apiMapping.RemoteProjects.all).then(function (response) { - process(response); - }); - }; - - this.getRemoteProjects = function () { - return remoteProjects; - }; - - this.getByScopeId = function (remoteProjectManagerId, scopeId) { - return $q(function (resolve, reject) { - this.ready.then(function () { - for (var i in remoteProjects[remoteProjectManagerId]) { - if (remoteProjects[remoteProjectManagerId][i].id === scopeId) { - resolve(remoteProjects[remoteProjectManagerId][i]); - } - } - }); - }.bind(this)); - }; - - this.refreshRemoteProjects(); - - this.ready = defer.promise; - -}); \ No newline at end of file + this.getRemoteProjectInfo = function () { + return remoteProjectInfo; + }; + + this.refreshRemoteProjectInfo(); + + this.ready = defer.promise; + +}); diff --git a/app/views/directives/remoteProjectManagerForm.html b/app/views/directives/remoteProjectManagerForm.html index edd17ad..93d85db 100644 --- a/app/views/directives/remoteProjectManagerForm.html +++ b/app/views/directives/remoteProjectManagerForm.html @@ -10,4 +10,4 @@ Use token auth - \ No newline at end of file + diff --git a/app/views/home.html b/app/views/home.html index 11a7f99..e8794a3 100644 --- a/app/views/home.html +++ b/app/views/home.html @@ -7,7 +7,10 @@ Active Sprints
  • - Projects + Products +
  • +
  • + Internal Requests

  • @@ -22,7 +25,7 @@ Id Name - Project + Product Number of Cards Total Points @@ -31,7 +34,7 @@ {{sprint.id}} {{sprint.name}} - {{sprint.project}} + {{sprint.product}} {{sprint.cards.length}} {{getSprintEstimateTotal(sprint)}} @@ -85,25 +88,46 @@ -
    +
    - +
    - + + - - - - - - - + + + + + + + + + +
    ProjectProduct Total Backlog Items Feature Count Defect Count Request Count Issue CountInternal Count
    {{project.name}}{{project.stats.backlogItemCount}}{{project.stats.featureCount}}{{project.stats.defectCount}}{{project.stats.requestCount}}{{project.stats.issueCount}}
    {{product.name}}{{product.stats.backlogItemCount}}{{product.stats.featureCount}}{{product.stats.defectCount}}{{product.stats.requestCount}}{{product.stats.issueCount}}{{product.stats.internalCount}}
    + +
    +
    + +
    +
    + + + + + + + + + + +
    Associated with a ProductNot Associated with a ProductTotal Internal Requests
    {{stats.assignedCount}}{{stats.unassignedCount}}{{stats.totalCount}}
    @@ -113,4 +137,4 @@
    -
    \ No newline at end of file + diff --git a/app/views/management.html b/app/views/management.html index 37495df..777ec91 100644 --- a/app/views/management.html +++ b/app/views/management.html @@ -3,9 +3,10 @@
    - Projects + Products Statuses - Remote Progect Managers + Remote Project Managers + Internal Requests Users @@ -13,4 +14,4 @@
    - \ No newline at end of file + diff --git a/app/views/management/internalRequests.html b/app/views/management/internalRequests.html new file mode 100644 index 0000000..ae48946 --- /dev/null +++ b/app/views/management/internalRequests.html @@ -0,0 +1,29 @@ +
    + + +
    + + + + + + + + + + + + + + +
    TitleDescriptionCreated OnActions
    {{internalRequest.title}}{{internalRequest.description}}{{internalRequest.createdOn | date : "medium"}} + + + +
    + + + + + +
    diff --git a/app/views/management/products.html b/app/views/management/products.html new file mode 100644 index 0000000..532d47b --- /dev/null +++ b/app/views/management/products.html @@ -0,0 +1,29 @@ +
    + + +
    + + + + + + + + + + + + + + + + +
    ProductRemote Project ManagerRemote ProjectScope IdActions
    {{product.name}}{{product.remoteProjectManager.name}}{{product.remoteProject.name}}{{product.scopeId}} + + +
    + + + + +
    diff --git a/app/views/management/projects.html b/app/views/management/projects.html deleted file mode 100644 index a543305..0000000 --- a/app/views/management/projects.html +++ /dev/null @@ -1,29 +0,0 @@ -
    - - -
    - - - - - - - - - - - - - - - - -
    ProjectRemote Project ManagerRemote ProjectScope IdActions
    {{project.name}}{{project.remoteProjectManager.name}}{{project.remoteProject.name}}{{project.scopeId}} - - -
    - - - - -
    \ No newline at end of file diff --git a/app/views/management/remoteProjectManager.html b/app/views/management/remoteProjectManager.html index a98978d..ed5c6e5 100644 --- a/app/views/management/remoteProjectManager.html +++ b/app/views/management/remoteProjectManager.html @@ -1,6 +1,6 @@
    - +
    @@ -29,4 +29,4 @@ - \ No newline at end of file + diff --git a/app/views/modals/addInternalRequestModal.html b/app/views/modals/addInternalRequestModal.html new file mode 100644 index 0000000..07dae81 --- /dev/null +++ b/app/views/modals/addInternalRequestModal.html @@ -0,0 +1,50 @@ + + + + + + + + + + + diff --git a/app/views/modals/addProductModal.html b/app/views/modals/addProductModal.html new file mode 100644 index 0000000..5b2ce41 --- /dev/null +++ b/app/views/modals/addProductModal.html @@ -0,0 +1,92 @@ + + + + + + + + + diff --git a/app/views/modals/addProjectModal.html b/app/views/modals/addProjectModal.html deleted file mode 100644 index 931a612..0000000 --- a/app/views/modals/addProjectModal.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/app/views/modals/addRemoteProjectManagerModal.html b/app/views/modals/addRemoteProjectManagerModal.html index ff8e9cc..b2efdb0 100644 --- a/app/views/modals/addRemoteProjectManagerModal.html +++ b/app/views/modals/addRemoteProjectManagerModal.html @@ -21,4 +21,4 @@ - \ No newline at end of file + diff --git a/app/views/modals/deleteInternalRequestModal.html b/app/views/modals/deleteInternalRequestModal.html new file mode 100644 index 0000000..2ea4a1e --- /dev/null +++ b/app/views/modals/deleteInternalRequestModal.html @@ -0,0 +1,17 @@ + + + + + + + + diff --git a/app/views/modals/deleteProjectModal.html b/app/views/modals/deleteProductModal.html similarity index 69% rename from app/views/modals/deleteProjectModal.html rename to app/views/modals/deleteProductModal.html index 609f0e0..450614d 100644 --- a/app/views/modals/deleteProjectModal.html +++ b/app/views/modals/deleteProductModal.html @@ -1,14 +1,14 @@ - + - \ No newline at end of file + diff --git a/app/views/modals/deleteRemoteProjectManagerModal.html b/app/views/modals/deleteRemoteProjectManagerModal.html index 12e8fc8..5f21bac 100644 --- a/app/views/modals/deleteRemoteProjectManagerModal.html +++ b/app/views/modals/deleteRemoteProjectManagerModal.html @@ -13,4 +13,4 @@

    Are you sure you want to remove:

    - \ No newline at end of file + diff --git a/app/views/modals/editInternalRequestModal.html b/app/views/modals/editInternalRequestModal.html new file mode 100644 index 0000000..3a8dedc --- /dev/null +++ b/app/views/modals/editInternalRequestModal.html @@ -0,0 +1,50 @@ + + + + + + + + + + + diff --git a/app/views/modals/editProductModal.html b/app/views/modals/editProductModal.html new file mode 100644 index 0000000..474f8af --- /dev/null +++ b/app/views/modals/editProductModal.html @@ -0,0 +1,97 @@ + + + + + + + + + diff --git a/app/views/modals/editProjectModal.html b/app/views/modals/editProjectModal.html deleted file mode 100644 index 3c28168..0000000 --- a/app/views/modals/editProjectModal.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/app/views/modals/editRemoteProjectManagerModal.html b/app/views/modals/editRemoteProjectManagerModal.html index cb4102a..2e1b114 100644 --- a/app/views/modals/editRemoteProjectManagerModal.html +++ b/app/views/modals/editRemoteProjectManagerModal.html @@ -19,6 +19,6 @@ - \ No newline at end of file + diff --git a/app/views/modals/editStatusModal.html b/app/views/modals/editStatusModal.html index f47785e..dc1f909 100644 --- a/app/views/modals/editStatusModal.html +++ b/app/views/modals/editStatusModal.html @@ -37,7 +37,7 @@ - \ No newline at end of file + diff --git a/app/views/modals/pushInternalRequestModal.html b/app/views/modals/pushInternalRequestModal.html new file mode 100644 index 0000000..b4e0c3f --- /dev/null +++ b/app/views/modals/pushInternalRequestModal.html @@ -0,0 +1,58 @@ + + + + + + + + + diff --git a/package-lock.json b/package-lock.json index 2ef7b44..ee18683 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "project-management", + "name": "product-management", "version": "0.2.0", "lockfileVersion": 1, "requires": true, diff --git a/package.json b/package.json index 10945fd..e4be77b 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { - "name": "project-management", + "name": "product-management", "private": false, "version": "0.2.0", - "description": "A UI for managing projects", - "repository": "https://github.com/TAMULib/ProjectManagementUI.git", + "description": "A UI for managing products", + "repository": "https://github.com/TAMULib/ProductManagementUI.git", "license": "MIT", "scripts": { "pretest": "npm install", @@ -15,9 +15,9 @@ "update-webdriver": "webdriver-manager update", "preprotractor": "npm run update-webdriver", "protractor": "protractor e2e-tests/protractor.conf.js", - "stop": "wvr server --stop", - "start": "wvr server -b /projects --prod --uid project-management-webserver", - "start:dev": "wvr server -b /projects --uid project-management-webserver" + "stop": "wvr server --stop --uid product-management-webserver", + "start": "wvr server -b /products --prod --uid product-management-webserver", + "start:dev": "wvr server -b /products --uid product-management-webserver" }, "dependencies": { "ng-file-upload": "12.2.13", diff --git a/tests/core/utility/coreUtility.js b/tests/core/utility/coreUtility.js index 5d85e6c..ac1798f 100644 --- a/tests/core/utility/coreUtility.js +++ b/tests/core/utility/coreUtility.js @@ -70,7 +70,7 @@ var dataPromise = function (defer, payload, messageStatus, httpStatus, action) { return defer.promise; }; -var rejectPromise = function (defer, payload, messageStatus, httpStatus) { +var rejectPromise = function (defer, payload, messageStatus, httpStatus, action) { defer.reject({ body: angular.toJson(buildPayloadPromiseBody(payload, messageStatus ? messageStatus : "INVALID", httpStatus ? httpStatus : 200, action)) }); @@ -78,7 +78,7 @@ var rejectPromise = function (defer, payload, messageStatus, httpStatus) { return defer.promise; }; -var failurePromise = function (defer, payload, messageStatus, httpStatus) { +var failurePromise = function (defer, payload, messageStatus, httpStatus, action) { defer.reject({ data: buildPayloadPromiseBody(payload, messageStatus ? messageStatus : "INVALID", httpStatus ? httpStatus : 500, action) }); diff --git a/tests/e2e/index-spec.js b/tests/e2e/index-spec.js index 42fc146..9cce2de 100644 --- a/tests/e2e/index-spec.js +++ b/tests/e2e/index-spec.js @@ -2,15 +2,15 @@ describe("index", function () { it("is navigatable", function () { browser.get(""); - }) + }); it("body is displayed", function () { expect($("body").isDisplayed()).toBeTruthy(); - }) + }); it("has tamuheader", function () { expect($("tamuheader").isDisplayed()).toBeTruthy(); - }) + }); it("has tamufooter", function () { expect($("tamufooter").isDisplayed()).toBeTruthy(); diff --git a/tests/e2e/protractor.conf.js b/tests/e2e/protractor.conf.js index 6e7eb01..30ce19f 100644 --- a/tests/e2e/protractor.conf.js +++ b/tests/e2e/protractor.conf.js @@ -1,6 +1,6 @@ exports.config = { seleniumAddress: "http://localhost:4444/wd/hub", - baseUrl: "http://localhost/projects/", + baseUrl: "http://localhost/products/", specs: [ "index-spec.js", "auth-spec.js", diff --git a/tests/e2e/users-spec.js b/tests/e2e/users-spec.js index 729a68c..472525d 100644 --- a/tests/e2e/users-spec.js +++ b/tests/e2e/users-spec.js @@ -24,11 +24,11 @@ describe("users", function () { browser.wait(EC.visibilityOf($("username")), 5000); expect($("username").getText()).toEqual("Library Test4"); - }) + }); it("synchronize", function () { browser.ignoreSynchronization = false; - }) + }); it("has access to manage users", function () { @@ -43,7 +43,7 @@ describe("users", function () { expect(cells.count()).toEqual(6); }); - }) + }); it("can change user role to manager", function () { @@ -68,7 +68,7 @@ describe("users", function () { }); }); - }) + }); it("can change user role back to user", function () { diff --git a/tests/mock/model/mockFeatureRequest.js b/tests/mock/model/mockFeatureRequest.js new file mode 100644 index 0000000..3d62eea --- /dev/null +++ b/tests/mock/model/mockFeatureRequest.js @@ -0,0 +1,34 @@ +var dataFeatureRequest1 = { + id: 1, + title: "Internal Request 1", + description: "description 1", + productId: 1, + rpmId: 1, + scopeId: "scope 1" +}; + +var dataFeatureRequest2 = { + id: 2, + title: "Internal Request 2", + description: "description 2", + productId: 1, + rpmId: 1, + scopeId: "scope 2" +}; + +var dataFeatureRequest3 = { + id: 3, + title: "Internal Request 3", + description: "description 3", + productId: 2, + rpmId: 2, + scopeId: "scope 3" +}; + +var mockFeatureRequest = function ($q) { + var model = mockModel("FeatureRequest", $q, dataFeatureRequest1); + + return model; +}; + +angular.module("mock.featureRequest", []).service("FeatureRequest", mockFeatureRequest); diff --git a/tests/mock/model/mockInternalRequest.js b/tests/mock/model/mockInternalRequest.js new file mode 100644 index 0000000..6674c32 --- /dev/null +++ b/tests/mock/model/mockInternalRequest.js @@ -0,0 +1,32 @@ +var dataInternalRequest1 = { + id: 1, + createdOn: 1588262229449, + description: "description 1", + product: null, + title: "Internal Request 1" +}; + +var dataInternalRequest2 = { + id: 2, + createdOn: 1588262283332, + description: "description 2", + product: null, + title: "Internal Request 2" +}; + +var dataInternalRequest3 = { + id: 3, + createdOn: 1588262294703, + description: "description 3", + product: null, + title: "Internal Request 3" + +}; + +var mockInternalRequest = function ($q) { + var model = mockModel("InternalRequest", $q, dataInternalRequest1); + + return model; +}; + +angular.module("mock.internalRequest", []).service("InternalRequest", mockInternalRequest); diff --git a/tests/mock/model/mockInternalStats.js b/tests/mock/model/mockInternalStats.js new file mode 100644 index 0000000..f5a4391 --- /dev/null +++ b/tests/mock/model/mockInternalStats.js @@ -0,0 +1,14 @@ +var dataInternalStats1 = { + id: 1, + internalCount: 2 +}; + +var dataInternalStats2 = { + id: 2, + internalCount: 0 +}; + +var dataInternalStats3 = { + id: 3, + internalCount: 7 +}; diff --git a/tests/mock/model/mockProduct.js b/tests/mock/model/mockProduct.js new file mode 100644 index 0000000..db35c6e --- /dev/null +++ b/tests/mock/model/mockProduct.js @@ -0,0 +1,61 @@ +var dataProduct1 = { + id: 1, + name: "Product 1", + remoteProjectInfo: [{ + remoteProjectManager: { + id: 1, + name: "Remote Project Manager 1", + settings: { + password: "password1", + url: "url1", + username: "username1" + }, + type: "VERSION_ONE" + }, + scopeId: "scope 1" + }] +}; + +var dataProduct2 = { + id: 2, + name: "Product 2", + remoteProjectInfo: [{ + remoteProjectManager: { + id: 1, + name: "Remote Project Manager 1", + settings: { + password: "password1", + url: "url1", + username: "username1" + }, + type: "VERSION_ONE" + }, + scopeId: "scope 2" + }] +}; + +var dataProduct3 = { + id: 3, + name: "Product 3", + remoteProjectInfo: [{ + remoteProjectManager: { + id: 1, + name: "Remote Project Manager 1", + settings: { + password: "password1", + url: "url1", + username: "username1" + }, + type: "VERSION_ONE" + }, + scopeId: "scope 3" + }] +}; + +var mockProduct = function ($q) { + var model = mockModel("Product", $q, dataProduct1); + + return model; +}; + +angular.module("mock.product", []).service("Product", mockProduct); diff --git a/tests/mock/model/mockProject.js b/tests/mock/model/mockProject.js deleted file mode 100644 index 244e61b..0000000 --- a/tests/mock/model/mockProject.js +++ /dev/null @@ -1,55 +0,0 @@ -var dataProject1 = { - id: 1, - name: "Project 1", - remoteProjectManager: { - id: 1, - name: "Remote Project Manager 1", - settings: { - password: "password1", - url: "url1", - username: "username1" - }, - type: "VERSION_ONE" - }, - scopeId: "scope 1" -}; - -var dataProject2 = { - id: 2, - name: "Project 2", - remoteProjectManager: { - id: 1, - name: "Remote Project Manager 1", - settings: { - password: "password1", - url: "url1", - username: "username1" - }, - type: "VERSION_ONE" - }, - scopeId: "scope 2" -}; - -var dataProject3 = { - id: 3, - name: "Project 3", - remoteProjectManager: { - id: 1, - name: "Remote Project Manager 1", - settings: { - password: "password1", - url: "url1", - username: "username1" - }, - type: "VERSION_ONE" - }, - scopeId: "scope 3" -}; - -var mockProject = function ($q) { - var model = mockModel("Project", $q, dataProject1); - - return model; -}; - -angular.module("mock.project", []).service("Project", mockProject); diff --git a/tests/mock/repo/mockInternalRequestRepo.js b/tests/mock/repo/mockInternalRequestRepo.js new file mode 100644 index 0000000..4dcea26 --- /dev/null +++ b/tests/mock/repo/mockInternalRequestRepo.js @@ -0,0 +1,30 @@ +var dataInternalRequestRepo1 = [ + dataInternalRequest1, + dataInternalRequest2, + dataInternalRequest3 +]; + +var dataInternalRequestRepo2 = [ + dataInternalRequest3, + dataInternalRequest2, + dataInternalRequest1 +]; + +var dataInternalRequestRepo3 = [ + dataInternalRequest1, + dataInternalRequest3, + dataInternalRequest2 +]; + +angular.module("mock.internalRequestRepo", []).service("InternalRequestRepo", function ($q) { + var repo = mockRepo("InternalRequestRepo", $q, mockInternalRequest, dataInternalRequestRepo1); + + repo.scaffold = { + title: '', + description: '', + product: null, + createdOn: null + }; + + return repo; +}); diff --git a/tests/mock/repo/mockProductRepo.js b/tests/mock/repo/mockProductRepo.js new file mode 100644 index 0000000..666b160 --- /dev/null +++ b/tests/mock/repo/mockProductRepo.js @@ -0,0 +1,39 @@ +var dataProductRepo1 = [ + dataProduct1, + dataProduct2, + dataProduct3 +]; + +var dataProductRepo2 = [ + dataProduct3, + dataProduct2, + dataProduct1 +]; + +var dataProductRepo3 = [ + dataProduct1, + dataProduct3, + dataProduct2 +]; + +angular.module("mock.productRepo", []).service("ProductRepo", function ($q) { + var repo = mockRepo("ProductRepo", $q, mockProduct, dataProductRepo1); + + repo.scaffold = { + name: '', + remoteProjectInfo: [] + }; + + repo.mockValidations({ + name: { + required: { + type: "required", + message: "A Product requires a name", + property: "name", + value: true + } + } + }); + + return repo; +}); diff --git a/tests/mock/repo/mockProjectRepo.js b/tests/mock/repo/mockProjectRepo.js deleted file mode 100644 index a4dd2a4..0000000 --- a/tests/mock/repo/mockProjectRepo.js +++ /dev/null @@ -1,38 +0,0 @@ -var dataProjectRepo1 = [ - dataProject1, - dataProject2, - dataProject3 -]; - -var dataProjectRepo2 = [ - dataProject3, - dataProject2, - dataProject1 -]; - -var dataProjectRepo3 = [ - dataProject1, - dataProject3, - dataProject2 -]; - -angular.module("mock.projectRepo", []).service("ProjectRepo", function ($q) { - var repo = mockRepo("ProjectRepo", $q, mockProject, dataProjectRepo1); - - repo.scaffold = { - name: '' - }; - - repo.mockValidations({ - name: { - required: { - type: "required", - message: "A Project requires a name", - property: "name", - value: true - } - } - }); - - return repo; -}); diff --git a/tests/mock/service/mockActiveSprintsService.js b/tests/mock/service/mockActiveSprintsService.js index 84d4e08..63a432b 100644 --- a/tests/mock/service/mockActiveSprintsService.js +++ b/tests/mock/service/mockActiveSprintsService.js @@ -1,7 +1,7 @@ var mockActiveSprints = [{ id: "7820", name: "Sprint 3", - project: "chronam", + product: "chronam", cards: [{ id: 7802, number: "B-03351", diff --git a/tests/mock/service/mockInternalRequestsService.js b/tests/mock/service/mockInternalRequestsService.js new file mode 100644 index 0000000..2742628 --- /dev/null +++ b/tests/mock/service/mockInternalRequestsService.js @@ -0,0 +1,11 @@ +var mockInternalRequestsService = function ($q) { + var service = mockService($q); + + service.pushFeatureRequest = function (featureRequest) { + return payloadPromise($q.defer(), featureRequest); + }; + + return service; +}; + +angular.module("mock.internalRequestsService", []).service("InternalRequestsService", mockInternalRequestsService); diff --git a/tests/mock/service/mockInternalStatsService.js b/tests/mock/service/mockInternalStatsService.js new file mode 100644 index 0000000..deef3b3 --- /dev/null +++ b/tests/mock/service/mockInternalStatsService.js @@ -0,0 +1,17 @@ +var mockInternalStatsService = function ($q) { + var service = mockService($q); + + service.refreshStats = function () { + return payloadPromise($q.defer(), dataInternalStats1); + }; + + service.getStats = function () { + return dataInternalStats1; + }; + + service.ready = $q.defer().promise; + + return service; +}; + +angular.module("mock.internalStatsService", []).service("InternalStatsService", mockInternalStatsService); diff --git a/tests/mock/service/mockProjectsStatsService.js b/tests/mock/service/mockProductStatsService.js similarity index 83% rename from tests/mock/service/mockProjectsStatsService.js rename to tests/mock/service/mockProductStatsService.js index 291f906..82df635 100644 --- a/tests/mock/service/mockProjectsStatsService.js +++ b/tests/mock/service/mockProductStatsService.js @@ -1,10 +1,11 @@ -var dataProjectsStats = [{ +var dataProductsStats = [{ id: 1, name: "Legacy DSpace", requestCount: 22, issueCount: 41, featureCount: 32, defectCount: 0, + internalCount: 0, backlogItemCount: 32 }, { id: 2, @@ -13,6 +14,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 5, defectCount: 0, + internalCount: 0, backlogItemCount: 5 }, { id: 3, @@ -21,6 +23,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 12, defectCount: 8, + internalCount: 0, backlogItemCount: 20 }, { id: 4, @@ -29,6 +32,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 42, defectCount: 0, + internalCount: 0, backlogItemCount: 42 }, { id: 5, @@ -37,6 +41,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 6, defectCount: 0, + internalCount: 0, backlogItemCount: 6 }, { id: 6, @@ -45,6 +50,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 43, defectCount: 0, + internalCount: 0, backlogItemCount: 43 }, { id: 7, @@ -53,6 +59,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 4, defectCount: 0, + internalCount: 0, backlogItemCount: 4 }, { id: 8, @@ -61,6 +68,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 10, defectCount: 0, + internalCount: 0, backlogItemCount: 10 }, { id: 9, @@ -69,6 +77,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 3, defectCount: 0, + internalCount: 0, backlogItemCount: 3 }, { id: 10, @@ -77,6 +86,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 0, defectCount: 0, + internalCount: 0, backlogItemCount: 0 }, { id: 11, @@ -85,6 +95,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 38, defectCount: 0, + internalCount: 0, backlogItemCount: 38 }, { id: 12, @@ -93,6 +104,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 10, defectCount: 0, + internalCount: 0, backlogItemCount: 10 }, { id: 13, @@ -101,6 +113,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 9, defectCount: 0, + internalCount: 0, backlogItemCount: 9 }, { id: 14, @@ -109,6 +122,7 @@ var dataProjectsStats = [{ issueCount: 1, featureCount: 5, defectCount: 0, + internalCount: 0, backlogItemCount: 5 }, { id: 15, @@ -117,6 +131,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 13, defectCount: 0, + internalCount: 0, backlogItemCount: 13 }, { id: 16, @@ -125,6 +140,7 @@ var dataProjectsStats = [{ issueCount: 4, featureCount: 25, defectCount: 6, + internalCount: 0, backlogItemCount: 31 }, { id: 17, @@ -133,6 +149,7 @@ var dataProjectsStats = [{ issueCount: 1, featureCount: 16, defectCount: 3, + internalCount: 0, backlogItemCount: 19 }, { id: 18, @@ -141,6 +158,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 18, defectCount: 0, + internalCount: 0, backlogItemCount: 18 }, { id: 19, @@ -149,6 +167,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 0, defectCount: 0, + internalCount: 0, backlogItemCount: 0 }, { id: 20, @@ -157,6 +176,7 @@ var dataProjectsStats = [{ issueCount: 9, featureCount: 24, defectCount: 1, + internalCount: 0, backlogItemCount: 25 }, { id: 21, @@ -165,6 +185,7 @@ var dataProjectsStats = [{ issueCount: 11, featureCount: 6, defectCount: 2, + internalCount: 0, backlogItemCount: 8 }, { id: 22, @@ -173,6 +194,7 @@ var dataProjectsStats = [{ issueCount: 2, featureCount: 8, defectCount: 0, + internalCount: 0, backlogItemCount: 8 }, { id: 23, @@ -181,14 +203,16 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 0, defectCount: 0, + internalCount: 0, backlogItemCount: 0 }, { id: 24, - name: "Legacy Projects", + name: "Legacy Products", requestCount: 0, issueCount: 0, featureCount: 0, defectCount: 0, + internalCount: 0, backlogItemCount: 0 }, { id: 25, @@ -197,6 +221,7 @@ var dataProjectsStats = [{ issueCount: 2, featureCount: 4, defectCount: 1, + internalCount: 0, backlogItemCount: 5 }, { id: 26, @@ -205,6 +230,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 2, defectCount: 1, + internalCount: 0, backlogItemCount: 3 }, { id: 27, @@ -213,6 +239,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 8, defectCount: 0, + internalCount: 0, backlogItemCount: 8 }, { id: 28, @@ -221,6 +248,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 8, defectCount: 0, + internalCount: 0, backlogItemCount: 8 }, { id: 29, @@ -229,6 +257,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 0, defectCount: 0, + internalCount: 0, backlogItemCount: 0 }, { id: 30, @@ -237,6 +266,7 @@ var dataProjectsStats = [{ issueCount: 1, featureCount: 24, defectCount: 0, + internalCount: 0, backlogItemCount: 24 }, { id: 31, @@ -245,6 +275,7 @@ var dataProjectsStats = [{ issueCount: 2, featureCount: 2, defectCount: 0, + internalCount: 0, backlogItemCount: 2 }, { id: 32, @@ -253,6 +284,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 9, defectCount: 0, + internalCount: 0, backlogItemCount: 9 }, { id: 33, @@ -261,6 +293,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 10, defectCount: 0, + internalCount: 0, backlogItemCount: 10 }, { id: 34, @@ -269,6 +302,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 18, defectCount: 5, + internalCount: 0, backlogItemCount: 23 }, { id: 35, @@ -277,6 +311,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 0, defectCount: 0, + internalCount: 0, backlogItemCount: 0 }, { id: 36, @@ -285,6 +320,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 0, defectCount: 0, + internalCount: 0, backlogItemCount: 0 }, { id: 37, @@ -293,6 +329,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 0, defectCount: 0, + internalCount: 0, backlogItemCount: 0 }, { id: 38, @@ -301,6 +338,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 5, defectCount: 1, + internalCount: 0, backlogItemCount: 6 }, { id: 39, @@ -309,6 +347,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 0, defectCount: 0, + internalCount: 0, backlogItemCount: 0 }, { id: 40, @@ -317,6 +356,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 3, defectCount: 0, + internalCount: 0, backlogItemCount: 3 }, { id: 41, @@ -325,6 +365,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 3, defectCount: 0, + internalCount: 0, backlogItemCount: 3 }, { id: 42, @@ -333,6 +374,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 1, defectCount: 0, + internalCount: 0, backlogItemCount: 1 }, { id: 43, @@ -341,6 +383,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 1, defectCount: 2, + internalCount: 0, backlogItemCount: 3 }, { id: 44, @@ -349,6 +392,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 4, defectCount: 0, + internalCount: 0, backlogItemCount: 4 }, { id: 45, @@ -357,6 +401,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 1, defectCount: 0, + internalCount: 0, backlogItemCount: 1 }, { id: 46, @@ -365,6 +410,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 5, defectCount: 5, + internalCount: 0, backlogItemCount: 10 }, { id: 47, @@ -373,6 +419,7 @@ var dataProjectsStats = [{ issueCount: 2, featureCount: 5, defectCount: 1, + internalCount: 0, backlogItemCount: 6 }, { id: 48, @@ -381,6 +428,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 4, defectCount: 1, + internalCount: 0, backlogItemCount: 5 }, { id: 49, @@ -389,6 +437,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 18, defectCount: 1, + internalCount: 0, backlogItemCount: 19 }, { id: 50, @@ -397,6 +446,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 34, defectCount: 4, + internalCount: 0, backlogItemCount: 38 }, { id: 51, @@ -405,6 +455,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 0, defectCount: 0, + internalCount: 0, backlogItemCount: 0 }, { id: 52, @@ -413,6 +464,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 19, defectCount: 2, + internalCount: 0, backlogItemCount: 21 }, { id: 53, @@ -421,6 +473,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 2, defectCount: 1, + internalCount: 0, backlogItemCount: 3 }, { id: 54, @@ -429,6 +482,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 10, defectCount: 2, + internalCount: 1, backlogItemCount: 12 }, { id: 55, @@ -437,6 +491,7 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 11, defectCount: 0, + internalCount: 2, backlogItemCount: 11 }, { id: 56, @@ -445,39 +500,41 @@ var dataProjectsStats = [{ issueCount: 0, featureCount: 0, defectCount: 0, + internalCount: 3, backlogItemCount: 0 }, { id: 57, - name: "Project Management Service", + name: "Product Management Service", requestCount: 0, issueCount: 0, featureCount: 17, defectCount: 1, + internalCount: 4, backlogItemCount: 18 }]; -angular.module("mock.projectsStatsService", []).service("ProjectsStatsService", function ($q) { +angular.module("mock.productsStatsService", []).service("ProductsStatsService", function ($q) { var service = mockService($q); - var projectsStats = dataProjectsStats; + var productsStats = dataProductsStats; - service.dataProjectsStats = function (toMock) { + service.dataProductsStats = function (toMock) { if (typeof toMock === "object") { - projectsStats = toMock; + productsStats = toMock; } else { - projectsStats = dataProjectsStats; + productsStats = dataProductsStats; } }; - service.getProjectsStats = function () { - return projectsStats; + service.getProductsStats = function () { + return productsStats; }; service.getById = function (id) { return $q(function (resolve, reject) { - for (var i in projectsStats) { - if (projectsStats[i].id == id) { - resolve(projectsStats[i]); + for (var i in productsStats) { + if (productsStats[i].id == id) { + resolve(productsStats[i]); } } reject(undefined); diff --git a/tests/mock/service/mockProductsService.js b/tests/mock/service/mockProductsService.js new file mode 100644 index 0000000..6d3cc2b --- /dev/null +++ b/tests/mock/service/mockProductsService.js @@ -0,0 +1,59 @@ +var mockProductsService = function ($q, $timeout) { + var service = mockService($q); + + var defer = $q.defer(); + var products = []; + var productsLoading = false; + var remoteProjects = {}; + var remoteProjectsLoading = []; + + service.mockProductsLoading = function (loading) { + productsLoading = loading ? true : false; + }; + + service.remoteProjectsLoading = function (productId, loading) { + remoteProjectsLoading[productId] = loading ? true : false; + }; + + service.refreshProducts = function () { + productsLoading = false; + return messagePromise($q.defer()); + }; + + service.refreshRemoteProjectsForProduct = function (productId) { + remoteProjectsLoading[productId] = false; + + if (dataFeatureRequest1.id == productId) { + return notifyPromise($timeout, $q.defer(), dataFeatureRequest1); + } + + return rejectPromise($q.defer()); + }; + + service.getProductsLoading = function () { + return productsLoading; + }; + + service.getRemoteProjects = function () { + return remoteProjects; + }; + + service.getRemoteProjectsLoading = function () { + return remoteProjectsLoading; + }; + + service.getRemoteProjectInfo = function (productId) { + for (var i in products) { + if (products[i].id == productId) { + return products[i].remoteProjectInfo; + } + } + }; + + service.ready = defer.promise; + defer.notify(); + + return service; +}; + +angular.module("mock.productsService", []).service("ProductsService", mockProductsService); diff --git a/tests/mock/service/mockRemoteProjectService.js b/tests/mock/service/mockRemoteProjectsService.js similarity index 85% rename from tests/mock/service/mockRemoteProjectService.js rename to tests/mock/service/mockRemoteProjectsService.js index b04e537..9654e9b 100644 --- a/tests/mock/service/mockRemoteProjectService.js +++ b/tests/mock/service/mockRemoteProjectsService.js @@ -6,6 +6,7 @@ var dataRemoteProjects = { issueCount: 41, featureCount: 32, defectCount: 0, + internalCount: 0, backlogItemCount: 32 }, { id: 3781, @@ -14,6 +15,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 5, defectCount: 0, + internalCount: 0, backlogItemCount: 5 }, { id: 3783, @@ -22,6 +24,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 12, defectCount: 8, + internalCount: 0, backlogItemCount: 20 }, { id: 3786, @@ -30,6 +33,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 42, defectCount: 0, + internalCount: 0, backlogItemCount: 42 }, { id: 3789, @@ -38,6 +42,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 6, defectCount: 0, + internalCount: 0, backlogItemCount: 6 }, { id: 3798, @@ -46,6 +51,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 43, defectCount: 0, + internalCount: 0, backlogItemCount: 43 }, { id: 3816, @@ -54,6 +60,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 4, defectCount: 0, + internalCount: 0, backlogItemCount: 4 }, { id: 3930, @@ -62,6 +69,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 10, defectCount: 0, + internalCount: 0, backlogItemCount: 10 }, { id: 3968, @@ -70,6 +78,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 3, defectCount: 0, + internalCount: 0, backlogItemCount: 3 }, { id: 4114, @@ -78,6 +87,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 0, defectCount: 0, + internalCount: 0, backlogItemCount: 0 }, { id: 4182, @@ -86,6 +96,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 38, defectCount: 0, + internalCount: 0, backlogItemCount: 38 }, { id: 4262, @@ -94,6 +105,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 10, defectCount: 0, + internalCount: 0, backlogItemCount: 10 }, { id: 4391, @@ -102,6 +114,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 9, defectCount: 0, + internalCount: 0, backlogItemCount: 9 }, { id: 4557, @@ -110,6 +123,7 @@ var dataRemoteProjects = { issueCount: 1, featureCount: 5, defectCount: 0, + internalCount: 0, backlogItemCount: 5 }, { id: 4731, @@ -118,6 +132,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 13, defectCount: 0, + internalCount: 0, backlogItemCount: 13 }, { id: 4871, @@ -126,6 +141,7 @@ var dataRemoteProjects = { issueCount: 4, featureCount: 25, defectCount: 6, + internalCount: 0, backlogItemCount: 31 }, { id: 4889, @@ -134,6 +150,7 @@ var dataRemoteProjects = { issueCount: 1, featureCount: 16, defectCount: 3, + internalCount: 0, backlogItemCount: 19 }, { id: 4912, @@ -142,6 +159,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 18, defectCount: 0, + internalCount: 0, backlogItemCount: 18 }, { id: 4965, @@ -150,6 +168,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 0, defectCount: 0, + internalCount: 0, backlogItemCount: 0 }, { id: 5070, @@ -158,6 +177,7 @@ var dataRemoteProjects = { issueCount: 9, featureCount: 24, defectCount: 1, + internalCount: 0, backlogItemCount: 25 }, { id: 5270, @@ -166,6 +186,7 @@ var dataRemoteProjects = { issueCount: 11, featureCount: 6, defectCount: 2, + internalCount: 0, backlogItemCount: 8 }, { id: 5342, @@ -174,6 +195,7 @@ var dataRemoteProjects = { issueCount: 2, featureCount: 8, defectCount: 0, + internalCount: 0, backlogItemCount: 8 }, { id: 5523, @@ -182,14 +204,16 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 0, defectCount: 0, + internalCount: 0, backlogItemCount: 0 }, { id: 5524, - name: "Legacy Projects", + name: "Legacy Products", requestCount: 0, issueCount: 0, featureCount: 0, defectCount: 0, + internalCount: 0, backlogItemCount: 0 }, { id: 5525, @@ -198,6 +222,7 @@ var dataRemoteProjects = { issueCount: 2, featureCount: 4, defectCount: 1, + internalCount: 0, backlogItemCount: 5 }, { id: 5798, @@ -206,6 +231,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 2, defectCount: 1, + internalCount: 0, backlogItemCount: 3 }, { id: 5870, @@ -214,6 +240,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 8, defectCount: 0, + internalCount: 0, backlogItemCount: 8 }, { id: 5910, @@ -222,6 +249,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 8, defectCount: 0, + internalCount: 0, backlogItemCount: 8 }, { id: 5962, @@ -230,6 +258,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 0, defectCount: 0, + internalCount: 0, backlogItemCount: 0 }, { id: 6004, @@ -238,6 +267,7 @@ var dataRemoteProjects = { issueCount: 1, featureCount: 24, defectCount: 0, + internalCount: 0, backlogItemCount: 24 }, { id: 6029, @@ -246,6 +276,7 @@ var dataRemoteProjects = { issueCount: 2, featureCount: 2, defectCount: 0, + internalCount: 0, backlogItemCount: 2 }, { id: 6126, @@ -254,6 +285,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 9, defectCount: 0, + internalCount: 0, backlogItemCount: 9 }, { id: 6157, @@ -262,6 +294,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 10, defectCount: 0, + internalCount: 0, backlogItemCount: 10 }, { id: 6368, @@ -270,6 +303,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 18, defectCount: 5, + internalCount: 0, backlogItemCount: 23 }, { id: 6369, @@ -278,6 +312,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 0, defectCount: 0, + internalCount: 0, backlogItemCount: 0 }, { id: 6373, @@ -286,6 +321,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 0, defectCount: 0, + internalCount: 0, backlogItemCount: 0 }, { id: 6486, @@ -294,6 +330,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 0, defectCount: 0, + internalCount: 0, backlogItemCount: 0 }, { id: 6487, @@ -302,6 +339,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 5, defectCount: 1, + internalCount: 0, backlogItemCount: 6 }, { id: 6620, @@ -310,6 +348,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 0, defectCount: 0, + internalCount: 0, backlogItemCount: 0 }, { id: 6625, @@ -318,6 +357,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 3, defectCount: 0, + internalCount: 0, backlogItemCount: 3 }, { id: 6626, @@ -326,6 +366,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 3, defectCount: 0, + internalCount: 0, backlogItemCount: 3 }, { id: 6627, @@ -334,6 +375,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 1, defectCount: 0, + internalCount: 0, backlogItemCount: 1 }, { id: 6629, @@ -342,6 +384,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 1, defectCount: 2, + internalCount: 0, backlogItemCount: 3 }, { id: 6664, @@ -350,6 +393,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 4, defectCount: 0, + internalCount: 0, backlogItemCount: 4 }, { id: 6828, @@ -358,6 +402,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 1, defectCount: 0, + internalCount: 0, backlogItemCount: 1 }, { id: 7001, @@ -366,6 +411,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 5, defectCount: 5, + internalCount: 0, backlogItemCount: 10 }, { id: 7036, @@ -374,6 +420,7 @@ var dataRemoteProjects = { issueCount: 2, featureCount: 5, defectCount: 1, + internalCount: 0, backlogItemCount: 6 }, { id: 7037, @@ -382,6 +429,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 4, defectCount: 1, + internalCount: 0, backlogItemCount: 5 }, { id: 7400, @@ -390,6 +438,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 18, defectCount: 1, + internalCount: 0, backlogItemCount: 19 }, { id: 7509, @@ -398,6 +447,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 34, defectCount: 4, + internalCount: 0, backlogItemCount: 38 }, { id: 7516, @@ -406,6 +456,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 0, defectCount: 0, + internalCount: 0, backlogItemCount: 0 }, { id: 7517, @@ -414,6 +465,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 19, defectCount: 2, + internalCount: 0, backlogItemCount: 21 }, { id: 7529, @@ -422,6 +474,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 2, defectCount: 1, + internalCount: 1, backlogItemCount: 3 }, { id: 7797, @@ -430,6 +483,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 10, defectCount: 2, + internalCount: 2, backlogItemCount: 12 }, { id: 7869, @@ -438,6 +492,7 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 11, defectCount: 0, + internalCount: 3, backlogItemCount: 11 }, { id: 7934, @@ -446,34 +501,29 @@ var dataRemoteProjects = { issueCount: 0, featureCount: 0, defectCount: 0, + internalCount: 4, backlogItemCount: 0 }, { id: 7948, - name: "Project Management Service", + name: "Product Management Service", requestCount: 0, issueCount: 0, featureCount: 17, defectCount: 1, + internalCount: 0, backlogItemCount: 18 }] }; -angular.module("mock.remoteProjectService", []).service("RemoteProjectsService", function ($q) { +angular.module("mock.remoteProjectsService", []).service("RemoteProjectsService", function ($q) { var service = mockService($q); - service.getRemoteProjects = function () { + service.getRemoteProjectInfo = function () { return dataRemoteProjects; }; - service.getByScopeId = function (remoteProjectManagerId, scopeId) { - return $q(function (resolve, reject) { - for (var i in dataRemoteProjects[remoteProjectManagerId]) { - if (dataRemoteProjects[remoteProjectManagerId][i].id === scopeId) { - resolve(dataRemoteProjects[remoteProjectManagerId][i]); - } - } - reject(undefined); - }); + service.refreshRemoteProjectInfo = function () { + return messagePromise($q.defer()); }; service.ready = $q.defer().promise; diff --git a/tests/mock/service/mockWsApi.js b/tests/mock/service/mockWsApi.js index 6c2ebe8..9f51668 100644 --- a/tests/mock/service/mockWsApi.js +++ b/tests/mock/service/mockWsApi.js @@ -1,6 +1,6 @@ angular.module("mock.wsApi", []).service("WsApi", function ($q) { var service = mockService($q); - var mapping; + var mapping = apiMapping; var fetchResponse; service.mockFetchResponse = function (data) { @@ -25,9 +25,13 @@ angular.module("mock.wsApi", []).service("WsApi", function ($q) { } }; - service.fetch = function (apiReq, parameters) { + service.fetch = function (apiReq, options) { var payload = {}; + if (angular.isUndefined(apiReq)) { + return rejectPromise($q.defer()); + } + if (fetchResponse) { switch (fetchResponse.type) { case "message": @@ -44,22 +48,59 @@ angular.module("mock.wsApi", []).service("WsApi", function ($q) { return failurePromise($q.defer(), fetchResponse.payload, fetchResponse.messageStatus, fetchResponse.httpStatus); } } else { - if (apiReq === apiMapping.ActiveSprints.all) { + if (apiReq === mapping.ActiveSprints.all) { payload = { "ArrayList": mockActiveSprints }; - } - - if (apiReq === apiMapping.ProjectsStats.all) { + } else if (apiReq === mapping.ProductsStats.all) { payload = { - "ArrayList": dataProjectsStats + "ArrayList": dataProductsStats }; - } - - if (apiReq === apiMapping.RemoteProjects.all) { + } else if (apiReq === mapping.RemoteProjects.byProduct) { + payload = { + "HashMap": dataRemoteProjects + }; + } else if (apiReq === mapping.RemoteProjects.all) { payload = { "HashMap": dataRemoteProjects }; + } else if (apiReq === mapping.Product.all) { + payload = { + "ArrayList": dataProductRepo1 + }; + } + + if (apiReq.controller === mapping.FeatureRequest.push.controller) { + if (apiReq.method === 'push/:requestId/:productId/:rpmId') { + var requestId = Number(options.pathValues.requestId); + var productId = Number(options.pathValues.productId); + var rpmId = Number(options.pathValues.rpmId); + var scopeId = typeof options.data === "string" ? options.data : ""; + + if (requestId > 0 && productId > 0 && rpmId > 0 && scopeId !== "") { + for (var key in dataInternalRequestRepo1) { + if (dataInternalRequestRepo1[key].id == requestId) { + payload = { + "FeatureRequest": { + id: requestId, + projectId: productId, + rpmId: rpmId, + scopeId: options.data + } + }; + + return payloadPromise($q.defer(), payload); + } + } + } + + return rejectPromise($q.defer()); + } + else if (apiReq.method === 'stats') { + payload = { + "InternalStats": dataInternalStats1 + }; + } } } diff --git a/tests/unit/controllers/internalRequestControllerTest.js b/tests/unit/controllers/internalRequestControllerTest.js new file mode 100644 index 0000000..b96d629 --- /dev/null +++ b/tests/unit/controllers/internalRequestControllerTest.js @@ -0,0 +1,407 @@ +describe("controller: InternalRequestController", function () { + var $q, $scope, $templateCache, MockedInternalRequest, InternalRequestRepo, InternalRequestsService, ProductRepo, ProductsService, WsApi, controller; + + var initializeVariables = function () { + inject(function (_$compile_, _$q_, _$templateCache_, _InternalRequestRepo_, _InternalRequestsService_, _ProductRepo_, _ProductsService_, _RemoteProjectManagerRepo_, _WsApi_) { + $compile = _$compile_; + $q = _$q_; + $templateCache = _$templateCache_; + + MockedInternalRequest = new mockInternalRequest($q); + + InternalRequestRepo = _InternalRequestRepo_; + InternalRequestsService = _InternalRequestsService_; + ProductRepo = _ProductRepo_; + ProductsService = _ProductsService_; + + WsApi = _WsApi_; + }); + }; + + var initializeController = function (settings) { + inject(function (_$controller_, _$rootScope_, _ModalService_, _UserService_) { + $scope = _$rootScope_.$new(); + + sessionStorage.role = settings && settings.role ? settings.role : "ROLE_ADMIN"; + sessionStorage.token = settings && settings.token ? settings.token : "faketoken"; + + controller = _$controller_("InternalRequestController", { + $scope: $scope, + InternalRequestRepo: InternalRequestRepo, + InternalRequestsService: InternalRequestsService, + ModalService: _ModalService_, + ProductRepo: ProductRepo, + ProductsService: ProductsService, + UserService: _UserService_ + }); + + // ensure that the isReady() is called. + if (!$scope.$$phase) { + $scope.$digest(); + } + }); + }; + + beforeEach(function () { + module("core"); + module("app"); + module("templates"); + module("mock.internalRequest", function ($provide) { + var InternalRequest = function () { + return MockedInternalRequest; + }; + $provide.value("InternalRequest", InternalRequest); + }); + module("mock.internalRequestRepo"); + module("mock.internalRequestsService"); + module("mock.remoteProjectManagerRepo"); + module("mock.product"); + module("mock.productsService"); + module("mock.user", function ($provide) { + var User = function () { + return MockedUser; + }; + $provide.value("User", User); + }); + module("mock.userService"); + module("mock.wsApi"); + + installPromiseMatchers(); + initializeVariables(); + initializeController(); + }); + + describe("Is the controller", function () { + var roles = [ "ROLE_ADMIN", "ROLE_MANAGER", "ROLE_USER", "ROLE_ANONYMOUS" ]; + + var controllerExists = function (setting) { + return function() { + initializeController(setting); + expect(controller).toBeDefined(); + }; + }; + + for (var i in roles) { + it("defined for " + roles[i], controllerExists({ role: roles[i] })); + } + }); + + describe("Is the scope method", function () { + var methods = [ + "cancelDeleteInternalRequest", + "cancelEditInternalRequest", + "cancelPushFeatureRequest", + "confirmDeleteInternalRequest", + "createInternalRequest", + "deleteInternalRequest", + "editInternalRequest", + "pushFeatureRequest", + "pushInternalRequest", + "refreshRemoteProjectsForProduct", + "resetCreateInternalRequest", + "resetInternalRequestForms", + "selectRemoteProjects", + "updateInternalRequest" + ]; + + var scopeMethodExists = function (method) { + return function() { + expect($scope[method]).toBeDefined(); + expect(typeof $scope[method]).toEqual("function"); + }; + }; + + for (var i in methods) { + it(methods[i] + " defined", scopeMethodExists(methods[i])); + } + }); + + describe("Does the scope method", function () { + it("cancelDeleteInternalRequest clear internalRequestToDelete and close the modal", function () { + var internalRequest = new mockInternalRequest($q); + + $scope.internalRequestToDelete = internalRequest; + + spyOn($scope, "closeModal"); + + $scope.cancelDeleteInternalRequest(); + + expect($scope.closeModal).toHaveBeenCalled(); + expect($scope.internalRequestToDelete).toEqual({}); + }); + + it("cancelEditInternalRequest clear out internalRequestToEdit, close the modal, and call resetInternalRequestForms", function () { + var internalRequest = new mockInternalRequest($q); + + $scope.internalRequestToEdit = internalRequest; + + spyOn($scope.internalRequestToEdit, "refresh"); + spyOn($scope, "resetInternalRequestForms"); + + $scope.cancelEditInternalRequest(); + + expect($scope.internalRequestToEdit.refresh).toHaveBeenCalled(); + expect($scope.resetInternalRequestForms).toHaveBeenCalled(); + }); + + it("cancelPushFeatureRequest clear out featureRequestToPush, close the modal, and call resetInternalRequestForms", function () { + var internalRequest = new mockInternalRequest($q); + + $scope.featureRequestToPush = dataFeatureRequest1; + + spyOn($scope, "resetInternalRequestForms"); + + $scope.cancelPushFeatureRequest(); + + expect($scope.featureRequestToPush).toEqual({}); + expect($scope.resetInternalRequestForms).toHaveBeenCalled(); + }); + + it("confirmDeleteInternalRequest set the internalRequestToDelete and open the modal", function () { + var internalRequest = new mockInternalRequest($q); + + spyOn($scope, "openModal"); + + $scope.confirmDeleteInternalRequest(internalRequest); + + expect($scope.openModal).toHaveBeenCalledWith("#deleteInternalRequestModal"); + expect($scope.internalRequestToDelete).toEqual(internalRequest); + }); + + it("addInternalRequest to open the modal", function () { + var internalRequest = new mockInternalRequest($q); + + spyOn($scope, "openModal"); + + $scope.addInternalRequest(); + expect($scope.openModal).toHaveBeenCalledWith("#addInternalRequestModal"); + }); + + it("createInternalRequest create a new Internal Requst", function () { + var internalRequest = new mockInternalRequest($q); + var id = dataInternalRequestRepo1.length + 1; + + internalRequest.mock({ + id: id, + name: "Mock Internal Request " + id + }); + + spyOn($scope, "resetCreateInternalRequest"); + + $scope.internalRequestToCreate = internalRequest; + $scope.createInternalRequest(); + $scope.$digest(); + + expect(InternalRequestRepo.findById(id)).toEqual(internalRequest); + expect($scope.resetCreateInternalRequest).toHaveBeenCalled(); + }); + + it("deleteInternalRequest call the repo delete method and then call cancelDeleteInternalRequest when successful", function () { + var internalRequest = new mockInternalRequest($q); + + $scope.internalRequestToDelete = internalRequest; + + spyOn(InternalRequestRepo, "delete").and.callThrough(); + spyOn($scope, "cancelDeleteInternalRequest"); + + $scope.deleteInternalRequest(internalRequest); + $scope.$digest(); + + expect(InternalRequestRepo.delete).toHaveBeenCalledWith(internalRequest); + expect($scope.cancelDeleteInternalRequest).toHaveBeenCalled(); + }); + + it("editInternalRequest set the internalRequestToEdit and open the modal", function () { + var internalRequest = new mockInternalRequest($q); + + spyOn($scope, "openModal"); + + $scope.editInternalRequest(internalRequest); + + expect($scope.internalRequestToEdit).toEqual(internalRequest); + expect($scope.openModal).toHaveBeenCalledWith("#editInternalRequestModal"); + }); + + it("pushFeatureRequest push a FeatureRequest", function () { + var featureRequest = new mockFeatureRequest($q); + + $scope.featureRequestToPush = featureRequest; + $scope.featureRequestToPush.product = new mockProduct($q); + $scope.products = [ + new mockProduct($q), + new mockProduct($q) + ]; + + $scope.products[0].mock(dataProduct2); + + spyOn(InternalRequestsService, "pushFeatureRequest").and.callThrough(); + spyOn($scope, "cancelPushFeatureRequest"); + + $scope.pushFeatureRequest(); + + $scope.$digest(); + + expect(InternalRequestsService.pushFeatureRequest).toHaveBeenCalledWith(featureRequest); + expect($scope.cancelPushFeatureRequest).toHaveBeenCalled(); + }); + + it("pushInternalRequest push an InternalRequest as a FeatureRequest", function () { + var internalRequest = new mockInternalRequest($q); + + spyOn($scope, "openModal"); + + $scope.pushInternalRequest(internalRequest); + + expect($scope.featureRequestToPush.title).toEqual(internalRequest.title); + expect($scope.featureRequestToPush.description).toEqual(internalRequest.description); + expect($scope.featureRequestToPush.product).toBe(null); + expect($scope.featureRequestToPush.rpmId).toBe(null); + expect($scope.featureRequestToPush.scopeId).toBe(null); + expect($scope.openModal).toHaveBeenCalledWith("#pushInternalRequestModal"); + }); + + it("refreshRemoteProjectsForProduct should call the service refresh for a given product id", function () { + var featureRequest = new mockFeatureRequest($q); + featureRequest.product = new mockProduct($q); + + $scope.remoteProjects = {}; + $scope.remoteProjects[featureRequest.product.id] = {}; + $scope.remoteProjectsLoading = {}; + $scope.remoteProjectsLoading[featureRequest.product.id] = false; + + spyOn(ProductsService, "refreshRemoteProjectsForProduct"); + + $scope.refreshRemoteProjectsForProduct(featureRequest.product.id); + expect(ProductsService.refreshRemoteProjectsForProduct).toHaveBeenCalledWith(featureRequest.product.id); + }); + + it("refreshRemoteProjectsForProduct should not call the service refresh for a given product id when remoteProjectsLoading for that product id", function () { + var featureRequest = new mockFeatureRequest($q); + featureRequest.product = new mockProduct($q); + + $scope.remoteProjects = {}; + $scope.remoteProjects[featureRequest.product.id] = {}; + $scope.remoteProjectsLoading = {}; + $scope.remoteProjectsLoading[featureRequest.product.id] = true; + + spyOn(ProductsService, "refreshRemoteProjectsForProduct"); + + $scope.refreshRemoteProjectsForProduct(featureRequest.product.id); + expect(ProductsService.refreshRemoteProjectsForProduct).not.toHaveBeenCalled(); + }); + + it("refreshRemoteProjectsForProduct should not call the service refresh when there is no given product id", function () { + var featureRequest = new mockFeatureRequest($q); + featureRequest.product = new mockProduct($q); + + $scope.remoteProjects = {}; + $scope.remoteProjects[featureRequest.product.id] = {}; + $scope.remoteProjectsLoading = {}; + $scope.remoteProjectsLoading[featureRequest.product.id] = false; + + spyOn(ProductsService, "refreshRemoteProjectsForProduct"); + + $scope.refreshRemoteProjectsForProduct(); + expect(ProductsService.refreshRemoteProjectsForProduct).not.toHaveBeenCalled(); + }); + + it("resetCreateInternalRequest call resetInternalRequestForms() and clear out the properties", function () { + var internalRequest = new mockInternalRequest($q); + var id = dataInternalRequestRepo1.length + 1; + + internalRequest.mock({ + id: id, + name: "Mock Internal Request " + id + }); + + $scope.internalRequestToCreate = internalRequest; + + var modal = angular.element($templateCache.get("views/modals/addInternalRequestModal.html")); + modal = $compile(modal)($scope); + + var form = $scope.internalRequestForms.create; + form.$setDirty(); + + expect(form.$dirty).toEqual(true); + + spyOn($scope, "resetInternalRequestForms"); + + $scope.resetCreateInternalRequest(); + + expect($scope.internalRequestToCreate.title).toEqual(""); + expect($scope.internalRequestToCreate.description).toEqual(""); + expect($scope.internalRequestToCreate.createdOn).toBe(null); + expect($scope.resetInternalRequestForms).toHaveBeenCalled(); + }); + + it("resetInternalRequestForms should close modals and reset InternalRequest forms", function () { + var modal = angular.element($templateCache.get("views/modals/editInternalRequestModal.html")); + modal = $compile(modal)($scope); + + var form = $scope.internalRequestForms.edit; + form.$setDirty(); + + expect(form.$dirty).toEqual(true); + + spyOn($scope, "closeModal"); + + $scope.resetInternalRequestForms(); + + expect(form.$pristine).toEqual(true); + expect(form.$dirty).toEqual(false); + expect($scope.closeModal).toHaveBeenCalled(); + }); + + it("selectRemoteProjects select should call refresh for a given product id", function () { + $scope.featureRequestToPush = new mockFeatureRequest($q); + $scope.featureRequestToPush.product = new mockProduct($q); + $scope.remoteProjects = {}; + + spyOn($scope, "refreshRemoteProjectsForProduct"); + + $scope.selectRemoteProjects(); + expect($scope.refreshRemoteProjectsForProduct).toHaveBeenCalled(); + }); + + it("selectRemoteProjects select should not call refresh for a given product id if already loaded", function () { + $scope.featureRequestToPush = new mockFeatureRequest($q); + $scope.featureRequestToPush.product = new mockProduct($q); + $scope.remoteProjects = {}; + $scope.remoteProjects[$scope.featureRequestToPush.product.id] = $scope.featureRequestToPush.product; + + spyOn($scope, "refreshRemoteProjectsForProduct"); + + $scope.selectRemoteProjects(); + expect($scope.refreshRemoteProjectsForProduct).not.toHaveBeenCalled(); + }); + + it("selectRemoteProjects should not call refresh if no product id is available", function () { + $scope.featureRequestToPush = {}; + $scope.remoteProjects = {}; + + spyOn($scope, "refreshRemoteProjectsForProduct"); + + $scope.selectRemoteProjects(); + expect($scope.refreshRemoteProjectsForProduct).not.toHaveBeenCalled(); + }); + + it("updateInternalRequest call dirty and save on the InternalRequest, and then call cancelEditInternalRequest", function () { + var internalRequest = new mockInternalRequest($q); + + $scope.internalRequestToEdit = internalRequest; + + spyOn($scope, "cancelEditInternalRequest"); + spyOn(internalRequest, "dirty").and.callThrough(); + spyOn(internalRequest, "save").and.callThrough(); + + $scope.updateInternalRequest(); + + $scope.$digest(); + + expect($scope.cancelEditInternalRequest).toHaveBeenCalled(); + expect(internalRequest.dirty).toHaveBeenCalledWith(true); + expect(internalRequest.save).toHaveBeenCalled(); + }); + }); + +}); diff --git a/tests/unit/controllers/internalStatsControllerTest.js b/tests/unit/controllers/internalStatsControllerTest.js new file mode 100644 index 0000000..c796835 --- /dev/null +++ b/tests/unit/controllers/internalStatsControllerTest.js @@ -0,0 +1,71 @@ +describe("controller: InternalStatsController", function () { + var $q, $scope, InternalRequestRepo, InternalStatsService, WsApi, controller; + + var initializeVariables = function () { + inject(function (_$compile_, _$q_, _InternalRequestRepo_, _InternalStatsService_, _WsApi_) { + $q = _$q_; + + InternalStatsService = _InternalStatsService_; + InternalRequestRepo = _InternalRequestRepo_; + + WsApi = _WsApi_; + }); + }; + + var initializeController = function (settings) { + inject(function (_$controller_, _$rootScope_, _UserService_) { + $scope = _$rootScope_.$new(); + + sessionStorage.role = settings && settings.role ? settings.role : "ROLE_ADMIN"; + sessionStorage.token = settings && settings.token ? settings.token : "faketoken"; + + controller = _$controller_("InternalStatsController", { + $scope: $scope, + InternalRequestRepo: InternalRequestRepo, + InternalStatsService: InternalStatsService, + UserService: _UserService_ + }); + + // ensure that the isReady() is called. + if (!$scope.$$phase) { + $scope.$digest(); + } + }); + }; + + beforeEach(function () { + module("core"); + module("app"); + module("templates"); + module("mock.internalRequestRepo"); + module("mock.internalStatsService"); + module("mock.user", function ($provide) { + var User = function () { + return MockedUser; + }; + $provide.value("User", User); + }); + module("mock.userService"); + module("mock.wsApi"); + + installPromiseMatchers(); + initializeVariables(); + initializeController(); + }); + + describe("Is the controller", function () { + var roles = [ "ROLE_ADMIN", "ROLE_MANAGER", "ROLE_USER", "ROLE_ANONYMOUS" ]; + + var controllerExists = function (setting) { + return function() { + initializeController(setting); + expect(controller).toBeDefined(); + }; + }; + + for (var i in roles) { + it("defined for " + roles[i], controllerExists({ role: roles[i] })); + } + }); + +}); diff --git a/tests/unit/controllers/productControllerTest.js b/tests/unit/controllers/productControllerTest.js new file mode 100644 index 0000000..23830d6 --- /dev/null +++ b/tests/unit/controllers/productControllerTest.js @@ -0,0 +1,320 @@ +describe("controller: ProductController", function () { + var $compile, $q, $scope, $templateCache, $templateRequest, MockedProduct, MockedRemoteProjectManager, MockedUser, WsApi, controller; + + var initializeVariables = function () { + inject(function (_$compile_, _$q_, _$templateCache_, _$templateRequest_, _ProductRepo_, _WsApi_) { + $compile = _$compile_; + $q = _$q_; + $templateCache = _$templateCache_; + $templateRequest = _$templateRequest_; + + MockedUser = new mockUser($q); + MockedProduct = new mockProduct($q); + MockedRemoteProjectManager = new mockRemoteProjectManager($q); + + ProductRepo = _ProductRepo_; + WsApi = _WsApi_; + }); + }; + + var initializeController = function (settings) { + inject(function (_$controller_, _$rootScope_, _ModalService_, _Product_, _RemoteProjectManagerRepo_, _RemoteProjectsService_, _UserService_) { + $scope = _$rootScope_.$new(); + + sessionStorage.role = settings && settings.role ? settings.role : "ROLE_ADMIN"; + sessionStorage.token = settings && settings.token ? settings.token : "faketoken"; + + controller = _$controller_("ProductController", { + $scope: $scope, + $compile: $compile, + $templateRequest: $templateRequest, + ModalService: _ModalService_, + Product: _Product_, + ProductRepo: ProductRepo, + RemoteProjectManagerRepo: _RemoteProjectManagerRepo_, + RemoteProjectsService: _RemoteProjectsService_, + UserService: _UserService_ + }); + + // ensure that the isReady() is called. + if (!$scope.$$phase) { + $scope.$digest(); + } + }); + }; + + beforeEach(function () { + module("core"); + module("app"); + module("templates"); + module("mock.product", function ($provide) { + var Product = function () { + return MockedProduct; + }; + $provide.value("Product", Product); + }); + module("mock.productRepo"); + module("mock.remoteProjectManager", function ($provide) { + var RemoteProjectManager = function () { + return MockedRemoteProjectManager; + }; + $provide.value("RemoteProjectManager", RemoteProjectManager); + }); + module("mock.remoteProjectManagerRepo"); + module("mock.remoteProjectsService"); + module("mock.user", function ($provide) { + var User = function () { + return MockedUser; + }; + $provide.value("User", User); + }); + module("mock.userService"); + module("mock.wsApi"); + + installPromiseMatchers(); + initializeVariables(); + initializeController(); + }); + + describe("Is the controller", function () { + var roles = [ "ROLE_ADMIN", "ROLE_MANAGER", "ROLE_USER", "ROLE_ANONYMOUS" ]; + + var controllerExists = function (setting) { + return function() { + initializeController(setting); + expect(controller).toBeDefined(); + }; + }; + + for (var i in roles) { + it("defined for " + roles[i], controllerExists({ role: roles[i] })); + } + }); + + describe("Is the scope method", function () { + var methods = [ + "addRemoteProjectInfo", + "cancelDeleteProduct", + "cancelEditProduct", + "confirmDeleteProduct", + "createProduct", + "deleteProduct", + "editProduct", + "getRemoteProjectByRemoteProjectInfo", + "getRemoteProjectManagerRemoteProjects", + "openAddRemoteProjectInfo", + "removeRemoteProjectInfo", + "resetCreateProduct", + "resetProductForms", + "updateProduct" + ]; + + var scopeMethodExists = function (method) { + return function() { + expect($scope[method]).toBeDefined(); + expect(typeof $scope[method]).toEqual("function"); + }; + }; + + for (var i in methods) { + it(methods[i] + " defined", scopeMethodExists(methods[i])); + } + }); + + describe("Does the scope method", function () { + it("addRemoteProjectInfo should push changes and close info", function () { + var remoteProjectInfo = [ + dataRemoteProjects[1], + dataRemoteProjects[2], + dataRemoteProjects[3], + ]; + var remoteProject = dataRemoteProjects[1]; + + $scope.remoteProjectInfoChanged = null; + + spyOn(remoteProjectInfo, "push"); + spyOn($scope, "remoteProjectInfoChanged"); + + $scope.addRemoteProjectInfo(remoteProjectInfo, remoteProject); + + expect($scope.remoteProjectInfoChanged).toEqual(true); + expect(remoteProjectInfo.push).toHaveBeenCalled(); + }); + + it("cancelEditProduct clear out productToEdit and call resetProductForms", function () { + var product = new mockProduct($q); + + spyOn($scope, "resetProductForms"); + $scope.productToEdit = product; + $scope.cancelEditProduct(); + + expect($scope.productToEdit).toEqual({}); + expect($scope.resetProductForms).toHaveBeenCalled(); + }); + + it("cancelDeleteProduct clear productToDelete and close the modal", function () { + spyOn($scope, "closeModal"); + $scope.productToDelete = dataProductRepo1[0]; + $scope.cancelDeleteProduct(); + + expect($scope.closeModal).toHaveBeenCalled(); + expect($scope.productToDelete).toEqual({}); + }); + + it("createProduct create a new product", function () { + var newProduct = new mockProduct($q); + + newProduct.mock({ + id: dataProductRepo1.length + 1, + name: "Mock Product 4" + }); + + spyOn($scope, "resetCreateProduct"); + + $scope.productToCreate = newProduct; + $scope.createProduct(); + $scope.$digest(); + + expect(ProductRepo.findById(newProduct.id)).toEqual(newProduct); + expect($scope.resetCreateProduct).toHaveBeenCalled(); + }); + + it("confirmDeleteProduct set the productToDelete and open the modal", function () { + spyOn($scope, "openModal"); + $scope.confirmDeleteProduct(dataProductRepo1[0]); + + expect($scope.openModal).toHaveBeenCalled(); + expect($scope.productToDelete).toEqual(dataProductRepo1[0]); + }); + + it("deleteProduct call the repo delete method and then call cancelDeleteProduct when successful", function () { + var product = new mockProduct($q); + + $scope.productToDelete = product; + deferred = $q.defer(); + spyOn(ProductRepo, "delete").and.returnValue(deferred.promise); + spyOn($scope, "cancelDeleteProduct"); + $scope.deleteProduct(product); + deferred.resolve({ + body: angular.toJson({ + meta: { + status: "SUCCESS" + } + }) + }); + $scope.$apply(); + + expect(ProductRepo.delete).toHaveBeenCalledWith(product); + expect($scope.cancelDeleteProduct).toHaveBeenCalled(); + }); + + it("editProduct set the productToEdit and open the modal", function () { + spyOn($scope, "openModal"); + + $scope.editProduct(dataProductRepo1[0]); + + expect($scope.productToEdit).toEqual(dataProductRepo1[0]); + expect($scope.openModal).toHaveBeenCalled(); + }); + + it("getRemoteProjectManagerRemoteProjects should return the remote project by id", function () { + var response; + + response = $scope.getRemoteProjectManagerRemoteProjects(2); + + expect(response).toEqual(dataRemoteProjects[2]); + }); + + it("getRemoteProjectByRemoteProjectInfo should return the remote project by scope id", function () { + var response; + var remoteProjectInfo = { + scopeId: "3783", + remoteProjectManager: new mockRemoteProjectManager($q) + }; + + response = $scope.getRemoteProjectByRemoteProjectInfo(remoteProjectInfo); + + expect(response).toEqual(dataRemoteProjects[3]); + }); + + it("openAddRemoteProjectInfo should assign addingRemoteProjectInfo to true", function () { + $scope.addingRemoteProjectInfo = null; + + $scope.openAddRemoteProjectInfo(); + + expect($scope.addingRemoteProjectInfo).toEqual(true); + }); + + it("resetCreateProduct call resetProductForms() and clear out the name field", function () { + spyOn($scope, "resetProductForms"); + + $scope.productToCreate = new mockProduct($q); + $scope.productToCreate.mock({ + id: dataProductRepo1.length + 1, + name: "Mock Product 4" + }); + + var modal = angular.element($templateCache.get("views/modals/addProductModal.html")); + modal = $compile(modal)($scope); + + var form = $scope.productForms.create; + form.$setDirty(); + $scope.resetCreateProduct(); + + expect($scope.productToCreate.name).toEqual(""); + expect($scope.resetProductForms).toHaveBeenCalled(); + }); + + it("resetProductForms reset product forms", function () { + var modal = angular.element($templateCache.get("views/modals/addProductModal.html")); + modal = $compile(modal)($scope); + + var form = $scope.productForms.create; + form.$setDirty(); + + expect(form.$dirty).toEqual(true); + + $scope.resetProductForms(); + + expect(form.$pristine).toEqual(true); + expect(form.$dirty).toEqual(false); + }); + + it("removeRemoteProjectInfo should remove remote project info", function () { + var remoteProjectInfo = [ + dataRemoteProjects[1], + dataRemoteProjects[2], + dataRemoteProjects[3], + ]; + var remoteProject = dataRemoteProjects[1]; + + $scope.remoteProjectInfoChanged = null; + + spyOn(remoteProjectInfo, "splice"); + + $scope.removeRemoteProjectInfo(remoteProjectInfo, remoteProject); + + expect($scope.remoteProjectInfoChanged).toEqual(true); + expect(remoteProjectInfo.splice).toHaveBeenCalled(); + }); + + it("updateProduct call dirty and save on the Product, and then call cancelEditProduct", function () { + var product = new mockProduct($q); + + spyOn($scope, "cancelEditProduct"); + spyOn(product, "dirty"); + deferred = $q.defer(); + spyOn(product, "save").and.returnValue(deferred.promise); + $scope.productToEdit = product; + $scope.updateProduct(); + deferred.resolve(); + $scope.$apply(); + + expect($scope.cancelEditProduct).toHaveBeenCalled(); + expect(product.dirty).toHaveBeenCalledWith(true); + expect(product.save).toHaveBeenCalled(); + }); + + }); + +}); diff --git a/tests/unit/controllers/projectControllerTest.js b/tests/unit/controllers/projectControllerTest.js deleted file mode 100644 index 92d53c7..0000000 --- a/tests/unit/controllers/projectControllerTest.js +++ /dev/null @@ -1,245 +0,0 @@ -describe("controller: ProjectController", function () { - var $compile, $q, $scope, $templateCache, $templateRequest, MockedProject, MockedRemoteProjectManager, MockedUser, WsApi, controller; - - var initializeVariables = function () { - inject(function (_$compile_, _$q_, _$templateCache_, _$templateRequest_, _ProjectRepo_, _WsApi_) { - $compile = _$compile_; - $q = _$q_; - $templateCache = _$templateCache_; - $templateRequest = _$templateRequest_; - - MockedUser = new mockUser($q); - MockedProject = new mockProject($q); - MockedRemoteProjectManager = new mockRemoteProjectManager($q); - - ProjectRepo = _ProjectRepo_; - WsApi = _WsApi_; - }); - }; - - var initializeController = function (settings) { - inject(function (_$controller_, _$rootScope_, _ModalService_, _Project_, _RemoteProjectManagerRepo_, _RemoteProjectsService_, _UserService_) { - $scope = _$rootScope_.$new(); - - sessionStorage.role = settings && settings.role ? settings.role : "ROLE_ADMIN"; - sessionStorage.token = settings && settings.token ? settings.token : "faketoken"; - - controller = _$controller_("ProjectController", { - $scope: $scope, - $compile: $compile, - $templateRequest: $templateRequest, - ModalService: _ModalService_, - Project: _Project_, - ProjectRepo: ProjectRepo, - RemoteProjectManagerRepo: _RemoteProjectManagerRepo_, - RemoteProjectsService: _RemoteProjectsService_, - UserService: _UserService_ - }); - - // ensure that the isReady() is called. - if (!$scope.$$phase) { - $scope.$digest(); - } - }); - }; - - beforeEach(function () { - module("core"); - module("app"); - module("templates"); - module("mock.project", function ($provide) { - var Project = function () { - return MockedProject; - }; - $provide.value("Project", Project); - }); - module("mock.projectRepo"); - module("mock.remoteProjectManager", function ($provide) { - var RemoteProjectManager = function () { - return MockedRemoteProjectManager; - }; - $provide.value("RemoteProjectManager", RemoteProjectManager); - }); - module("mock.remoteProjectManagerRepo"); - module("mock.remoteProjectService"); - module("mock.user", function ($provide) { - var User = function () { - return MockedUser; - }; - $provide.value("User", User); - }); - module("mock.userService"); - module("mock.wsApi"); - - installPromiseMatchers(); - initializeVariables(); - initializeController(); - }); - - describe("Is the controller", function () { - var roles = [ "ROLE_ADMIN", "ROLE_MANAGER", "ROLE_USER", "ROLE_ANONYMOUS" ]; - - var controllerExists = function (setting) { - return function() { - initializeController(setting); - expect(controller).toBeDefined(); - }; - }; - - for (var i in roles) { - it("defined for " + roles[i], controllerExists({ role: roles[i] })); - } - }); - - describe("Is the scope method", function () { - var methods = [ - "resetProjectForms", - "createProject", - "resetCreateProject", - "editProject", - "updateProject", - "cancelEditProject", - "confirmDeleteProject", - "cancelDeleteProject", - "deleteProject" - ]; - - var scopeMethodExists = function (method) { - return function() { - expect($scope[method]).toBeDefined(); - expect(typeof $scope[method]).toEqual("function"); - }; - }; - - for (var i in methods) { - it(methods[i] + " defined", scopeMethodExists(methods[i])); - } - }); - - describe("Does the scope method", function () { - it("resetProjectForms reset project forms", function () { - var modal = angular.element($templateCache.get("views/modals/addProjectModal.html")); - modal = $compile(modal)($scope); - - var form = $scope.projectForms.create; - form.$setDirty(); - - expect(form.$dirty).toEqual(true); - - $scope.resetProjectForms(); - - expect(form.$pristine).toEqual(true); - expect(form.$dirty).toEqual(false); - }); - - it("createProject create a new project", function () { - var newProject = new mockProject($q); - - newProject.mock({ - id: dataProjectRepo1.length + 1, - name: "Mock Project 4" - }); - - $scope.projectToCreate = newProject; - $scope.createProject(); - - expect(ProjectRepo.findById(newProject.id)).toEqual(newProject); - }); - - it("resetCreateProject call resetProjectForms() and clear out the name field", function () { - spyOn($scope, "resetProjectForms"); - - $scope.projectToCreate = new mockProject($q); - $scope.projectToCreate.mock({ - id: dataProjectRepo1.length + 1, - name: "Mock Project 4" - }); - - var modal = angular.element($templateCache.get("views/modals/addProjectModal.html")); - modal = $compile(modal)($scope); - - var form = $scope.projectForms.create; - form.$setDirty(); - $scope.resetCreateProject(); - - expect($scope.projectToCreate.name).toEqual(""); - expect($scope.resetProjectForms).toHaveBeenCalled(); - }); - - it("editProject set the projectToEdit and open the modal", function () { - spyOn($scope, "openModal"); - $scope.editProject(dataProjectRepo1[0]); - - expect($scope.projectToEdit).toEqual(dataProjectRepo1[0]); - expect($scope.openModal).toHaveBeenCalled(); - }); - - it("updateProject call dirty and save on the Project, and then call cancelEditProject", function () { - var project = new mockProject($q); - - spyOn($scope, "cancelEditProject"); - spyOn(project, "dirty"); - deferred = $q.defer(); - spyOn(project, "save").and.returnValue(deferred.promise); - $scope.projectToEdit = project; - $scope.updateProject(); - deferred.resolve(); - $scope.$apply(); - - expect($scope.cancelEditProject).toHaveBeenCalled(); - expect(project.dirty).toHaveBeenCalledWith(true); - expect(project.save).toHaveBeenCalled(); - }); - - it("cancelEditProject clear out projectToEdit and call resetProjectForms", function () { - var project = new mockProject($q); - - spyOn($scope, "resetProjectForms"); - $scope.projectToEdit = project; - $scope.cancelEditProject(); - - expect($scope.projectToEdit).toEqual({}); - expect($scope.resetProjectForms).toHaveBeenCalled(); - }); - - it("confirmDeleteProject set the projectToDelete and open the modal", function () { - spyOn($scope, "openModal"); - $scope.confirmDeleteProject(dataProjectRepo1[0]); - - expect($scope.openModal).toHaveBeenCalled(); - expect($scope.projectToDelete).toEqual(dataProjectRepo1[0]); - }); - - it("cancelDeleteProject clear projectToDelete and close the modal", function () { - spyOn($scope, "closeModal"); - $scope.projectToDelete = dataProjectRepo1[0]; - $scope.cancelDeleteProject(); - - expect($scope.closeModal).toHaveBeenCalled(); - expect($scope.projectToDelete).toEqual({}); - }); - - it("deleteProject call the repo delete method and then call cancelDeleteProject when successful", function () { - var project = new mockProject($q); - - $scope.projectToDelete = project; - deferred = $q.defer(); - spyOn(ProjectRepo, "delete").and.returnValue(deferred.promise); - spyOn($scope, "cancelDeleteProject"); - $scope.deleteProject(project); - deferred.resolve({ - body: angular.toJson({ - meta: { - status: "SUCCESS" - } - }) - }); - $scope.$apply(); - - expect(ProjectRepo.delete).toHaveBeenCalledWith(project); - expect($scope.cancelDeleteProject).toHaveBeenCalled(); - }); - - }); - -}); diff --git a/tests/unit/controllers/remoteProjectManagerControllerTest.js b/tests/unit/controllers/remoteProjectManagerControllerTest.js index 633b719..966d9ff 100644 --- a/tests/unit/controllers/remoteProjectManagerControllerTest.js +++ b/tests/unit/controllers/remoteProjectManagerControllerTest.js @@ -71,6 +71,7 @@ describe("controller: RemoteProjectManagerController", function () { describe("Is the scope method", function () { var methods = [ + "addRemoteProjectManager", "resetRemoteProjectManagerForms", "createRemoteProjectManager", "resetCreateRemoteProjectManager", @@ -96,6 +97,15 @@ describe("controller: RemoteProjectManagerController", function () { }); describe("Does the scope method", function () { + it("addRemoteProjectManager to open the modal", function () { + var remoteProjectManager = new mockRemoteProjectManager($q); + + spyOn($scope, "openModal"); + + $scope.addRemoteProjectManager(); + expect($scope.openModal).toHaveBeenCalledWith("#addRemoteProjectManagerModal"); + }); + it("resetRemoteProjectManagerForms reset Remote Project Manager forms", function () { var modal = angular.element($templateCache.get("views/modals/addRemoteProjectManagerModal.html")); diff --git a/tests/unit/model/internalRequestTest.js b/tests/unit/model/internalRequestTest.js new file mode 100644 index 0000000..09df01a --- /dev/null +++ b/tests/unit/model/internalRequestTest.js @@ -0,0 +1,34 @@ +describe("model: InternalRequest", function () { + var $rootScope, $scope, WsApi, model; + + var initializeVariables = function (settings) { + inject(function (_$rootScope_, _WsApi_) { + $rootScope = _$rootScope_; + + WsApi = _WsApi_; + }); + }; + + var initializeModel = function (settings) { + inject(function (_InternalRequest_) { + $scope = $rootScope.$new(); + + model = angular.extend(new _InternalRequest_(), dataInternalRequest1); + }); + }; + + beforeEach(function () { + module("core"); + module("app"); + module("mock.wsApi"); + + initializeVariables(); + initializeModel(); + }); + + describe("Is the model", function () { + it("defined", function () { + expect(model).toBeDefined(); + }); + }); +}); diff --git a/tests/unit/model/projectTest.js b/tests/unit/model/productTest.js similarity index 80% rename from tests/unit/model/projectTest.js rename to tests/unit/model/productTest.js index 5e97d37..b109b9d 100644 --- a/tests/unit/model/projectTest.js +++ b/tests/unit/model/productTest.js @@ -1,4 +1,4 @@ -describe("model: Project", function () { +describe("model: Product", function () { var $rootScope, $scope, WsApi, model; var initializeVariables = function (settings) { @@ -10,10 +10,10 @@ describe("model: Project", function () { }; var initializeModel = function (settings) { - inject(function (_Project_) { + inject(function (_Product_) { $scope = $rootScope.$new(); - model = angular.extend(new _Project_(), dataProject1); + model = angular.extend(new _Product_(), dataProduct1); }); }; diff --git a/tests/unit/model/remoteProjectManagerTetst.js b/tests/unit/model/remoteProjectManagerTest.js similarity index 100% rename from tests/unit/model/remoteProjectManagerTetst.js rename to tests/unit/model/remoteProjectManagerTest.js diff --git a/tests/unit/repo/internalRequestRepoTest.js b/tests/unit/repo/internalRequestRepoTest.js new file mode 100644 index 0000000..d689bd3 --- /dev/null +++ b/tests/unit/repo/internalRequestRepoTest.js @@ -0,0 +1,36 @@ +describe("service: InternalRequestRepo", function () { + var $q, $rootScope, $scope, WsApi, repo; + + var initializeVariables = function (settings) { + inject(function (_$q_, _$rootScope_, _WsApi_) { + $q = _$q_; + $rootScope = _$rootScope_; + + WsApi = _WsApi_; + }); + }; + + var initializeRepo = function (settings) { + inject(function ($injector, _InternalRequestRepo_) { + $scope = $rootScope.$new(); + + repo = _InternalRequestRepo_; + }); + }; + + beforeEach(function () { + module("core"); + module("app"); + module("mock.wsApi"); + + initializeVariables(); + initializeRepo(); + }); + + describe("Is the repo", function () { + it("defined", function () { + expect(repo).toBeDefined(); + }); + }); + +}); diff --git a/tests/unit/repo/projectRepoTest.js b/tests/unit/repo/productRepoTest.js similarity index 82% rename from tests/unit/repo/projectRepoTest.js rename to tests/unit/repo/productRepoTest.js index 208e0a9..41098e8 100644 --- a/tests/unit/repo/projectRepoTest.js +++ b/tests/unit/repo/productRepoTest.js @@ -1,4 +1,4 @@ -describe("service: ProjectRepo", function () { +describe("service: ProductRepo", function () { var $q, $rootScope, $scope, WsApi, repo; var initializeVariables = function (settings) { @@ -11,10 +11,10 @@ describe("service: ProjectRepo", function () { }; var initializeRepo = function (settings) { - inject(function ($injector, _ProjectRepo_) { + inject(function ($injector, _ProductRepo_) { $scope = $rootScope.$new(); - repo = _ProjectRepo_; + repo = _ProductRepo_; }); }; diff --git a/tests/unit/services/internalRequestsServiceTest.js b/tests/unit/services/internalRequestsServiceTest.js new file mode 100644 index 0000000..63f1c5e --- /dev/null +++ b/tests/unit/services/internalRequestsServiceTest.js @@ -0,0 +1,147 @@ +describe("service: InternalRequestsService", function () { + var $q, $rootScope, $scope, InternalRequestRepo, WsApi, service; + + var initializeVariables = function (settings) { + inject(function (_$q_, _$rootScope_, _$timeout_, _InternalRequestRepo_, _WsApi_) { + $q = _$q_; + $rootScope = _$rootScope_; + + InternalRequestRepo = _InternalRequestRepo_; + WsApi = _WsApi_; + }); + }; + + var initializeService = function (settings) { + inject(function ($injector, _InternalRequestsService_) { + $scope = $rootScope.$new(); + + service = _InternalRequestsService_; + + // ensure that the isReady() is called. + if (!$scope.$$phase) { + $scope.$digest(); + } + }); + }; + + beforeEach(function () { + module("core"); + module("app"); + module("mock.internalRequest"); + module("mock.internalRequestRepo"); + module("mock.product"); + module("mock.wsApi"); + + initializeVariables(); + initializeService(); + }); + + describe("Is the service", function () { + it("defined", function () { + expect(service).toBeDefined(); + }); + }); + + describe("Is the service method", function () { + var methods = [ + "pushFeatureRequest" + ]; + + var serviceMethodExists = function (method) { + return function() { + expect(service[method]).toBeDefined(); + expect(typeof service[method]).toEqual("function"); + }; + }; + + for (var i in methods) { + it(methods[i] + " defined", serviceMethodExists(methods[i])); + } + }); + + describe("Do the service method", function () { + it("pushFeatureRequest should push a FeatureRequest", function () { + var response; + var featureRequest = new mockFeatureRequest($q); + featureRequest.product = new mockProduct($q); + + service.pushFeatureRequest(featureRequest).then(function () { + response = true; + }).catch(function () { + response = false; + }); + + $scope.$digest(); + + expect(response).toBe(true); + }); + + it("pushFeatureRequest should not push an invalid FeatureRequest id", function () { + var response; + var featureRequest = new mockFeatureRequest($q); + featureRequest.id = undefined; + featureRequest.product = new mockProduct($q); + + service.pushFeatureRequest(featureRequest).then(function () { + response = true; + }).catch(function () { + response = false; + }); + + $scope.$digest(); + + expect(response).toBe(false); + }); + + it("pushFeatureRequest should not push an invalid FeatureRequest productId", function () { + var response; + var featureRequest = new mockFeatureRequest($q); + featureRequest.product = undefined; + + service.pushFeatureRequest(featureRequest).then(function () { + response = true; + }).catch(function () { + response = false; + }); + + $scope.$digest(); + + expect(response).toBe(false); + }); + + it("pushFeatureRequest should not push an invalid FeatureRequest rpmId", function () { + var response; + var featureRequest = new mockFeatureRequest($q); + featureRequest.product = new mockProduct($q); + featureRequest.rpmId = undefined; + + service.pushFeatureRequest(featureRequest).then(function () { + response = true; + }).catch(function () { + response = false; + }); + + $scope.$digest(); + + expect(response).toBe(false); + }); + + it("pushFeatureRequest should not push an invalid FeatureRequest scopeId", function () { + var response; + var featureRequest = new mockFeatureRequest($q); + featureRequest.product = new mockProduct($q); + featureRequest.scopeId = undefined; + + service.pushFeatureRequest(featureRequest).then(function () { + response = true; + }).catch(function () { + response = false; + }); + + $scope.$digest(); + + expect(response).toBe(false); + }); + }); + +}); diff --git a/tests/unit/services/internalStatsServiceTest.js b/tests/unit/services/internalStatsServiceTest.js new file mode 100644 index 0000000..dc5e659 --- /dev/null +++ b/tests/unit/services/internalStatsServiceTest.js @@ -0,0 +1,92 @@ +describe("service: InternalStatsService", function () { + var $q, $rootScope, $scope, InternalRequestRepo, WsApi, service; + + var initializeVariables = function (settings) { + inject(function (_$q_, _$rootScope_, _$timeout_, _InternalRequestRepo_, _WsApi_) { + $q = _$q_; + $rootScope = _$rootScope_; + + InternalRequestRepo = _InternalRequestRepo_; + WsApi = _WsApi_; + }); + }; + + var initializeService = function (settings) { + inject(function ($injector, _InternalStatsService_) { + $scope = $rootScope.$new(); + + service = _InternalStatsService_; + + // ensure that the isReady() is called. + if (!$scope.$$phase) { + $scope.$digest(); + } + }); + }; + + beforeEach(function () { + module("core"); + module("app"); + module("mock.internalRequest"); + module("mock.internalRequestRepo"); + module("mock.wsApi"); + + initializeVariables(); + initializeService(); + }); + + describe("Is the service", function () { + it("defined", function () { + expect(service).toBeDefined(); + }); + }); + + describe("Is the service method", function () { + var methods = [ + "getStats", + "refreshStats" + ]; + + var serviceMethodExists = function (method) { + return function() { + expect(service[method]).toBeDefined(); + expect(typeof service[method]).toEqual("function"); + }; + }; + + for (var i in methods) { + it(methods[i] + " defined", serviceMethodExists(methods[i])); + } + }); + + describe("Is the service property", function () { + var properties = [ + "ready" + ]; + + var servicePropertyExists = function (property) { + return function() { + expect(service[property]).toBeDefined(); + expect(typeof service[property]).toEqual("object"); + }; + }; + + for (var i in properties) { + it(properties[i] + " defined", servicePropertyExists(properties[i])); + } + }); + + describe("Do the service method", function () { + it("getStats should return internal stats", function () { + var response = service.getStats(); + expect(response).toEqual(dataInternalStats1); + }); + + it("refreshStats should refresh stats", function () { + var response; + + // @todo + }); + }); + +}); diff --git a/tests/unit/services/productsServiceTest.js b/tests/unit/services/productsServiceTest.js new file mode 100644 index 0000000..e973f03 --- /dev/null +++ b/tests/unit/services/productsServiceTest.js @@ -0,0 +1,134 @@ +describe("service: ProductsService", function () { + var $q, $rootScope, $scope, ProductRepo, WsApi, service; + + var initializeVariables = function (settings) { + inject(function (_$q_, _$rootScope_, _ProductRepo_, _WsApi_) { + $q = _$q_; + $rootScope = _$rootScope_; + + ProductRepo = _ProductRepo_; + WsApi = _WsApi_; + }); + }; + + var initializeService = function (settings) { + inject(function ($injector, _ProductsService_) { + $scope = $rootScope.$new(); + + service = _ProductsService_; + + // ensure that the isReady() is called. + if (!$scope.$$phase) { + $scope.$digest(); + } + }); + }; + + beforeEach(function () { + module("core"); + module("app"); + module("mock.product"); + module("mock.wsApi"); + + initializeVariables(); + initializeService(); + }); + + describe("Is the service", function () { + it("defined", function () { + expect(service).toBeDefined(); + }); + }); + + describe("Is the service method", function () { + var methods = [ + "getProducts", + "getProductsLoading", + "getRemoteProjects", + "getRemoteProjectInfo", + "getRemoteProjectsLoading", + "refreshProducts", + "refreshRemoteProjectsForProduct" + ]; + + var serviceMethodExists = function (method) { + return function() { + expect(service[method]).toBeDefined(); + expect(typeof service[method]).toEqual("function"); + }; + }; + + for (var i in methods) { + it(methods[i] + " defined", serviceMethodExists(methods[i])); + } + }); + + describe("Is the service property", function () { + var properties = [ + "ready" + ]; + + var servicePropertyExists = function (property) { + return function() { + expect(service[property]).toBeDefined(); + expect(typeof service[property]).toEqual("object"); + }; + }; + + for (var i in properties) { + it(properties[i] + " defined", servicePropertyExists(properties[i])); + } + }); + + describe("Do the service method", function () { + it("getProducts should return all products", function () { + var response = service.getProducts(); + expect(response).toEqual(dataProductRepo1); + }); + + it("getProductsLoading should return the current loading status for projects", function () { + var response = service.getProductsLoading(); + expect(response).toEqual(false); + }); + + it("getRemoteProjects should return all remote projects for a given product", function () { + // @todo + //var response = service.getRemoteProjects(); + //expect(response).toEqual(dataRemoteProjects); + }); + + it("getRemoteProjectsLoading should return the current loading status for all remote projects", function () { + var response = service.getRemoteProjectsLoading(); + expect(response).toBeDefined(); + }); + + it("getRemoteProjectInfo should return all remote project info for a given product", function () { + var response; + + // @todo + //response = service.getById(id); + //$scope.$digest(); + + //expect(response.id).toBe(id); + }); + + it("refreshProducts should refresh products", function () { + var response; + + // @todo + //response = service.refreshProducts(); + //$scope.$digest(); + + //expect(response.id).toBe(id); + }); + + it("refreshRemoteProjectsForProduct should refresh remote projects", function () { + var response; + + // @todo + //response = service.refreshRemoteProjectsForProduct(id); + //$scope.$digest(); + }); + }); + +}); diff --git a/tests/unit/services/projectsStatsServiceTest.js b/tests/unit/services/productsStatsServiceTest.js similarity index 64% rename from tests/unit/services/projectsStatsServiceTest.js rename to tests/unit/services/productsStatsServiceTest.js index b0595ab..2d5cb1a 100644 --- a/tests/unit/services/projectsStatsServiceTest.js +++ b/tests/unit/services/productsStatsServiceTest.js @@ -1,21 +1,21 @@ -describe("service: ProjectsStatsService", function () { - var $q, $rootScope, $scope, ProjectRepo, WsApi, service; +describe("service: ProductsStatsService", function () { + var $q, $rootScope, $scope, ProductRepo, WsApi, service; var initializeVariables = function (settings) { - inject(function (_$q_, _$rootScope_, _ProjectRepo_, _WsApi_) { + inject(function (_$q_, _$rootScope_, _ProductRepo_, _WsApi_) { $q = _$q_; $rootScope = _$rootScope_; - ProjectRepo = _ProjectRepo_; + ProductRepo = _ProductRepo_; WsApi = _WsApi_; }); }; var initializeService = function (settings) { - inject(function ($injector, _ProjectsStatsService_) { + inject(function ($injector, _ProductsStatsService_) { $scope = $rootScope.$new(); - service = _ProjectsStatsService_; + service = _ProductsStatsService_; // ensure that the isReady() is called. if (!$scope.$$phase) { @@ -27,7 +27,7 @@ describe("service: ProjectsStatsService", function () { beforeEach(function () { module("core"); module("app"); - module("mock.projectRepo"); + module("mock.productRepo"); module("mock.wsApi"); initializeVariables(); @@ -43,8 +43,8 @@ describe("service: ProjectsStatsService", function () { describe("Is the service method", function () { var methods = [ "getById", - "getProjectsStats", - "refreshProjectsStats" + "getProductsStats", + "refreshProductsStats" ]; var serviceMethodExists = function (method) { @@ -77,24 +77,24 @@ describe("service: ProjectsStatsService", function () { }); describe("Do the service method", function () { - it("getById get project stats by id", function () { + it("getById get product stats by id", function () { $rootScope.$apply(); - service.getById(1).then(function (projectStats) { - expect(projectStats).toEqual(dataProjectsStats[0]); + service.getById(1).then(function (productStats) { + expect(productStats).toEqual(dataProductsStats[0]); }); }); - it("getProjectsStats get project stats", function () { - var projectsStats = service.getProjectsStats(); - expect(projectsStats).toEqual(dataProjectsStats); + it("getProductsStats get product stats", function () { + var productsStats = service.getProductsStats(); + expect(productsStats).toEqual(dataProductsStats); }); - it("refreshProjectsStats fetch project stats", function () { + it("refreshProductsStats fetch product stats", function () { deferred = $q.defer(); spyOn(WsApi, "fetch").and.returnValue(deferred.promise); - service.refreshProjectsStats(); - deferred.resolve(dataProjectsStats); - expect(WsApi.fetch).toHaveBeenCalledWith(apiMapping.ProjectsStats.all); + service.refreshProductsStats(); + deferred.resolve(dataProductsStats); + expect(WsApi.fetch).toHaveBeenCalledWith(apiMapping.ProductsStats.all); }); }); diff --git a/tests/unit/services/remoteProjectsServiceTest.js b/tests/unit/services/remoteProjectsServiceTest.js index a0bc0cc..42817ca 100644 --- a/tests/unit/services/remoteProjectsServiceTest.js +++ b/tests/unit/services/remoteProjectsServiceTest.js @@ -1,12 +1,12 @@ describe("service: RemoteProjectsService", function () { - var $q, $rootScope, $scope, ProjectRepo, WsApi, service; + var $q, $rootScope, $scope, ProductRepo, WsApi, service; var initializeVariables = function (settings) { - inject(function (_$q_, _$rootScope_, _ProjectRepo_, _WsApi_) { + inject(function (_$q_, _$rootScope_, _ProductRepo_, _WsApi_) { $q = _$q_; $rootScope = _$rootScope_; - ProjectRepo = _ProjectRepo_; + ProductRepo = _ProductRepo_; WsApi = _WsApi_; }); }; @@ -27,7 +27,7 @@ describe("service: RemoteProjectsService", function () { beforeEach(function () { module("core"); module("app"); - module("mock.projectRepo"); + module("mock.productRepo"); module("mock.wsApi"); initializeVariables(); @@ -42,9 +42,8 @@ describe("service: RemoteProjectsService", function () { describe("Is the service method", function () { var methods = [ - "getByScopeId", - "getRemoteProjects", - "refreshRemoteProjects" + "getRemoteProjectInfo", + "refreshRemoteProjectInfo" ]; var serviceMethodExists = function (method) { @@ -77,22 +76,15 @@ describe("service: RemoteProjectsService", function () { }); describe("Does the service method", function () { - it("getByScopeId get remote project by remote project manager id and scope id", function () { - $rootScope.$apply(); - service.getByScopeId(1, 1934).then(function (remoteProject) { - expect(remoteProject).toEqual(dataRemoteProjects["1"][0]); - }); - }); - - it("getRemoteProjects get remote projects", function () { - var remoteProjects = service.getRemoteProjects(); + it("getRemoteProjectInfo get remote projects", function () { + var remoteProjects = service.getRemoteProjectInfo(); expect(remoteProjects).toEqual(dataRemoteProjects); }); - it("refreshRemoteProjects fetch remote projects", function () { + it("refreshRemoteProjectInfo fetch remote projects", function () { deferred = $q.defer(); spyOn(WsApi, "fetch").and.returnValue(deferred.promise); - service.refreshRemoteProjects(); + service.refreshRemoteProjectInfo(); deferred.resolve(dataRemoteProjects); expect(WsApi.fetch).toHaveBeenCalledWith(apiMapping.RemoteProjects.all); });