aboutsummaryrefslogtreecommitdiffstats
path: root/test/ngMobile/directive/ngClickSpec.js
diff options
context:
space:
mode:
Diffstat (limited to 'test/ngMobile/directive/ngClickSpec.js')
-rw-r--r--test/ngMobile/directive/ngClickSpec.js295
1 files changed, 295 insertions, 0 deletions
diff --git a/test/ngMobile/directive/ngClickSpec.js b/test/ngMobile/directive/ngClickSpec.js
new file mode 100644
index 00000000..2f42662d
--- /dev/null
+++ b/test/ngMobile/directive/ngClickSpec.js
@@ -0,0 +1,295 @@
+'use strict';
+
+describe('ngClick (mobile)', function() {
+ var element, time, orig_now;
+
+ // TODO(braden): Once we have other touch-friendly browsers on CI, allow them here.
+ // Currently Firefox and IE refuse to fire touch events.
+ var chrome = /chrome/.test(navigator.userAgent.toLowerCase());
+ if (!chrome) {
+ return;
+ }
+
+ function mockTime() {
+ return time;
+ }
+
+
+ beforeEach(function() {
+ module('ngMobile');
+ orig_now = Date.now;
+ time = 0;
+ Date.now = mockTime;
+ });
+
+ afterEach(function() {
+ dealoc(element);
+ Date.now = orig_now;
+ });
+
+
+ it('should get called on a tap', inject(function($rootScope, $compile) {
+ element = $compile('<div ng-click="tapped = true"></div>')($rootScope);
+ $rootScope.$digest();
+ expect($rootScope.tapped).toBeUndefined();
+
+ browserTrigger(element, 'touchstart');
+ browserTrigger(element, 'touchend');
+ expect($rootScope.tapped).toEqual(true);
+ }));
+
+
+ it('should pass event object', inject(function($rootScope, $compile) {
+ element = $compile('<div ng-click="event = $event"></div>')($rootScope);
+ $rootScope.$digest();
+
+ browserTrigger(element, 'touchstart');
+ browserTrigger(element, 'touchend');
+ expect($rootScope.event).toBeDefined();
+ }));
+
+
+ it('should not click if the touch is held too long', inject(function($rootScope, $compile, $rootElement) {
+ element = $compile('<div ng-click="count = count + 1"></div>')($rootScope);
+ $rootElement.append(element);
+ $rootScope.count = 0;
+ $rootScope.$digest();
+
+ expect($rootScope.count).toBe(0);
+
+ time = 10;
+ browserTrigger(element, 'touchstart', [], 10, 10);
+
+ time = 900;
+ browserTrigger(element, 'touchend', [], 10, 10);
+
+ expect($rootScope.count).toBe(0);
+ }));
+
+
+ it('should not click if the touchend is too far away', inject(function($rootScope, $compile, $rootElement) {
+ element = $compile('<div ng-click="tapped = true"></div>')($rootScope);
+ $rootElement.append(element);
+ $rootScope.$digest();
+
+ expect($rootScope.tapped).toBeUndefined();
+
+ browserTrigger(element, 'touchstart', [], 10, 10);
+ browserTrigger(element, 'touchend', [], 400, 400);
+
+ expect($rootScope.tapped).toBeUndefined();
+ }));
+
+
+ it('should not click if a touchmove comes before touchend', inject(function($rootScope, $compile, $rootElement) {
+ element = $compile('<div ng-tap="tapped = true"></div>')($rootScope);
+ $rootElement.append(element);
+ $rootScope.$digest();
+
+ expect($rootScope.tapped).toBeUndefined();
+
+ browserTrigger(element, 'touchstart', [], 10, 10);
+ browserTrigger(element, 'touchmove');
+ browserTrigger(element, 'touchend', [], 400, 400);
+
+ expect($rootScope.tapped).toBeUndefined();
+ }));
+
+
+ describe('the clickbuster', function() {
+ var element1, element2;
+
+ beforeEach(inject(function($rootElement, $document) {
+ $document.find('body').append($rootElement);
+ }));
+
+ afterEach(inject(function($document) {
+ $document.find('body').html('');
+ }));
+
+
+ it('should cancel the following click event', inject(function($rootScope, $compile, $rootElement, $document) {
+ element = $compile('<div ng-click="count = count + 1"></div>')($rootScope);
+ $rootElement.append(element);
+
+ $rootScope.count = 0;
+ $rootScope.$digest();
+
+ expect($rootScope.count).toBe(0);
+
+ // Fire touchstart at 10ms, touchend at 50ms, the click at 300ms.
+ time = 10;
+ browserTrigger(element, 'touchstart', [], 10, 10);
+
+ time = 50;
+ browserTrigger(element, 'touchend', [], 10, 10);
+
+ expect($rootScope.count).toBe(1);
+
+ time = 100;
+ browserTrigger(element, 'click', [], 10, 10);
+
+ expect($rootScope.count).toBe(1);
+ }));
+
+
+ it('should cancel the following click event even when the element has changed', inject(
+ function($rootScope, $compile, $rootElement) {
+ $rootElement.append(
+ '<div ng-show="!tapped" ng-click="count1 = count1 + 1; tapped = true">x</div>' +
+ '<div ng-show="tapped" ng-click="count2 = count2 + 1">y</div>'
+ );
+ $compile($rootElement)($rootScope);
+
+ element1 = $rootElement.find('div').eq(0);
+ element2 = $rootElement.find('div').eq(1);
+
+ $rootScope.count1 = 0;
+ $rootScope.count2 = 0;
+
+ $rootScope.$digest();
+
+ expect($rootScope.count1).toBe(0);
+ expect($rootScope.count2).toBe(0);
+
+ time = 10;
+ browserTrigger(element1, 'touchstart', [], 10, 10);
+
+ time = 50;
+ browserTrigger(element1, 'touchend', [], 10, 10);
+
+ expect($rootScope.count1).toBe(1);
+
+ time = 100;
+ browserTrigger(element2, 'click', [], 10, 10);
+
+ expect($rootScope.count1).toBe(1);
+ expect($rootScope.count2).toBe(0);
+ }));
+
+
+ it('should not cancel clicks on distant elements', inject(function($rootScope, $compile, $rootElement) {
+ $rootElement.append(
+ '<div ng-click="count1 = count1 + 1">x</div>' +
+ '<div ng-click="count2 = count2 + 1">y</div>'
+ );
+ $compile($rootElement)($rootScope);
+
+ element1 = $rootElement.find('div').eq(0);
+ element2 = $rootElement.find('div').eq(1);
+
+ $rootScope.count1 = 0;
+ $rootScope.count2 = 0;
+
+ $rootScope.$digest();
+
+ expect($rootScope.count1).toBe(0);
+ expect($rootScope.count2).toBe(0);
+
+ time = 10;
+ browserTrigger(element1, 'touchstart', [], 10, 10);
+
+ time = 50;
+ browserTrigger(element1, 'touchend', [], 10, 10);
+
+ expect($rootScope.count1).toBe(1);
+
+ time = 90;
+ browserTrigger(element1, 'click', [], 10, 10);
+
+ expect($rootScope.count1).toBe(1);
+
+ time = 100;
+ browserTrigger(element1, 'touchstart', [], 10, 10);
+
+ time = 130;
+ browserTrigger(element1, 'touchend', [], 10, 10);
+
+ expect($rootScope.count1).toBe(2);
+
+ // Click on other element that should go through.
+ time = 150;
+ browserTrigger(element2, 'touchstart', [], 100, 120);
+ browserTrigger(element2, 'touchend', [], 100, 120);
+ browserTrigger(element2, 'click', [], 100, 120);
+
+ expect($rootScope.count2).toBe(1);
+
+ // Click event for the element that should be busted.
+ time = 200;
+ browserTrigger(element1, 'click', [], 10, 10);
+
+ expect($rootScope.count1).toBe(2);
+ expect($rootScope.count2).toBe(1);
+ }));
+
+
+ it('should not cancel clicks that come long after', inject(function($rootScope, $compile) {
+ element1 = $compile('<div ng-click="count = count + 1"></div>')($rootScope);
+
+ $rootScope.count = 0;
+
+ $rootScope.$digest();
+
+ expect($rootScope.count).toBe(0);
+
+ time = 10;
+ browserTrigger(element1, 'touchstart', [], 10, 10);
+
+ time = 50;
+ browserTrigger(element1, 'touchend', [], 10, 10);
+ expect($rootScope.count).toBe(1);
+
+ time = 2700;
+ browserTrigger(element1, 'click', [], 10, 10);
+
+ expect($rootScope.count).toBe(2);
+ }));
+
+
+ it('should not cancel clicks that come long after', inject(function($rootScope, $compile) {
+ element1 = $compile('<div ng-click="count = count + 1"></div>')($rootScope);
+
+ $rootScope.count = 0;
+
+ $rootScope.$digest();
+
+ expect($rootScope.count).toBe(0);
+
+ time = 10;
+ browserTrigger(element1, 'touchstart', [], 10, 10);
+
+ time = 50;
+ browserTrigger(element1, 'touchend', [], 10, 10);
+
+ expect($rootScope.count).toBe(1);
+
+ time = 2700;
+ browserTrigger(element1, 'click', [], 10, 10);
+
+ expect($rootScope.count).toBe(2);
+ }));
+ });
+
+
+ describe('click fallback', function() {
+
+ it('should treat a click as a tap on desktop', inject(function($rootScope, $compile) {
+ element = $compile('<div ng-click="tapped = true"></div>')($rootScope);
+ $rootScope.$digest();
+ expect($rootScope.tapped).toBeFalsy();
+
+ browserTrigger(element, 'click');
+ expect($rootScope.tapped).toEqual(true);
+ }));
+
+
+ it('should pass event object', inject(function($rootScope, $compile) {
+ element = $compile('<div ng-click="event = $event"></div>')($rootScope);
+ $rootScope.$digest();
+
+ browserTrigger(element, 'click');
+ expect($rootScope.event).toBeDefined();
+ }));
+ });
+});