aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Rakefile7
-rw-r--r--css/angular-scenario.css40
-rw-r--r--scenario/widgets-scenario.js17
-rw-r--r--scenario/widgets.html2
-rw-r--r--src/Angular.js4
-rw-r--r--src/jqLite.js11
-rw-r--r--src/scenario/Scenario.js49
-rw-r--r--src/scenario/SpecRunner.js34
-rw-r--r--src/scenario/angular.prefix1
-rw-r--r--src/scenario/angular.suffix13
-rw-r--r--src/scenario/bootstrap.js8
-rwxr-xr-xtest.sh4
-rw-r--r--test/BinderTest.js4
-rw-r--r--test/scenario/dslSpec.js42
-rw-r--r--test/testabilityPatch.js19
-rw-r--r--test/widgetsSpec.js16
16 files changed, 119 insertions, 152 deletions
diff --git a/Rakefile b/Rakefile
index 8d3e50c8..70425603 100644
--- a/Rakefile
+++ b/Rakefile
@@ -53,7 +53,7 @@ end
desc 'Compile Scenario'
task :compile_scenario do
-
+
deps = [
'lib/jquery/jquery-1.4.2.js',
'src/scenario/angular.prefix',
@@ -66,7 +66,7 @@ task :compile_scenario do
File.open('angular-scenario.js', 'w') do |f|
f.write(%x{#{concat}})
- f.write(gen_css('css/angular.css'))
+ f.write(gen_css('css/angular.css') + "\n")
f.write(gen_css('css/angular-scenario.css'))
end
end
@@ -234,7 +234,8 @@ def gen_css(cssFile, minify = false)
end
#escape for js
- css.gsub! /'/, "\\'"
+ css.gsub! /\\/, "\\\\\\"
+ css.gsub! /'/, "\\\\'"
css.gsub! /\n/, "\\n"
return %Q{document.write('<style type="text/css">#{css}</style>');}
diff --git a/css/angular-scenario.css b/css/angular-scenario.css
index 2cf24b19..3462ecef 100644
--- a/css/angular-scenario.css
+++ b/css/angular-scenario.css
@@ -38,15 +38,15 @@ body {
padding: 0.5em;
font-size: 1.1em;
}
-
+
#status-legend {
margin-top: 10px;
margin-right: 10px;
}
-#header,
+#header,
#frame,
-.test-info,
+.test-info,
.test-actions li {
overflow: hidden;
}
@@ -67,10 +67,10 @@ body {
#frame iframe {
border: none;
}
-
-.tests li,
+
+.tests li,
.test-actions li,
-.test-it li,
+.test-it li,
.test-it ol,
.status-display {
list-style-type: none;
@@ -83,14 +83,14 @@ body {
padding: 0;
}
-.test-info {
+.test-info {
margin-left: 1em;
margin-top: 0.5em;
border-radius: 8px 0 0 8px;
-webkit-border-radius: 8px 0 0 8px;
-moz-border-radius: 8px 0 0 8px;
}
-
+
.test-it ol {
margin-left: 2.5em;
}
@@ -104,7 +104,7 @@ body {
padding: 5px 10px;
}
-.timer-result,
+.timer-result,
.test-title {
display: inline-block;
margin: 0;
@@ -129,7 +129,7 @@ body {
}
.test-actions .status-pending .test-title:before {
- content: 'ยป ';
+ content: '\00bb\00A0';
}
/** Colors */
@@ -150,7 +150,7 @@ body {
#frame {
border: 1px solid #BABAD1;
}
-
+
.test-describe .test-describe {
border-left: 1px solid #BABAD1;
border-right: 1px solid #BABAD1;
@@ -168,29 +168,29 @@ body {
.status-display .status-success,
.status-success .test-info {
- background-color: #B1D7A1;
+ background-color: #B1D7A1;
}
-
+
.status-display .status-failure,
-.status-failure .test-info {
- background-color: #FF8286;
+.status-failure .test-info {
+ background-color: #FF8286;
}
.status-display .status-error,
-.status-error .test-info {
+.status-error .test-info {
background-color: black;
color: white;
}
-.test-actions .status-success .test-title {
- color: #30B30A;
+.test-actions .status-success .test-title {
+ color: #30B30A;
}
-.test-actions .status-failure .test-title {
+.test-actions .status-failure .test-title {
color: #DF0000;
}
-.test-actions .status-error .test-title {
+.test-actions .status-error .test-title {
color: black;
}
diff --git a/scenario/widgets-scenario.js b/scenario/widgets-scenario.js
index befc481c..0cb189f7 100644
--- a/scenario/widgets-scenario.js
+++ b/scenario/widgets-scenario.js
@@ -1,17 +1,17 @@
describe('widgets', function() {
it('should verify that basic widgets work', function(){
navigateTo('widgets.html');
-
+
using('#text-basic-box').input('text.basic').enter('Carlos');
expect(binding('text.basic')).toEqual('Carlos');
input('text.basic').enter('Carlos Santana');
expect(binding('text.basic')).not().toEqual('Carlos Boozer');
-
+
input('text.password').enter('secret');
expect(binding('text.password')).toEqual('secret');
-
+
expect(binding('text.hidden')).toEqual('hiddenValue');
-
+
expect(binding('gender')).toEqual('male');
input('gender').select('female');
expect(using('#gender-box').binding('gender')).toEqual('female');
@@ -19,10 +19,11 @@ describe('widgets', function() {
expect(repeater('#repeater-row ul li').count()).toEqual(2);
expect(repeater('#repeater-row ul li').row(1)).toEqual(['adam']);
expect(repeater('#repeater-row ul li').column('name')).toEqual(['misko', 'adam']);
-
+
select('select').option('B');
expect(binding('select')).toEqual('B');
-
+
+
select('multiselect').options('A', 'C');
expect(binding('multiselect').fromJson()).toEqual(['A', 'C']);
@@ -35,14 +36,14 @@ describe('widgets', function() {
expect(binding('button').fromJson()).toEqual({'count': 3});
element('input[type="image"]').click();
expect(binding('button').fromJson()).toEqual({'count': 4});
-
+
/**
* Custom value parser for futures.
*/
function checkboxParser(value) {
return angular.fromJson(value.substring(value.indexOf('=')+1));
}
-
+
input('checkbox.tea').check();
expect(binding('checkbox').parsedWith(checkboxParser)).toEqual({coffee: false, tea: false});
input('checkbox.coffee').check();
diff --git a/scenario/widgets.html b/scenario/widgets.html
index 80a0a22f..8960f5f4 100644
--- a/scenario/widgets.html
+++ b/scenario/widgets.html
@@ -2,7 +2,7 @@
<html xmlns:ng="http://angularjs.org">
<head>
<link rel="stylesheet" type="text/css" href="style.css"/>
- <script type="text/javascript" src="../lib/jquery/jquery-1.4.2.js"></script>
+ <script type="text/javascript" src="../libs/jquery/jquery-1.4.2.js"></script>
<script type="text/javascript" src="../src/angular-bootstrap.js" ng:autobind></script>
</head>
<body ng:init="$window.$scope = this">
diff --git a/src/Angular.js b/src/Angular.js
index 8cacb9e4..b97c4226 100644
--- a/src/Angular.js
+++ b/src/Angular.js
@@ -146,12 +146,12 @@ function HTML(html) {
if (msie) {
nodeName = function(element) {
- element = element[0] || element;
+ element = element.nodeName ? element : element[0];
return (element.scopeName && element.scopeName != 'HTML' ) ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;
};
} else {
nodeName = function(element) {
- return (element[0] || element).nodeName;
+ return element.nodeName ? element.nodeName : element[0].nodeName;
};
}
diff --git a/src/jqLite.js b/src/jqLite.js
index a2ea286b..6c70f2a8 100644
--- a/src/jqLite.js
+++ b/src/jqLite.js
@@ -118,17 +118,6 @@ JQLite.prototype = {
});
},
- trigger: function(type) {
- if (msie) {
- this[0].fireEvent('on' + type);
- } else {
- var evnt = document.createEvent('MouseEvents'),
- element = this[0];
- evnt.initMouseEvent(type, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, element);
- element.dispatchEvent(evnt);
- }
- },
-
replaceWith: function(replaceNode) {
this[0].parentNode.replaceChild(jqLite(replaceNode)[0], this[0]);
},
diff --git a/src/scenario/Scenario.js b/src/scenario/Scenario.js
index e93f6b2e..ba206632 100644
--- a/src/scenario/Scenario.js
+++ b/src/scenario/Scenario.js
@@ -1,5 +1,5 @@
/**
- * Setup file for the Scenario.
+ * Setup file for the Scenario.
* Must be first in the compilation/bootstrap list.
*/
@@ -19,7 +19,7 @@ angular.scenario.ui = {};
* functions.
*
* @param {String} The name of the statement
- * @param {Function} Factory function(application), return a function for
+ * @param {Function} Factory function(application), return a function for
* the statement.
*/
angular.scenario.dsl = function(name, fn) {
@@ -50,7 +50,7 @@ angular.scenario.dsl = function(name, fn) {
/**
* Defines a new matcher for use with the expects() statement. The value
- * this.actual (like in Jasmine) is available in your matcher to compare
+ * this.actual (like in Jasmine) is available in your matcher to compare
* against. Your function should return a boolean. The future is automatically
* created for you.
*
@@ -83,7 +83,7 @@ angular.scenario.matcher = function(name, fn) {
*
* @param {Array} list to iterate over
* @param {Function} Callback function(value, continueFunction)
- * @param {Function} Callback function(error, result) called when iteration
+ * @param {Function} Callback function(error, result) called when iteration
* finishes or an error occurs.
*/
function asyncForEach(list, iterator, done) {
@@ -101,3 +101,44 @@ function asyncForEach(list, iterator, done) {
}
loop();
}
+
+
+function browserTrigger(element, type) {
+ if (!element.nodeName) element = element[0];
+ 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'
+ }[element.type] || 'click';
+ }
+ if (lowercase(nodeName(element)) == 'option') {
+ element.parentNode.value = element.value;
+ element = element.parentNode;
+ type = 'change';
+ }
+ if (msie) {
+ element.fireEvent('on' + type);
+ } else {
+ var evnt = document.createEvent('MouseEvents');
+ evnt.initMouseEvent(type, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, element);
+ element.dispatchEvent(evnt);
+ }
+}
+
+_jQuery.fn.trigger = function(type) {
+ return this.each(function(index, node) {
+ browserTrigger(node, type);
+ });
+};
+
+
diff --git a/src/scenario/SpecRunner.js b/src/scenario/SpecRunner.js
index d6cbdcdc..26fa9b91 100644
--- a/src/scenario/SpecRunner.js
+++ b/src/scenario/SpecRunner.js
@@ -21,7 +21,7 @@ angular.scenario.SpecRunner = function() {
*/
angular.scenario.SpecRunner.prototype.run = function(ui, spec, specDone) {
var specUI = ui.addSpec(spec);
-
+
try {
spec.fn.call(this);
} catch (e) {
@@ -29,9 +29,9 @@ angular.scenario.SpecRunner.prototype.run = function(ui, spec, specDone) {
specDone();
return;
}
-
+
asyncForEach(
- this.futures,
+ this.futures,
function(future, futureDone) {
var stepUI = specUI.addStep(future.name);
try {
@@ -43,10 +43,10 @@ angular.scenario.SpecRunner.prototype.run = function(ui, spec, specDone) {
stepUI.error(e);
throw e;
}
- },
+ },
function(e) {
- specUI.finish(e);
- specDone();
+ specUI.finish(e);
+ specDone();
}
);
};
@@ -89,29 +89,9 @@ angular.scenario.SpecRunner.prototype.addFutureAction = function(name, behavior)
};
}
- result.trigger = function(type) {
- result.each(function(index, node) {
- var element = $window.angular.element(node);
- //TODO(esprehn): HACK!!! Something is broken in angular event dispatching
- // and if the real jQuery is used we need to set the attribtue after too
- if (angular.isDefined(element.selector)) {
- if (type === 'click' && node.nodeName.toLowerCase() === 'input') {
- element.attr('checked', !element.attr('checked'));
- }
- }
- //TODO(esprehn): HACK!! See above comment.
- element.trigger(type);
- if (angular.isDefined(element.selector)) {
- if (type === 'click' && node.nodeName.toLowerCase() === 'input') {
- element.attr('checked', !element.attr('checked'));
- }
- }
- });
- };
-
return result;
});
-
+
try {
behavior.call(this, $window, $document, done);
} catch(e) {
diff --git a/src/scenario/angular.prefix b/src/scenario/angular.prefix
index a1b4e151..d6660d61 100644
--- a/src/scenario/angular.prefix
+++ b/src/scenario/angular.prefix
@@ -22,3 +22,4 @@
* THE SOFTWARE.
*/
(function(window, document, previousOnLoad){
+ var _jQuery = window.jQuery.noConflict(true); \ No newline at end of file
diff --git a/src/scenario/angular.suffix b/src/scenario/angular.suffix
index 53d99dd2..c38f0ab5 100644
--- a/src/scenario/angular.suffix
+++ b/src/scenario/angular.suffix
@@ -4,22 +4,19 @@
try {
if (previousOnLoad) previousOnLoad();
} catch(e) {}
- jQuery(document.body).append(
+ _jQuery(document.body).append(
'<div id="runner"></div>' +
'<div id="frame"></div>'
);
- var frame = jQuery('#frame');
- var runner = jQuery('#runner');
+ var frame = _jQuery('#frame');
+ var runner = _jQuery('#runner');
var application = new angular.scenario.Application(frame);
var ui = new angular.scenario.ui.Html(runner);
- $scenario.run(ui, application, function(error) {
+ $scenario.run(ui, application, angular.scenario.SpecRunner, function(error) {
frame.remove();
if (error) {
if (window.console) {
- console.log(error);
- if (error.stack) {
- console.log(error.stack);
- }
+ console.log(error.stack || error);
} else {
// Do something for IE
alert(error);
diff --git a/src/scenario/bootstrap.js b/src/scenario/bootstrap.js
index 014c636d..4661bfb2 100644
--- a/src/scenario/bootstrap.js
+++ b/src/scenario/bootstrap.js
@@ -10,7 +10,7 @@
}
}
})();
-
+
function addScript(path) {
document.write('<script type="text/javascript" src="' + prefix + path + '"></script>');
}
@@ -46,6 +46,11 @@
addCSS("../../css/angular-scenario.css");
addScript("../../lib/jquery/jquery-1.4.2.js");
+ document.write(
+ '<script type="text/javascript">' +
+ 'var _jQuery = jQuery.noConflict(true);' +
+ '</script>'
+ );
addScript("../angular-bootstrap.js");
addScript("Scenario.js");
@@ -61,7 +66,6 @@
// Create the runner (which also sets up the global API)
document.write(
'<script type="text/javascript">' +
- 'var _jQuery = jQuery.noConflict(true);' +
'var $scenario = new angular.scenario.Runner(window);' +
'</script>'
);
diff --git a/test.sh b/test.sh
index 19a74d4b..a43c1ddc 100755
--- a/test.sh
+++ b/test.sh
@@ -3,5 +3,5 @@ if [[ $tests = "" ]]; then
tests="all"
fi
-java -jar lib/jstestdriver/JsTestDriver.jar --tests "$tests"
-#java -jar lib/jstestdriver/JsTestDriver.jar --tests "$tests" --config jsTestDriver-jquery.conf
+#java -jar lib/jstestdriver/JsTestDriver.jar --tests "$tests"
+java -jar lib/jstestdriver/JsTestDriver.jar --tests "$tests" --config jsTestDriver-jquery.conf
diff --git a/test/BinderTest.js b/test/BinderTest.js
index 5d72206d..daaaeffe 100644
--- a/test/BinderTest.js
+++ b/test/BinderTest.js
@@ -589,13 +589,13 @@ BinderTest.prototype.testItShouldSelectTheCorrectRadioBox = function() {
var female = jqLite(c.node[0].childNodes[0]);
var male = jqLite(c.node[0].childNodes[1]);
- click(female);
+ browserTrigger(female);
assertEquals("female", c.scope.sex);
assertEquals(true, female[0].checked);
assertEquals(false, male[0].checked);
assertEquals("female", female.val());
- click(male);
+ browserTrigger(male);
assertEquals("male", c.scope.sex);
assertEquals(false, female[0].checked);
assertEquals(true, male[0].checked);
diff --git a/test/scenario/dslSpec.js b/test/scenario/dslSpec.js
index a30fe165..dd489d86 100644
--- a/test/scenario/dslSpec.js
+++ b/test/scenario/dslSpec.js
@@ -10,24 +10,6 @@ AngularMock.prototype.reset = function() {
this.log = [];
};
-AngularMock.prototype.element = function(node) {
- this.log.push('element(' + node.nodeName.toLowerCase() + ')');
- var mock = this;
- return {
- selector: '',
- attr: function(name, value) {
- mock.log.push('attr(' + name + (angular.isDefined(value) ? ',' + value : '') + ')');
- return _jQuery.fn.attr.apply(_jQuery(node), arguments);
- },
- trigger: function(type) {
- mock.log.push('element().trigger(' + type + ')');
- //TODO(esprehn): See the HACK!! in the SpecRunner. This avoids
- // triggering the second part of the hack in tests
- delete this.selector;
- }
- };
-};
-
AngularMock.prototype.$browser = function() {
this.log.push('$brower()');
return this;
@@ -181,7 +163,7 @@ describe("angular.scenario.dsl", function() {
$root.dsl.select('test').options('A', 'B');
expect(_jQuery('[name="test"]').val()).toEqual(['A','B']);
});
-
+
it('should fail to select multiple options on non-multiple select', function() {
doc.append('<select name="test"></select>');
$root.dsl.select('test').options('A', 'B');
@@ -198,7 +180,7 @@ describe("angular.scenario.dsl", function() {
});
$root.dsl.element('a').click();
});
-
+
it('should get attribute', function() {
doc.append('<div id="test" class="foo"></div>');
$root.dsl.element('#test').attr('class');
@@ -210,13 +192,13 @@ describe("angular.scenario.dsl", function() {
$root.dsl.element('#test').attr('class', 'bam');
expect(doc.find('div').attr('class')).toEqual('bam');
});
-
+
it('should get val', function() {
doc.append('<input value="bar">');
$root.dsl.element('input').val();
expect($root.futureResult).toEqual('bar');
});
-
+
it('should set val', function() {
doc.append('<input value="bar">');
$root.dsl.element('input').val('baz');
@@ -259,7 +241,7 @@ describe("angular.scenario.dsl", function() {
$root.dsl.binding('foo.bar');
expect($root.futureResult).toEqual('some value');
});
-
+
it('should select binding in template by name', function() {
doc.append('<pre ng:bind-template="foo {{bar}} baz">foo some baz</pre>');
$root.dsl.binding('bar');
@@ -271,7 +253,7 @@ describe("angular.scenario.dsl", function() {
expect($root.futureError).toMatch(/did not match/);
});
});
-
+
describe('Using', function() {
it('should prefix selector in $document.elements()', function() {
var chain;
@@ -281,8 +263,6 @@ describe("angular.scenario.dsl", function() {
);
chain = $root.dsl.using('div#test2');
chain.input('test.input').enter('foo');
- expect($window.angular.log).toContain('element(input)');
- expect($window.angular.log).toContain('element().trigger(change)');
var inputs = _jQuery('input[name="test.input"]');
expect(inputs.first().val()).toEqual('something');
expect(inputs.last().val()).toEqual('foo');
@@ -294,8 +274,6 @@ describe("angular.scenario.dsl", function() {
doc.append('<input name="test.input" value="something">');
var chain = $root.dsl.input('test.input');
chain.enter('foo');
- expect($window.angular.log).toContain('element(input)');
- expect($window.angular.log).toContain('element().trigger(change)');
expect(_jQuery('input[name="test.input"]').val()).toEqual('foo');
});
@@ -311,14 +289,10 @@ describe("angular.scenario.dsl", function() {
attr('checked')).toBeTruthy();
var chain = $root.dsl.input('test.input');
chain.check();
- expect($window.angular.log).toContain('element(input)');
- expect($window.angular.log).toContain('element().trigger(click)');
expect(_jQuery('input[name="test.input"]').
attr('checked')).toBeFalsy();
$window.angular.reset();
chain.check();
- expect($window.angular.log).toContain('element(input)');
- expect($window.angular.log).toContain('element().trigger(click)');
expect(_jQuery('input[name="test.input"]').
attr('checked')).toBeTruthy();
});
@@ -342,8 +316,6 @@ describe("angular.scenario.dsl", function() {
attr('checked')).toBeFalsy();
var chain = $root.dsl.input('test.input');
chain.select('foo');
- expect($window.angular.log).toContain('element(input)');
- expect($window.angular.log).toContain('element().trigger(click)');
expect(_jQuery('input[name="0@test.input"][value="bar"]').
attr('checked')).toBeFalsy();
expect(_jQuery('input[name="0@test.input"][value="foo"]').
@@ -356,6 +328,6 @@ describe("angular.scenario.dsl", function() {
expect($root.futureError).toMatch(/did not match/);
});
});
-
+
});
});
diff --git a/test/testabilityPatch.js b/test/testabilityPatch.js
index 59d8f4ac..247faa19 100644
--- a/test/testabilityPatch.js
+++ b/test/testabilityPatch.js
@@ -189,25 +189,6 @@ function assertThrows(error, fn){
log = noop;
error = noop;
-function click(element) {
- element = jqLite(element);
- var type = lowercase(element.attr('type'));
- var name = lowercase(nodeName(element));
- if (msie) {
- if (name == 'input') {
- if (type == 'radio' || type == 'checkbox') {
- element[0].checked = ! element[0].checked;
- }
- }
- }
- if (name == 'option') {
- element.parent().val(element.val());
- JQLite.prototype.trigger.call(element.parent(), 'change');
- } else {
- JQLite.prototype.trigger.call(element, 'click');
- }
-}
-
function rethrow(e) {
if(e) {
throw e;
diff --git a/test/widgetsSpec.js b/test/widgetsSpec.js
index 31596a48..cc254eff 100644
--- a/test/widgetsSpec.js
+++ b/test/widgetsSpec.js
@@ -128,10 +128,10 @@ describe("widget", function(){
it('should support type="checkbox"', function(){
compile('<input type="checkBox" name="checkbox" checked ng:change="action = true"/>');
expect(scope.checkbox).toEqual(true);
- click(element);
+ browserTrigger(element);
expect(scope.checkbox).toEqual(false);
expect(scope.action).toEqual(true);
- click(element);
+ browserTrigger(element);
expect(scope.checkbox).toEqual(true);
});
@@ -151,7 +151,7 @@ describe("widget", function(){
expect(scope.state).toEqual("Worked");
expect(scope.$element[0].checked).toEqual(true);
- click(scope.$element);
+ browserTrigger(scope.$element);
expect(scope.state).toEqual("Failed");
expect(scope.$element[0].checked).toEqual(false);
@@ -278,13 +278,13 @@ describe("widget", function(){
it('should call ng:change on button click', function(){
compile('<input type="button" value="Click Me" ng:change="clicked = true"/>');
- click(element);
+ browserTrigger(element);
expect(scope.$get('clicked')).toEqual(true);
});
it('should support button alias', function(){
compile('<button ng:change="clicked = true">Click Me</button>');
- click(element);
+ browserTrigger(element);
expect(scope.$get('clicked')).toEqual(true);
});
@@ -310,7 +310,7 @@ describe("widget", function(){
expect(b.checked).toEqual(true);
expect(scope.clicked).not.toBeDefined();
- click(a);
+ browserTrigger(a);
expect(scope.chose).toEqual('A');
expect(scope.clicked).toEqual(1);
});
@@ -363,7 +363,7 @@ describe("widget", function(){
// childNodes[0] is repeater comment
expect(scope.selection).toEqual(undefined);
- click(element[0].childNodes[2]);
+ browserTrigger(element[0].childNodes[2], 'change');
expect(scope.selection).toEqual(1);
scope.selection = 2;
@@ -423,7 +423,7 @@ describe("widget", function(){
it('should report error on ng:change exception', function(){
compile('<button ng:change="a-2=x">click</button>');
- click(element);
+ browserTrigger(element);
expect(element.hasClass('ng-exception')).toBeTruthy();
});
});