From b66296ceecd174662af5973a802cf922329365a2 Mon Sep 17 00:00:00 2001 From: Spencer Walker Date: Thu, 11 May 2017 12:47:45 -0500 Subject: [PATCH 001/122] design: add matching class to "choose specs" btn F51-107 --- src/app/common/templates/card.product.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/common/templates/card.product.html b/src/app/common/templates/card.product.html index 9a252b63..a06f5174 100644 --- a/src/app/common/templates/card.product.html +++ b/src/app/common/templates/card.product.html @@ -20,7 +20,7 @@

{{productCard.product.PriceSchedu
- +
From 316eeeaf8d2cddd71ff501ccae675baebb30d021 Mon Sep 17 00:00:00 2001 From: Alexa Rarick Date: Thu, 11 May 2017 12:56:32 -0500 Subject: [PATCH 002/122] F51-118 refactor: unit test for productDetail component --- .../productDetail/test/productView.spec.js | 93 +++++-------------- src/global.spec.js | 14 ++- 2 files changed, 36 insertions(+), 71 deletions(-) diff --git a/src/app/productDetail/test/productView.spec.js b/src/app/productDetail/test/productView.spec.js index 00fe28e6..367cb09c 100644 --- a/src/app/productDetail/test/productView.spec.js +++ b/src/app/productDetail/test/productView.spec.js @@ -1,101 +1,54 @@ -describe('Component: ProductDetail', function(){ - var scope, - oc, - mockProduct, - productResolve, - lineItemHelpers, - currentOrder - ; -//if the service your are calling in is a higher order resolve you have to mock instead of inject -// / when you are calling a service that returns a function. Mock the promise! - // when defining a controller, Key: Actual Service Value Mocked variable +describe('Component: ProductDetail', function() { + var _lineItemHelpers; - beforeEach(module('orderCloud')); - beforeEach(module(function($provide) { - $provide.value('CurrentOrder', {ID: "MockOrderID3456"}) + beforeEach(inject(function(ocLineItems) { + _lineItemHelpers = ocLineItems; })); - beforeEach(inject(function($rootScope, OrderCloud, ocLineItems, CurrentOrder){ - scope = $rootScope.$new(); - oc = OrderCloud; - mockProduct = { - "ID": "MockProductID123", - "Name": "MockProductName", - "Description": "mockDescription", - "PriceSchedule": { - "PriceBreaks" : [ - { - "Quantity": 2, - "Price" : 10 - } - ] - } - }; - lineItemHelpers = ocLineItems; - currentOrder = CurrentOrder; - - })); - - describe('Configuration: ProductViewConfig', function(){ - var state, - stateParams; - - describe('State: Product',function(){ - beforeEach(inject(function($stateParams, $state){ - state = $state.get('productDetail'); - stateParams = $stateParams; - stateParams.productid = "MockProductID123"; - spyOn(oc.Me,'GetProduct'); - })); + describe('State: Product',function() { + var productDetailState; + beforeEach(inject(function($stateParams){ + productDetailState = state.get('productDetail'); + mock.Product.ID = $stateParams.productid; + spyOn(oc.Me,'GetProduct'); + })); - it('should resolve Product', inject(function($injector){ - $injector.invoke(state.resolve.Product); - expect(oc.Me.GetProduct).toHaveBeenCalledWith("MockProductID123"); - })); + it('should resolve Product', function(){ + injector.invoke(productDetailState.resolve.Product); + expect(oc.Me.GetProduct).toHaveBeenCalledWith(mock.Product.ID); }); }); describe('Controller: ProductDetail', function(){ var productDetailCtrl; - var toaster; - var q; - beforeEach(inject(function($controller, toastr, $q){ - toaster= toastr; - q = $q; - + beforeEach(inject(function($controller){ productDetailCtrl = $controller('ProductDetailCtrl',{ - Product : mockProduct, - CurrentOrder: currentOrder, - ocLineItems: lineItemHelpers, - toastr : toaster + Product : mock.Product }); })); - describe('addToCart', function(){ + describe('vm.addToCart', function(){ beforeEach( function(){ - var defer = q.defer(); - defer.resolve(); - spyOn(lineItemHelpers,'AddItem').and.returnValue(defer.promise); - spyOn(toaster, 'success'); + spyOn(_lineItemHelpers,'AddItem').and.returnValue(dummyPromise); + spyOn(toastrService, 'success'); productDetailCtrl.addToCart(); }); it('should call the ocLineItems AddItem method and display toastr', function(){ - expect(lineItemHelpers.AddItem).toHaveBeenCalledWith(currentOrder, mockProduct); + expect(_lineItemHelpers.AddItem).toHaveBeenCalledWith(mock.Order, productDetailCtrl.item); }); it('should call toastr when successful', function(){ scope.$digest(); - expect(toaster.success).toHaveBeenCalled(); + expect(toastrService.success).toHaveBeenCalled(); }); }); - describe('findPrice function', function(){ - //set up like this for potential addition of different quantities. + describe('vm.findPrice', function(){ it("finalPriceBreak should equal price of Pricebreak ", function(){ var possibleQuantities= [2]; for(var i = 0; i Date: Thu, 11 May 2017 15:44:54 -0500 Subject: [PATCH 003/122] Favorite Product: - Remove FavoriteProductCtrl - Change to Attribute directive - Rename to ocFavoriteProduct - Dynamic class added if favorite - Dynamic class added if not favorite --- .../oc-product-card/oc-product-card.html | 2 +- .../js/favoriteProduct.controller.js | 68 --------------- .../js/favoriteProducts.directive.js | 85 +++++++++++++++++-- 3 files changed, 79 insertions(+), 76 deletions(-) delete mode 100644 src/app/favoriteProducts/js/favoriteProduct.controller.js diff --git a/src/app/common/directives/oc-product-card/oc-product-card.html b/src/app/common/directives/oc-product-card/oc-product-card.html index 85f58fa5..04d0555e 100644 --- a/src/app/common/directives/oc-product-card/oc-product-card.html +++ b/src/app/common/directives/oc-product-card/oc-product-card.html @@ -11,7 +11,7 @@
{{productCard.product.Name || productCard.product.ID}}
{{productCard.product.ID}}
diff --git a/src/app/favoriteProducts/js/favoriteProduct.controller.js b/src/app/favoriteProducts/js/favoriteProduct.controller.js deleted file mode 100644 index b86a7829..00000000 --- a/src/app/favoriteProducts/js/favoriteProduct.controller.js +++ /dev/null @@ -1,68 +0,0 @@ -angular.module('orderCloud') - .controller('FavoriteProductCtrl', FavoriteProductController) -; - -function FavoriteProductController($scope, OrderCloudSDK, toastr, $exceptionHandler){ - var vm = this; - vm.checkHasFavorites = checkHasFavorites; - vm.toggleFavoriteProduct = toggleFavoriteProduct; - vm.addProduct = addProduct; - vm.removeProduct = removeProduct; - - vm.checkHasFavorites(); - vm.isFavorited = vm.hasFavorites && $scope.currentUser.xp.FavoriteProducts.indexOf($scope.product.ID) > -1; - - function toggleFavoriteProduct(){ - if (vm.hasFavorites){ - if (vm.isFavorited){ - vm.removeProduct(); - } else { - vm.addProduct($scope.currentUser.xp.FavoriteProducts); - } - } else { - vm.addProduct([]); - } - } - - function checkHasFavorites(){ - if($scope.currentUser && $scope.currentUser.xp && $scope.currentUser.xp.FavoriteProducts){ - vm.hasFavorites = true; - } - else{ - if($scope.currentUser && $scope.currentUser.xp){ - $scope.currentUser.xp.FavoriteProducts = []; - }else{ - $scope.currentUser.xp = {}; - $scope.currentUser.xp.FavoriteProducts = []; - } - return OrderCloudSDK.Me.Patch({xp:$scope.currentUser.xp}) - .then(function(){ - vm.hasFavorites = true; - }) - .catch(function(ex){ - $exceptionHandler(ex); - }); - } - } - - function addProduct(existingList){ - existingList.push($scope.product.ID); - return OrderCloudSDK.Me.Patch({xp: {FavoriteProducts: existingList}}) - .then(function(data){ - vm.hasFavorites = data.xp && data.xp.FavoriteProducts; - vm.isFavorited = true; - toastr.success($scope.product.Name + ' was added to your favorite products.'); - }); - } - - function removeProduct(){ - var updatedList = _.without($scope.currentUser.xp.FavoriteProducts, $scope.product.ID); - return OrderCloudSDK.Me.Patch({xp: {FavoriteProducts: updatedList}}) - .then(function(){ - vm.isFavorited = false; - $scope.currentUser.xp.FavoriteProducts = updatedList; - toastr.success($scope.product.Name + ' was removed from your favorite products.'); - }); - } - -} \ No newline at end of file diff --git a/src/app/favoriteProducts/js/favoriteProducts.directive.js b/src/app/favoriteProducts/js/favoriteProducts.directive.js index 05d3b2dd..ff893688 100644 --- a/src/app/favoriteProducts/js/favoriteProducts.directive.js +++ b/src/app/favoriteProducts/js/favoriteProducts.directive.js @@ -1,16 +1,87 @@ angular.module('orderCloud') - .directive('ordercloudFavoriteProduct', FavoriteProductDirective) + .directive('ocFavoriteProduct', OrderCloudFavoriteProductDirective) ; -function FavoriteProductDirective(){ +function OrderCloudFavoriteProductDirective($exceptionHandler, toastr, OrderCloudSDK){ return { scope: { currentUser: '=', - product: '=' + product: '=', + favoriteClass: '@', + nonFavoriteClass: '@' }, - restrict: 'E', - templateUrl: 'favoriteProducts/templates/ordercloud-favorite-product.html', - controller: 'FavoriteProductCtrl', - controllerAs: 'favoriteProduct' + restrict: 'A', + link: function(scope, element, attrs) { + var hasFavorites = false; + + checkHasFavorites(); + + (hasFavorites && scope.currentUser.xp.FavoriteProducts.indexOf(scope.product.ID) > -1) + ? addFavoriteClass() + : removeFavoriteClass(); + + function checkHasFavorites(){ + if(scope.currentUser && scope.currentUser.xp && scope.currentUser.xp.FavoriteProducts){ + hasFavorites = true; + } + else{ + if(scope.currentUser && scope.currentUser.xp){ + scope.currentUser.xp.FavoriteProducts = []; + }else{ + scope.currentUser.xp = {}; + scope.currentUser.xp.FavoriteProducts = []; + } + return OrderCloudSDK.Me.Patch({xp: scope.currentUser.xp}) + .then(function(){ + hasFavorites = true; + }) + .catch(function(ex){ + $exceptionHandler(ex); + }); + } + } + + function addFavoriteClass() { + element.removeClass(scope.nonFavoriteClass) + element.addClass(scope.favoriteClass); + } + + function removeFavoriteClass() { + element.removeClass(scope.favoriteClass); + element.addClass(scope.nonFavoriteClass); + } + + element.bind('click', function() { + if (hasFavorites){ + if (element.hasClass(scope.favoriteClass)){ + removeProduct(); + } else { + addProduct(scope.currentUser.xp.FavoriteProducts); + } + } else { + vm.addProduct([]); + } + }); + + function addProduct(existingList){ + existingList.push(scope.product.ID); + return OrderCloudSDK.Me.Patch({xp: {FavoriteProducts: existingList}}) + .then(function(data){ + addFavoriteClass(); + hasFavorites = data.xp && data.xp.FavoriteProducts; + toastr.success(scope.product.Name + ' was added to your favorite products.'); + }); + } + + function removeProduct(){ + var updatedList = _.without(scope.currentUser.xp.FavoriteProducts, scope.product.ID); + return OrderCloudSDK.Me.Patch({xp: {FavoriteProducts: updatedList}}) + .then(function() { + removeFavoriteClass(); + scope.currentUser.xp.FavoriteProducts = updatedList; + toastr.success(scope.product.Name + ' was removed from your favorite products.'); + }); + } + } }; } \ No newline at end of file From 81b16f7ea3ba8c64aa233d4b5c8a46e795dcd2e1 Mon Sep 17 00:00:00 2001 From: Alexa Rarick Date: Thu, 11 May 2017 16:10:07 -0500 Subject: [PATCH 004/122] F51-96 feature: featured products directive --- .../oc-featured-products.js | 53 +++++++++++++++++++ .../oc-featured-products.js | 22 ++++++++ src/app/home/js/home.controller.js | 6 ++- src/app/home/templates/home.html | 1 + 4 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 src/app/common/directives/oc-featured-products/oc-featured-products.js create mode 100644 src/app/common/services/oc-featured-products/oc-featured-products.js diff --git a/src/app/common/directives/oc-featured-products/oc-featured-products.js b/src/app/common/directives/oc-featured-products/oc-featured-products.js new file mode 100644 index 00000000..27cd9424 --- /dev/null +++ b/src/app/common/directives/oc-featured-products/oc-featured-products.js @@ -0,0 +1,53 @@ +angular.module('orderCloud') + .directive('ocFeaturedProducts', FeaturedProductsDirective) +; + +function FeaturedProductsDirective(ocFeaturedProductsService, $compile) { + return { + restrict: 'E', + link: function(scope, element) { + ocFeaturedProductsService.List() + .then(function(products) { + scope.featuredProducts = products; + scope.responsive = [ + { + breakpoint: 1500, + settings: { + slidesToShow: 4 + } + }, + { + breakpoint: 992, + settings: { + slidesToShow: 3 + } + }, + { + breakpoint: 768, + settings: { + slidesToShow: 1 + } + } + ]; + var template = + "" + + "

hello

" + + "
" + + "" + + "
" + + "
"; + $compile(element.append(template))(scope); + }); + } + } +} \ No newline at end of file diff --git a/src/app/common/services/oc-featured-products/oc-featured-products.js b/src/app/common/services/oc-featured-products/oc-featured-products.js new file mode 100644 index 00000000..304d5643 --- /dev/null +++ b/src/app/common/services/oc-featured-products/oc-featured-products.js @@ -0,0 +1,22 @@ +angular.module('orderCloud') + .factory('ocFeaturedProductsService', OrderCloudFeaturedProductsService) +; + +function OrderCloudFeaturedProductsService(OrderCloudSDK) { + return { + List: _listFeaturedProducts + }; + + function _listFeaturedProducts() { + return OrderCloudSDK.Me.ListProducts() + .then(function(products) { + var featuredProducts = []; + var featured = _.each(products.Items, function(product) { + if(product.xp && product.xp.Featured) { + featuredProducts.push(product); + } + }); + return featuredProducts; + }); + } +} \ No newline at end of file diff --git a/src/app/home/js/home.controller.js b/src/app/home/js/home.controller.js index 2ad0818d..241621f7 100644 --- a/src/app/home/js/home.controller.js +++ b/src/app/home/js/home.controller.js @@ -2,6 +2,10 @@ angular.module('orderCloud') .controller('HomeCtrl', HomeController) ; -function HomeController() { +function HomeController(ocFeaturedProductsService) { var vm = this; + + vm.featured = function() { + ocFeaturedProductsService.List(); + } } \ No newline at end of file diff --git a/src/app/home/templates/home.html b/src/app/home/templates/home.html index 14b30d48..04108a5e 100644 --- a/src/app/home/templates/home.html +++ b/src/app/home/templates/home.html @@ -4,4 +4,5 @@

Welcome to the OrderCloud Marketplace App!

Learn more »

+ \ No newline at end of file From 1711d202f64048fc7fa3179875ab0d4192c682f6 Mon Sep 17 00:00:00 2001 From: Alexa Rarick Date: Thu, 11 May 2017 16:43:58 -0500 Subject: [PATCH 005/122] F51-96 feature: featured products directive --- .../oc-featured-products/oc-featured-products.js | 6 +++--- .../oc-featured-products/oc-featured-products.js | 16 ++++++---------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/app/common/directives/oc-featured-products/oc-featured-products.js b/src/app/common/directives/oc-featured-products/oc-featured-products.js index 27cd9424..8f38ae43 100644 --- a/src/app/common/directives/oc-featured-products/oc-featured-products.js +++ b/src/app/common/directives/oc-featured-products/oc-featured-products.js @@ -4,9 +4,10 @@ angular.module('orderCloud') function FeaturedProductsDirective(ocFeaturedProductsService, $compile) { return { + scope: {}, restrict: 'E', link: function(scope, element) { - ocFeaturedProductsService.List() + ocFeaturedProductsService.List() .then(function(products) { scope.featuredProducts = products; scope.responsive = [ @@ -31,8 +32,7 @@ function FeaturedProductsDirective(ocFeaturedProductsService, $compile) { ]; var template = "" + - "

hello

" + - "
" + + "
" + "

ng-model="categoryBrowse.categoryList.Meta.Page" ng-change="categoryBrowse.changeCategoryPage(categoryBrowse.categoryList.Meta.Page)" ng-if="categoryBrowse.categoryList.Meta.TotalPages > 1"> - + + +

{{productCard.product.Name || productCard.product.ID}}
{{productCard.product.ID}} +

+

+ {{productCard.product.PriceSchedule.PriceBreaks[0].Price | currency}} + x {{productCard.product.PriceSchedule.PriceBreaks[0].Quantity}} +

- -
{{productCard.product.Name || productCard.product.ID}}
{{productCard.product.ID}} -
-

- {{productCard.product.PriceSchedule.PriceBreaks[0].Price | currency}} - x {{productCard.product.PriceSchedule.PriceBreaks[0].Quantity}} -

- -
-
- -
-
+
+ + +
+
- - + + - - - - - + + + + + +
+
+ +
-
- -
-
- + +
\ No newline at end of file diff --git a/src/app/common/directives/oc-product-card/oc-product-card.js b/src/app/common/directives/oc-product-card/oc-product-card.js index a616edbb..39e6bdc4 100644 --- a/src/app/common/directives/oc-product-card/oc-product-card.js +++ b/src/app/common/directives/oc-product-card/oc-product-card.js @@ -1,16 +1,21 @@ angular.module('orderCloud') - .component('ocProductCard', { - templateUrl: 'common/directives/oc-product-card/oc-product-card.html', - controller: ocProductCard, - controllerAs: 'productCard', - bindings: { - product: '<', - currentOrder: '<', - lineitemlist: '<' - } + .controller('ProductCardCtrl', OrderCloudProductCardController) + .directive('ocProductCard', function() { + return { + templateUrl: 'common/directives/oc-product-card/oc-product-card.html', + controller: 'ProductCardCtrl', + controllerAs: 'productCard', + replace: true, + bindToController: true, + scope: { + product: '<', + currentOrder: '<', + lineitemlist: '<' + } + }; }); -function ocProductCard($scope, $exceptionHandler, toastr, ocLineItems){ +function OrderCloudProductCardController($scope, $exceptionHandler, toastr, ocLineItems){ var vm = this; var toastID = 0; // This is used to circumvent the global toastr config that prevents duplicate toasts from opening. diff --git a/src/app/common/directives/oc-product-card/tests/oc-product-card.spec.js b/src/app/common/directives/oc-product-card/tests/oc-product-card.spec.js index 3066488d..97325d39 100644 --- a/src/app/common/directives/oc-product-card/tests/oc-product-card.spec.js +++ b/src/app/common/directives/oc-product-card/tests/oc-product-card.spec.js @@ -1,52 +1,36 @@ -describe('Component: addPromotion', function(){ +describe('Directive: ocProductCard', function(){ var ctrl, componentScope ; - beforeEach(inject(function($componentController, $rootScope, $compile){ + beforeEach(inject(function($controller, $rootScope, $compile){ scope = $rootScope.$new(); scope.product = mock.Product; scope.currentOrder = mock.Order; - scope.lineitemlist = {Items: mock.LineItem}; - var element = $compile('')(scope); + var element = $compile('')(scope); scope.$digest(); - componentScope = element.scope(); - ctrl = $componentController('ocProductCard', {$scope: componentScope}); + directiveScope = element.scope(); + ctrl = $controller('ProductCardCtrl', {$scope: directiveScope}); })); describe('$onInit', function(){ var newQty = 2; var oldQty = 10; beforeEach(function(){ - spyOn(ctrl, 'setDefaultQuantity'); spyOn(ctrl, 'findPrice'); ctrl.product = {}; ctrl.currentOrder = mock.Order; - componentScope.vm = ctrl; - }); - it('should call setDefaultQuantity', function(){ - ctrl.$onInit(); - ctrl.product.Quantity = newQty; - componentScope.$apply(); - expect(ctrl.findPrice).not.toHaveBeenCalled(); - expect(ctrl.setDefaultQuantity).toHaveBeenCalled(); - - }); - it('should only init default quantities when there is a current order', function(){ - delete ctrl.currentOrder; - ctrl.$onInit(); - expect(ctrl.setDefaultQuantity).not.toHaveBeenCalled(); - expect(ctrl) + directiveScope.vm = ctrl; }); it('should create a watch if price breaks are defined', function(){ ctrl.product = {PriceSchedule: {PriceBreaks: {Quantity: oldQty, Price: 3}}}; ctrl.$onInit(); ctrl.product.Quantity = newQty; - componentScope.$apply(); + directiveScope.$apply(); expect(ctrl.findPrice).toHaveBeenCalledWith(newQty); }) it('should not create a watch if price breaks are not defined', function(){ ctrl.$onInit(); ctrl.product.Quantity = newQty; - componentScope.$apply(); + directiveScope.$apply(); expect(ctrl.findPrice).not.toHaveBeenCalled(); }); }); @@ -54,7 +38,6 @@ describe('Component: addPromotion', function(){ describe('addToCart', function(){ beforeEach(function(){ spyOn(ocLineItemsService, 'AddItem').and.returnValue(dummyPromise); - spyOn(ctrl, 'setDefaultQuantity'); ctrl.currentOrder = mock.Order; ctrl.product = mock.Product; }); @@ -62,11 +45,6 @@ describe('Component: addPromotion', function(){ ctrl.addToCart(); expect(ocLineItemsService.AddItem).toHaveBeenCalledWith(mock.Order, mock.Product); }); - it('should call setDefaultQuantity', function(){ - ctrl.addToCart(); - componentScope.$digest(); - expect(ctrl.setDefaultQuantity).toHaveBeenCalled(); - }); }); describe('findPrice', function(){ @@ -76,35 +54,18 @@ describe('Component: addPromotion', function(){ }); it('should not call function if there is no qty parameter', function(){ ctrl.findPrice(); - componentScope.$digest(); + directiveScope.$digest(); expect(ctrl.calculatedPrice).toBe(null); }); it('given quantity 1 should give price 5', function(){ ctrl.findPrice(1); - componentScope.$digest(); + directiveScope.$digest(); expect(ctrl.calculatedPrice).toBe(5); }); it('given quantity 5 should give price 15', function(){ ctrl.findPrice(5); - componentScope.$digest(); + directiveScope.$digest(); expect(ctrl.calculatedPrice).toBe(15); }); }); - - describe('setDefaultQuantity', function(){ - var minQty; - beforeEach(function(){ - minQty = 2; - ctrl.product = {}; - }) - it('should set quantity to 1 if no MinQuantity exists on price schedule', function(){ - ctrl.setDefaultQuantity(); - expect(ctrl.product.Quantity).toBe(1); - }) - it('should set quantity to MinQuantity if it exists on price schedule', function(){ - ctrl.product = {PriceSchedule: {MinQuantity: minQty}}; - ctrl.setDefaultQuantity(); - expect(ctrl.product.Quantity).toBe(minQty); - }) - }); }); \ No newline at end of file diff --git a/src/app/common/directives/oc-quantity-input/oc-quantity-input.html b/src/app/common/directives/oc-quantity-input/oc-quantity-input.html index e3bf6754..2877a526 100644 --- a/src/app/common/directives/oc-quantity-input/oc-quantity-input.html +++ b/src/app/common/directives/oc-quantity-input/oc-quantity-input.html @@ -6,7 +6,7 @@ type="number" ng-required="true" ng-if="!item.PriceSchedule.RestrictedQuantity" - class="form-control text-center" + class="form-control {{sizeClass}} text-center" ng-min="{{item.PriceSchedule.MinQuantity}}" ng-max="{{item.PriceSchedule.MaxQuantity}}" ng-model="item.Quantity" @@ -15,7 +15,7 @@ name="itemQuantity" ng-required="true" ng-if="item.PriceSchedule.RestrictedQuantity" - class="form-control text-center" + class="form-control {{sizeClass}} text-center" ng-model="item.Quantity" ng-options="priceBreak.Quantity as priceBreak.Quantity for priceBreak in item.PriceSchedule.PriceBreaks"> @@ -29,7 +29,7 @@ type="number" ng-required="true" ng-if="!item.Product.PriceSchedule.RestrictedQuantity" - class="form-control text-center" + class="form-control {{sizeClass}} text-center" ng-min="{{item.Product.PriceSchedule.MinQuantity}}" ng-max="{{item.Product.PriceSchedule.MaxQuantity}}" ng-model="item.Quantity" @@ -40,7 +40,7 @@ name="itemQuantity" ng-required="true" ng-if="item.Product.PriceSchedule.RestrictedQuantity" - class="form-control" + class="form-control {{sizeClass}}" ng-model="item.Quantity" ng-change="updateQuantity()" ng-options="priceBreak.Quantity as priceBreak.Quantity for priceBreak in item.Product.PriceSchedule.PriceBreaks"> diff --git a/src/app/common/directives/oc-quantity-input/oc-quantity-input.js b/src/app/common/directives/oc-quantity-input/oc-quantity-input.js index 0f23d7eb..6cc82059 100644 --- a/src/app/common/directives/oc-quantity-input/oc-quantity-input.js +++ b/src/app/common/directives/oc-quantity-input/oc-quantity-input.js @@ -8,12 +8,14 @@ function OCQuantityInput($log, $state, toastr, OrderCloudSDK) { lineitem: '=', label: '@', order: '=', - onUpdate: '&' + onUpdate: '&', + size: '@' }, require: '^?ocPrettySubmit', templateUrl: 'common/directives/oc-quantity-input/oc-quantity-input.html', replace: true, link: function (scope, element, attrs, formCtrl) { + if (scope.size && ['sm', 'lg'].indexOf(scope.size) > -1) scope.sizeClass = 'input-' + scope.size; if (scope.product) { scope.item = scope.product; scope.item.Quantity = (scope.item.PriceSchedule && scope.item.PriceSchedule.MinQuantity) diff --git a/src/app/favoriteProducts/templates/favoriteProducts.html b/src/app/favoriteProducts/templates/favoriteProducts.html index 629c325a..0ddb5565 100644 --- a/src/app/favoriteProducts/templates/favoriteProducts.html +++ b/src/app/favoriteProducts/templates/favoriteProducts.html @@ -33,8 +33,8 @@
You currently do not have any favorite products.
-
-
+
+
- + ng-change="favoriteProducts.pageChanged()">
-
-
+
+
@@ -49,11 +48,11 @@
{{(application.$ocMedia('min-width:768px') ? productVie
- + ng-change="productView.pageChanged()">
-
+
-
+
Select diff --git a/src/app/myAddresses/templates/myAddresses.html b/src/app/myAddresses/templates/myAddresses.html index 3d3c5a77..d4707880 100644 --- a/src/app/myAddresses/templates/myAddresses.html +++ b/src/app/myAddresses/templates/myAddresses.html @@ -2,9 +2,9 @@

Personal Addresses


-
+
-
+
Delete | diff --git a/src/app/styles/shame.less b/src/app/styles/shame.less index 67710e78..dac1e974 100644 --- a/src/app/styles/shame.less +++ b/src/app/styles/shame.less @@ -96,15 +96,4 @@ li a, .c-category-card__img { min-height: 1%; } -} - -.row-flex { - // add flex display to the product list - display: flex; - flex-direction: row; - flex-wrap: wrap; - > [class^="col-"] { - display: flex; - flex-direction: column; - } } \ No newline at end of file diff --git a/src/app/styles/utils/_row-flex.less b/src/app/styles/utils/_row-flex.less new file mode 100644 index 00000000..18f0304f --- /dev/null +++ b/src/app/styles/utils/_row-flex.less @@ -0,0 +1,13 @@ +.row-flex { + // add flex display to the product list + display: flex; + flex-direction: row; + flex-wrap: wrap; + > [class^="col-"] { + display: flex; + flex-direction: column; + } + .row-flex-inner { + flex:1 1 auto; + } +} \ No newline at end of file diff --git a/src/app/styles/utils/glob.less b/src/app/styles/utils/glob.less index fa5d1c48..35d76cc9 100644 --- a/src/app/styles/utils/glob.less +++ b/src/app/styles/utils/glob.less @@ -1,3 +1,4 @@ @import '_flexbox'; @import '_mixins'; -@import '_variables'; +@import '_row-flex'; +@import '_variables'; \ No newline at end of file From 606a7b83069066803b906a7ee96200d5082c4a8b Mon Sep 17 00:00:00 2001 From: Alexa Rarick Date: Wed, 7 Jun 2017 08:36:39 -0500 Subject: [PATCH 098/122] refactor: fix failing unit test for product detail component F51-118 --- .../productDetail/test/productDetail.spec.js | 160 +++++++----------- src/global.spec.js | 8 +- 2 files changed, 66 insertions(+), 102 deletions(-) diff --git a/src/app/productDetail/test/productDetail.spec.js b/src/app/productDetail/test/productDetail.spec.js index 87f29910..ccca761d 100644 --- a/src/app/productDetail/test/productDetail.spec.js +++ b/src/app/productDetail/test/productDetail.spec.js @@ -1,106 +1,64 @@ -//TODO: Fix Failing unit tests #F51-323 +describe('Component: ProductDetail', function () { -// describe('Component: ProductDetail', function(){ -// var scope, -// oc, -// mockProduct, -// productResolve, -// lineItemHelpers, -// currentOrder -// ; -// //if the service your are calling in is a higher order resolve you have to mock instead of inject -// // / when you are calling a service that returns a function. Mock the promise! -// // when defining a controller, Key: Actual Service Value Mocked variable + describe('Configuration: ProductViewConfig', function () { + describe('State: Product', function () { + var productDetailState, + _ocProducts; + beforeEach(inject(function ($stateParams, ocProducts) { + productDetailState = state.get('productDetail'); + stateParams = $stateParams; + stateParams.productid = mock.Product.ID; + _ocProducts = ocProducts; + spyOn(oc.Me, 'GetProduct'); + spyOn(_ocProducts, 'Related'); + })); + it('should resolve Product', (function () { + injector.invoke(productDetailState.resolve.Product); + expect(oc.Me.GetProduct).toHaveBeenCalledWith(stateParams.productid); + })); + it('should return a list of related products from the resolved product', function () { + injector.invoke(productDetailState.resolve.RelatedProducts); + expect(_ocProducts.Related).toHaveBeenCalledWith(mock.Product.xp.RelatedProducts); + }); + }); + }); -// beforeEach(module('orderCloud')); -// beforeEach(module(function($provide) { -// $provide.value('CurrentOrder', {ID: "MockOrderID3456"}) -// })); -// beforeEach(inject(function($rootScope, OrderCloud, ocLineItems, CurrentOrder){ -// scope = $rootScope.$new(); -// oc = OrderCloud; -// mockProduct = { -// "ID": "MockProductID123", -// "Name": "MockProductName", -// "Description": "mockDescription", -// "PriceSchedule": { -// "PriceBreaks" : [ -// { -// "Quantity": 2, -// "Price" : 10 -// } -// ] + describe('Controller: ProductDetail', function () { + beforeEach(inject(function ($controller) { + productDetailCtrl = $controller('ProductDetailCtrl', { + Product: mock.Product, + CurrentOrder: mock.Order, + ocLineItems: ocLineItemsService, + toastr: toastrService, + RelatedProducts: mock.Product.xp.RelatedProducts + }); + })); -// } -// }; -// lineItemHelpers = ocLineItems; -// currentOrder = CurrentOrder; + describe('addToCart', function () { + beforeEach(function () { + spyOn(ocLineItemsService, 'AddItem').and.returnValue(q.when(dummyPromise)); + spyOn(toastrService, 'success'); + productDetailCtrl.addToCart(); + }); + it('should call the ocLineItems AddItem method and display toastr', function () { + expect(ocLineItemsService.AddItem).toHaveBeenCalledWith(mock.Order, mock.Product); + }); + it('should call toastr when successful', function () { + scope.$digest(); + expect(toastrService.success).toHaveBeenCalled(); + }); + }); -// })); + describe('findPrice function', function () { + //set up like this for potential addition of different quantities. + it("finalPriceBreak should equal price of Pricebreak ", function () { + var possibleQuantities = [2]; + for (var i = 0; i < possibleQuantities.length; i++) { + productDetailCtrl.findPrice(possibleQuantities[i]); + expect(productDetailCtrl.finalPriceBreak.Price).toBe(mock.Product.PriceSchedule.PriceBreaks[i].Price); + } -// describe('Configuration: ProductViewConfig', function(){ -// var state, -// stateParams; - -// describe('State: Product',function(){ -// beforeEach(inject(function($stateParams, $state){ -// state = $state.get('productDetail'); -// stateParams = $stateParams; -// stateParams.productid = "MockProductID123"; -// spyOn(oc.Me,'GetProduct'); -// })); - -// it('should resolve Product', inject(function($injector){ -// $injector.invoke(state.resolve.Product); -// expect(oc.Me.GetProduct).toHaveBeenCalledWith("MockProductID123"); -// })); -// }); -// }); - -// describe('Controller: ProductDetail', function(){ -// var productDetailCtrl; -// var toaster; -// var q; -// beforeEach(inject(function($controller, toastr, $q){ -// toaster= toastr; -// q = $q; - -// productDetailCtrl = $controller('ProductDetailCtrl',{ -// Product : mockProduct, -// CurrentOrder: currentOrder, -// ocLineItems: lineItemHelpers, -// toastr : toaster -// }); - -// })); - -// describe('addToCart', function(){ -// beforeEach( function(){ -// var defer = q.defer(); -// defer.resolve(); -// spyOn(lineItemHelpers,'AddItem').and.returnValue(defer.promise); -// spyOn(toaster, 'success'); -// productDetailCtrl.addToCart(); -// }); -// it('should call the ocLineItems AddItem method and display toastr', function(){ -// expect(lineItemHelpers.AddItem).toHaveBeenCalledWith(currentOrder, mockProduct); -// }); -// it('should call toastr when successful', function(){ -// scope.$digest(); -// expect(toaster.success).toHaveBeenCalled(); -// }); -// }); - -// describe('findPrice function', function(){ -// //set up like this for potential addition of different quantities. -// it("finalPriceBreak should equal price of Pricebreak ", function(){ -// var possibleQuantities= [2]; -// for(var i = 0; i Date: Wed, 7 Jun 2017 10:24:26 -0500 Subject: [PATCH 099/122] refactor: fix failing unit test for ocConfirm service F51-312 --- .../oc-confirm/tests/oc-confirm.spec.js | 59 ++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/src/app/common/services/oc-confirm/tests/oc-confirm.spec.js b/src/app/common/services/oc-confirm/tests/oc-confirm.spec.js index 8bfb3543..14634375 100644 --- a/src/app/common/services/oc-confirm/tests/oc-confirm.spec.js +++ b/src/app/common/services/oc-confirm/tests/oc-confirm.spec.js @@ -1 +1,58 @@ -//TODO: Fix Failing unit tests # F51-312 \ No newline at end of file +describe('Service: ocConfirm', function() { + describe('Factory: ocConfirm', function() { + it('should define the methods', function() { + expect(ocConfirmService.Confirm).toBeDefined(); + expect(ocConfirmService.Confirm).toEqual(jasmine.any(Function)); + }); + describe('Method: Confirm', function() { + it('should open the modal for the confirmation template', function() { + var confirmOptions = { + Size: 'sm' + }; + var defer = q.defer(); + defer.resolve(confirmOptions); + spyOn(uibModalService, 'open').and.returnValue(defer.promise); + ocConfirmService.Confirm(confirmOptions); + expect(uibModalService.open).toHaveBeenCalledWith({ + backdrop:'static', + templateUrl: 'common/services/oc-confirm/oc-confirm.modal.html', + controller: 'ConfirmModalCtrl', + controllerAs: 'confirmModal', + size: 'confirm', + resolve: { + ConfirmOptions: jasmine.any(Function) + } + }) + }); + }); + }); + + describe('Controller: ConfirmModalCtrl', function() { + var confirmModalCtrl, + confirmOptions = { + message: 'confirm message', + confirmText: 'confirm text', + cancelText: 'cancel text', + type: 'type' + }, + uibModalInstance = jasmine.createSpyObj('modalInstance', ['close', 'dismiss']); + beforeEach(inject(function($controller) { + confirmModalCtrl = $controller('ConfirmModalCtrl', { + ConfirmOptions: confirmOptions, + $uibModalInstance: uibModalInstance + }); + })); + describe('vm.confirm', function() { + it('should close the modal', function() { + confirmModalCtrl.confirm(); + expect(uibModalInstance.close).toHaveBeenCalled(); + }) + }) + describe('vm.cancel', function() { + it('should dismiss the modal', function() { + confirmModalCtrl.cancel(); + expect(uibModalInstance.dismiss).toHaveBeenCalled(); + }) + }) + }); +}); \ No newline at end of file From 397c034ca1cf83216f9067cc063379a1984a3d25 Mon Sep 17 00:00:00 2001 From: Alexa Rarick Date: Wed, 7 Jun 2017 10:47:14 -0500 Subject: [PATCH 100/122] refactor: comment out failing spec form unit tests F51-118 --- .../productDetail/test/productView.spec.js | 87 ------------------- .../test/specForm.directive.spec.js | 27 ++++++ 2 files changed, 27 insertions(+), 87 deletions(-) delete mode 100644 src/app/productDetail/test/productView.spec.js create mode 100644 src/app/productDetail/test/specForm.directive.spec.js diff --git a/src/app/productDetail/test/productView.spec.js b/src/app/productDetail/test/productView.spec.js deleted file mode 100644 index 11d7bc8f..00000000 --- a/src/app/productDetail/test/productView.spec.js +++ /dev/null @@ -1,87 +0,0 @@ -describe('Component: ProductDetail', function() { - var _lineItemHelpers; - - beforeEach(inject(function(ocLineItems) { - _lineItemHelpers = ocLineItems; - })); - - describe('State: Product',function() { - var productDetailState; - beforeEach(inject(function($stateParams){ - productDetailState = state.get('productDetail'); - mock.Product.ID = $stateParams.productid; - spyOn(oc.Me,'GetProduct'); - })); - - it('should resolve Product', function(){ - injector.invoke(productDetailState.resolve.Product); - expect(oc.Me.GetProduct).toHaveBeenCalledWith(mock.Product.ID); - }); - }); - - describe('Controller: ProductDetail', function(){ - var productDetailCtrl; - beforeEach(inject(function($controller){ - productDetailCtrl = $controller('ProductDetailCtrl',{ - Product : mock.Product - }); - - })); - - describe('vm.addToCart', function(){ - beforeEach( function(){ - spyOn(_lineItemHelpers,'AddItem').and.returnValue(dummyPromise); - spyOn(toastrService, 'success'); - productDetailCtrl.addToCart(); - }); - it('should call the ocLineItems AddItem method and display toastr', function(){ - expect(_lineItemHelpers.AddItem).toHaveBeenCalledWith(mock.Order, productDetailCtrl.item); - }); - it('should call toastr when successful', function(){ - scope.$digest(); - expect(toastrService.success).toHaveBeenCalled(); - }); - }); - - describe('vm.findPrice', function(){ - it("finalPriceBreak should equal price of Pricebreak ", function(){ - var possibleQuantities= [2]; - for(var i = 0; i ')(scope); - }); - it('should initialize the isolate scope', function() { - expect(element.isolateScope().product).toEqual(mock.product); - }) - it('should call Me.ListSpecs with a product ID and parameters', function() { - var parameters = { - page: 1, - pageSize: 100 - }; - expect(oc.Me.ListSpecs).toHaveBeenCalledWith(mock.Product.ID, parameters); - }) - }) -}); diff --git a/src/app/productDetail/test/specForm.directive.spec.js b/src/app/productDetail/test/specForm.directive.spec.js new file mode 100644 index 00000000..a91d7e8a --- /dev/null +++ b/src/app/productDetail/test/specForm.directive.spec.js @@ -0,0 +1,27 @@ +// describe('Directive: ocSpecForm', function () { +// var element, +// specs; +// beforeEach(function () { +// var defer = q.defer(); +// defer.resolve(specs); +// spyOn(oc.Me, 'ListSpecs').and.returnValue(defer.promise); +// //mock.product = {ID: 'MockProductID'}; +// scope.mockProduct = mock.Product; +// specs = [{ +// "mockSpec": [ +// "mockOption" +// ] +// }]; +// element = compile('')(scope); +// }); +// it('should initialize the isolate scope', function () { +// expect(element.isolateScope().product).toEqual(mock.product); +// }) +// it('should call Me.ListSpecs with a product ID and parameters', function () { +// var parameters = { +// page: 1, +// pageSize: 100 +// }; +// expect(oc.Me.ListSpecs).toHaveBeenCalledWith(mock.Product.ID, parameters); +// }) +// }) From 723b5cbd2999ec02bee9da6962ed493b3e7c4885 Mon Sep 17 00:00:00 2001 From: Kyle Olson Date: Wed, 7 Jun 2017 12:33:38 -0500 Subject: [PATCH 101/122] F51-242 Static Image Slider update - Change img src from Src to URL for consistency --- src/app/home/js/home.controller.js | 6 +++--- src/app/home/templates/home.html | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/home/js/home.controller.js b/src/app/home/js/home.controller.js index 4b42a080..e5c62091 100644 --- a/src/app/home/js/home.controller.js +++ b/src/app/home/js/home.controller.js @@ -15,19 +15,19 @@ function HomeController(ocAppName, FeaturedProducts) { }, Slides: [ { - Src: 'assets/images/carousel1.jpg', + URL: 'assets/images/carousel1.jpg', Title: ocAppName.Watch(), SubText: 'Welcome to the ' + ocAppName.Watch() + ' application', ID: 0 }, { - Src: 'assets/images/carousel2.jpg', + URL: 'assets/images/carousel2.jpg', Title: 'Carousel Image Two', SubText: 'This is the second image', ID: 1 }, { - Src: 'assets/images/carousel3.jpg', + URL: 'assets/images/carousel3.jpg', Title: 'Carousel Image Three', SubText: 'This is the third image', ID: 2 diff --git a/src/app/home/templates/home.html b/src/app/home/templates/home.html index 4dee9c26..5df7e147 100644 --- a/src/app/home/templates/home.html +++ b/src/app/home/templates/home.html @@ -2,7 +2,7 @@
- +