mirror of
https://github.com/zhigang1992/angular.js.git
synced 2026-01-12 22:45:52 +08:00
Workaround for http://bugs.jquery.com/ticket/7292
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
build/
|
||||
angularjs.netrc
|
||||
jstd.log
|
||||
.DS_Store
|
||||
@@ -1,7 +1,7 @@
|
||||
server: http://localhost:9876
|
||||
|
||||
load:
|
||||
- lib/jasmine/jasmine-1.0.1.js
|
||||
- lib/jasmine-1.0.1/jasmine.js
|
||||
- lib/jasmine-jstd-adapter/JasmineAdapter.js
|
||||
- lib/jquery/jquery-1.4.2.js
|
||||
- test/jquery_alias.js
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
server: http://localhost:9876
|
||||
|
||||
load:
|
||||
- lib/jasmine/jasmine-1.0.1.js
|
||||
- lib/jasmine-1.0.1/jasmine.js
|
||||
- lib/jasmine-jstd-adapter/JasmineAdapter.js
|
||||
- lib/jquery/jquery-1.4.2.js
|
||||
- test/jquery_remove.js
|
||||
|
||||
20
lib/jasmine-1.0.1/MIT.LICENSE
Normal file
20
lib/jasmine-1.0.1/MIT.LICENSE
Normal file
@@ -0,0 +1,20 @@
|
||||
Copyright (c) 2008-2010 Pivotal Labs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
188
lib/jasmine-1.0.1/jasmine-html.js
Normal file
188
lib/jasmine-1.0.1/jasmine-html.js
Normal file
@@ -0,0 +1,188 @@
|
||||
jasmine.TrivialReporter = function(doc) {
|
||||
this.document = doc || document;
|
||||
this.suiteDivs = {};
|
||||
this.logRunningSpecs = false;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
|
||||
var el = document.createElement(type);
|
||||
|
||||
for (var i = 2; i < arguments.length; i++) {
|
||||
var child = arguments[i];
|
||||
|
||||
if (typeof child === 'string') {
|
||||
el.appendChild(document.createTextNode(child));
|
||||
} else {
|
||||
if (child) { el.appendChild(child); }
|
||||
}
|
||||
}
|
||||
|
||||
for (var attr in attrs) {
|
||||
if (attr == "className") {
|
||||
el[attr] = attrs[attr];
|
||||
} else {
|
||||
el.setAttribute(attr, attrs[attr]);
|
||||
}
|
||||
}
|
||||
|
||||
return el;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
|
||||
var showPassed, showSkipped;
|
||||
|
||||
this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' },
|
||||
this.createDom('div', { className: 'banner' },
|
||||
this.createDom('div', { className: 'logo' },
|
||||
this.createDom('a', { href: 'http://pivotal.github.com/jasmine/', target: "_blank" }, "Jasmine"),
|
||||
this.createDom('span', { className: 'version' }, runner.env.versionString())),
|
||||
this.createDom('div', { className: 'options' },
|
||||
"Show ",
|
||||
showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }),
|
||||
this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "),
|
||||
showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }),
|
||||
this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped")
|
||||
)
|
||||
),
|
||||
|
||||
this.runnerDiv = this.createDom('div', { className: 'runner running' },
|
||||
this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
|
||||
this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
|
||||
this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
|
||||
);
|
||||
|
||||
this.document.body.appendChild(this.outerDiv);
|
||||
|
||||
var suites = runner.suites();
|
||||
for (var i = 0; i < suites.length; i++) {
|
||||
var suite = suites[i];
|
||||
var suiteDiv = this.createDom('div', { className: 'suite' },
|
||||
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
|
||||
this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
|
||||
this.suiteDivs[suite.id] = suiteDiv;
|
||||
var parentDiv = this.outerDiv;
|
||||
if (suite.parentSuite) {
|
||||
parentDiv = this.suiteDivs[suite.parentSuite.id];
|
||||
}
|
||||
parentDiv.appendChild(suiteDiv);
|
||||
}
|
||||
|
||||
this.startedAt = new Date();
|
||||
|
||||
var self = this;
|
||||
showPassed.onclick = function(evt) {
|
||||
if (showPassed.checked) {
|
||||
self.outerDiv.className += ' show-passed';
|
||||
} else {
|
||||
self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
|
||||
}
|
||||
};
|
||||
|
||||
showSkipped.onclick = function(evt) {
|
||||
if (showSkipped.checked) {
|
||||
self.outerDiv.className += ' show-skipped';
|
||||
} else {
|
||||
self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
|
||||
var results = runner.results();
|
||||
var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
|
||||
this.runnerDiv.setAttribute("class", className);
|
||||
//do it twice for IE
|
||||
this.runnerDiv.setAttribute("className", className);
|
||||
var specs = runner.specs();
|
||||
var specCount = 0;
|
||||
for (var i = 0; i < specs.length; i++) {
|
||||
if (this.specFilter(specs[i])) {
|
||||
specCount++;
|
||||
}
|
||||
}
|
||||
var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
|
||||
message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s";
|
||||
this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild);
|
||||
|
||||
this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString()));
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
|
||||
var results = suite.results();
|
||||
var status = results.passed() ? 'passed' : 'failed';
|
||||
if (results.totalCount == 0) { // todo: change this to check results.skipped
|
||||
status = 'skipped';
|
||||
}
|
||||
this.suiteDivs[suite.id].className += " " + status;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) {
|
||||
if (this.logRunningSpecs) {
|
||||
this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
|
||||
var results = spec.results();
|
||||
var status = results.passed() ? 'passed' : 'failed';
|
||||
if (results.skipped) {
|
||||
status = 'skipped';
|
||||
}
|
||||
var specDiv = this.createDom('div', { className: 'spec ' + status },
|
||||
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
|
||||
this.createDom('a', {
|
||||
className: 'description',
|
||||
href: '?spec=' + encodeURIComponent(spec.getFullName()),
|
||||
title: spec.getFullName()
|
||||
}, spec.description));
|
||||
|
||||
|
||||
var resultItems = results.getItems();
|
||||
var messagesDiv = this.createDom('div', { className: 'messages' });
|
||||
for (var i = 0; i < resultItems.length; i++) {
|
||||
var result = resultItems[i];
|
||||
|
||||
if (result.type == 'log') {
|
||||
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
|
||||
} else if (result.type == 'expect' && result.passed && !result.passed()) {
|
||||
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
|
||||
|
||||
if (result.trace.stack) {
|
||||
messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (messagesDiv.childNodes.length > 0) {
|
||||
specDiv.appendChild(messagesDiv);
|
||||
}
|
||||
|
||||
this.suiteDivs[spec.suite.id].appendChild(specDiv);
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.log = function() {
|
||||
var console = jasmine.getGlobal().console;
|
||||
if (console && console.log) {
|
||||
if (console.log.apply) {
|
||||
console.log.apply(console, arguments);
|
||||
} else {
|
||||
console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.getLocation = function() {
|
||||
return this.document.location;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.specFilter = function(spec) {
|
||||
var paramMap = {};
|
||||
var params = this.getLocation().search.substring(1).split('&');
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
var p = params[i].split('=');
|
||||
paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
|
||||
}
|
||||
|
||||
if (!paramMap["spec"]) return true;
|
||||
return spec.getFullName().indexOf(paramMap["spec"]) == 0;
|
||||
};
|
||||
166
lib/jasmine-1.0.1/jasmine.css
Normal file
166
lib/jasmine-1.0.1/jasmine.css
Normal file
@@ -0,0 +1,166 @@
|
||||
body {
|
||||
font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif;
|
||||
}
|
||||
|
||||
|
||||
.jasmine_reporter a:visited, .jasmine_reporter a {
|
||||
color: #303;
|
||||
}
|
||||
|
||||
.jasmine_reporter a:hover, .jasmine_reporter a:active {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.run_spec {
|
||||
float:right;
|
||||
padding-right: 5px;
|
||||
font-size: .8em;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.jasmine_reporter {
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.banner {
|
||||
color: #303;
|
||||
background-color: #fef;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
float: left;
|
||||
font-size: 1.1em;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.logo .version {
|
||||
font-size: .6em;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.runner.running {
|
||||
background-color: yellow;
|
||||
}
|
||||
|
||||
|
||||
.options {
|
||||
text-align: right;
|
||||
font-size: .8em;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.suite {
|
||||
border: 1px outset gray;
|
||||
margin: 5px 0;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.suite .suite {
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.suite.passed {
|
||||
background-color: #dfd;
|
||||
}
|
||||
|
||||
.suite.failed {
|
||||
background-color: #fdd;
|
||||
}
|
||||
|
||||
.spec {
|
||||
margin: 5px;
|
||||
padding-left: 1em;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.spec.failed, .spec.passed, .spec.skipped {
|
||||
padding-bottom: 5px;
|
||||
border: 1px solid gray;
|
||||
}
|
||||
|
||||
.spec.failed {
|
||||
background-color: #fbb;
|
||||
border-color: red;
|
||||
}
|
||||
|
||||
.spec.passed {
|
||||
background-color: #bfb;
|
||||
border-color: green;
|
||||
}
|
||||
|
||||
.spec.skipped {
|
||||
background-color: #bbb;
|
||||
}
|
||||
|
||||
.messages {
|
||||
border-left: 1px dashed gray;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
.passed {
|
||||
background-color: #cfc;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.failed {
|
||||
background-color: #fbb;
|
||||
}
|
||||
|
||||
.skipped {
|
||||
color: #777;
|
||||
background-color: #eee;
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/*.resultMessage {*/
|
||||
/*white-space: pre;*/
|
||||
/*}*/
|
||||
|
||||
.resultMessage span.result {
|
||||
display: block;
|
||||
line-height: 2em;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.resultMessage .mismatch {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.stackTrace {
|
||||
white-space: pre;
|
||||
font-size: .8em;
|
||||
margin-left: 10px;
|
||||
max-height: 5em;
|
||||
overflow: auto;
|
||||
border: 1px inset red;
|
||||
padding: 1em;
|
||||
background: #eef;
|
||||
}
|
||||
|
||||
.finished-at {
|
||||
padding-left: 1em;
|
||||
font-size: .6em;
|
||||
}
|
||||
|
||||
.show-passed .passed,
|
||||
.show-skipped .skipped {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
#jasmine_content {
|
||||
position:fixed;
|
||||
right: 100%;
|
||||
}
|
||||
|
||||
.runner {
|
||||
border: 1px solid gray;
|
||||
display: block;
|
||||
margin: 5px 0;
|
||||
padding: 2px 0 2px 10px;
|
||||
}
|
||||
BIN
lib/jasmine/.DS_Store
vendored
BIN
lib/jasmine/.DS_Store
vendored
Binary file not shown.
@@ -1 +1 @@
|
||||
java -jar lib/jstestdriver/JsTestDriver.jar --port 9876
|
||||
java -jar lib/jstestdriver/JsTestDriver.jar --port 9876 --browserTimeout 20000
|
||||
|
||||
@@ -193,13 +193,6 @@ function browserTrigger(element, type) {
|
||||
case 'checkbox':
|
||||
element.checked = !element.checked;
|
||||
break;
|
||||
case 'text':
|
||||
case 'textarea':
|
||||
case 'password':
|
||||
// TODO: FIX THIS HACK
|
||||
// for some reason on IE 'change' event does not fire in
|
||||
// jQuery but keyup does. So we are hacking it!
|
||||
type = 'keyup';
|
||||
}
|
||||
element.fireEvent('on' + type);
|
||||
} else {
|
||||
@@ -229,3 +222,4 @@ function browserTrigger(element, type) {
|
||||
return parentTrigger.apply(this, arguments);
|
||||
};
|
||||
})(_jQuery.fn);
|
||||
|
||||
|
||||
103
test/manual.html
Normal file
103
test/manual.html
Normal file
@@ -0,0 +1,103 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Jasmine Test Runner</title>
|
||||
<link rel="stylesheet" type="text/css" href="../lib/jasmine-1.0.1/jasmine.css">
|
||||
<script type="text/javascript" src="../lib/jasmine-1.0.1/jasmine.js"></script>
|
||||
<script type="text/javascript" src="../lib/jasmine-1.0.1/jasmine-html.js"></script>
|
||||
|
||||
|
||||
<!-- include source files here... -->
|
||||
<script type="text/javascript" src="../lib/jquery/jquery-1.4.2.js"></script>
|
||||
<script type="text/javascript"> var _jQuery = $;</script>
|
||||
|
||||
<script type="text/javascript" src="../src/Angular.js"></script>
|
||||
<script type="text/javascript" src="../src/JSON.js"></script>
|
||||
<script type="text/javascript" src="../src/Compiler.js"></script>
|
||||
<script type="text/javascript" src="../src/Scope.js"></script>
|
||||
<script type="text/javascript" src="../src/Injector.js"></script>
|
||||
<script type="text/javascript" src="../src/jqLite.js"></script>
|
||||
<script type="text/javascript" src="../src/parser.js"></script>
|
||||
<script type="text/javascript" src="../src/Resource.js"></script>
|
||||
<script type="text/javascript" src="../src/Browser.js"></script>
|
||||
<script type="text/javascript" src="../src/AngularPublic.js"></script>
|
||||
<script type="text/javascript" src="../src/services.js"></script>
|
||||
<script type="text/javascript" src="../src/apis.js"></script>
|
||||
<script type="text/javascript" src="../src/filters.js"></script>
|
||||
<script type="text/javascript" src="../src/formatters.js"></script>
|
||||
<script type="text/javascript" src="../src/validators.js"></script>
|
||||
<script type="text/javascript" src="../src/directives.js"></script>
|
||||
<script type="text/javascript" src="../src/markups.js"></script>
|
||||
<script type="text/javascript" src="../src/widgets.js"></script>
|
||||
|
||||
<script type="text/javascript" src="../src/scenario/Scenario.js"></script>
|
||||
<script type="text/javascript" src="../src/scenario/Application.js"></script>
|
||||
<script type="text/javascript" src="../src/scenario/Describe.js"></script>
|
||||
<script type="text/javascript" src="../src/scenario/Future.js"></script>
|
||||
<script type="text/javascript" src="../src/scenario/HtmlUI.js"></script>
|
||||
<script type="text/javascript" src="../src/scenario/Runner.js"></script>
|
||||
<script type="text/javascript" src="../src/scenario/SpecRunner.js"></script>
|
||||
<script type="text/javascript" src="../src/scenario/dsl.js"></script>
|
||||
<script type="text/javascript" src="../src/scenario/matchers.js"></script>
|
||||
|
||||
<script type="text/javascript" src="angular-mocks.js"></script>
|
||||
<script type="text/javascript" src="testabilityPatch.js"></script>
|
||||
|
||||
<!-- include spec files here... -->
|
||||
<script type="text/javascript">
|
||||
describe('manual', function(){
|
||||
var scope;
|
||||
|
||||
function compile(html, initialScope, parent) {
|
||||
var compiler = new Compiler(angularTextMarkup, angularAttrMarkup, angularDirective, angularWidget);
|
||||
var element = self.element = jqLite(html);
|
||||
scope = compiler.compile(element)(element);
|
||||
|
||||
if (parent) parent.append(element);
|
||||
|
||||
extend(scope, initialScope);
|
||||
scope.$init();
|
||||
return {node:element, scope:scope};
|
||||
};
|
||||
|
||||
it('should debug', function(){
|
||||
var x = compile(
|
||||
'<select name="selection" ng:format="number">' +
|
||||
'<option value="{{$index}}" ng:repeat="name in [\'A\', \'B\', \'C\']">{{name}}</option>' +
|
||||
'</select>');
|
||||
expect(scope.selection).toEqual(undefined);
|
||||
|
||||
browserTrigger(element[0].childNodes[2], 'change');
|
||||
expect(scope.selection).toEqual(1);
|
||||
|
||||
scope.selection = 2;
|
||||
scope.$eval();
|
||||
expect(element[0].childNodes[3].selected).toEqual(true);
|
||||
});
|
||||
|
||||
it('should reproduce', function(){
|
||||
var select = $('<select name=""><option>a</option></select>');
|
||||
var log = '';
|
||||
select.bind('change', function(){ log += 'change;'; });
|
||||
select.bind('click', function(){ log += 'click;'; });
|
||||
select.bind('keyup', function(){ log += 'keyup;'; });
|
||||
select[0].attachEvent('onchange', function(){ log += 'CHANGE;';});
|
||||
select[0].fireEvent('onfocusout');
|
||||
select[0].fireEvent('onchange');
|
||||
select[0].fireEvent('onclick');
|
||||
select[0].fireEvent('onkeyup');
|
||||
expect(log).toEqual('CHANGE;change;click;keyup;');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script type="text/javascript">
|
||||
jasmine.getEnv().addReporter(new jasmine.TrivialReporter());
|
||||
jasmine.getEnv().execute();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,5 +1,16 @@
|
||||
jstd = jstestdriver;
|
||||
dump = bind(jstd.console, jstd.console.log);
|
||||
/**
|
||||
* Here is the problem: http://bugs.jquery.com/ticket/7292
|
||||
* basically jQuery treats change event on some browsers (IE) as a
|
||||
* special event and changes it form 'change' to 'click/keyup' and
|
||||
* few others. This horrible hack removes the special treatment
|
||||
*/
|
||||
_jQuery.event.special.change = undefined;
|
||||
|
||||
|
||||
if (window.jstestdriver) {
|
||||
jstd = jstestdriver;
|
||||
dump = bind(jstd.console, jstd.console.log);
|
||||
}
|
||||
|
||||
beforeEach(function(){
|
||||
this.addMatchers({
|
||||
|
||||
@@ -345,9 +345,9 @@ describe("widget", function(){
|
||||
it('should initialize to selected', function(){
|
||||
compile(
|
||||
'<select name="selection">' +
|
||||
'<option>A</option>' +
|
||||
'<option selected>B</option>' +
|
||||
'</select>');
|
||||
'<option>A</option>' +
|
||||
'<option selected>B</option>' +
|
||||
'</select>');
|
||||
expect(scope.selection).toEqual('B');
|
||||
scope.selection = 'A';
|
||||
scope.$eval();
|
||||
|
||||
Reference in New Issue
Block a user