├── lib
├── jasmine
│ ├── jasmine-html.js
│ ├── jasmine.css
│ ├── jasmine.js
│ └── jasmine_favicon.png
└── jquery
│ └── jquery-1.7.1.js
├── readme.md
└── src
├── jquery.debounce
├── jquery.debounce.js
├── jquery.debounce.min.js
├── jquery.debounce.specs.html
└── jquery.debounce.specs.js
├── jquery.identify
├── jquery.identify.js
├── jquery.identify.min.js
├── jquery.identify.specs.html
└── jquery.identify.specs.js
├── jquery.inherit
├── jquery.inherit.js
├── jquery.inherit.min.js
├── jquery.inherit.specs.html
├── jquery.inherit.specs.js
└── readme.md
├── jquery.memoize
├── jquery.memoize.js
├── jquery.memoize.min.js
├── jquery.memoize.specs.html
├── jquery.memoize.specs.js
└── readme.md
└── jquery.observable
├── jquery.observable.js
├── jquery.observable.min.js
├── jquery.observable.specs.html
├── jquery.observable.specs.js
└── readme.md
/lib/jasmine/jasmine-html.js:
--------------------------------------------------------------------------------
1 | jasmine.TrivialReporter = function(doc) {
2 | this.document = doc || document;
3 | this.suiteDivs = {};
4 | this.logRunningSpecs = false;
5 | };
6 |
7 | jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
8 | var el = document.createElement(type);
9 |
10 | for (var i = 2; i < arguments.length; i++) {
11 | var child = arguments[i];
12 |
13 | if (typeof child === 'string') {
14 | el.appendChild(document.createTextNode(child));
15 | } else {
16 | if (child) { el.appendChild(child); }
17 | }
18 | }
19 |
20 | for (var attr in attrs) {
21 | if (attr == "className") {
22 | el[attr] = attrs[attr];
23 | } else {
24 | el.setAttribute(attr, attrs[attr]);
25 | }
26 | }
27 |
28 | return el;
29 | };
30 |
31 | jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
32 | var showPassed, showSkipped;
33 |
34 | this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' },
35 | this.createDom('div', { className: 'banner' },
36 | this.createDom('div', { className: 'logo' },
37 | this.createDom('span', { className: 'title' }, "Jasmine"),
38 | this.createDom('span', { className: 'version' }, runner.env.versionString())),
39 | this.createDom('div', { className: 'options' },
40 | "Show ",
41 | showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }),
42 | this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "),
43 | showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }),
44 | this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped")
45 | )
46 | ),
47 |
48 | this.runnerDiv = this.createDom('div', { className: 'runner running' },
49 | this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
50 | this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
51 | this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
52 | );
53 |
54 | this.document.body.appendChild(this.outerDiv);
55 |
56 | var suites = runner.suites();
57 | for (var i = 0; i < suites.length; i++) {
58 | var suite = suites[i];
59 | var suiteDiv = this.createDom('div', { className: 'suite' },
60 | this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
61 | this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
62 | this.suiteDivs[suite.id] = suiteDiv;
63 | var parentDiv = this.outerDiv;
64 | if (suite.parentSuite) {
65 | parentDiv = this.suiteDivs[suite.parentSuite.id];
66 | }
67 | parentDiv.appendChild(suiteDiv);
68 | }
69 |
70 | this.startedAt = new Date();
71 |
72 | var self = this;
73 | showPassed.onclick = function(evt) {
74 | if (showPassed.checked) {
75 | self.outerDiv.className += ' show-passed';
76 | } else {
77 | self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
78 | }
79 | };
80 |
81 | showSkipped.onclick = function(evt) {
82 | if (showSkipped.checked) {
83 | self.outerDiv.className += ' show-skipped';
84 | } else {
85 | self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
86 | }
87 | };
88 | };
89 |
90 | jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
91 | var results = runner.results();
92 | var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
93 | this.runnerDiv.setAttribute("class", className);
94 | //do it twice for IE
95 | this.runnerDiv.setAttribute("className", className);
96 | var specs = runner.specs();
97 | var specCount = 0;
98 | for (var i = 0; i < specs.length; i++) {
99 | if (this.specFilter(specs[i])) {
100 | specCount++;
101 | }
102 | }
103 | var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
104 | message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s";
105 | this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild);
106 |
107 | this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString()));
108 | };
109 |
110 | jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
111 | var results = suite.results();
112 | var status = results.passed() ? 'passed' : 'failed';
113 | if (results.totalCount === 0) { // todo: change this to check results.skipped
114 | status = 'skipped';
115 | }
116 | this.suiteDivs[suite.id].className += " " + status;
117 | };
118 |
119 | jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) {
120 | if (this.logRunningSpecs) {
121 | this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
122 | }
123 | };
124 |
125 | jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
126 | var results = spec.results();
127 | var status = results.passed() ? 'passed' : 'failed';
128 | if (results.skipped) {
129 | status = 'skipped';
130 | }
131 | var specDiv = this.createDom('div', { className: 'spec ' + status },
132 | this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
133 | this.createDom('a', {
134 | className: 'description',
135 | href: '?spec=' + encodeURIComponent(spec.getFullName()),
136 | title: spec.getFullName()
137 | }, spec.description));
138 |
139 |
140 | var resultItems = results.getItems();
141 | var messagesDiv = this.createDom('div', { className: 'messages' });
142 | for (var i = 0; i < resultItems.length; i++) {
143 | var result = resultItems[i];
144 |
145 | if (result.type == 'log') {
146 | messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
147 | } else if (result.type == 'expect' && result.passed && !result.passed()) {
148 | messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
149 |
150 | if (result.trace.stack) {
151 | messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
152 | }
153 | }
154 | }
155 |
156 | if (messagesDiv.childNodes.length > 0) {
157 | specDiv.appendChild(messagesDiv);
158 | }
159 |
160 | this.suiteDivs[spec.suite.id].appendChild(specDiv);
161 | };
162 |
163 | jasmine.TrivialReporter.prototype.log = function() {
164 | var console = jasmine.getGlobal().console;
165 | if (console && console.log) {
166 | if (console.log.apply) {
167 | console.log.apply(console, arguments);
168 | } else {
169 | console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
170 | }
171 | }
172 | };
173 |
174 | jasmine.TrivialReporter.prototype.getLocation = function() {
175 | return this.document.location;
176 | };
177 |
178 | jasmine.TrivialReporter.prototype.specFilter = function(spec) {
179 | var paramMap = {};
180 | var params = this.getLocation().search.substring(1).split('&');
181 | for (var i = 0; i < params.length; i++) {
182 | var p = params[i].split('=');
183 | paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
184 | }
185 |
186 | if (!paramMap.spec) {
187 | return true;
188 | }
189 | return spec.getFullName().indexOf(paramMap.spec) === 0;
190 | };
191 |
--------------------------------------------------------------------------------
/lib/jasmine/jasmine.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif;
3 | }
4 |
5 |
6 | .jasmine_reporter a:visited, .jasmine_reporter a {
7 | color: #303;
8 | }
9 |
10 | .jasmine_reporter a:hover, .jasmine_reporter a:active {
11 | color: blue;
12 | }
13 |
14 | .run_spec {
15 | float:right;
16 | padding-right: 5px;
17 | font-size: .8em;
18 | text-decoration: none;
19 | }
20 |
21 | .jasmine_reporter {
22 | margin: 0 5px;
23 | }
24 |
25 | .banner {
26 | color: #303;
27 | background-color: #fef;
28 | padding: 5px;
29 | }
30 |
31 | .logo {
32 | float: left;
33 | font-size: 1.1em;
34 | padding-left: 5px;
35 | }
36 |
37 | .logo .version {
38 | font-size: .6em;
39 | padding-left: 1em;
40 | }
41 |
42 | .runner.running {
43 | background-color: yellow;
44 | }
45 |
46 |
47 | .options {
48 | text-align: right;
49 | font-size: .8em;
50 | }
51 |
52 |
53 |
54 |
55 | .suite {
56 | border: 1px outset gray;
57 | margin: 5px 0;
58 | padding-left: 1em;
59 | }
60 |
61 | .suite .suite {
62 | margin: 5px;
63 | }
64 |
65 | .suite.passed {
66 | background-color: #dfd;
67 | }
68 |
69 | .suite.failed {
70 | background-color: #fdd;
71 | }
72 |
73 | .spec {
74 | margin: 5px;
75 | padding-left: 1em;
76 | clear: both;
77 | }
78 |
79 | .spec.failed, .spec.passed, .spec.skipped {
80 | padding-bottom: 5px;
81 | border: 1px solid gray;
82 | }
83 |
84 | .spec.failed {
85 | background-color: #fbb;
86 | border-color: red;
87 | }
88 |
89 | .spec.passed {
90 | background-color: #bfb;
91 | border-color: green;
92 | }
93 |
94 | .spec.skipped {
95 | background-color: #bbb;
96 | }
97 |
98 | .messages {
99 | border-left: 1px dashed gray;
100 | padding-left: 1em;
101 | padding-right: 1em;
102 | }
103 |
104 | .passed {
105 | background-color: #cfc;
106 | display: none;
107 | }
108 |
109 | .failed {
110 | background-color: #fbb;
111 | }
112 |
113 | .skipped {
114 | color: #777;
115 | background-color: #eee;
116 | display: none;
117 | }
118 |
119 |
120 | /*.resultMessage {*/
121 | /*white-space: pre;*/
122 | /*}*/
123 |
124 | .resultMessage span.result {
125 | display: block;
126 | line-height: 2em;
127 | color: black;
128 | }
129 |
130 | .resultMessage .mismatch {
131 | color: black;
132 | }
133 |
134 | .stackTrace {
135 | white-space: pre;
136 | font-size: .8em;
137 | margin-left: 10px;
138 | max-height: 5em;
139 | overflow: auto;
140 | border: 1px inset red;
141 | padding: 1em;
142 | background: #eef;
143 | }
144 |
145 | .finished-at {
146 | padding-left: 1em;
147 | font-size: .6em;
148 | }
149 |
150 | .show-passed .passed,
151 | .show-skipped .skipped {
152 | display: block;
153 | }
154 |
155 |
156 | #jasmine_content {
157 | position:fixed;
158 | right: 100%;
159 | }
160 |
161 | .runner {
162 | border: 1px solid gray;
163 | display: block;
164 | margin: 5px 0;
165 | padding: 2px 0 2px 10px;
166 | }
167 |
--------------------------------------------------------------------------------
/lib/jasmine/jasmine.js:
--------------------------------------------------------------------------------
1 | var isCommonJS = typeof window == "undefined";
2 |
3 | /**
4 | * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework.
5 | *
6 | * @namespace
7 | */
8 | var jasmine = {};
9 | if (isCommonJS) exports.jasmine = jasmine;
10 | /**
11 | * @private
12 | */
13 | jasmine.unimplementedMethod_ = function() {
14 | throw new Error("unimplemented method");
15 | };
16 |
17 | /**
18 | * Use jasmine.undefined
instead of undefined
, since undefined
is just
19 | * a plain old variable and may be redefined by somebody else.
20 | *
21 | * @private
22 | */
23 | jasmine.undefined = jasmine.___undefined___;
24 |
25 | /**
26 | * Show diagnostic messages in the console if set to true
27 | *
28 | */
29 | jasmine.VERBOSE = false;
30 |
31 | /**
32 | * Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed.
33 | *
34 | */
35 | jasmine.DEFAULT_UPDATE_INTERVAL = 250;
36 |
37 | /**
38 | * Default timeout interval in milliseconds for waitsFor() blocks.
39 | */
40 | jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
41 |
42 | jasmine.getGlobal = function() {
43 | function getGlobal() {
44 | return this;
45 | }
46 |
47 | return getGlobal();
48 | };
49 |
50 | /**
51 | * Allows for bound functions to be compared. Internal use only.
52 | *
53 | * @ignore
54 | * @private
55 | * @param base {Object} bound 'this' for the function
56 | * @param name {Function} function to find
57 | */
58 | jasmine.bindOriginal_ = function(base, name) {
59 | var original = base[name];
60 | if (original.apply) {
61 | return function() {
62 | return original.apply(base, arguments);
63 | };
64 | } else {
65 | // IE support
66 | return jasmine.getGlobal()[name];
67 | }
68 | };
69 |
70 | jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout');
71 | jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout');
72 | jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval');
73 | jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval');
74 |
75 | jasmine.MessageResult = function(values) {
76 | this.type = 'log';
77 | this.values = values;
78 | this.trace = new Error(); // todo: test better
79 | };
80 |
81 | jasmine.MessageResult.prototype.toString = function() {
82 | var text = "";
83 | for (var i = 0; i < this.values.length; i++) {
84 | if (i > 0) text += " ";
85 | if (jasmine.isString_(this.values[i])) {
86 | text += this.values[i];
87 | } else {
88 | text += jasmine.pp(this.values[i]);
89 | }
90 | }
91 | return text;
92 | };
93 |
94 | jasmine.ExpectationResult = function(params) {
95 | this.type = 'expect';
96 | this.matcherName = params.matcherName;
97 | this.passed_ = params.passed;
98 | this.expected = params.expected;
99 | this.actual = params.actual;
100 | this.message = this.passed_ ? 'Passed.' : params.message;
101 |
102 | var trace = (params.trace || new Error(this.message));
103 | this.trace = this.passed_ ? '' : trace;
104 | };
105 |
106 | jasmine.ExpectationResult.prototype.toString = function () {
107 | return this.message;
108 | };
109 |
110 | jasmine.ExpectationResult.prototype.passed = function () {
111 | return this.passed_;
112 | };
113 |
114 | /**
115 | * Getter for the Jasmine environment. Ensures one gets created
116 | */
117 | jasmine.getEnv = function() {
118 | var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env();
119 | return env;
120 | };
121 |
122 | /**
123 | * @ignore
124 | * @private
125 | * @param value
126 | * @returns {Boolean}
127 | */
128 | jasmine.isArray_ = function(value) {
129 | return jasmine.isA_("Array", value);
130 | };
131 |
132 | /**
133 | * @ignore
134 | * @private
135 | * @param value
136 | * @returns {Boolean}
137 | */
138 | jasmine.isString_ = function(value) {
139 | return jasmine.isA_("String", value);
140 | };
141 |
142 | /**
143 | * @ignore
144 | * @private
145 | * @param value
146 | * @returns {Boolean}
147 | */
148 | jasmine.isNumber_ = function(value) {
149 | return jasmine.isA_("Number", value);
150 | };
151 |
152 | /**
153 | * @ignore
154 | * @private
155 | * @param {String} typeName
156 | * @param value
157 | * @returns {Boolean}
158 | */
159 | jasmine.isA_ = function(typeName, value) {
160 | return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';
161 | };
162 |
163 | /**
164 | * Pretty printer for expecations. Takes any object and turns it into a human-readable string.
165 | *
166 | * @param value {Object} an object to be outputted
167 | * @returns {String}
168 | */
169 | jasmine.pp = function(value) {
170 | var stringPrettyPrinter = new jasmine.StringPrettyPrinter();
171 | stringPrettyPrinter.format(value);
172 | return stringPrettyPrinter.string;
173 | };
174 |
175 | /**
176 | * Returns true if the object is a DOM Node.
177 | *
178 | * @param {Object} obj object to check
179 | * @returns {Boolean}
180 | */
181 | jasmine.isDomNode = function(obj) {
182 | return obj.nodeType > 0;
183 | };
184 |
185 | /**
186 | * Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter.
187 | *
188 | * @example
189 | * // don't care about which function is passed in, as long as it's a function
190 | * expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function));
191 | *
192 | * @param {Class} clazz
193 | * @returns matchable object of the type clazz
194 | */
195 | jasmine.any = function(clazz) {
196 | return new jasmine.Matchers.Any(clazz);
197 | };
198 |
199 | /**
200 | * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks.
201 | *
202 | * Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine
203 | * expectation syntax. Spies can be checked if they were called or not and what the calling params were.
204 | *
205 | * A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs).
206 | *
207 | * Spies are torn down at the end of every spec.
208 | *
209 | * Note: Do not call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj.
210 | *
211 | * @example
212 | * // a stub
213 | * var myStub = jasmine.createSpy('myStub'); // can be used anywhere
214 | *
215 | * // spy example
216 | * var foo = {
217 | * not: function(bool) { return !bool; }
218 | * }
219 | *
220 | * // actual foo.not will not be called, execution stops
221 | * spyOn(foo, 'not');
222 |
223 | // foo.not spied upon, execution will continue to implementation
224 | * spyOn(foo, 'not').andCallThrough();
225 | *
226 | * // fake example
227 | * var foo = {
228 | * not: function(bool) { return !bool; }
229 | * }
230 | *
231 | * // foo.not(val) will return val
232 | * spyOn(foo, 'not').andCallFake(function(value) {return value;});
233 | *
234 | * // mock example
235 | * foo.not(7 == 7);
236 | * expect(foo.not).toHaveBeenCalled();
237 | * expect(foo.not).toHaveBeenCalledWith(true);
238 | *
239 | * @constructor
240 | * @see spyOn, jasmine.createSpy, jasmine.createSpyObj
241 | * @param {String} name
242 | */
243 | jasmine.Spy = function(name) {
244 | /**
245 | * The name of the spy, if provided.
246 | */
247 | this.identity = name || 'unknown';
248 | /**
249 | * Is this Object a spy?
250 | */
251 | this.isSpy = true;
252 | /**
253 | * The actual function this spy stubs.
254 | */
255 | this.plan = function() {
256 | };
257 | /**
258 | * Tracking of the most recent call to the spy.
259 | * @example
260 | * var mySpy = jasmine.createSpy('foo');
261 | * mySpy(1, 2);
262 | * mySpy.mostRecentCall.args = [1, 2];
263 | */
264 | this.mostRecentCall = {};
265 |
266 | /**
267 | * Holds arguments for each call to the spy, indexed by call count
268 | * @example
269 | * var mySpy = jasmine.createSpy('foo');
270 | * mySpy(1, 2);
271 | * mySpy(7, 8);
272 | * mySpy.mostRecentCall.args = [7, 8];
273 | * mySpy.argsForCall[0] = [1, 2];
274 | * mySpy.argsForCall[1] = [7, 8];
275 | */
276 | this.argsForCall = [];
277 | this.calls = [];
278 | };
279 |
280 | /**
281 | * Tells a spy to call through to the actual implemenatation.
282 | *
283 | * @example
284 | * var foo = {
285 | * bar: function() { // do some stuff }
286 | * }
287 | *
288 | * // defining a spy on an existing property: foo.bar
289 | * spyOn(foo, 'bar').andCallThrough();
290 | */
291 | jasmine.Spy.prototype.andCallThrough = function() {
292 | this.plan = this.originalValue;
293 | return this;
294 | };
295 |
296 | /**
297 | * For setting the return value of a spy.
298 | *
299 | * @example
300 | * // defining a spy from scratch: foo() returns 'baz'
301 | * var foo = jasmine.createSpy('spy on foo').andReturn('baz');
302 | *
303 | * // defining a spy on an existing property: foo.bar() returns 'baz'
304 | * spyOn(foo, 'bar').andReturn('baz');
305 | *
306 | * @param {Object} value
307 | */
308 | jasmine.Spy.prototype.andReturn = function(value) {
309 | this.plan = function() {
310 | return value;
311 | };
312 | return this;
313 | };
314 |
315 | /**
316 | * For throwing an exception when a spy is called.
317 | *
318 | * @example
319 | * // defining a spy from scratch: foo() throws an exception w/ message 'ouch'
320 | * var foo = jasmine.createSpy('spy on foo').andThrow('baz');
321 | *
322 | * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch'
323 | * spyOn(foo, 'bar').andThrow('baz');
324 | *
325 | * @param {String} exceptionMsg
326 | */
327 | jasmine.Spy.prototype.andThrow = function(exceptionMsg) {
328 | this.plan = function() {
329 | throw exceptionMsg;
330 | };
331 | return this;
332 | };
333 |
334 | /**
335 | * Calls an alternate implementation when a spy is called.
336 | *
337 | * @example
338 | * var baz = function() {
339 | * // do some stuff, return something
340 | * }
341 | * // defining a spy from scratch: foo() calls the function baz
342 | * var foo = jasmine.createSpy('spy on foo').andCall(baz);
343 | *
344 | * // defining a spy on an existing property: foo.bar() calls an anonymnous function
345 | * spyOn(foo, 'bar').andCall(function() { return 'baz';} );
346 | *
347 | * @param {Function} fakeFunc
348 | */
349 | jasmine.Spy.prototype.andCallFake = function(fakeFunc) {
350 | this.plan = fakeFunc;
351 | return this;
352 | };
353 |
354 | /**
355 | * Resets all of a spy's the tracking variables so that it can be used again.
356 | *
357 | * @example
358 | * spyOn(foo, 'bar');
359 | *
360 | * foo.bar();
361 | *
362 | * expect(foo.bar.callCount).toEqual(1);
363 | *
364 | * foo.bar.reset();
365 | *
366 | * expect(foo.bar.callCount).toEqual(0);
367 | */
368 | jasmine.Spy.prototype.reset = function() {
369 | this.wasCalled = false;
370 | this.callCount = 0;
371 | this.argsForCall = [];
372 | this.calls = [];
373 | this.mostRecentCall = {};
374 | };
375 |
376 | jasmine.createSpy = function(name) {
377 |
378 | var spyObj = function() {
379 | spyObj.wasCalled = true;
380 | spyObj.callCount++;
381 | var args = jasmine.util.argsToArray(arguments);
382 | spyObj.mostRecentCall.object = this;
383 | spyObj.mostRecentCall.args = args;
384 | spyObj.argsForCall.push(args);
385 | spyObj.calls.push({object: this, args: args});
386 | return spyObj.plan.apply(this, arguments);
387 | };
388 |
389 | var spy = new jasmine.Spy(name);
390 |
391 | for (var prop in spy) {
392 | spyObj[prop] = spy[prop];
393 | }
394 |
395 | spyObj.reset();
396 |
397 | return spyObj;
398 | };
399 |
400 | /**
401 | * Determines whether an object is a spy.
402 | *
403 | * @param {jasmine.Spy|Object} putativeSpy
404 | * @returns {Boolean}
405 | */
406 | jasmine.isSpy = function(putativeSpy) {
407 | return putativeSpy && putativeSpy.isSpy;
408 | };
409 |
410 | /**
411 | * Creates a more complicated spy: an Object that has every property a function that is a spy. Used for stubbing something
412 | * large in one call.
413 | *
414 | * @param {String} baseName name of spy class
415 | * @param {Array} methodNames array of names of methods to make spies
416 | */
417 | jasmine.createSpyObj = function(baseName, methodNames) {
418 | if (!jasmine.isArray_(methodNames) || methodNames.length === 0) {
419 | throw new Error('createSpyObj requires a non-empty array of method names to create spies for');
420 | }
421 | var obj = {};
422 | for (var i = 0; i < methodNames.length; i++) {
423 | obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]);
424 | }
425 | return obj;
426 | };
427 |
428 | /**
429 | * All parameters are pretty-printed and concatenated together, then written to the current spec's output.
430 | *
431 | * Be careful not to leave calls to jasmine.log
in production code.
432 | */
433 | jasmine.log = function() {
434 | var spec = jasmine.getEnv().currentSpec;
435 | spec.log.apply(spec, arguments);
436 | };
437 |
438 | /**
439 | * Function that installs a spy on an existing object's method name. Used within a Spec to create a spy.
440 | *
441 | * @example
442 | * // spy example
443 | * var foo = {
444 | * not: function(bool) { return !bool; }
445 | * }
446 | * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops
447 | *
448 | * @see jasmine.createSpy
449 | * @param obj
450 | * @param methodName
451 | * @returns a Jasmine spy that can be chained with all spy methods
452 | */
453 | var spyOn = function(obj, methodName) {
454 | return jasmine.getEnv().currentSpec.spyOn(obj, methodName);
455 | };
456 | if (isCommonJS) exports.spyOn = spyOn;
457 |
458 | /**
459 | * Creates a Jasmine spec that will be added to the current suite.
460 | *
461 | * // TODO: pending tests
462 | *
463 | * @example
464 | * it('should be true', function() {
465 | * expect(true).toEqual(true);
466 | * });
467 | *
468 | * @param {String} desc description of this specification
469 | * @param {Function} func defines the preconditions and expectations of the spec
470 | */
471 | var it = function(desc, func) {
472 | return jasmine.getEnv().it(desc, func);
473 | };
474 | if (isCommonJS) exports.it = it;
475 |
476 | /**
477 | * Creates a disabled Jasmine spec.
478 | *
479 | * A convenience method that allows existing specs to be disabled temporarily during development.
480 | *
481 | * @param {String} desc description of this specification
482 | * @param {Function} func defines the preconditions and expectations of the spec
483 | */
484 | var xit = function(desc, func) {
485 | return jasmine.getEnv().xit(desc, func);
486 | };
487 | if (isCommonJS) exports.xit = xit;
488 |
489 | /**
490 | * Starts a chain for a Jasmine expectation.
491 | *
492 | * It is passed an Object that is the actual value and should chain to one of the many
493 | * jasmine.Matchers functions.
494 | *
495 | * @param {Object} actual Actual value to test against and expected value
496 | */
497 | var expect = function(actual) {
498 | return jasmine.getEnv().currentSpec.expect(actual);
499 | };
500 | if (isCommonJS) exports.expect = expect;
501 |
502 | /**
503 | * Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs.
504 | *
505 | * @param {Function} func Function that defines part of a jasmine spec.
506 | */
507 | var runs = function(func) {
508 | jasmine.getEnv().currentSpec.runs(func);
509 | };
510 | if (isCommonJS) exports.runs = runs;
511 |
512 | /**
513 | * Waits a fixed time period before moving to the next block.
514 | *
515 | * @deprecated Use waitsFor() instead
516 | * @param {Number} timeout milliseconds to wait
517 | */
518 | var waits = function(timeout) {
519 | jasmine.getEnv().currentSpec.waits(timeout);
520 | };
521 | if (isCommonJS) exports.waits = waits;
522 |
523 | /**
524 | * Waits for the latchFunction to return true before proceeding to the next block.
525 | *
526 | * @param {Function} latchFunction
527 | * @param {String} optional_timeoutMessage
528 | * @param {Number} optional_timeout
529 | */
530 | var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
531 | jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments);
532 | };
533 | if (isCommonJS) exports.waitsFor = waitsFor;
534 |
535 | /**
536 | * A function that is called before each spec in a suite.
537 | *
538 | * Used for spec setup, including validating assumptions.
539 | *
540 | * @param {Function} beforeEachFunction
541 | */
542 | var beforeEach = function(beforeEachFunction) {
543 | jasmine.getEnv().beforeEach(beforeEachFunction);
544 | };
545 | if (isCommonJS) exports.beforeEach = beforeEach;
546 |
547 | /**
548 | * A function that is called after each spec in a suite.
549 | *
550 | * Used for restoring any state that is hijacked during spec execution.
551 | *
552 | * @param {Function} afterEachFunction
553 | */
554 | var afterEach = function(afterEachFunction) {
555 | jasmine.getEnv().afterEach(afterEachFunction);
556 | };
557 | if (isCommonJS) exports.afterEach = afterEach;
558 |
559 | /**
560 | * Defines a suite of specifications.
561 | *
562 | * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared
563 | * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization
564 | * of setup in some tests.
565 | *
566 | * @example
567 | * // TODO: a simple suite
568 | *
569 | * // TODO: a simple suite with a nested describe block
570 | *
571 | * @param {String} description A string, usually the class under test.
572 | * @param {Function} specDefinitions function that defines several specs.
573 | */
574 | var describe = function(description, specDefinitions) {
575 | return jasmine.getEnv().describe(description, specDefinitions);
576 | };
577 | if (isCommonJS) exports.describe = describe;
578 |
579 | /**
580 | * Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development.
581 | *
582 | * @param {String} description A string, usually the class under test.
583 | * @param {Function} specDefinitions function that defines several specs.
584 | */
585 | var xdescribe = function(description, specDefinitions) {
586 | return jasmine.getEnv().xdescribe(description, specDefinitions);
587 | };
588 | if (isCommonJS) exports.xdescribe = xdescribe;
589 |
590 |
591 | // Provide the XMLHttpRequest class for IE 5.x-6.x:
592 | jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() {
593 | function tryIt(f) {
594 | try {
595 | return f();
596 | } catch(e) {
597 | }
598 | return null;
599 | }
600 |
601 | var xhr = tryIt(function() {
602 | return new ActiveXObject("Msxml2.XMLHTTP.6.0");
603 | }) ||
604 | tryIt(function() {
605 | return new ActiveXObject("Msxml2.XMLHTTP.3.0");
606 | }) ||
607 | tryIt(function() {
608 | return new ActiveXObject("Msxml2.XMLHTTP");
609 | }) ||
610 | tryIt(function() {
611 | return new ActiveXObject("Microsoft.XMLHTTP");
612 | });
613 |
614 | if (!xhr) throw new Error("This browser does not support XMLHttpRequest.");
615 |
616 | return xhr;
617 | } : XMLHttpRequest;
618 | /**
619 | * @namespace
620 | */
621 | jasmine.util = {};
622 |
623 | /**
624 | * Declare that a child class inherit it's prototype from the parent class.
625 | *
626 | * @private
627 | * @param {Function} childClass
628 | * @param {Function} parentClass
629 | */
630 | jasmine.util.inherit = function(childClass, parentClass) {
631 | /**
632 | * @private
633 | */
634 | var subclass = function() {
635 | };
636 | subclass.prototype = parentClass.prototype;
637 | childClass.prototype = new subclass();
638 | };
639 |
640 | jasmine.util.formatException = function(e) {
641 | var lineNumber;
642 | if (e.line) {
643 | lineNumber = e.line;
644 | }
645 | else if (e.lineNumber) {
646 | lineNumber = e.lineNumber;
647 | }
648 |
649 | var file;
650 |
651 | if (e.sourceURL) {
652 | file = e.sourceURL;
653 | }
654 | else if (e.fileName) {
655 | file = e.fileName;
656 | }
657 |
658 | var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString();
659 |
660 | if (file && lineNumber) {
661 | message += ' in ' + file + ' (line ' + lineNumber + ')';
662 | }
663 |
664 | return message;
665 | };
666 |
667 | jasmine.util.htmlEscape = function(str) {
668 | if (!str) return str;
669 | return str.replace(/&/g, '&')
670 | .replace(//g, '>');
672 | };
673 |
674 | jasmine.util.argsToArray = function(args) {
675 | var arrayOfArgs = [];
676 | for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]);
677 | return arrayOfArgs;
678 | };
679 |
680 | jasmine.util.extend = function(destination, source) {
681 | for (var property in source) destination[property] = source[property];
682 | return destination;
683 | };
684 |
685 | /**
686 | * Environment for Jasmine
687 | *
688 | * @constructor
689 | */
690 | jasmine.Env = function() {
691 | this.currentSpec = null;
692 | this.currentSuite = null;
693 | this.currentRunner_ = new jasmine.Runner(this);
694 |
695 | this.reporter = new jasmine.MultiReporter();
696 |
697 | this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL;
698 | this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL;
699 | this.lastUpdate = 0;
700 | this.specFilter = function() {
701 | return true;
702 | };
703 |
704 | this.nextSpecId_ = 0;
705 | this.nextSuiteId_ = 0;
706 | this.equalityTesters_ = [];
707 |
708 | // wrap matchers
709 | this.matchersClass = function() {
710 | jasmine.Matchers.apply(this, arguments);
711 | };
712 | jasmine.util.inherit(this.matchersClass, jasmine.Matchers);
713 |
714 | jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass);
715 | };
716 |
717 |
718 | jasmine.Env.prototype.setTimeout = jasmine.setTimeout;
719 | jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout;
720 | jasmine.Env.prototype.setInterval = jasmine.setInterval;
721 | jasmine.Env.prototype.clearInterval = jasmine.clearInterval;
722 |
723 | /**
724 | * @returns an object containing jasmine version build info, if set.
725 | */
726 | jasmine.Env.prototype.version = function () {
727 | if (jasmine.version_) {
728 | return jasmine.version_;
729 | } else {
730 | throw new Error('Version not set');
731 | }
732 | };
733 |
734 | /**
735 | * @returns string containing jasmine version build info, if set.
736 | */
737 | jasmine.Env.prototype.versionString = function() {
738 | if (!jasmine.version_) {
739 | return "version unknown";
740 | }
741 |
742 | var version = this.version();
743 | var versionString = version.major + "." + version.minor + "." + version.build;
744 | if (version.release_candidate) {
745 | versionString += ".rc" + version.release_candidate;
746 | }
747 | versionString += " revision " + version.revision;
748 | return versionString;
749 | };
750 |
751 | /**
752 | * @returns a sequential integer starting at 0
753 | */
754 | jasmine.Env.prototype.nextSpecId = function () {
755 | return this.nextSpecId_++;
756 | };
757 |
758 | /**
759 | * @returns a sequential integer starting at 0
760 | */
761 | jasmine.Env.prototype.nextSuiteId = function () {
762 | return this.nextSuiteId_++;
763 | };
764 |
765 | /**
766 | * Register a reporter to receive status updates from Jasmine.
767 | * @param {jasmine.Reporter} reporter An object which will receive status updates.
768 | */
769 | jasmine.Env.prototype.addReporter = function(reporter) {
770 | this.reporter.addReporter(reporter);
771 | };
772 |
773 | jasmine.Env.prototype.execute = function() {
774 | this.currentRunner_.execute();
775 | };
776 |
777 | jasmine.Env.prototype.describe = function(description, specDefinitions) {
778 | var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite);
779 |
780 | var parentSuite = this.currentSuite;
781 | if (parentSuite) {
782 | parentSuite.add(suite);
783 | } else {
784 | this.currentRunner_.add(suite);
785 | }
786 |
787 | this.currentSuite = suite;
788 |
789 | var declarationError = null;
790 | try {
791 | specDefinitions.call(suite);
792 | } catch(e) {
793 | declarationError = e;
794 | }
795 |
796 | if (declarationError) {
797 | this.it("encountered a declaration exception", function() {
798 | throw declarationError;
799 | });
800 | }
801 |
802 | this.currentSuite = parentSuite;
803 |
804 | return suite;
805 | };
806 |
807 | jasmine.Env.prototype.beforeEach = function(beforeEachFunction) {
808 | if (this.currentSuite) {
809 | this.currentSuite.beforeEach(beforeEachFunction);
810 | } else {
811 | this.currentRunner_.beforeEach(beforeEachFunction);
812 | }
813 | };
814 |
815 | jasmine.Env.prototype.currentRunner = function () {
816 | return this.currentRunner_;
817 | };
818 |
819 | jasmine.Env.prototype.afterEach = function(afterEachFunction) {
820 | if (this.currentSuite) {
821 | this.currentSuite.afterEach(afterEachFunction);
822 | } else {
823 | this.currentRunner_.afterEach(afterEachFunction);
824 | }
825 |
826 | };
827 |
828 | jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) {
829 | return {
830 | execute: function() {
831 | }
832 | };
833 | };
834 |
835 | jasmine.Env.prototype.it = function(description, func) {
836 | var spec = new jasmine.Spec(this, this.currentSuite, description);
837 | this.currentSuite.add(spec);
838 | this.currentSpec = spec;
839 |
840 | if (func) {
841 | spec.runs(func);
842 | }
843 |
844 | return spec;
845 | };
846 |
847 | jasmine.Env.prototype.xit = function(desc, func) {
848 | return {
849 | id: this.nextSpecId(),
850 | runs: function() {
851 | }
852 | };
853 | };
854 |
855 | jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) {
856 | if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) {
857 | return true;
858 | }
859 |
860 | a.__Jasmine_been_here_before__ = b;
861 | b.__Jasmine_been_here_before__ = a;
862 |
863 | var hasKey = function(obj, keyName) {
864 | return obj !== null && obj[keyName] !== jasmine.undefined;
865 | };
866 |
867 | for (var property in b) {
868 | if (!hasKey(a, property) && hasKey(b, property)) {
869 | mismatchKeys.push("expected has key '" + property + "', but missing from actual.");
870 | }
871 | }
872 | for (property in a) {
873 | if (!hasKey(b, property) && hasKey(a, property)) {
874 | mismatchKeys.push("expected missing key '" + property + "', but present in actual.");
875 | }
876 | }
877 | for (property in b) {
878 | if (property == '__Jasmine_been_here_before__') continue;
879 | if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) {
880 | mismatchValues.push("'" + property + "' was '" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "' in expected, but was '" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "' in actual.");
881 | }
882 | }
883 |
884 | if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) {
885 | mismatchValues.push("arrays were not the same length");
886 | }
887 |
888 | delete a.__Jasmine_been_here_before__;
889 | delete b.__Jasmine_been_here_before__;
890 | return (mismatchKeys.length === 0 && mismatchValues.length === 0);
891 | };
892 |
893 | jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {
894 | mismatchKeys = mismatchKeys || [];
895 | mismatchValues = mismatchValues || [];
896 |
897 | for (var i = 0; i < this.equalityTesters_.length; i++) {
898 | var equalityTester = this.equalityTesters_[i];
899 | var result = equalityTester(a, b, this, mismatchKeys, mismatchValues);
900 | if (result !== jasmine.undefined) return result;
901 | }
902 |
903 | if (a === b) return true;
904 |
905 | if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) {
906 | return (a == jasmine.undefined && b == jasmine.undefined);
907 | }
908 |
909 | if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) {
910 | return a === b;
911 | }
912 |
913 | if (a instanceof Date && b instanceof Date) {
914 | return a.getTime() == b.getTime();
915 | }
916 |
917 | if (a instanceof jasmine.Matchers.Any) {
918 | return a.matches(b);
919 | }
920 |
921 | if (b instanceof jasmine.Matchers.Any) {
922 | return b.matches(a);
923 | }
924 |
925 | if (jasmine.isString_(a) && jasmine.isString_(b)) {
926 | return (a == b);
927 | }
928 |
929 | if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) {
930 | return (a == b);
931 | }
932 |
933 | if (typeof a === "object" && typeof b === "object") {
934 | return this.compareObjects_(a, b, mismatchKeys, mismatchValues);
935 | }
936 |
937 | //Straight check
938 | return (a === b);
939 | };
940 |
941 | jasmine.Env.prototype.contains_ = function(haystack, needle) {
942 | if (jasmine.isArray_(haystack)) {
943 | for (var i = 0; i < haystack.length; i++) {
944 | if (this.equals_(haystack[i], needle)) return true;
945 | }
946 | return false;
947 | }
948 | return haystack.indexOf(needle) >= 0;
949 | };
950 |
951 | jasmine.Env.prototype.addEqualityTester = function(equalityTester) {
952 | this.equalityTesters_.push(equalityTester);
953 | };
954 | /** No-op base class for Jasmine reporters.
955 | *
956 | * @constructor
957 | */
958 | jasmine.Reporter = function() {
959 | };
960 |
961 | //noinspection JSUnusedLocalSymbols
962 | jasmine.Reporter.prototype.reportRunnerStarting = function(runner) {
963 | };
964 |
965 | //noinspection JSUnusedLocalSymbols
966 | jasmine.Reporter.prototype.reportRunnerResults = function(runner) {
967 | };
968 |
969 | //noinspection JSUnusedLocalSymbols
970 | jasmine.Reporter.prototype.reportSuiteResults = function(suite) {
971 | };
972 |
973 | //noinspection JSUnusedLocalSymbols
974 | jasmine.Reporter.prototype.reportSpecStarting = function(spec) {
975 | };
976 |
977 | //noinspection JSUnusedLocalSymbols
978 | jasmine.Reporter.prototype.reportSpecResults = function(spec) {
979 | };
980 |
981 | //noinspection JSUnusedLocalSymbols
982 | jasmine.Reporter.prototype.log = function(str) {
983 | };
984 |
985 | /**
986 | * Blocks are functions with executable code that make up a spec.
987 | *
988 | * @constructor
989 | * @param {jasmine.Env} env
990 | * @param {Function} func
991 | * @param {jasmine.Spec} spec
992 | */
993 | jasmine.Block = function(env, func, spec) {
994 | this.env = env;
995 | this.func = func;
996 | this.spec = spec;
997 | };
998 |
999 | jasmine.Block.prototype.execute = function(onComplete) {
1000 | try {
1001 | this.func.apply(this.spec);
1002 | } catch (e) {
1003 | this.spec.fail(e);
1004 | }
1005 | onComplete();
1006 | };
1007 | /** JavaScript API reporter.
1008 | *
1009 | * @constructor
1010 | */
1011 | jasmine.JsApiReporter = function() {
1012 | this.started = false;
1013 | this.finished = false;
1014 | this.suites_ = [];
1015 | this.results_ = {};
1016 | };
1017 |
1018 | jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) {
1019 | this.started = true;
1020 | var suites = runner.topLevelSuites();
1021 | for (var i = 0; i < suites.length; i++) {
1022 | var suite = suites[i];
1023 | this.suites_.push(this.summarize_(suite));
1024 | }
1025 | };
1026 |
1027 | jasmine.JsApiReporter.prototype.suites = function() {
1028 | return this.suites_;
1029 | };
1030 |
1031 | jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) {
1032 | var isSuite = suiteOrSpec instanceof jasmine.Suite;
1033 | var summary = {
1034 | id: suiteOrSpec.id,
1035 | name: suiteOrSpec.description,
1036 | type: isSuite ? 'suite' : 'spec',
1037 | children: []
1038 | };
1039 |
1040 | if (isSuite) {
1041 | var children = suiteOrSpec.children();
1042 | for (var i = 0; i < children.length; i++) {
1043 | summary.children.push(this.summarize_(children[i]));
1044 | }
1045 | }
1046 | return summary;
1047 | };
1048 |
1049 | jasmine.JsApiReporter.prototype.results = function() {
1050 | return this.results_;
1051 | };
1052 |
1053 | jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) {
1054 | return this.results_[specId];
1055 | };
1056 |
1057 | //noinspection JSUnusedLocalSymbols
1058 | jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) {
1059 | this.finished = true;
1060 | };
1061 |
1062 | //noinspection JSUnusedLocalSymbols
1063 | jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) {
1064 | };
1065 |
1066 | //noinspection JSUnusedLocalSymbols
1067 | jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) {
1068 | this.results_[spec.id] = {
1069 | messages: spec.results().getItems(),
1070 | result: spec.results().failedCount > 0 ? "failed" : "passed"
1071 | };
1072 | };
1073 |
1074 | //noinspection JSUnusedLocalSymbols
1075 | jasmine.JsApiReporter.prototype.log = function(str) {
1076 | };
1077 |
1078 | jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){
1079 | var results = {};
1080 | for (var i = 0; i < specIds.length; i++) {
1081 | var specId = specIds[i];
1082 | results[specId] = this.summarizeResult_(this.results_[specId]);
1083 | }
1084 | return results;
1085 | };
1086 |
1087 | jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){
1088 | var summaryMessages = [];
1089 | var messagesLength = result.messages.length;
1090 | for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) {
1091 | var resultMessage = result.messages[messageIndex];
1092 | summaryMessages.push({
1093 | text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined,
1094 | passed: resultMessage.passed ? resultMessage.passed() : true,
1095 | type: resultMessage.type,
1096 | message: resultMessage.message,
1097 | trace: {
1098 | stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined
1099 | }
1100 | });
1101 | }
1102 |
1103 | return {
1104 | result : result.result,
1105 | messages : summaryMessages
1106 | };
1107 | };
1108 |
1109 | /**
1110 | * @constructor
1111 | * @param {jasmine.Env} env
1112 | * @param actual
1113 | * @param {jasmine.Spec} spec
1114 | */
1115 | jasmine.Matchers = function(env, actual, spec, opt_isNot) {
1116 | this.env = env;
1117 | this.actual = actual;
1118 | this.spec = spec;
1119 | this.isNot = opt_isNot || false;
1120 | this.reportWasCalled_ = false;
1121 | };
1122 |
1123 | // todo: @deprecated as of Jasmine 0.11, remove soon [xw]
1124 | jasmine.Matchers.pp = function(str) {
1125 | throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!");
1126 | };
1127 |
1128 | // todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw]
1129 | jasmine.Matchers.prototype.report = function(result, failing_message, details) {
1130 | throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs");
1131 | };
1132 |
1133 | jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) {
1134 | for (var methodName in prototype) {
1135 | if (methodName == 'report') continue;
1136 | var orig = prototype[methodName];
1137 | matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig);
1138 | }
1139 | };
1140 |
1141 | jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) {
1142 | return function() {
1143 | var matcherArgs = jasmine.util.argsToArray(arguments);
1144 | var result = matcherFunction.apply(this, arguments);
1145 |
1146 | if (this.isNot) {
1147 | result = !result;
1148 | }
1149 |
1150 | if (this.reportWasCalled_) return result;
1151 |
1152 | var message;
1153 | if (!result) {
1154 | if (this.message) {
1155 | message = this.message.apply(this, arguments);
1156 | if (jasmine.isArray_(message)) {
1157 | message = message[this.isNot ? 1 : 0];
1158 | }
1159 | } else {
1160 | var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); });
1161 | message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate;
1162 | if (matcherArgs.length > 0) {
1163 | for (var i = 0; i < matcherArgs.length; i++) {
1164 | if (i > 0) message += ",";
1165 | message += " " + jasmine.pp(matcherArgs[i]);
1166 | }
1167 | }
1168 | message += ".";
1169 | }
1170 | }
1171 | var expectationResult = new jasmine.ExpectationResult({
1172 | matcherName: matcherName,
1173 | passed: result,
1174 | expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0],
1175 | actual: this.actual,
1176 | message: message
1177 | });
1178 | this.spec.addMatcherResult(expectationResult);
1179 | return jasmine.undefined;
1180 | };
1181 | };
1182 |
1183 |
1184 |
1185 |
1186 | /**
1187 | * toBe: compares the actual to the expected using ===
1188 | * @param expected
1189 | */
1190 | jasmine.Matchers.prototype.toBe = function(expected) {
1191 | return this.actual === expected;
1192 | };
1193 |
1194 | /**
1195 | * toNotBe: compares the actual to the expected using !==
1196 | * @param expected
1197 | * @deprecated as of 1.0. Use not.toBe() instead.
1198 | */
1199 | jasmine.Matchers.prototype.toNotBe = function(expected) {
1200 | return this.actual !== expected;
1201 | };
1202 |
1203 | /**
1204 | * toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc.
1205 | *
1206 | * @param expected
1207 | */
1208 | jasmine.Matchers.prototype.toEqual = function(expected) {
1209 | return this.env.equals_(this.actual, expected);
1210 | };
1211 |
1212 | /**
1213 | * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual
1214 | * @param expected
1215 | * @deprecated as of 1.0. Use not.toNotEqual() instead.
1216 | */
1217 | jasmine.Matchers.prototype.toNotEqual = function(expected) {
1218 | return !this.env.equals_(this.actual, expected);
1219 | };
1220 |
1221 | /**
1222 | * Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes
1223 | * a pattern or a String.
1224 | *
1225 | * @param expected
1226 | */
1227 | jasmine.Matchers.prototype.toMatch = function(expected) {
1228 | return new RegExp(expected).test(this.actual);
1229 | };
1230 |
1231 | /**
1232 | * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch
1233 | * @param expected
1234 | * @deprecated as of 1.0. Use not.toMatch() instead.
1235 | */
1236 | jasmine.Matchers.prototype.toNotMatch = function(expected) {
1237 | return !(new RegExp(expected).test(this.actual));
1238 | };
1239 |
1240 | /**
1241 | * Matcher that compares the actual to jasmine.undefined.
1242 | */
1243 | jasmine.Matchers.prototype.toBeDefined = function() {
1244 | return (this.actual !== jasmine.undefined);
1245 | };
1246 |
1247 | /**
1248 | * Matcher that compares the actual to jasmine.undefined.
1249 | */
1250 | jasmine.Matchers.prototype.toBeUndefined = function() {
1251 | return (this.actual === jasmine.undefined);
1252 | };
1253 |
1254 | /**
1255 | * Matcher that compares the actual to null.
1256 | */
1257 | jasmine.Matchers.prototype.toBeNull = function() {
1258 | return (this.actual === null);
1259 | };
1260 |
1261 | /**
1262 | * Matcher that boolean not-nots the actual.
1263 | */
1264 | jasmine.Matchers.prototype.toBeTruthy = function() {
1265 | return !!this.actual;
1266 | };
1267 |
1268 |
1269 | /**
1270 | * Matcher that boolean nots the actual.
1271 | */
1272 | jasmine.Matchers.prototype.toBeFalsy = function() {
1273 | return !this.actual;
1274 | };
1275 |
1276 |
1277 | /**
1278 | * Matcher that checks to see if the actual, a Jasmine spy, was called.
1279 | */
1280 | jasmine.Matchers.prototype.toHaveBeenCalled = function() {
1281 | if (arguments.length > 0) {
1282 | throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith');
1283 | }
1284 |
1285 | if (!jasmine.isSpy(this.actual)) {
1286 | throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
1287 | }
1288 |
1289 | this.message = function() {
1290 | return [
1291 | "Expected spy " + this.actual.identity + " to have been called.",
1292 | "Expected spy " + this.actual.identity + " not to have been called."
1293 | ];
1294 | };
1295 |
1296 | return this.actual.wasCalled;
1297 | };
1298 |
1299 | /** @deprecated Use expect(xxx).toHaveBeenCalled() instead */
1300 | jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled;
1301 |
1302 | /**
1303 | * Matcher that checks to see if the actual, a Jasmine spy, was not called.
1304 | *
1305 | * @deprecated Use expect(xxx).not.toHaveBeenCalled() instead
1306 | */
1307 | jasmine.Matchers.prototype.wasNotCalled = function() {
1308 | if (arguments.length > 0) {
1309 | throw new Error('wasNotCalled does not take arguments');
1310 | }
1311 |
1312 | if (!jasmine.isSpy(this.actual)) {
1313 | throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
1314 | }
1315 |
1316 | this.message = function() {
1317 | return [
1318 | "Expected spy " + this.actual.identity + " to not have been called.",
1319 | "Expected spy " + this.actual.identity + " to have been called."
1320 | ];
1321 | };
1322 |
1323 | return !this.actual.wasCalled;
1324 | };
1325 |
1326 | /**
1327 | * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters.
1328 | *
1329 | * @example
1330 | *
1331 | */
1332 | jasmine.Matchers.prototype.toHaveBeenCalledWith = function() {
1333 | var expectedArgs = jasmine.util.argsToArray(arguments);
1334 | if (!jasmine.isSpy(this.actual)) {
1335 | throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
1336 | }
1337 | this.message = function() {
1338 | if (this.actual.callCount === 0) {
1339 | // todo: what should the failure message for .not.toHaveBeenCalledWith() be? is this right? test better. [xw]
1340 | return [
1341 | "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.",
1342 | "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was."
1343 | ];
1344 | } else {
1345 | return [
1346 | "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall),
1347 | "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall)
1348 | ];
1349 | }
1350 | };
1351 |
1352 | return this.env.contains_(this.actual.argsForCall, expectedArgs);
1353 | };
1354 |
1355 | /** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */
1356 | jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith;
1357 |
1358 | /** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */
1359 | jasmine.Matchers.prototype.wasNotCalledWith = function() {
1360 | var expectedArgs = jasmine.util.argsToArray(arguments);
1361 | if (!jasmine.isSpy(this.actual)) {
1362 | throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
1363 | }
1364 |
1365 | this.message = function() {
1366 | return [
1367 | "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was",
1368 | "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was"
1369 | ];
1370 | };
1371 |
1372 | return !this.env.contains_(this.actual.argsForCall, expectedArgs);
1373 | };
1374 |
1375 | /**
1376 | * Matcher that checks that the expected item is an element in the actual Array.
1377 | *
1378 | * @param {Object} expected
1379 | */
1380 | jasmine.Matchers.prototype.toContain = function(expected) {
1381 | return this.env.contains_(this.actual, expected);
1382 | };
1383 |
1384 | /**
1385 | * Matcher that checks that the expected item is NOT an element in the actual Array.
1386 | *
1387 | * @param {Object} expected
1388 | * @deprecated as of 1.0. Use not.toNotContain() instead.
1389 | */
1390 | jasmine.Matchers.prototype.toNotContain = function(expected) {
1391 | return !this.env.contains_(this.actual, expected);
1392 | };
1393 |
1394 | jasmine.Matchers.prototype.toBeLessThan = function(expected) {
1395 | return this.actual < expected;
1396 | };
1397 |
1398 | jasmine.Matchers.prototype.toBeGreaterThan = function(expected) {
1399 | return this.actual > expected;
1400 | };
1401 |
1402 | /**
1403 | * Matcher that checks that the expected item is equal to the actual item
1404 | * up to a given level of decimal precision (default 2).
1405 | *
1406 | * @param {Number} expected
1407 | * @param {Number} precision
1408 | */
1409 | jasmine.Matchers.prototype.toBeCloseTo = function(expected, precision) {
1410 | if (!(precision === 0)) {
1411 | precision = precision || 2;
1412 | }
1413 | var multiplier = Math.pow(10, precision);
1414 | var actual = Math.round(this.actual * multiplier);
1415 | expected = Math.round(expected * multiplier);
1416 | return expected == actual;
1417 | };
1418 |
1419 | /**
1420 | * Matcher that checks that the expected exception was thrown by the actual.
1421 | *
1422 | * @param {String} expected
1423 | */
1424 | jasmine.Matchers.prototype.toThrow = function(expected) {
1425 | var result = false;
1426 | var exception;
1427 | if (typeof this.actual != 'function') {
1428 | throw new Error('Actual is not a function');
1429 | }
1430 | try {
1431 | this.actual();
1432 | } catch (e) {
1433 | exception = e;
1434 | }
1435 | if (exception) {
1436 | result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected));
1437 | }
1438 |
1439 | var not = this.isNot ? "not " : "";
1440 |
1441 | this.message = function() {
1442 | if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) {
1443 | return ["Expected function " + not + "to throw", expected ? expected.message || expected : "an exception", ", but it threw", exception.message || exception].join(' ');
1444 | } else {
1445 | return "Expected function to throw an exception.";
1446 | }
1447 | };
1448 |
1449 | return result;
1450 | };
1451 |
1452 | jasmine.Matchers.Any = function(expectedClass) {
1453 | this.expectedClass = expectedClass;
1454 | };
1455 |
1456 | jasmine.Matchers.Any.prototype.matches = function(other) {
1457 | if (this.expectedClass == String) {
1458 | return typeof other == 'string' || other instanceof String;
1459 | }
1460 |
1461 | if (this.expectedClass == Number) {
1462 | return typeof other == 'number' || other instanceof Number;
1463 | }
1464 |
1465 | if (this.expectedClass == Function) {
1466 | return typeof other == 'function' || other instanceof Function;
1467 | }
1468 |
1469 | if (this.expectedClass == Object) {
1470 | return typeof other == 'object';
1471 | }
1472 |
1473 | return other instanceof this.expectedClass;
1474 | };
1475 |
1476 | jasmine.Matchers.Any.prototype.toString = function() {
1477 | return '';
1478 | };
1479 |
1480 | /**
1481 | * @constructor
1482 | */
1483 | jasmine.MultiReporter = function() {
1484 | this.subReporters_ = [];
1485 | };
1486 | jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter);
1487 |
1488 | jasmine.MultiReporter.prototype.addReporter = function(reporter) {
1489 | this.subReporters_.push(reporter);
1490 | };
1491 |
1492 | (function() {
1493 | var functionNames = [
1494 | "reportRunnerStarting",
1495 | "reportRunnerResults",
1496 | "reportSuiteResults",
1497 | "reportSpecStarting",
1498 | "reportSpecResults",
1499 | "log"
1500 | ];
1501 | for (var i = 0; i < functionNames.length; i++) {
1502 | var functionName = functionNames[i];
1503 | jasmine.MultiReporter.prototype[functionName] = (function(functionName) {
1504 | return function() {
1505 | for (var j = 0; j < this.subReporters_.length; j++) {
1506 | var subReporter = this.subReporters_[j];
1507 | if (subReporter[functionName]) {
1508 | subReporter[functionName].apply(subReporter, arguments);
1509 | }
1510 | }
1511 | };
1512 | })(functionName);
1513 | }
1514 | })();
1515 | /**
1516 | * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults
1517 | *
1518 | * @constructor
1519 | */
1520 | jasmine.NestedResults = function() {
1521 | /**
1522 | * The total count of results
1523 | */
1524 | this.totalCount = 0;
1525 | /**
1526 | * Number of passed results
1527 | */
1528 | this.passedCount = 0;
1529 | /**
1530 | * Number of failed results
1531 | */
1532 | this.failedCount = 0;
1533 | /**
1534 | * Was this suite/spec skipped?
1535 | */
1536 | this.skipped = false;
1537 | /**
1538 | * @ignore
1539 | */
1540 | this.items_ = [];
1541 | };
1542 |
1543 | /**
1544 | * Roll up the result counts.
1545 | *
1546 | * @param result
1547 | */
1548 | jasmine.NestedResults.prototype.rollupCounts = function(result) {
1549 | this.totalCount += result.totalCount;
1550 | this.passedCount += result.passedCount;
1551 | this.failedCount += result.failedCount;
1552 | };
1553 |
1554 | /**
1555 | * Adds a log message.
1556 | * @param values Array of message parts which will be concatenated later.
1557 | */
1558 | jasmine.NestedResults.prototype.log = function(values) {
1559 | this.items_.push(new jasmine.MessageResult(values));
1560 | };
1561 |
1562 | /**
1563 | * Getter for the results: message & results.
1564 | */
1565 | jasmine.NestedResults.prototype.getItems = function() {
1566 | return this.items_;
1567 | };
1568 |
1569 | /**
1570 | * Adds a result, tracking counts (total, passed, & failed)
1571 | * @param {jasmine.ExpectationResult|jasmine.NestedResults} result
1572 | */
1573 | jasmine.NestedResults.prototype.addResult = function(result) {
1574 | if (result.type != 'log') {
1575 | if (result.items_) {
1576 | this.rollupCounts(result);
1577 | } else {
1578 | this.totalCount++;
1579 | if (result.passed()) {
1580 | this.passedCount++;
1581 | } else {
1582 | this.failedCount++;
1583 | }
1584 | }
1585 | }
1586 | this.items_.push(result);
1587 | };
1588 |
1589 | /**
1590 | * @returns {Boolean} True if everything below passed
1591 | */
1592 | jasmine.NestedResults.prototype.passed = function() {
1593 | return this.passedCount === this.totalCount;
1594 | };
1595 | /**
1596 | * Base class for pretty printing for expectation results.
1597 | */
1598 | jasmine.PrettyPrinter = function() {
1599 | this.ppNestLevel_ = 0;
1600 | };
1601 |
1602 | /**
1603 | * Formats a value in a nice, human-readable string.
1604 | *
1605 | * @param value
1606 | */
1607 | jasmine.PrettyPrinter.prototype.format = function(value) {
1608 | if (this.ppNestLevel_ > 40) {
1609 | throw new Error('jasmine.PrettyPrinter: format() nested too deeply!');
1610 | }
1611 |
1612 | this.ppNestLevel_++;
1613 | try {
1614 | if (value === jasmine.undefined) {
1615 | this.emitScalar('undefined');
1616 | } else if (value === null) {
1617 | this.emitScalar('null');
1618 | } else if (value === jasmine.getGlobal()) {
1619 | this.emitScalar('');
1620 | } else if (value instanceof jasmine.Matchers.Any) {
1621 | this.emitScalar(value.toString());
1622 | } else if (typeof value === 'string') {
1623 | this.emitString(value);
1624 | } else if (jasmine.isSpy(value)) {
1625 | this.emitScalar("spy on " + value.identity);
1626 | } else if (value instanceof RegExp) {
1627 | this.emitScalar(value.toString());
1628 | } else if (typeof value === 'function') {
1629 | this.emitScalar('Function');
1630 | } else if (typeof value.nodeType === 'number') {
1631 | this.emitScalar('HTMLNode');
1632 | } else if (value instanceof Date) {
1633 | this.emitScalar('Date(' + value + ')');
1634 | } else if (value.__Jasmine_been_here_before__) {
1635 | this.emitScalar('');
1636 | } else if (jasmine.isArray_(value) || typeof value == 'object') {
1637 | value.__Jasmine_been_here_before__ = true;
1638 | if (jasmine.isArray_(value)) {
1639 | this.emitArray(value);
1640 | } else {
1641 | this.emitObject(value);
1642 | }
1643 | delete value.__Jasmine_been_here_before__;
1644 | } else {
1645 | this.emitScalar(value.toString());
1646 | }
1647 | } finally {
1648 | this.ppNestLevel_--;
1649 | }
1650 | };
1651 |
1652 | jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) {
1653 | for (var property in obj) {
1654 | if (property == '__Jasmine_been_here_before__') continue;
1655 | fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined &&
1656 | obj.__lookupGetter__(property) !== null) : false);
1657 | }
1658 | };
1659 |
1660 | jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_;
1661 | jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_;
1662 | jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_;
1663 | jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_;
1664 |
1665 | jasmine.StringPrettyPrinter = function() {
1666 | jasmine.PrettyPrinter.call(this);
1667 |
1668 | this.string = '';
1669 | };
1670 | jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter);
1671 |
1672 | jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) {
1673 | this.append(value);
1674 | };
1675 |
1676 | jasmine.StringPrettyPrinter.prototype.emitString = function(value) {
1677 | this.append("'" + value + "'");
1678 | };
1679 |
1680 | jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
1681 | this.append('[ ');
1682 | for (var i = 0; i < array.length; i++) {
1683 | if (i > 0) {
1684 | this.append(', ');
1685 | }
1686 | this.format(array[i]);
1687 | }
1688 | this.append(' ]');
1689 | };
1690 |
1691 | jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) {
1692 | var self = this;
1693 | this.append('{ ');
1694 | var first = true;
1695 |
1696 | this.iterateObject(obj, function(property, isGetter) {
1697 | if (first) {
1698 | first = false;
1699 | } else {
1700 | self.append(', ');
1701 | }
1702 |
1703 | self.append(property);
1704 | self.append(' : ');
1705 | if (isGetter) {
1706 | self.append('');
1707 | } else {
1708 | self.format(obj[property]);
1709 | }
1710 | });
1711 |
1712 | this.append(' }');
1713 | };
1714 |
1715 | jasmine.StringPrettyPrinter.prototype.append = function(value) {
1716 | this.string += value;
1717 | };
1718 | jasmine.Queue = function(env) {
1719 | this.env = env;
1720 | this.blocks = [];
1721 | this.running = false;
1722 | this.index = 0;
1723 | this.offset = 0;
1724 | this.abort = false;
1725 | };
1726 |
1727 | jasmine.Queue.prototype.addBefore = function(block) {
1728 | this.blocks.unshift(block);
1729 | };
1730 |
1731 | jasmine.Queue.prototype.add = function(block) {
1732 | this.blocks.push(block);
1733 | };
1734 |
1735 | jasmine.Queue.prototype.insertNext = function(block) {
1736 | this.blocks.splice((this.index + this.offset + 1), 0, block);
1737 | this.offset++;
1738 | };
1739 |
1740 | jasmine.Queue.prototype.start = function(onComplete) {
1741 | this.running = true;
1742 | this.onComplete = onComplete;
1743 | this.next_();
1744 | };
1745 |
1746 | jasmine.Queue.prototype.isRunning = function() {
1747 | return this.running;
1748 | };
1749 |
1750 | jasmine.Queue.LOOP_DONT_RECURSE = true;
1751 |
1752 | jasmine.Queue.prototype.next_ = function() {
1753 | var self = this;
1754 | var goAgain = true;
1755 |
1756 | while (goAgain) {
1757 | goAgain = false;
1758 |
1759 | if (self.index < self.blocks.length && !this.abort) {
1760 | var calledSynchronously = true;
1761 | var completedSynchronously = false;
1762 |
1763 | var onComplete = function () {
1764 | if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) {
1765 | completedSynchronously = true;
1766 | return;
1767 | }
1768 |
1769 | if (self.blocks[self.index].abort) {
1770 | self.abort = true;
1771 | }
1772 |
1773 | self.offset = 0;
1774 | self.index++;
1775 |
1776 | var now = new Date().getTime();
1777 | if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) {
1778 | self.env.lastUpdate = now;
1779 | self.env.setTimeout(function() {
1780 | self.next_();
1781 | }, 0);
1782 | } else {
1783 | if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) {
1784 | goAgain = true;
1785 | } else {
1786 | self.next_();
1787 | }
1788 | }
1789 | };
1790 | self.blocks[self.index].execute(onComplete);
1791 |
1792 | calledSynchronously = false;
1793 | if (completedSynchronously) {
1794 | onComplete();
1795 | }
1796 |
1797 | } else {
1798 | self.running = false;
1799 | if (self.onComplete) {
1800 | self.onComplete();
1801 | }
1802 | }
1803 | }
1804 | };
1805 |
1806 | jasmine.Queue.prototype.results = function() {
1807 | var results = new jasmine.NestedResults();
1808 | for (var i = 0; i < this.blocks.length; i++) {
1809 | if (this.blocks[i].results) {
1810 | results.addResult(this.blocks[i].results());
1811 | }
1812 | }
1813 | return results;
1814 | };
1815 |
1816 |
1817 | /**
1818 | * Runner
1819 | *
1820 | * @constructor
1821 | * @param {jasmine.Env} env
1822 | */
1823 | jasmine.Runner = function(env) {
1824 | var self = this;
1825 | self.env = env;
1826 | self.queue = new jasmine.Queue(env);
1827 | self.before_ = [];
1828 | self.after_ = [];
1829 | self.suites_ = [];
1830 | };
1831 |
1832 | jasmine.Runner.prototype.execute = function() {
1833 | var self = this;
1834 | if (self.env.reporter.reportRunnerStarting) {
1835 | self.env.reporter.reportRunnerStarting(this);
1836 | }
1837 | self.queue.start(function () {
1838 | self.finishCallback();
1839 | });
1840 | };
1841 |
1842 | jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) {
1843 | beforeEachFunction.typeName = 'beforeEach';
1844 | this.before_.splice(0,0,beforeEachFunction);
1845 | };
1846 |
1847 | jasmine.Runner.prototype.afterEach = function(afterEachFunction) {
1848 | afterEachFunction.typeName = 'afterEach';
1849 | this.after_.splice(0,0,afterEachFunction);
1850 | };
1851 |
1852 |
1853 | jasmine.Runner.prototype.finishCallback = function() {
1854 | this.env.reporter.reportRunnerResults(this);
1855 | };
1856 |
1857 | jasmine.Runner.prototype.addSuite = function(suite) {
1858 | this.suites_.push(suite);
1859 | };
1860 |
1861 | jasmine.Runner.prototype.add = function(block) {
1862 | if (block instanceof jasmine.Suite) {
1863 | this.addSuite(block);
1864 | }
1865 | this.queue.add(block);
1866 | };
1867 |
1868 | jasmine.Runner.prototype.specs = function () {
1869 | var suites = this.suites();
1870 | var specs = [];
1871 | for (var i = 0; i < suites.length; i++) {
1872 | specs = specs.concat(suites[i].specs());
1873 | }
1874 | return specs;
1875 | };
1876 |
1877 | jasmine.Runner.prototype.suites = function() {
1878 | return this.suites_;
1879 | };
1880 |
1881 | jasmine.Runner.prototype.topLevelSuites = function() {
1882 | var topLevelSuites = [];
1883 | for (var i = 0; i < this.suites_.length; i++) {
1884 | if (!this.suites_[i].parentSuite) {
1885 | topLevelSuites.push(this.suites_[i]);
1886 | }
1887 | }
1888 | return topLevelSuites;
1889 | };
1890 |
1891 | jasmine.Runner.prototype.results = function() {
1892 | return this.queue.results();
1893 | };
1894 | /**
1895 | * Internal representation of a Jasmine specification, or test.
1896 | *
1897 | * @constructor
1898 | * @param {jasmine.Env} env
1899 | * @param {jasmine.Suite} suite
1900 | * @param {String} description
1901 | */
1902 | jasmine.Spec = function(env, suite, description) {
1903 | if (!env) {
1904 | throw new Error('jasmine.Env() required');
1905 | }
1906 | if (!suite) {
1907 | throw new Error('jasmine.Suite() required');
1908 | }
1909 | var spec = this;
1910 | spec.id = env.nextSpecId ? env.nextSpecId() : null;
1911 | spec.env = env;
1912 | spec.suite = suite;
1913 | spec.description = description;
1914 | spec.queue = new jasmine.Queue(env);
1915 |
1916 | spec.afterCallbacks = [];
1917 | spec.spies_ = [];
1918 |
1919 | spec.results_ = new jasmine.NestedResults();
1920 | spec.results_.description = description;
1921 | spec.matchersClass = null;
1922 | };
1923 |
1924 | jasmine.Spec.prototype.getFullName = function() {
1925 | return this.suite.getFullName() + ' ' + this.description + '.';
1926 | };
1927 |
1928 |
1929 | jasmine.Spec.prototype.results = function() {
1930 | return this.results_;
1931 | };
1932 |
1933 | /**
1934 | * All parameters are pretty-printed and concatenated together, then written to the spec's output.
1935 | *
1936 | * Be careful not to leave calls to jasmine.log
in production code.
1937 | */
1938 | jasmine.Spec.prototype.log = function() {
1939 | return this.results_.log(arguments);
1940 | };
1941 |
1942 | jasmine.Spec.prototype.runs = function (func) {
1943 | var block = new jasmine.Block(this.env, func, this);
1944 | this.addToQueue(block);
1945 | return this;
1946 | };
1947 |
1948 | jasmine.Spec.prototype.addToQueue = function (block) {
1949 | if (this.queue.isRunning()) {
1950 | this.queue.insertNext(block);
1951 | } else {
1952 | this.queue.add(block);
1953 | }
1954 | };
1955 |
1956 | /**
1957 | * @param {jasmine.ExpectationResult} result
1958 | */
1959 | jasmine.Spec.prototype.addMatcherResult = function(result) {
1960 | this.results_.addResult(result);
1961 | };
1962 |
1963 | jasmine.Spec.prototype.expect = function(actual) {
1964 | var positive = new (this.getMatchersClass_())(this.env, actual, this);
1965 | positive.not = new (this.getMatchersClass_())(this.env, actual, this, true);
1966 | return positive;
1967 | };
1968 |
1969 | /**
1970 | * Waits a fixed time period before moving to the next block.
1971 | *
1972 | * @deprecated Use waitsFor() instead
1973 | * @param {Number} timeout milliseconds to wait
1974 | */
1975 | jasmine.Spec.prototype.waits = function(timeout) {
1976 | var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this);
1977 | this.addToQueue(waitsFunc);
1978 | return this;
1979 | };
1980 |
1981 | /**
1982 | * Waits for the latchFunction to return true before proceeding to the next block.
1983 | *
1984 | * @param {Function} latchFunction
1985 | * @param {String} optional_timeoutMessage
1986 | * @param {Number} optional_timeout
1987 | */
1988 | jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
1989 | var latchFunction_ = null;
1990 | var optional_timeoutMessage_ = null;
1991 | var optional_timeout_ = null;
1992 |
1993 | for (var i = 0; i < arguments.length; i++) {
1994 | var arg = arguments[i];
1995 | switch (typeof arg) {
1996 | case 'function':
1997 | latchFunction_ = arg;
1998 | break;
1999 | case 'string':
2000 | optional_timeoutMessage_ = arg;
2001 | break;
2002 | case 'number':
2003 | optional_timeout_ = arg;
2004 | break;
2005 | }
2006 | }
2007 |
2008 | var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this);
2009 | this.addToQueue(waitsForFunc);
2010 | return this;
2011 | };
2012 |
2013 | jasmine.Spec.prototype.fail = function (e) {
2014 | var expectationResult = new jasmine.ExpectationResult({
2015 | passed: false,
2016 | message: e ? jasmine.util.formatException(e) : 'Exception',
2017 | trace: { stack: e.stack }
2018 | });
2019 | this.results_.addResult(expectationResult);
2020 | };
2021 |
2022 | jasmine.Spec.prototype.getMatchersClass_ = function() {
2023 | return this.matchersClass || this.env.matchersClass;
2024 | };
2025 |
2026 | jasmine.Spec.prototype.addMatchers = function(matchersPrototype) {
2027 | var parent = this.getMatchersClass_();
2028 | var newMatchersClass = function() {
2029 | parent.apply(this, arguments);
2030 | };
2031 | jasmine.util.inherit(newMatchersClass, parent);
2032 | jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass);
2033 | this.matchersClass = newMatchersClass;
2034 | };
2035 |
2036 | jasmine.Spec.prototype.finishCallback = function() {
2037 | this.env.reporter.reportSpecResults(this);
2038 | };
2039 |
2040 | jasmine.Spec.prototype.finish = function(onComplete) {
2041 | this.removeAllSpies();
2042 | this.finishCallback();
2043 | if (onComplete) {
2044 | onComplete();
2045 | }
2046 | };
2047 |
2048 | jasmine.Spec.prototype.after = function(doAfter) {
2049 | if (this.queue.isRunning()) {
2050 | this.queue.add(new jasmine.Block(this.env, doAfter, this));
2051 | } else {
2052 | this.afterCallbacks.unshift(doAfter);
2053 | }
2054 | };
2055 |
2056 | jasmine.Spec.prototype.execute = function(onComplete) {
2057 | var spec = this;
2058 | if (!spec.env.specFilter(spec)) {
2059 | spec.results_.skipped = true;
2060 | spec.finish(onComplete);
2061 | return;
2062 | }
2063 |
2064 | this.env.reporter.reportSpecStarting(this);
2065 |
2066 | spec.env.currentSpec = spec;
2067 |
2068 | spec.addBeforesAndAftersToQueue();
2069 |
2070 | spec.queue.start(function () {
2071 | spec.finish(onComplete);
2072 | });
2073 | };
2074 |
2075 | jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() {
2076 | var runner = this.env.currentRunner();
2077 | var i;
2078 |
2079 | for (var suite = this.suite; suite; suite = suite.parentSuite) {
2080 | for (i = 0; i < suite.before_.length; i++) {
2081 | this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this));
2082 | }
2083 | }
2084 | for (i = 0; i < runner.before_.length; i++) {
2085 | this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this));
2086 | }
2087 | for (i = 0; i < this.afterCallbacks.length; i++) {
2088 | this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this));
2089 | }
2090 | for (suite = this.suite; suite; suite = suite.parentSuite) {
2091 | for (i = 0; i < suite.after_.length; i++) {
2092 | this.queue.add(new jasmine.Block(this.env, suite.after_[i], this));
2093 | }
2094 | }
2095 | for (i = 0; i < runner.after_.length; i++) {
2096 | this.queue.add(new jasmine.Block(this.env, runner.after_[i], this));
2097 | }
2098 | };
2099 |
2100 | jasmine.Spec.prototype.explodes = function() {
2101 | throw 'explodes function should not have been called';
2102 | };
2103 |
2104 | jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) {
2105 | if (obj == jasmine.undefined) {
2106 | throw "spyOn could not find an object to spy upon for " + methodName + "()";
2107 | }
2108 |
2109 | if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) {
2110 | throw methodName + '() method does not exist';
2111 | }
2112 |
2113 | if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) {
2114 | throw new Error(methodName + ' has already been spied upon');
2115 | }
2116 |
2117 | var spyObj = jasmine.createSpy(methodName);
2118 |
2119 | this.spies_.push(spyObj);
2120 | spyObj.baseObj = obj;
2121 | spyObj.methodName = methodName;
2122 | spyObj.originalValue = obj[methodName];
2123 |
2124 | obj[methodName] = spyObj;
2125 |
2126 | return spyObj;
2127 | };
2128 |
2129 | jasmine.Spec.prototype.removeAllSpies = function() {
2130 | for (var i = 0; i < this.spies_.length; i++) {
2131 | var spy = this.spies_[i];
2132 | spy.baseObj[spy.methodName] = spy.originalValue;
2133 | }
2134 | this.spies_ = [];
2135 | };
2136 |
2137 | /**
2138 | * Internal representation of a Jasmine suite.
2139 | *
2140 | * @constructor
2141 | * @param {jasmine.Env} env
2142 | * @param {String} description
2143 | * @param {Function} specDefinitions
2144 | * @param {jasmine.Suite} parentSuite
2145 | */
2146 | jasmine.Suite = function(env, description, specDefinitions, parentSuite) {
2147 | var self = this;
2148 | self.id = env.nextSuiteId ? env.nextSuiteId() : null;
2149 | self.description = description;
2150 | self.queue = new jasmine.Queue(env);
2151 | self.parentSuite = parentSuite;
2152 | self.env = env;
2153 | self.before_ = [];
2154 | self.after_ = [];
2155 | self.children_ = [];
2156 | self.suites_ = [];
2157 | self.specs_ = [];
2158 | };
2159 |
2160 | jasmine.Suite.prototype.getFullName = function() {
2161 | var fullName = this.description;
2162 | for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) {
2163 | fullName = parentSuite.description + ' ' + fullName;
2164 | }
2165 | return fullName;
2166 | };
2167 |
2168 | jasmine.Suite.prototype.finish = function(onComplete) {
2169 | this.env.reporter.reportSuiteResults(this);
2170 | this.finished = true;
2171 | if (typeof(onComplete) == 'function') {
2172 | onComplete();
2173 | }
2174 | };
2175 |
2176 | jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) {
2177 | beforeEachFunction.typeName = 'beforeEach';
2178 | this.before_.unshift(beforeEachFunction);
2179 | };
2180 |
2181 | jasmine.Suite.prototype.afterEach = function(afterEachFunction) {
2182 | afterEachFunction.typeName = 'afterEach';
2183 | this.after_.unshift(afterEachFunction);
2184 | };
2185 |
2186 | jasmine.Suite.prototype.results = function() {
2187 | return this.queue.results();
2188 | };
2189 |
2190 | jasmine.Suite.prototype.add = function(suiteOrSpec) {
2191 | this.children_.push(suiteOrSpec);
2192 | if (suiteOrSpec instanceof jasmine.Suite) {
2193 | this.suites_.push(suiteOrSpec);
2194 | this.env.currentRunner().addSuite(suiteOrSpec);
2195 | } else {
2196 | this.specs_.push(suiteOrSpec);
2197 | }
2198 | this.queue.add(suiteOrSpec);
2199 | };
2200 |
2201 | jasmine.Suite.prototype.specs = function() {
2202 | return this.specs_;
2203 | };
2204 |
2205 | jasmine.Suite.prototype.suites = function() {
2206 | return this.suites_;
2207 | };
2208 |
2209 | jasmine.Suite.prototype.children = function() {
2210 | return this.children_;
2211 | };
2212 |
2213 | jasmine.Suite.prototype.execute = function(onComplete) {
2214 | var self = this;
2215 | this.queue.start(function () {
2216 | self.finish(onComplete);
2217 | });
2218 | };
2219 | jasmine.WaitsBlock = function(env, timeout, spec) {
2220 | this.timeout = timeout;
2221 | jasmine.Block.call(this, env, null, spec);
2222 | };
2223 |
2224 | jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block);
2225 |
2226 | jasmine.WaitsBlock.prototype.execute = function (onComplete) {
2227 | if (jasmine.VERBOSE) {
2228 | this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...');
2229 | }
2230 | this.env.setTimeout(function () {
2231 | onComplete();
2232 | }, this.timeout);
2233 | };
2234 | /**
2235 | * A block which waits for some condition to become true, with timeout.
2236 | *
2237 | * @constructor
2238 | * @extends jasmine.Block
2239 | * @param {jasmine.Env} env The Jasmine environment.
2240 | * @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true.
2241 | * @param {Function} latchFunction A function which returns true when the desired condition has been met.
2242 | * @param {String} message The message to display if the desired condition hasn't been met within the given time period.
2243 | * @param {jasmine.Spec} spec The Jasmine spec.
2244 | */
2245 | jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) {
2246 | this.timeout = timeout || env.defaultTimeoutInterval;
2247 | this.latchFunction = latchFunction;
2248 | this.message = message;
2249 | this.totalTimeSpentWaitingForLatch = 0;
2250 | jasmine.Block.call(this, env, null, spec);
2251 | };
2252 | jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block);
2253 |
2254 | jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10;
2255 |
2256 | jasmine.WaitsForBlock.prototype.execute = function(onComplete) {
2257 | if (jasmine.VERBOSE) {
2258 | this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen'));
2259 | }
2260 | var latchFunctionResult;
2261 | try {
2262 | latchFunctionResult = this.latchFunction.apply(this.spec);
2263 | } catch (e) {
2264 | this.spec.fail(e);
2265 | onComplete();
2266 | return;
2267 | }
2268 |
2269 | if (latchFunctionResult) {
2270 | onComplete();
2271 | } else if (this.totalTimeSpentWaitingForLatch >= this.timeout) {
2272 | var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen');
2273 | this.spec.fail({
2274 | name: 'timeout',
2275 | message: message
2276 | });
2277 |
2278 | this.abort = true;
2279 | onComplete();
2280 | } else {
2281 | this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT;
2282 | var self = this;
2283 | this.env.setTimeout(function() {
2284 | self.execute(onComplete);
2285 | }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT);
2286 | }
2287 | };
2288 | // Mock setTimeout, clearTimeout
2289 | // Contributed by Pivotal Computer Systems, www.pivotalsf.com
2290 |
2291 | jasmine.FakeTimer = function() {
2292 | this.reset();
2293 |
2294 | var self = this;
2295 | self.setTimeout = function(funcToCall, millis) {
2296 | self.timeoutsMade++;
2297 | self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false);
2298 | return self.timeoutsMade;
2299 | };
2300 |
2301 | self.setInterval = function(funcToCall, millis) {
2302 | self.timeoutsMade++;
2303 | self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true);
2304 | return self.timeoutsMade;
2305 | };
2306 |
2307 | self.clearTimeout = function(timeoutKey) {
2308 | self.scheduledFunctions[timeoutKey] = jasmine.undefined;
2309 | };
2310 |
2311 | self.clearInterval = function(timeoutKey) {
2312 | self.scheduledFunctions[timeoutKey] = jasmine.undefined;
2313 | };
2314 |
2315 | };
2316 |
2317 | jasmine.FakeTimer.prototype.reset = function() {
2318 | this.timeoutsMade = 0;
2319 | this.scheduledFunctions = {};
2320 | this.nowMillis = 0;
2321 | };
2322 |
2323 | jasmine.FakeTimer.prototype.tick = function(millis) {
2324 | var oldMillis = this.nowMillis;
2325 | var newMillis = oldMillis + millis;
2326 | this.runFunctionsWithinRange(oldMillis, newMillis);
2327 | this.nowMillis = newMillis;
2328 | };
2329 |
2330 | jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) {
2331 | var scheduledFunc;
2332 | var funcsToRun = [];
2333 | for (var timeoutKey in this.scheduledFunctions) {
2334 | scheduledFunc = this.scheduledFunctions[timeoutKey];
2335 | if (scheduledFunc != jasmine.undefined &&
2336 | scheduledFunc.runAtMillis >= oldMillis &&
2337 | scheduledFunc.runAtMillis <= nowMillis) {
2338 | funcsToRun.push(scheduledFunc);
2339 | this.scheduledFunctions[timeoutKey] = jasmine.undefined;
2340 | }
2341 | }
2342 |
2343 | if (funcsToRun.length > 0) {
2344 | funcsToRun.sort(function(a, b) {
2345 | return a.runAtMillis - b.runAtMillis;
2346 | });
2347 | for (var i = 0; i < funcsToRun.length; ++i) {
2348 | try {
2349 | var funcToRun = funcsToRun[i];
2350 | this.nowMillis = funcToRun.runAtMillis;
2351 | funcToRun.funcToCall();
2352 | if (funcToRun.recurring) {
2353 | this.scheduleFunction(funcToRun.timeoutKey,
2354 | funcToRun.funcToCall,
2355 | funcToRun.millis,
2356 | true);
2357 | }
2358 | } catch(e) {
2359 | }
2360 | }
2361 | this.runFunctionsWithinRange(oldMillis, nowMillis);
2362 | }
2363 | };
2364 |
2365 | jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) {
2366 | this.scheduledFunctions[timeoutKey] = {
2367 | runAtMillis: this.nowMillis + millis,
2368 | funcToCall: funcToCall,
2369 | recurring: recurring,
2370 | timeoutKey: timeoutKey,
2371 | millis: millis
2372 | };
2373 | };
2374 |
2375 | /**
2376 | * @namespace
2377 | */
2378 | jasmine.Clock = {
2379 | defaultFakeTimer: new jasmine.FakeTimer(),
2380 |
2381 | reset: function() {
2382 | jasmine.Clock.assertInstalled();
2383 | jasmine.Clock.defaultFakeTimer.reset();
2384 | },
2385 |
2386 | tick: function(millis) {
2387 | jasmine.Clock.assertInstalled();
2388 | jasmine.Clock.defaultFakeTimer.tick(millis);
2389 | },
2390 |
2391 | runFunctionsWithinRange: function(oldMillis, nowMillis) {
2392 | jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis);
2393 | },
2394 |
2395 | scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) {
2396 | jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring);
2397 | },
2398 |
2399 | useMock: function() {
2400 | if (!jasmine.Clock.isInstalled()) {
2401 | var spec = jasmine.getEnv().currentSpec;
2402 | spec.after(jasmine.Clock.uninstallMock);
2403 |
2404 | jasmine.Clock.installMock();
2405 | }
2406 | },
2407 |
2408 | installMock: function() {
2409 | jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer;
2410 | },
2411 |
2412 | uninstallMock: function() {
2413 | jasmine.Clock.assertInstalled();
2414 | jasmine.Clock.installed = jasmine.Clock.real;
2415 | },
2416 |
2417 | real: {
2418 | setTimeout: jasmine.getGlobal().setTimeout,
2419 | clearTimeout: jasmine.getGlobal().clearTimeout,
2420 | setInterval: jasmine.getGlobal().setInterval,
2421 | clearInterval: jasmine.getGlobal().clearInterval
2422 | },
2423 |
2424 | assertInstalled: function() {
2425 | if (!jasmine.Clock.isInstalled()) {
2426 | throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
2427 | }
2428 | },
2429 |
2430 | isInstalled: function() {
2431 | return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer;
2432 | },
2433 |
2434 | installed: null
2435 | };
2436 | jasmine.Clock.installed = jasmine.Clock.real;
2437 |
2438 | //else for IE support
2439 | jasmine.getGlobal().setTimeout = function(funcToCall, millis) {
2440 | if (jasmine.Clock.installed.setTimeout.apply) {
2441 | return jasmine.Clock.installed.setTimeout.apply(this, arguments);
2442 | } else {
2443 | return jasmine.Clock.installed.setTimeout(funcToCall, millis);
2444 | }
2445 | };
2446 |
2447 | jasmine.getGlobal().setInterval = function(funcToCall, millis) {
2448 | if (jasmine.Clock.installed.setInterval.apply) {
2449 | return jasmine.Clock.installed.setInterval.apply(this, arguments);
2450 | } else {
2451 | return jasmine.Clock.installed.setInterval(funcToCall, millis);
2452 | }
2453 | };
2454 |
2455 | jasmine.getGlobal().clearTimeout = function(timeoutKey) {
2456 | if (jasmine.Clock.installed.clearTimeout.apply) {
2457 | return jasmine.Clock.installed.clearTimeout.apply(this, arguments);
2458 | } else {
2459 | return jasmine.Clock.installed.clearTimeout(timeoutKey);
2460 | }
2461 | };
2462 |
2463 | jasmine.getGlobal().clearInterval = function(timeoutKey) {
2464 | if (jasmine.Clock.installed.clearTimeout.apply) {
2465 | return jasmine.Clock.installed.clearInterval.apply(this, arguments);
2466 | } else {
2467 | return jasmine.Clock.installed.clearInterval(timeoutKey);
2468 | }
2469 | };
2470 |
2471 | jasmine.version_= {
2472 | "major": 1,
2473 | "minor": 1,
2474 | "build": 0,
2475 | "revision": 1315677058
2476 | };
2477 |
--------------------------------------------------------------------------------
/lib/jasmine/jasmine_favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dfilatov/jquery-plugins/8f4d6d542952ae65884153b6ee2cdafdf3db3e4a/lib/jasmine/jasmine_favicon.png
--------------------------------------------------------------------------------
/lib/jquery/jquery-1.7.1.js:
--------------------------------------------------------------------------------
1 | /*! jQuery v1.7.1 jquery.com | jquery.org/license */
2 | (function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"":"")+""),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){if(c!=="border")for(;g=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;ca",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o=""+"",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};
3 | f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;le&&i.push({elem:this,matches:d.slice(e)});for(j=0;j0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h0)for(h=g;h=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/",""],legend:[1,""],thead:[1,""],tr:[2,""],td:[3,""],col:[2,""],area:[1,""],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div","
"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function()
4 | {for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1>$2>");try{for(var c=0,d=this.length;c1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||!bc.test("<"+a.nodeName)?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1>$2>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");b===c?bh.appendChild(o):U(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]===""&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return br.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bq,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bq.test(g)?g.replace(bq,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,b){var c,d,e;b=b.replace(bs,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b)));return c}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bt.test(f)&&bu.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bD=/%20/g,bE=/\[\]$/,bF=/\r?\n/g,bG=/#.*$/,bH=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bI=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bJ=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bK=/^(?:GET|HEAD)$/,bL=/^\/\//,bM=/\?/,bN=/
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
21 |
--------------------------------------------------------------------------------
/src/jquery.debounce/jquery.debounce.specs.js:
--------------------------------------------------------------------------------
1 | describe('jquery.debounce specs', function() {
2 |
3 | it('should be function debounced', function() {
4 | var spy = jasmine.createSpy(),
5 | debouncedFn = $.debounce(spy, 50),
6 | cnt = 0, cntMax = 10,
7 | completed = false,
8 | testFn = function test() {
9 | if(cnt < cntMax) {
10 | debouncedFn();
11 | debouncedFn();
12 | debouncedFn();
13 | cnt++;
14 | setTimeout(test, 35);
15 | }
16 | else {
17 | setTimeout(function() {
18 | if(cntMax == 20) {
19 | completed = true;
20 | }
21 | else {
22 | cntMax = 20;
23 | setTimeout(test, 35);
24 | }
25 | }, 70);
26 | }
27 | };
28 |
29 | testFn();
30 |
31 | waitsFor(function() {
32 | return completed;
33 | });
34 | runs(function() {
35 | expect(spy.callCount).toBe(2);
36 | });
37 | });
38 |
39 | it('should be function throttled', function() {
40 | var spy = jasmine.createSpy(),
41 | throttledFn = $.throttle(spy, 50),
42 | cnt = 0,
43 | completed = false,
44 | testFn = function test() {
45 | if(cnt === 10) {
46 | completed = true;
47 | }
48 | else {
49 | throttledFn();
50 | throttledFn();
51 | throttledFn();
52 | cnt++;
53 | setTimeout(test, 42);
54 | }
55 | };
56 |
57 | testFn();
58 |
59 | waitsFor(function() {
60 | return completed;
61 | });
62 | runs(function() {
63 | expect(spy.callCount).toBe(9);
64 | });
65 | });
66 |
67 | });
--------------------------------------------------------------------------------
/src/jquery.identify/jquery.identify.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Identify plugin
3 | *
4 | * Copyright (c) 2009 Filatov Dmitry (dfilatov@yandex-team.ru)
5 | * Dual licensed under the MIT and GPL licenses:
6 | * http://www.opensource.org/licenses/mit-license.php
7 | * http://www.gnu.org/licenses/gpl.html
8 | *
9 | * @version 1.0.0
10 | */
11 |
12 | (function($) {
13 |
14 | var cnt = 0,
15 | expando = '__' + (+new Date),
16 | get = function() {
17 | return 'uniq' + ++cnt;
18 | };
19 |
20 | /**
21 | * @param {Object} [obj] object to identify, return next unique id if no passed
22 | * @param {Boolean} [onlyGet=false] return unique id only if before assigned
23 | * @returns {String} unique id
24 | */
25 | $.identify = function(obj, onlyGet) {
26 |
27 | if(!obj) return get();
28 |
29 | var key = 'uniqueID' in obj? 'uniqueID' : expando; // use native uniqueID for IE elements
30 |
31 | return onlyGet || key in obj?
32 | obj[key] :
33 | obj[key] = get();
34 |
35 | };
36 |
37 | })(jQuery);
--------------------------------------------------------------------------------
/src/jquery.identify/jquery.identify.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Identify plugin
3 | *
4 | * Copyright (c) 2009 Filatov Dmitry (dfilatov@yandex-team.ru)
5 | * Dual licensed under the MIT and GPL licenses:
6 | * http://www.opensource.org/licenses/mit-license.php
7 | * http://www.gnu.org/licenses/gpl.html
8 | *
9 | * @version 1.0.0
10 | */(function(a){var b=0,c="__"+ +(new Date),d=function(){return"uniq"+ ++b};a.identify=function(a,b){if(!a)return d();var e="uniqueID"in a?"uniqueID":c;return b||e in a?a[e]:a[e]=d()}})(jQuery);
--------------------------------------------------------------------------------
/src/jquery.identify/jquery.identify.specs.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | jquery.identify specs
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
21 |
--------------------------------------------------------------------------------
/src/jquery.identify/jquery.identify.specs.js:
--------------------------------------------------------------------------------
1 | describe('jquery.identify specs', function() {
2 |
3 | it('same object should be identified', function() {
4 | var obj1 = {};
5 |
6 | expect($.identify(obj1)).toEqual($.identify(obj1));
7 | });
8 |
9 | it('different objects should have different id', function() {
10 | var obj1 = {},
11 | obj2 = {};
12 |
13 | expect($.identify(obj1)).not.toEqual($.identify(obj2));
14 | });
15 |
16 | it('object shouldn\'t have id if only getting used', function() {
17 | var obj1 = {};
18 |
19 | expect($.identify(obj1, true)).toBeUndefined();
20 | });
21 |
22 | it('object should have id on getting if before identified', function() {
23 | var obj1 = {},
24 | id = $.identify(obj1);
25 |
26 | expect($.identify(obj1, true)).toBe(id);
27 | });
28 |
29 | it('should return unique id without params', function() {
30 | expect($.identify()).not.toBe($.identify());
31 | });
32 |
33 | });
--------------------------------------------------------------------------------
/src/jquery.inherit/jquery.inherit.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Inheritance plugin
3 | *
4 | * Copyright (c) 2010 Filatov Dmitry (dfilatov@yandex-team.ru)
5 | * Dual licensed under the MIT and GPL licenses:
6 | * http://www.opensource.org/licenses/mit-license.php
7 | * http://www.gnu.org/licenses/gpl.html
8 | *
9 | * @version 1.3.6
10 | */
11 |
12 | (function($) {
13 |
14 | var hasIntrospection = (function(){'_';}).toString().indexOf('_') > -1,
15 | emptyBase = function() {},
16 | objCreate = Object.create || function(ptp) {
17 | var inheritance = function() {};
18 | inheritance.prototype = ptp;
19 | return new inheritance();
20 | },
21 | needCheckProps = true,
22 | testPropObj = { toString : '' };
23 |
24 | for(var i in testPropObj) { // fucking ie hasn't toString, valueOf in for
25 | testPropObj.hasOwnProperty(i) && (needCheckProps = false);
26 | }
27 |
28 | var specProps = needCheckProps? ['toString', 'valueOf'] : null;
29 |
30 | function override(base, result, add) {
31 |
32 | var hasSpecProps = false;
33 | if(needCheckProps) {
34 | var addList = [];
35 | $.each(specProps, function() {
36 | add.hasOwnProperty(this) && (hasSpecProps = true) && addList.push({
37 | name : this,
38 | val : add[this]
39 | });
40 | });
41 | if(hasSpecProps) {
42 | $.each(add, function(name) {
43 | addList.push({
44 | name : name,
45 | val : this
46 | });
47 | });
48 | add = addList;
49 | }
50 | }
51 |
52 | $.each(add, function(name, prop) {
53 | if(hasSpecProps) {
54 | name = prop.name;
55 | prop = prop.val;
56 | }
57 | if($.isFunction(prop) &&
58 | (!hasIntrospection || prop.toString().indexOf('.__base') > -1)) {
59 |
60 | var baseMethod = base[name] || function() {};
61 | result[name] = function() {
62 | var baseSaved = this.__base;
63 | this.__base = baseMethod;
64 | var result = prop.apply(this, arguments);
65 | this.__base = baseSaved;
66 | return result;
67 | };
68 |
69 | }
70 | else {
71 | result[name] = prop;
72 | }
73 |
74 | });
75 |
76 | }
77 |
78 | $.inherit = function() {
79 |
80 | var args = arguments,
81 | hasBase = $.isFunction(args[0]),
82 | base = hasBase? args[0] : emptyBase,
83 | props = args[hasBase? 1 : 0] || {},
84 | staticProps = args[hasBase? 2 : 1],
85 | result = props.__constructor || (hasBase && base.prototype.__constructor)?
86 | function() {
87 | return this.__constructor.apply(this, arguments);
88 | } : function() {};
89 |
90 | if(!hasBase) {
91 | result.prototype = props;
92 | result.prototype.__self = result.prototype.constructor = result;
93 | return $.extend(result, staticProps);
94 | }
95 |
96 | $.extend(result, base);
97 |
98 | var basePtp = base.prototype,
99 | resultPtp = result.prototype = objCreate(basePtp);
100 |
101 | resultPtp.__self = resultPtp.constructor = result;
102 |
103 | override(basePtp, resultPtp, props);
104 | staticProps && override(base, result, staticProps);
105 |
106 | return result;
107 |
108 | };
109 |
110 | $.inheritSelf = function(base, props, staticProps) {
111 |
112 | var basePtp = base.prototype;
113 |
114 | override(basePtp, basePtp, props);
115 | staticProps && override(base, base, staticProps);
116 |
117 | return base;
118 |
119 | };
120 |
121 | })(jQuery);
122 |
--------------------------------------------------------------------------------
/src/jquery.inherit/jquery.inherit.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Inheritance plugin
3 | *
4 | * Copyright (c) 2010 Filatov Dmitry (dfilatov@yandex-team.ru)
5 | * Dual licensed under the MIT and GPL licenses:
6 | * http://www.opensource.org/licenses/mit-license.php
7 | * http://www.gnu.org/licenses/gpl.html
8 | *
9 | * @version 1.3.5
10 | */(function(e){function a(n,r,s){var o=!1;if(i){var a=[];e.each(u,function(){s.hasOwnProperty(this)&&(o=!0)&&a.push({name:this,val:s[this]})}),o&&(e.each(s,function(e){a.push({name:e,val:this})}),s=a)}e.each(s,function(i,s){o&&(i=s.name,s=s.val);if(e.isFunction(s)&&(!t||s.toString().indexOf(".__base")>-1)){var u=n[i]||function(){};r[i]=function(){var e=this.__base;this.__base=u;var t=s.apply(this,arguments);return this.__base=e,t}}else r[i]=s})}var t=function(){_}.toString().indexOf("_")>-1,n=function(){},r=Object.create||function(e){var t=function(){};return t.prototype=e,new t},i=!0,s={toString:""};for(var o in s)s.hasOwnProperty(o)&&(i=!1);var u=i?["toString","valueOf"]:null;e.inherit=function(){var t=arguments,i=e.isFunction(t[0]),s=i?t[0]:n,o=t[i?1:0]||{},u=t[i?2:1],f=o.__constructor||i&&s.prototype.__constructor?function(){return this.__constructor.apply(this,arguments)}:function(){};if(!i)return f.prototype=o,f.prototype.__self=f.prototype.constructor=f,e.extend(f,u);e.extend(f,s);var l=s.prototype,c=f.prototype=r(l);return c.__self=c.constructor=f,a(l,c,o),u&&a(s,f,u),f},e.inheritSelf=function(e,t,n){var r=e.prototype;return a(r,r,t),n&&a(e,e,n),e}})(jQuery);
--------------------------------------------------------------------------------
/src/jquery.inherit/jquery.inherit.specs.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | jquery.inherit specs
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
21 |
--------------------------------------------------------------------------------
/src/jquery.inherit/jquery.inherit.specs.js:
--------------------------------------------------------------------------------
1 | describe('jquery.inherit specs', function() {
2 |
3 | it('should be valid instance\'s properties', function() {
4 | var A = $.inherit({
5 | __constructor : function(val) {
6 | this.prop = val;
7 | }
8 | });
9 |
10 | expect(new A('test').prop).toBe('test');
11 | expect(new A('other').prop).toBe('other');
12 | });
13 |
14 | it('should be valid instanceOf value', function() {
15 | var A = $.inherit({}),
16 | B = $.inherit(A, {});
17 |
18 | expect(new A() instanceof A).toBeTruthy();
19 | expect(new A() instanceof B).toBeFalsy();
20 | expect(new B() instanceof A).toBeTruthy();
21 | expect(new B() instanceof B).toBeTruthy();
22 | });
23 |
24 | it('should be used constructor\'s result', function() {
25 | var A = $.inherit({}),
26 | B = $.inherit({
27 | __constructor : function() {
28 | return new A();
29 | }
30 | });
31 |
32 | expect(new B() instanceof A).toBeTruthy();
33 | });
34 |
35 | it('should __self property contains constructor', function() {
36 | var A = $.inherit({}),
37 | B = $.inherit(A, {});
38 |
39 | expect(new A().__self).toBe(A);
40 | expect(new B().__self).toBe(B);
41 | });
42 |
43 | it('should be properties inherited', function() {
44 | var A = $.inherit({
45 | method1 : function() {
46 | return 'A';
47 | }
48 | }),
49 | B = $.inherit(A, {
50 | method2 : function() {
51 | return 'B';
52 | }
53 | });
54 |
55 | expect(new A().method2).toBeUndefined();
56 | expect(new B().method1()).toEqual('A');
57 | });
58 |
59 | it('should be static properties inherited', function() {
60 | var A = $.inherit({}, {
61 | method1 : function() {
62 | return 'A';
63 | }
64 | }),
65 | B = $.inherit(A, {}, {
66 | method2 : function() {
67 | return 'B';
68 | }
69 | });
70 |
71 | expect(A.method2).toBeUndefined();
72 | expect(B.method1()).toEqual('A');
73 | });
74 |
75 | it('should be properties overrided', function() {
76 | var A = $.inherit({
77 | method : function() {
78 | return 'A';
79 | }
80 | }),
81 | B = $.inherit(A, {
82 | method : function() {
83 | return 'B';
84 | }
85 | });
86 |
87 | expect(new A().method(), 'A');
88 | expect(new B().method(), 'B');
89 | });
90 |
91 | it('should be static properties overrided', function() {
92 | var A = $.inherit({}, {
93 | method : function() {
94 | return 'A';
95 | }
96 | }),
97 | B = $.inherit(A, {}, {
98 | method : function() {
99 | return 'B';
100 | }
101 | });
102 |
103 | expect(A.method(), 'A');
104 | expect(B.method(), 'B');
105 | });
106 |
107 | it('should be allowed for base call', function() {
108 | var A = $.inherit({
109 | method1 : function() {
110 | return 'A';
111 | }
112 | }),
113 | B = $.inherit(A, {
114 | method1 : function() {
115 | return this.__base() + 'B';
116 | },
117 | method2 : function() {
118 | return this.__base() + 'B2';
119 | }
120 | }),
121 | C = $.inherit(B, {
122 | method1 : function() {
123 | return this.__base() + 'C';
124 | }
125 | });
126 |
127 | expect(new C().method1()).toBe('ABC');
128 | expect(new C().method2()).toBe('undefinedB2');
129 | });
130 |
131 | it('should be allowed for static base call', function() {
132 | var A = $.inherit({}, {
133 | method1 : function() {
134 | return 'A';
135 | }
136 | }),
137 | B = $.inherit(A, {}, {
138 | method1 : function() {
139 | return this.__base() + 'B';
140 | },
141 | method2 : function() {
142 | return this.__base() + 'B2';
143 | }
144 | }),
145 | C = $.inherit(B, {}, {
146 | method1 : function() {
147 | return this.__base() + 'C';
148 | }
149 | });
150 |
151 | expect(C.method1()).toBe('ABC');
152 | expect(C.method2()).toBe('undefinedB2');
153 | });
154 |
155 | });
--------------------------------------------------------------------------------
/src/jquery.inherit/readme.md:
--------------------------------------------------------------------------------
1 | jQuery inherit plugin
2 | =====================
3 | Plugin provides "class" and inheritance implementation.
4 | It brings some syntax sugar for "class" declarations, constructors, "super" calls and static members.
5 |
6 | Usage
7 | -----
8 | var MyClass = $.inherit([myBaseClass], props, [staticProps]);
9 |
10 | Example
11 | -------
12 | ```javascript
13 | // base "class"
14 | var A = $.inherit(/** @lends A.prototype */{
15 | __constructor : function(property) { // constructor
16 | this.property = property;
17 | },
18 |
19 | getProperty : function() {
20 | return this.property + ' of instanceA';
21 | },
22 |
23 | getType : function() {
24 | return 'A';
25 | },
26 |
27 | getStaticProperty : function() {
28 | return this.__self.staticMember; // access to static
29 | }
30 | }, /** @lends A */ {
31 | staticProperty : 'staticA',
32 |
33 | staticMethod : function() {
34 | return this.staticProperty;
35 | }
36 | });
37 |
38 | // inherited "class" from A
39 | var B = $.inherit(A, /** @lends B.prototype */{
40 | getProperty : function() { // overriding
41 | return this.property + ' of instanceB';
42 | },
43 |
44 | getType : function() { // overriding + "super" call
45 | return this.__base() + 'B';
46 | }
47 | }, /** @lends B */ {
48 | staticMethod : function() { // static overriding + "super" call
49 | return this.__base() + ' of staticB';
50 | }
51 | });
52 |
53 | var instanceOfB = new B('property');
54 |
55 | instanceOfB.getProperty(); // returns 'property of instanceB'
56 | instanceOfB.getType(); // returns 'AB'
57 | B.staticMethod(); // returns 'staticA of staticB'
58 | ```
59 |
--------------------------------------------------------------------------------
/src/jquery.memoize/jquery.memoize.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Memoization plugin
3 | *
4 | * Copyright (c) 2009 Filatov Dmitry (alpha@zforms.ru)
5 | * Dual licensed under the MIT and GPL licenses:
6 | * http://www.opensource.org/licenses/mit-license.php
7 | * http://www.gnu.org/licenses/gpl.html
8 | *
9 | * @version 1.0.2
10 | * @requires $.identify
11 | */
12 |
13 | (function($) {
14 |
15 | var DELIMITER = '\x0B',
16 | /** default serializer */
17 | serialize = function(args) {
18 | var res = [],
19 | i = 0, len = args.length;
20 |
21 | while(i < len) {
22 | res.push(typeof args[i], args[i++]);
23 | }
24 |
25 | return res.join(DELIMITER);
26 | };
27 |
28 | /**
29 | * @param {Function} fn original function
30 | * @param {Function} [serializeFn] custom argument's serializer
31 | * @returns Function memoized version of original function
32 | */
33 | $.memoize = function(fn, serializeFn) {
34 | var memo = {};
35 | return function() {
36 | var hash = $.identify(this) + DELIMITER + (serializeFn || serialize)(arguments);
37 | return hash in memo?
38 | memo[hash] :
39 | memo[hash] = fn.apply(this, arguments);
40 | };
41 | };
42 |
43 | })(jQuery);
--------------------------------------------------------------------------------
/src/jquery.memoize/jquery.memoize.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Memoization plugin
3 | *
4 | * Copyright (c) 2009 Filatov Dmitry (alpha@zforms.ru)
5 | * Dual licensed under the MIT and GPL licenses:
6 | * http://www.opensource.org/licenses/mit-license.php
7 | * http://www.gnu.org/licenses/gpl.html
8 | *
9 | * @version 1.0.2
10 | * @requires $.identify
11 | */(function(a){var b="",c=function(a){var c=[],d=0,e=a.length;while(d
2 |
3 | jquery.memoize specs
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
22 |