mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-03-24 02:10:24 +00:00
test(modules): fix module tests which got disabled by ngMobile
When ngMobile was merged in, we accidentaly included angular-scenario.js in the test file set for modules. Loading this file overrode jasmine's `it` and `describe` global functions which essentially disabled all of ~200 unit tests for wrapped modules. This change refactors the code to run the wrapped module tests. I had to extract browserTrigger from scenario runner in order to achieve this without code duplication.
This commit is contained in:
parent
695c54c17b
commit
5da6b125a7
4 changed files with 166 additions and 117 deletions
4
angularFiles.js
vendored
4
angularFiles.js
vendored
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
116
src/ngScenario/browserTrigger.js
Normal file
116
src/ngScenario/browserTrigger.js
Normal file
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}());
|
||||
|
|
@ -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]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue