aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--angularFiles.js4
-rw-r--r--src/ngScenario/Scenario.js96
-rw-r--r--src/ngScenario/browserTrigger.js116
-rw-r--r--test/testabilityPatch.js67
4 files changed, 166 insertions, 117 deletions
diff --git a/angularFiles.js b/angularFiles.js
index b2c23a8f..30c65df1 100644
--- a/angularFiles.js
+++ b/angularFiles.js
@@ -80,6 +80,7 @@ angularFiles = {
'angularScenario': [
'src/ngScenario/Scenario.js',
+ 'src/ngScenario/browserTrigger.js',
'src/ngScenario/Application.js',
'src/ngScenario/Describe.js',
'src/ngScenario/Future.js',
@@ -147,7 +148,6 @@ angularFiles = {
'lib/jasmine/jasmine.js',
'lib/jasmine-jstd-adapter/JasmineAdapter.js',
'build/angular.js',
- 'build/angular-scenario.js',
'src/ngMock/angular-mocks.js',
'src/ngCookies/cookies.js',
'src/ngResource/resource.js',
@@ -157,7 +157,9 @@ angularFiles = {
'src/ngSanitize/sanitize.js',
'src/ngSanitize/directive/ngBindHtml.js',
'src/ngSanitize/filter/linky.js',
+ 'src/ngScenario/browserTrigger.js',
'test/matchers.js',
+ 'test/testabilityPatch.js',
'test/ngMock/*.js',
'test/ngCookies/*.js',
'test/ngResource/*.js',
diff --git a/src/ngScenario/Scenario.js b/src/ngScenario/Scenario.js
index 1ed9d119..f78e3931 100644
--- a/src/ngScenario/Scenario.js
+++ b/src/ngScenario/Scenario.js
@@ -223,102 +223,6 @@ function callerFile(offset) {
};
}
-/**
- * Triggers a browser event. Attempts to choose the right event if one is
- * not specified.
- *
- * @param {Object} element Either a wrapped jQuery/jqLite node or a DOMElement
- * @param {string} type Optional event type.
- * @param {Array.<string>=} keys Optional list of pressed keys
- * (valid values: 'alt', 'meta', 'shift', 'ctrl')
- * @param {number} x Optional x-coordinate for mouse/touch events.
- * @param {number} y Optional y-coordinate for mouse/touch events.
- */
-function browserTrigger(element, type, keys, x, y) {
- if (element && !element.nodeName) element = element[0];
- if (!element) return;
- if (!type) {
- type = {
- 'text': 'change',
- 'textarea': 'change',
- 'hidden': 'change',
- 'password': 'change',
- 'button': 'click',
- 'submit': 'click',
- 'reset': 'click',
- 'image': 'click',
- 'checkbox': 'click',
- 'radio': 'click',
- 'select-one': 'change',
- 'select-multiple': 'change'
- }[lowercase(element.type)] || 'click';
- }
- if (lowercase(nodeName_(element)) == 'option') {
- element.parentNode.value = element.value;
- element = element.parentNode;
- type = 'change';
- }
-
- keys = keys || [];
- function pressed(key) {
- return indexOf(keys, key) !== -1;
- }
-
- if (msie < 9) {
- switch(element.type) {
- case 'radio':
- case 'checkbox':
- element.checked = !element.checked;
- break;
- }
- // WTF!!! Error: Unspecified error.
- // Don't know why, but some elements when detached seem to be in inconsistent state and
- // calling .fireEvent() on them will result in very unhelpful error (Error: Unspecified error)
- // forcing the browser to compute the element position (by reading its CSS)
- // puts the element in consistent state.
- element.style.posLeft;
-
- // TODO(vojta): create event objects with pressed keys to get it working on IE<9
- var ret = element.fireEvent('on' + type);
- if (lowercase(element.type) == 'submit') {
- while(element) {
- if (lowercase(element.nodeName) == 'form') {
- element.fireEvent('onsubmit');
- break;
- }
- element = element.parentNode;
- }
- }
- return ret;
- } else {
- var evnt = document.createEvent('MouseEvents'),
- originalPreventDefault = evnt.preventDefault,
- iframe = _jQuery('#application iframe')[0],
- appWindow = iframe ? iframe.contentWindow : window,
- fakeProcessDefault = true,
- finalProcessDefault,
- angular = appWindow.angular || {};
-
- // igor: temporary fix for https://bugzilla.mozilla.org/show_bug.cgi?id=684208
- angular['ff-684208-preventDefault'] = false;
- evnt.preventDefault = function() {
- fakeProcessDefault = false;
- return originalPreventDefault.apply(evnt, arguments);
- };
-
- x = x || 0;
- y = y || 0;
- evnt.initMouseEvent(type, true, true, window, 0, x, y, x, y, pressed('ctrl'), pressed('alt'),
- pressed('shift'), pressed('meta'), 0, element);
-
- element.dispatchEvent(evnt);
- finalProcessDefault = !(angular['ff-684208-preventDefault'] || !fakeProcessDefault);
-
- delete angular['ff-684208-preventDefault'];
-
- return finalProcessDefault;
- }
-}
/**
* Don't use the jQuery trigger method since it works incorrectly.
diff --git a/src/ngScenario/browserTrigger.js b/src/ngScenario/browserTrigger.js
new file mode 100644
index 00000000..dc7a9916
--- /dev/null
+++ b/src/ngScenario/browserTrigger.js
@@ -0,0 +1,116 @@
+'use strict';
+
+(function() {
+ var msie = parseInt((/msie (\d+)/.exec(navigator.userAgent.toLowerCase()) || [])[1], 10);
+
+ function indexOf(array, obj) {
+ if (array.indexOf) return array.indexOf(obj);
+
+ for ( var i = 0; i < array.length; i++) {
+ if (obj === array[i]) return i;
+ }
+ return -1;
+ }
+
+
+
+ /**
+ * Triggers a browser event. Attempts to choose the right event if one is
+ * not specified.
+ *
+ * @param {Object} element Either a wrapped jQuery/jqLite node or a DOMElement
+ * @param {string} eventType Optional event type.
+ * @param {Array.<string>=} keys Optional list of pressed keys
+ * (valid values: 'alt', 'meta', 'shift', 'ctrl')
+ * @param {number} x Optional x-coordinate for mouse/touch events.
+ * @param {number} y Optional y-coordinate for mouse/touch events.
+ */
+ window.browserTrigger = function browserTrigger(element, eventType, keys, x, y) {
+ if (element && !element.nodeName) element = element[0];
+ if (!element) return;
+
+ var inputType = (element.type) ? element.type.toLowerCase() : null,
+ nodeName = element.nodeName.toLowerCase();
+
+ if (!eventType) {
+ eventType = {
+ 'text': 'change',
+ 'textarea': 'change',
+ 'hidden': 'change',
+ 'password': 'change',
+ 'button': 'click',
+ 'submit': 'click',
+ 'reset': 'click',
+ 'image': 'click',
+ 'checkbox': 'click',
+ 'radio': 'click',
+ 'select-one': 'change',
+ 'select-multiple': 'change',
+ '_default_': 'click'
+ }[inputType || '_default_'];
+ }
+
+ if (nodeName == 'option') {
+ element.parentNode.value = element.value;
+ element = element.parentNode;
+ eventType = 'change';
+ }
+
+ keys = keys || [];
+ function pressed(key) {
+ return indexOf(keys, key) !== -1;
+ }
+
+ if (msie < 9) {
+ if (inputType == 'radio' || inputType == 'checkbox') {
+ element.checked = !element.checked;
+ }
+
+ // WTF!!! Error: Unspecified error.
+ // Don't know why, but some elements when detached seem to be in inconsistent state and
+ // calling .fireEvent() on them will result in very unhelpful error (Error: Unspecified error)
+ // forcing the browser to compute the element position (by reading its CSS)
+ // puts the element in consistent state.
+ element.style.posLeft;
+
+ // TODO(vojta): create event objects with pressed keys to get it working on IE<9
+ var ret = element.fireEvent('on' + eventType);
+ if (inputType == 'submit') {
+ while(element) {
+ if (element.nodeName.toLowerCase() == 'form') {
+ element.fireEvent('onsubmit');
+ break;
+ }
+ element = element.parentNode;
+ }
+ }
+ return ret;
+ } else {
+ var evnt = document.createEvent('MouseEvents'),
+ originalPreventDefault = evnt.preventDefault,
+ appWindow = element.ownerDocument.defaultView,
+ fakeProcessDefault = true,
+ finalProcessDefault,
+ angular = appWindow.angular || {};
+
+ // igor: temporary fix for https://bugzilla.mozilla.org/show_bug.cgi?id=684208
+ angular['ff-684208-preventDefault'] = false;
+ evnt.preventDefault = function() {
+ fakeProcessDefault = false;
+ return originalPreventDefault.apply(evnt, arguments);
+ };
+
+ x = x || 0;
+ y = y || 0;
+ evnt.initMouseEvent(eventType, true, true, window, 0, x, y, x, y, pressed('ctrl'), pressed('alt'),
+ pressed('shift'), pressed('meta'), 0, element);
+
+ element.dispatchEvent(evnt);
+ finalProcessDefault = !(angular['ff-684208-preventDefault'] || !fakeProcessDefault);
+
+ delete angular['ff-684208-preventDefault'];
+
+ return finalProcessDefault;
+ }
+ }
+}());
diff --git a/test/testabilityPatch.js b/test/testabilityPatch.js
index a4d4b46f..679294ee 100644
--- a/test/testabilityPatch.js
+++ b/test/testabilityPatch.js
@@ -6,25 +6,31 @@
* special event and changes it form 'change' to 'click/keydown' and
* few others. This horrible hack removes the special treatment
*/
-_jQuery.event.special.change = undefined;
+if (window._jQuery) _jQuery.event.special.change = undefined;
+
+if (window.bindJQuery) bindJQuery();
-bindJQuery();
beforeEach(function() {
- publishExternalAPI(angular);
+ // all this stuff is not needed for module tests, where jqlite and publishExternalAPI and jqLite are not global vars
+ if (window.publishExternalAPI) {
+ publishExternalAPI(angular);
+
+ // workaround for IE bug https://plus.google.com/104744871076396904202/posts/Kqjuj6RSbbT
+ // IE overwrite window.jQuery with undefined because of empty jQuery var statement, so we have to
+ // correct this, but only if we are not running in jqLite mode
+ if (!_jqLiteMode && _jQuery !== jQuery) {
+ jQuery = _jQuery;
+ }
- // workaround for IE bug https://plus.google.com/104744871076396904202/posts/Kqjuj6RSbbT
- // IE overwrite window.jQuery with undefined because of empty jQuery var statement, so we have to
- // correct this, but only if we are not running in jqLite mode
- if (!_jqLiteMode && _jQuery !== jQuery) {
- jQuery = _jQuery;
+ // This resets global id counter;
+ uid = ['0', '0', '0'];
+
+ // reset to jQuery or default to us.
+ bindJQuery();
}
- // This resets global id counter;
- uid = ['0', '0', '0'];
- // reset to jQuery or default to us.
- bindJQuery();
- jqLite(document.body).html('').removeData();
+ angular.element(document.body).html('').removeData();
});
afterEach(function() {
@@ -45,29 +51,50 @@ afterEach(function() {
// This line should be enabled as soon as this bug is fixed: http://bugs.jquery.com/ticket/11775
//var cache = jqLite.cache;
- var cache = JQLite.cache;
+ var cache = angular.element.cache;
forEachSorted(cache, function(expando, key){
- forEach(expando.data, function(value, key){
+ angular.forEach(expando.data, function(value, key){
count ++;
if (value.$element) {
dump('LEAK', key, value.$id, sortedHtml(value.$element));
} else {
- dump('LEAK', key, toJson(value));
+ dump('LEAK', key, angular.toJson(value));
}
});
});
if (count) {
throw new Error('Found jqCache references that were not deallocated! count: ' + count);
}
+
+
+ // copied from Angular.js
+ // we need these two methods here so that we can run module tests with wrapped angular.js
+ function sortedKeys(obj) {
+ var keys = [];
+ for (var key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ keys.push(key);
+ }
+ }
+ return keys.sort();
+ }
+
+ function forEachSorted(obj, iterator, context) {
+ var keys = sortedKeys(obj);
+ for ( var i = 0; i < keys.length; i++) {
+ iterator.call(context, obj[keys[i]], keys[i]);
+ }
+ return keys;
+ }
});
function dealoc(obj) {
- var jqCache = jqLite.cache;
+ var jqCache = angular.element.cache;
if (obj) {
- if (isElement(obj)) {
- cleanup(jqLite(obj));
+ if (angular.isElement(obj)) {
+ cleanup(angular.element(obj));
} else {
for(var key in jqCache) {
var value = jqCache[key];
@@ -81,7 +108,7 @@ function dealoc(obj) {
function cleanup(element) {
element.unbind().removeData();
for ( var i = 0, children = element.contents() || []; i < children.length; i++) {
- cleanup(jqLite(children[i]));
+ cleanup(angular.element(children[i]));
}
}
}