From f5f5851b2e493a944656c1af7491c0ba03d3e75e Mon Sep 17 00:00:00 2001 From: Andrew Joslin Date: Wed, 4 Jun 2014 14:03:44 -0600 Subject: [PATCH] fix(ionItem): make target attribute work properly Closes #1521 --- js/angular/directive/item.js | 5 +- test/unit/angular/directive/item.unit.js | 132 +++++++++++++ test/unit/angular/directive/list.unit.js | 191 ------------------- test/unit/controllers/listController.unit.js | 67 +++++++ 4 files changed, 203 insertions(+), 192 deletions(-) create mode 100644 test/unit/angular/directive/item.unit.js create mode 100644 test/unit/controllers/listController.unit.js diff --git a/js/angular/directive/item.js b/js/angular/directive/item.js index 29e9092740c..8556cb9bef1 100644 --- a/js/angular/directive/item.js +++ b/js/angular/directive/item.js @@ -1,5 +1,5 @@ var ITEM_TPL_CONTENT_ANCHOR = - ''; + ''; var ITEM_TPL_CONTENT = '
'; /** @@ -58,6 +58,9 @@ function($animate, $compile) { $scope.$href = function() { return $attrs.href || $attrs.ngHref; }; + $scope.$target = function() { + return $attrs.target || '_self'; + }; }; } }; diff --git a/test/unit/angular/directive/item.unit.js b/test/unit/angular/directive/item.unit.js new file mode 100644 index 00000000000..ee40d2dccc8 --- /dev/null +++ b/test/unit/angular/directive/item.unit.js @@ -0,0 +1,132 @@ +describe('ionItem directive', function() { + beforeEach(module('ionic')); + function setup(attrs, content) { + var el; + inject(function($rootScope, $compile) { + el = angular.element('').html(content || ''); + el.data('$ionListController', {}); + $compile(el)($rootScope); + $rootScope.$apply(); + }); + return el; + } + + it('should be simple item by default', function() { + var el = setup('', '{{1}} 2'); + expect(el.html()).toBe('1 2'); + expect(el.hasClass('item')).toBe(true); + expect(el.hasClass('item-complex')).toBe(false); + }); + it('should be complex if ui-sref', function() { + var el = setup('ui-sref="something"'); + expect(el.hasClass('item item-complex')).toBe(true); + expect(el.children()[0].tagName).toBe('A'); + expect(el.children().hasClass('item-content')).toBe(true); + }); + ['href', 'ng-href'].forEach(function(attr) { + it('should be complex anchor if '+attr+' is defined', function() { + var el = setup(attr+'="something/{{foo}}"'); + expect(el.hasClass('item item-complex')).toBe(true); + expect(el.children()[0].tagName).toBe('A'); + expect(el.children().hasClass('item-content')).toBe(true); + expect(el.children().attr('href')).toBe('something/'); + el.scope().$apply('foo = 44'); + expect(el.children().attr('href')).toBe('something/44'); + }); + }); + it('complex item should have target self by default', function() { + var el = setup('href="foo"'); + expect(el.find('a').attr('target')).toBe('_self'); + }); + it('complex item should have target if specified', function() { + var el = setup('href="foo" target="bar"'); + expect(el.find('a').attr('target')).toBe('bar'); + }); + ['ion-option-button','ion-reorder-button','ion-delete-button'].forEach(function(tag) { + it('should be complex div if '+tag+' is found', function() { + var el = setup('', tag); + expect(el.hasClass('item item-complex')).toBe(true); + expect(el.children()[0].tagName).toBe('DIV'); + expect(el.children().hasClass('item-content')).toBe(true); + expect(el.children().html()).toBe(tag); + }); + }); +}); + +describe('ionDeleteButton directive', function() { + beforeEach(module('ionic')); + it('should have delete button', inject(function($compile, $rootScope) { + var setSpy = jasmine.createSpy('setDeleteButton'); + var el = angular.element(''); + el.data('$ionListController', { + showDelete: function() { return false; } + }); + $compile(el)($rootScope.$new()); + $rootScope.$apply(); + + var deleteContainer = angular.element(el[0].querySelector('.item-left-edit.item-delete.ng-hide')); + expect(deleteContainer.length).toBe(1); + expect(deleteContainer.children().hasClass('button icon button-icon')).toBe(true); + })); + it('should unhide if delete is shown', inject(function($compile, $rootScope) { + var setSpy = jasmine.createSpy('setDeleteButton'); + var el = angular.element(''); + el.data('$ionListController', { + showDelete: function() { return true; } + }); + $compile(el)($rootScope.$new()); + $rootScope.$apply(); + + var deleteContainer = angular.element(el[0].querySelector('.item-left-edit.item-delete')); + expect(deleteContainer.length).toBe(1); + expect(deleteContainer.hasClass('ng-hide')).toBe(false); + })); +}); + +describe('ionReorderButton directive', function() { + beforeEach(module('ionic')); + it('should have reorder button', inject(function($compile, $rootScope) { + var setSpy = jasmine.createSpy('setReorderButton'); + var el = angular.element(''); + el.data('$ionListController', { + showReorder: function() { return false; } + }); + $compile(el)($rootScope.$new()); + $rootScope.$apply(); + + var reorderContainer = angular.element(el[0].querySelector('.item-right-edit.item-reorder.ng-hide')); + expect(reorderContainer.length).toBe(1); + expect(reorderContainer.children().hasClass('button icon button-icon')).toBe(true); + expect(reorderContainer.attr('data-prevent-scroll')).toBe('true'); + expect(reorderContainer.children().attr('data-prevent-scroll')).toBe('true'); + })); + it('should remove ng-hide if reorder is already active', inject(function($compile, $rootScope) { + var setSpy = jasmine.createSpy('setReorderButton'); + var el = angular.element(''); + el.data('$ionListController', { + showReorder: function() { return true; } + }); + $compile(el)($rootScope.$new()); + $rootScope.$apply(); + var reorderContainer = angular.element(el[0].querySelector('.item-right-edit.item-reorder')); + expect(reorderContainer.length).toBe(1); + expect(reorderContainer.hasClass('ng-hide')).toBe(false); + })); +}); + +describe('ionOptionButton directive', function() { + beforeEach(module('ionic')); + it('should have option button', inject(function($compile, $rootScope) { + var setSpy = jasmine.createSpy('setOptionButton'); + var el = angular.element(''); + el.data('$ionListController', { + showDelete: function() { return false; } + }); + $compile(el)($rootScope.$new()); + $rootScope.$apply(); + + var optionContainer = angular.element(el[0].querySelector('.item-options')); + expect(optionContainer.length).toBe(1); + expect(optionContainer.children().hasClass('button')).toBe(true); + })); +}); diff --git a/test/unit/angular/directive/list.unit.js b/test/unit/angular/directive/list.unit.js index 83191f10c0a..7b4583ef517 100644 --- a/test/unit/angular/directive/list.unit.js +++ b/test/unit/angular/directive/list.unit.js @@ -1,70 +1,3 @@ -describe('$ionicList controller', function() { - beforeEach(module('ionic')); - function setup(attrs) { - var ctrl; - inject(function($controller, $rootScope) { - var scope = $rootScope.$new(); - ctrl = $controller('$ionicList', { - $scope: scope, - $attrs: attrs || {}, - }); - ctrl.$scope = scope; - }); - return ctrl; - } - - it('should register with handle', inject(function($ionicListDelegate) { - spyOn($ionicListDelegate, '_registerInstance'); - var ctrl = setup({delegateHandle: 'foobar'}); - expect($ionicListDelegate._registerInstance) - .toHaveBeenCalledWith(ctrl, 'foobar'); - })); - - it('should register with given handle and deregister on destroy', inject(function($ionicListDelegate) { - var deregisterSpy = jasmine.createSpy('deregister'); - spyOn($ionicListDelegate, '_registerInstance').andCallFake(function() { - return deregisterSpy; - }); - var ctrl = setup({ - delegateHandle: 'something' - }); - expect($ionicListDelegate._registerInstance) - .toHaveBeenCalledWith(ctrl, 'something'); - - expect(deregisterSpy).not.toHaveBeenCalled(); - ctrl.$scope.$destroy(); - expect(deregisterSpy).toHaveBeenCalled(); - })); - - it('.showReorder sets/gets', function() { - var ctrl = setup(); - expect(ctrl.showReorder()).toBe(false); - ctrl.showReorder(true); - expect(ctrl.showReorder()).toBe(true); - }); - - it('.showDelete sets/gets', function() { - var ctrl = setup(); - expect(ctrl.showDelete()).toBe(false); - ctrl.showDelete(true); - expect(ctrl.showDelete()).toBe(true); - }); - - it('.canSwipeItems sets/gets', function() { - var ctrl = setup(); - expect(ctrl.canSwipeItems()).toBe(true); - ctrl.canSwipeItems(false); - expect(ctrl.canSwipeItems()).toBe(false); - }); - - it('.closeOptionButtons closes calls clearDragEffects', function() { - var ctrl = setup(); - ctrl.listView = { clearDragEffects: jasmine.createSpy('clearDragEffects') }; - ctrl.closeOptionButtons(); - expect(ctrl.listView.clearDragEffects).toHaveBeenCalled(); - }); -}); - describe('ionList directive', function() { beforeEach(module('ionic')); @@ -228,127 +161,3 @@ describe('ionList directive', function() { })); }); -describe('ionItem directive', function() { - beforeEach(module('ionic')); - function setup(attrs, content) { - var el; - inject(function($rootScope, $compile) { - el = angular.element('').html(content || ''); - el.data('$ionListController', {}); - $compile(el)($rootScope); - $rootScope.$apply(); - }); - return el; - } - - it('should be simple item by default', function() { - var el = setup('', '{{1}} 2'); - expect(el.html()).toBe('1 2'); - expect(el.hasClass('item')).toBe(true); - expect(el.hasClass('item-complex')).toBe(false); - }); - it('should be complex if ui-sref', function() { - var el = setup('ui-sref="something"'); - expect(el.hasClass('item item-complex')).toBe(true); - expect(el.children()[0].tagName).toBe('A'); - expect(el.children().hasClass('item-content')).toBe(true); - }); - ['href', 'ng-href'].forEach(function(attr) { - it('should be complex anchor if '+attr+' is defined', function() { - var el = setup(attr+'="something/{{foo}}"'); - expect(el.hasClass('item item-complex')).toBe(true); - expect(el.children()[0].tagName).toBe('A'); - expect(el.children().hasClass('item-content')).toBe(true); - expect(el.children().attr('href')).toBe('something/'); - el.scope().$apply('foo = 44'); - expect(el.children().attr('href')).toBe('something/44'); - }); - }); - ['ion-option-button','ion-reorder-button','ion-delete-button'].forEach(function(tag) { - it('should be complex div if '+tag+' is found', function() { - var el = setup('', tag); - expect(el.hasClass('item item-complex')).toBe(true); - expect(el.children()[0].tagName).toBe('DIV'); - expect(el.children().hasClass('item-content')).toBe(true); - expect(el.children().html()).toBe(tag); - }); - }); -}); - -describe('ionDeleteButton directive', function() { - beforeEach(module('ionic')); - it('should have delete button', inject(function($compile, $rootScope) { - var setSpy = jasmine.createSpy('setDeleteButton'); - var el = angular.element(''); - el.data('$ionListController', { - showDelete: function() { return false; } - }); - $compile(el)($rootScope.$new()); - $rootScope.$apply(); - - var deleteContainer = angular.element(el[0].querySelector('.item-left-edit.item-delete.ng-hide')); - expect(deleteContainer.length).toBe(1); - expect(deleteContainer.children().hasClass('button icon button-icon')).toBe(true); - })); - it('should unhide if delete is shown', inject(function($compile, $rootScope) { - var setSpy = jasmine.createSpy('setDeleteButton'); - var el = angular.element(''); - el.data('$ionListController', { - showDelete: function() { return true; } - }); - $compile(el)($rootScope.$new()); - $rootScope.$apply(); - - var deleteContainer = angular.element(el[0].querySelector('.item-left-edit.item-delete')); - expect(deleteContainer.length).toBe(1); - expect(deleteContainer.hasClass('ng-hide')).toBe(false); - })); -}); - -describe('ionReorderButton directive', function() { - beforeEach(module('ionic')); - it('should have reorder button', inject(function($compile, $rootScope) { - var setSpy = jasmine.createSpy('setReorderButton'); - var el = angular.element(''); - el.data('$ionListController', { - showReorder: function() { return false; } - }); - $compile(el)($rootScope.$new()); - $rootScope.$apply(); - - var reorderContainer = angular.element(el[0].querySelector('.item-right-edit.item-reorder.ng-hide')); - expect(reorderContainer.length).toBe(1); - expect(reorderContainer.children().hasClass('button icon button-icon')).toBe(true); - expect(reorderContainer.attr('data-prevent-scroll')).toBe('true'); - expect(reorderContainer.children().attr('data-prevent-scroll')).toBe('true'); - })); - it('should remove ng-hide if reorder is already active', inject(function($compile, $rootScope) { - var setSpy = jasmine.createSpy('setReorderButton'); - var el = angular.element(''); - el.data('$ionListController', { - showReorder: function() { return true; } - }); - $compile(el)($rootScope.$new()); - $rootScope.$apply(); - var reorderContainer = angular.element(el[0].querySelector('.item-right-edit.item-reorder')); - expect(reorderContainer.length).toBe(1); - expect(reorderContainer.hasClass('ng-hide')).toBe(false); - })); -}); - -describe('ionOptionButton directive', function() { - beforeEach(module('ionic')); - it('should have option button', inject(function($compile, $rootScope) { - var setSpy = jasmine.createSpy('setOptionButton'); - var el = angular.element(''); - el.data('$ionListController', { - showDelete: function() { return false; } - }); - $compile(el)($rootScope.$new()); - $rootScope.$apply(); - - var optionContainer = angular.element(el[0].querySelector('.item-options')); - expect(optionContainer.length).toBe(1); - expect(optionContainer.children().hasClass('button')).toBe(true); - })); -}); diff --git a/test/unit/controllers/listController.unit.js b/test/unit/controllers/listController.unit.js new file mode 100644 index 00000000000..ffd01c5d2bd --- /dev/null +++ b/test/unit/controllers/listController.unit.js @@ -0,0 +1,67 @@ +describe('$ionicList controller', function() { + beforeEach(module('ionic')); + function setup(attrs) { + var ctrl; + inject(function($controller, $rootScope) { + var scope = $rootScope.$new(); + ctrl = $controller('$ionicList', { + $scope: scope, + $attrs: attrs || {}, + }); + ctrl.$scope = scope; + }); + return ctrl; + } + + it('should register with handle', inject(function($ionicListDelegate) { + spyOn($ionicListDelegate, '_registerInstance'); + var ctrl = setup({delegateHandle: 'foobar'}); + expect($ionicListDelegate._registerInstance) + .toHaveBeenCalledWith(ctrl, 'foobar'); + })); + + it('should register with given handle and deregister on destroy', inject(function($ionicListDelegate) { + var deregisterSpy = jasmine.createSpy('deregister'); + spyOn($ionicListDelegate, '_registerInstance').andCallFake(function() { + return deregisterSpy; + }); + var ctrl = setup({ + delegateHandle: 'something' + }); + expect($ionicListDelegate._registerInstance) + .toHaveBeenCalledWith(ctrl, 'something'); + + expect(deregisterSpy).not.toHaveBeenCalled(); + ctrl.$scope.$destroy(); + expect(deregisterSpy).toHaveBeenCalled(); + })); + + it('.showReorder sets/gets', function() { + var ctrl = setup(); + expect(ctrl.showReorder()).toBe(false); + ctrl.showReorder(true); + expect(ctrl.showReorder()).toBe(true); + }); + + it('.showDelete sets/gets', function() { + var ctrl = setup(); + expect(ctrl.showDelete()).toBe(false); + ctrl.showDelete(true); + expect(ctrl.showDelete()).toBe(true); + }); + + it('.canSwipeItems sets/gets', function() { + var ctrl = setup(); + expect(ctrl.canSwipeItems()).toBe(true); + ctrl.canSwipeItems(false); + expect(ctrl.canSwipeItems()).toBe(false); + }); + + it('.closeOptionButtons closes calls clearDragEffects', function() { + var ctrl = setup(); + ctrl.listView = { clearDragEffects: jasmine.createSpy('clearDragEffects') }; + ctrl.closeOptionButtons(); + expect(ctrl.listView.clearDragEffects).toHaveBeenCalled(); + }); +}); +