newjs 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +4 -0
- data/License.txt +20 -0
- data/Manifest.txt +68 -0
- data/README.txt +9 -0
- data/Rakefile +4 -0
- data/app_generators/newjs/USAGE +9 -0
- data/app_generators/newjs/newjs_generator.rb +113 -0
- data/app_generators/newjs/templates/History.txt.erb +4 -0
- data/app_generators/newjs/templates/License.txt.erb +20 -0
- data/app_generators/newjs/templates/README.txt +1 -0
- data/app_generators/newjs/templates/Rakefile.erb +82 -0
- data/app_generators/newjs/templates/config/javascript_test_autotest.yml.sample +15 -0
- data/app_generators/newjs/templates/lib/jstest.rb +382 -0
- data/app_generators/newjs/templates/lib/protodoc.rb +36 -0
- data/app_generators/newjs/templates/script/js_autotest +1 -0
- data/app_generators/newjs/templates/script/rstakeout +98 -0
- data/app_generators/newjs/templates/src/HEADER.erb +8 -0
- data/app_generators/newjs/templates/src/library.js.erb +7 -0
- data/app_generators/newjs/templates/tasks/environment.rake +7 -0
- data/app_generators/newjs/templates/tasks/javascript_test_autotest_tasks.rake +44 -0
- data/app_generators/newjs/templates/test/assets/prototype.js +4236 -0
- data/app_generators/newjs/templates/test/assets/unittest.css +50 -0
- data/app_generators/newjs/templates/test/assets/unittest.js +556 -0
- data/bin/newjs +17 -0
- data/config/hoe.rb +75 -0
- data/config/requirements.rb +17 -0
- data/javascript_test_generators/javascript_test/USAGE +2 -0
- data/javascript_test_generators/javascript_test/javascript_test_generator.rb +54 -0
- data/javascript_test_generators/javascript_test/templates/test/test.html.erb +58 -0
- data/lib/newjs.rb +7 -0
- data/lib/newjs/autotest.rb +3 -0
- data/lib/newjs/autotest/javascript_test_autotest.rb +22 -0
- data/lib/newjs/autotest/javascript_test_autotest/config.rb +20 -0
- data/lib/newjs/autotest/javascript_test_ext.rb +29 -0
- data/lib/newjs/jstest.rb +382 -0
- data/lib/newjs/version.rb +9 -0
- data/log/debug.log +0 -0
- data/newjs_generators/install_website/USAGE +5 -0
- data/newjs_generators/install_website/install_website_generator.rb +79 -0
- data/newjs_generators/install_website/templates/script/txt2html +74 -0
- data/newjs_generators/install_website/templates/script/win_script.cmd +1 -0
- data/newjs_generators/install_website/templates/tasks/website.rake +17 -0
- data/newjs_generators/install_website/templates/website/index.html +11 -0
- data/newjs_generators/install_website/templates/website/index.txt +37 -0
- data/newjs_theme_generators/plain_theme/USAGE +0 -0
- data/newjs_theme_generators/plain_theme/plain_theme_generator.rb +54 -0
- data/newjs_theme_generators/plain_theme/templates/website/javascripts/rounded_corners_lite.inc.js +285 -0
- data/newjs_theme_generators/plain_theme/templates/website/stylesheets/screen.css +138 -0
- data/newjs_theme_generators/plain_theme/templates/website/template.html.erb +48 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +74 -0
- data/setup.rb +1585 -0
- data/tasks/deployment.rake +34 -0
- data/tasks/environment.rake +7 -0
- data/tasks/website.rake +17 -0
- data/test/test_generator_helper.rb +20 -0
- data/test/test_helper.rb +4 -0
- data/test/test_install_website_generator.rb +39 -0
- data/test/test_javascript_test_generator.rb +43 -0
- data/test/test_newjs_generator.rb +63 -0
- data/test/test_plain_theme_generator.rb +37 -0
- data/website/images/example-unittest-log.jpg +0 -0
- data/website/index.html +271 -0
- data/website/index.txt +181 -0
- data/website/javascripts/rounded_corners_lite.inc.js +285 -0
- data/website/stylesheets/screen.css +138 -0
- data/website/template.html.erb +48 -0
- metadata +168 -0
@@ -0,0 +1,50 @@
|
|
1
|
+
body, div, p, h1, h2, h3, ul, ol, span, a, table, td, form, img, li {
|
2
|
+
font-family: sans-serif;
|
3
|
+
}
|
4
|
+
|
5
|
+
body {
|
6
|
+
font-size:0.8em;
|
7
|
+
}
|
8
|
+
|
9
|
+
#log {
|
10
|
+
padding-bottom: 1em;
|
11
|
+
border-bottom: 2px solid #000;
|
12
|
+
margin-bottom: 2em;
|
13
|
+
}
|
14
|
+
|
15
|
+
.logsummary {
|
16
|
+
margin-top: 1em;
|
17
|
+
margin-bottom: 1em;
|
18
|
+
padding: 1ex;
|
19
|
+
border: 1px solid #000;
|
20
|
+
font-weight: bold;
|
21
|
+
}
|
22
|
+
|
23
|
+
.logtable {
|
24
|
+
width:100%;
|
25
|
+
border-collapse: collapse;
|
26
|
+
border: 1px dotted #666;
|
27
|
+
}
|
28
|
+
|
29
|
+
.logtable td, .logtable th {
|
30
|
+
text-align: left;
|
31
|
+
padding: 3px 8px;
|
32
|
+
border: 1px dotted #666;
|
33
|
+
}
|
34
|
+
|
35
|
+
.logtable .passed {
|
36
|
+
background-color: #cfc;
|
37
|
+
}
|
38
|
+
|
39
|
+
.logtable .failed, .logtable .error {
|
40
|
+
background-color: #fcc;
|
41
|
+
}
|
42
|
+
|
43
|
+
.logtable td div.action_buttons {
|
44
|
+
display: inline;
|
45
|
+
}
|
46
|
+
|
47
|
+
.logtable td div.action_buttons input {
|
48
|
+
margin: 0 5px;
|
49
|
+
font-size: 10px;
|
50
|
+
}
|
@@ -0,0 +1,556 @@
|
|
1
|
+
// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
|
2
|
+
// (c) 2005 Jon Tirsen (http://www.tirsen.com)
|
3
|
+
// (c) 2005 Michael Schuerig (http://www.schuerig.de/michael/)
|
4
|
+
//
|
5
|
+
// Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
// a copy of this software and associated documentation files (the
|
7
|
+
// "Software"), to deal in the Software without restriction, including
|
8
|
+
// without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
// distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
// permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
// the following conditions:
|
12
|
+
//
|
13
|
+
// The above copyright notice and this permission notice shall be
|
14
|
+
// included in all copies or substantial portions of the Software.
|
15
|
+
//
|
16
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
|
25
|
+
// experimental, Firefox-only
|
26
|
+
Event.simulateMouse = function(element, eventName) {
|
27
|
+
var options = Object.extend({
|
28
|
+
pointerX: 0,
|
29
|
+
pointerY: 0,
|
30
|
+
buttons: 0
|
31
|
+
}, arguments[2] || {});
|
32
|
+
var oEvent = document.createEvent("MouseEvents");
|
33
|
+
oEvent.initMouseEvent(eventName, true, true, document.defaultView,
|
34
|
+
options.buttons, options.pointerX, options.pointerY, options.pointerX, options.pointerY,
|
35
|
+
false, false, false, false, 0, $(element));
|
36
|
+
|
37
|
+
if(this.mark) Element.remove(this.mark);
|
38
|
+
|
39
|
+
var style = 'position: absolute; width: 5px; height: 5px;' +
|
40
|
+
'top: #{pointerY}px; left: #{pointerX}px;'.interpolate(options) +
|
41
|
+
'border-top: 1px solid red; border-left: 1px solid red;'
|
42
|
+
|
43
|
+
this.mark = new Element('div', { style: style });
|
44
|
+
this.mark.appendChild(document.createTextNode(" "));
|
45
|
+
document.body.appendChild(this.mark);
|
46
|
+
|
47
|
+
if(this.step)
|
48
|
+
alert('['+new Date().getTime().toString()+'] '+eventName+'/'+Test.Unit.inspect(options));
|
49
|
+
|
50
|
+
$(element).dispatchEvent(oEvent);
|
51
|
+
};
|
52
|
+
|
53
|
+
// Note: Due to a fix in Firefox 1.0.5/6 that probably fixed "too much", this doesn't work in 1.0.6 or DP2.
|
54
|
+
// You need to downgrade to 1.0.4 for now to get this working
|
55
|
+
// See https://bugzilla.mozilla.org/show_bug.cgi?id=289940 for the fix that fixed too much
|
56
|
+
Event.simulateKey = function(element, eventName) {
|
57
|
+
var options = Object.extend({
|
58
|
+
ctrlKey: false,
|
59
|
+
altKey: false,
|
60
|
+
shiftKey: false,
|
61
|
+
metaKey: false,
|
62
|
+
keyCode: 0,
|
63
|
+
charCode: 0
|
64
|
+
}, arguments[2] || {});
|
65
|
+
|
66
|
+
var oEvent = document.createEvent("KeyEvents");
|
67
|
+
oEvent.initKeyEvent(eventName, true, true, window,
|
68
|
+
options.ctrlKey, options.altKey, options.shiftKey, options.metaKey,
|
69
|
+
options.keyCode, options.charCode );
|
70
|
+
$(element).dispatchEvent(oEvent);
|
71
|
+
};
|
72
|
+
|
73
|
+
Event.simulateKeys = function(element, command) {
|
74
|
+
for(var i=0; i<command.length; i++) {
|
75
|
+
Event.simulateKey(element,'keypress',{charCode:command.charCodeAt(i)});
|
76
|
+
}
|
77
|
+
};
|
78
|
+
|
79
|
+
var Test = {
|
80
|
+
Unit: {
|
81
|
+
inspect: Object.inspect // security exception workaround
|
82
|
+
}
|
83
|
+
};
|
84
|
+
|
85
|
+
Test.Unit.Logger = Class.create({
|
86
|
+
initialize: function(element) {
|
87
|
+
this.element = $(element);
|
88
|
+
if (this.element) this._createLogTable();
|
89
|
+
},
|
90
|
+
|
91
|
+
start: function(testName) {
|
92
|
+
if (!this.element) return;
|
93
|
+
this.element.down('tbody').insert('<tr><td>' + testName + '</td><td></td><td></td></tr>');
|
94
|
+
},
|
95
|
+
|
96
|
+
setStatus: function(status) {
|
97
|
+
this.getLastLogLine().addClassName(status).down('td', 1).update(status);
|
98
|
+
},
|
99
|
+
|
100
|
+
finish: function(status, summary) {
|
101
|
+
if (!this.element) return;
|
102
|
+
this.setStatus(status);
|
103
|
+
this.message(summary);
|
104
|
+
},
|
105
|
+
|
106
|
+
message: function(message) {
|
107
|
+
if (!this.element) return;
|
108
|
+
this.getMessageCell().update(this._toHTML(message));
|
109
|
+
},
|
110
|
+
|
111
|
+
summary: function(summary) {
|
112
|
+
if (!this.element) return;
|
113
|
+
this.element.down('div').update(this._toHTML(summary));
|
114
|
+
},
|
115
|
+
|
116
|
+
getLastLogLine: function() {
|
117
|
+
return this.element.select('tr').last()
|
118
|
+
},
|
119
|
+
|
120
|
+
getMessageCell: function() {
|
121
|
+
return this.getLastLogLine().down('td', 2);
|
122
|
+
},
|
123
|
+
|
124
|
+
_createLogTable: function() {
|
125
|
+
var html = '<div class="logsummary">running...</div>' +
|
126
|
+
'<table class="logtable">' +
|
127
|
+
'<thead><tr><th>Status</th><th>Test</th><th>Message</th></tr></thead>' +
|
128
|
+
'<tbody class="loglines"></tbody>' +
|
129
|
+
'</table>';
|
130
|
+
this.element.update(html);
|
131
|
+
|
132
|
+
},
|
133
|
+
|
134
|
+
appendActionButtons: function(actions) {
|
135
|
+
actions = $H(actions);
|
136
|
+
if (!actions.any()) return;
|
137
|
+
var div = new Element("div", {className: 'action_buttons'});
|
138
|
+
actions.inject(div, function(container, action) {
|
139
|
+
var button = new Element("input").setValue(action.key).observe("click", action.value);
|
140
|
+
button.type = "button";
|
141
|
+
return container.insert(button);
|
142
|
+
});
|
143
|
+
this.getMessageCell().insert(div);
|
144
|
+
},
|
145
|
+
|
146
|
+
_toHTML: function(txt) {
|
147
|
+
return txt.escapeHTML().replace(/\n/g,"<br/>");
|
148
|
+
}
|
149
|
+
});
|
150
|
+
|
151
|
+
Test.Unit.Runner = Class.create({
|
152
|
+
initialize: function(testcases) {
|
153
|
+
var options = this.options = Object.extend({
|
154
|
+
testLog: 'testlog'
|
155
|
+
}, arguments[1] || {});
|
156
|
+
|
157
|
+
options.resultsURL = this.queryParams.resultsURL;
|
158
|
+
options.testLog = $(options.testLog);
|
159
|
+
|
160
|
+
this.tests = this.getTests(testcases);
|
161
|
+
this.currentTest = 0;
|
162
|
+
this.logger = new Test.Unit.Logger(options.testLog);
|
163
|
+
Event.observe(window, "load", function() {
|
164
|
+
this.runTests.bind(this).delay(0.1);
|
165
|
+
}.bind(this));
|
166
|
+
},
|
167
|
+
|
168
|
+
queryParams: window.location.search.parseQuery(),
|
169
|
+
|
170
|
+
getTests: function(testcases) {
|
171
|
+
var tests, options = this.options;
|
172
|
+
if (this.queryParams.tests) tests = this.queryParams.tests.split(',');
|
173
|
+
else if (options.tests) tests = options.tests;
|
174
|
+
else if (options.test) tests = [option.test];
|
175
|
+
else tests = Object.keys(testcases).grep(/^test/);
|
176
|
+
|
177
|
+
return tests.map(function(test) {
|
178
|
+
if (testcases[test])
|
179
|
+
return new Test.Unit.Testcase(test, testcases[test], testcases.setup, testcases.teardown);
|
180
|
+
}).compact();
|
181
|
+
},
|
182
|
+
|
183
|
+
getResult: function() {
|
184
|
+
var results = {
|
185
|
+
tests: this.tests.length,
|
186
|
+
assertions: 0,
|
187
|
+
failures: 0,
|
188
|
+
errors: 0
|
189
|
+
};
|
190
|
+
|
191
|
+
return this.tests.inject(results, function(results, test) {
|
192
|
+
results.assertions += test.assertions;
|
193
|
+
results.failures += test.failures;
|
194
|
+
results.errors += test.errors;
|
195
|
+
return results;
|
196
|
+
});
|
197
|
+
},
|
198
|
+
|
199
|
+
postResults: function() {
|
200
|
+
if (this.options.resultsURL) {
|
201
|
+
new Ajax.Request(this.options.resultsURL,
|
202
|
+
{ method: 'get', parameters: this.getResult(), asynchronous: false });
|
203
|
+
}
|
204
|
+
},
|
205
|
+
|
206
|
+
runTests: function() {
|
207
|
+
var test = this.tests[this.currentTest], actions;
|
208
|
+
|
209
|
+
if (!test) return this.finish();
|
210
|
+
if (!test.isWaiting) this.logger.start(test.name);
|
211
|
+
test.run();
|
212
|
+
if(test.isWaiting) {
|
213
|
+
this.logger.message("Waiting for " + test.timeToWait + "ms");
|
214
|
+
setTimeout(this.runTests.bind(this), test.timeToWait || 1000);
|
215
|
+
return;
|
216
|
+
}
|
217
|
+
|
218
|
+
this.logger.finish(test.status(), test.summary());
|
219
|
+
if (actions = test.actions) this.logger.appendActionButtons(actions);
|
220
|
+
this.currentTest++;
|
221
|
+
// tail recursive, hopefully the browser will skip the stackframe
|
222
|
+
this.runTests();
|
223
|
+
},
|
224
|
+
|
225
|
+
finish: function() {
|
226
|
+
this.postResults();
|
227
|
+
this.logger.summary(this.summary());
|
228
|
+
},
|
229
|
+
|
230
|
+
summary: function() {
|
231
|
+
return '#{tests} tests, #{assertions} assertions, #{failures} failures, #{errors} errors'
|
232
|
+
.interpolate(this.getResult());
|
233
|
+
}
|
234
|
+
});
|
235
|
+
|
236
|
+
Test.Unit.MessageTemplate = Class.create({
|
237
|
+
initialize: function(string) {
|
238
|
+
var parts = [];
|
239
|
+
(string || '').scan(/(?=[^\\])\?|(?:\\\?|[^\?])+/, function(part) {
|
240
|
+
parts.push(part[0]);
|
241
|
+
});
|
242
|
+
this.parts = parts;
|
243
|
+
},
|
244
|
+
|
245
|
+
evaluate: function(params) {
|
246
|
+
return this.parts.map(function(part) {
|
247
|
+
return part == '?' ? Test.Unit.inspect(params.shift()) : part.replace(/\\\?/, '?');
|
248
|
+
}).join('');
|
249
|
+
}
|
250
|
+
});
|
251
|
+
|
252
|
+
Test.Unit.Assertions = {
|
253
|
+
buildMessage: function(message, template) {
|
254
|
+
var args = $A(arguments).slice(2);
|
255
|
+
return (message ? message + '\n' : '') + new Test.Unit.MessageTemplate(template).evaluate(args);
|
256
|
+
},
|
257
|
+
|
258
|
+
flunk: function(message) {
|
259
|
+
this.assertBlock(message || 'Flunked', function() { return false });
|
260
|
+
},
|
261
|
+
|
262
|
+
assertBlock: function(message, block) {
|
263
|
+
try {
|
264
|
+
block.call(this) ? this.pass() : this.fail(message);
|
265
|
+
} catch(e) { this.error(e) }
|
266
|
+
},
|
267
|
+
|
268
|
+
assert: function(expression, message) {
|
269
|
+
message = this.buildMessage(message || 'assert', 'got <?>', expression);
|
270
|
+
this.assertBlock(message, function() { return expression });
|
271
|
+
},
|
272
|
+
|
273
|
+
assertEqual: function(expected, actual, message) {
|
274
|
+
message = this.buildMessage(message || 'assertEqual', 'expected <?>, actual: <?>', expected, actual);
|
275
|
+
this.assertBlock(message, function() { return expected == actual });
|
276
|
+
},
|
277
|
+
|
278
|
+
assertNotEqual: function(expected, actual, message) {
|
279
|
+
message = this.buildMessage(message || 'assertNotEqual', 'expected <?>, actual: <?>', expected, actual);
|
280
|
+
this.assertBlock(message, function() { return expected != actual });
|
281
|
+
},
|
282
|
+
|
283
|
+
assertEnumEqual: function(expected, actual, message) {
|
284
|
+
expected = $A(expected);
|
285
|
+
actual = $A(actual);
|
286
|
+
message = this.buildMessage(message || 'assertEnumEqual', 'expected <?>, actual: <?>', expected, actual);
|
287
|
+
this.assertBlock(message, function() {
|
288
|
+
return expected.length == actual.length && expected.zip(actual).all(function(pair) { return pair[0] == pair[1] });
|
289
|
+
});
|
290
|
+
},
|
291
|
+
|
292
|
+
assertEnumNotEqual: function(expected, actual, message) {
|
293
|
+
expected = $A(expected);
|
294
|
+
actual = $A(actual);
|
295
|
+
message = this.buildMessage(message || 'assertEnumNotEqual', '<?> was the same as <?>', expected, actual);
|
296
|
+
this.assertBlock(message, function() {
|
297
|
+
return expected.length != actual.length || expected.zip(actual).any(function(pair) { return pair[0] != pair[1] });
|
298
|
+
});
|
299
|
+
},
|
300
|
+
|
301
|
+
assertHashEqual: function(expected, actual, message) {
|
302
|
+
expected = $H(expected);
|
303
|
+
actual = $H(actual);
|
304
|
+
var expected_array = expected.toArray().sort(), actual_array = actual.toArray().sort();
|
305
|
+
message = this.buildMessage(message || 'assertHashEqual', 'expected <?>, actual: <?>', expected, actual);
|
306
|
+
// from now we recursively zip & compare nested arrays
|
307
|
+
var block = function() {
|
308
|
+
return expected_array.length == actual_array.length &&
|
309
|
+
expected_array.zip(actual_array).all(function(pair) {
|
310
|
+
return pair.all(Object.isArray) ?
|
311
|
+
pair[0].zip(pair[1]).all(arguments.callee) : pair[0] == pair[1];
|
312
|
+
});
|
313
|
+
};
|
314
|
+
this.assertBlock(message, block);
|
315
|
+
},
|
316
|
+
|
317
|
+
assertHashNotEqual: function(expected, actual, message) {
|
318
|
+
expected = $H(expected);
|
319
|
+
actual = $H(actual);
|
320
|
+
var expected_array = expected.toArray().sort(), actual_array = actual.toArray().sort();
|
321
|
+
message = this.buildMessage(message || 'assertHashNotEqual', '<?> was the same as <?>', expected, actual);
|
322
|
+
// from now we recursively zip & compare nested arrays
|
323
|
+
var block = function() {
|
324
|
+
return !(expected_array.length == actual_array.length &&
|
325
|
+
expected_array.zip(actual_array).all(function(pair) {
|
326
|
+
return pair.all(Object.isArray) ?
|
327
|
+
pair[0].zip(pair[1]).all(arguments.callee) : pair[0] == pair[1];
|
328
|
+
}));
|
329
|
+
};
|
330
|
+
this.assertBlock(message, block);
|
331
|
+
},
|
332
|
+
|
333
|
+
assertIdentical: function(expected, actual, message) {
|
334
|
+
message = this.buildMessage(message || 'assertIdentical', 'expected <?>, actual: <?>', expected, actual);
|
335
|
+
this.assertBlock(message, function() { return expected === actual });
|
336
|
+
},
|
337
|
+
|
338
|
+
assertNotIdentical: function(expected, actual, message) {
|
339
|
+
message = this.buildMessage(message || 'assertNotIdentical', 'expected <?>, actual: <?>', expected, actual);
|
340
|
+
this.assertBlock(message, function() { return expected !== actual });
|
341
|
+
},
|
342
|
+
|
343
|
+
assertNull: function(obj, message) {
|
344
|
+
message = this.buildMessage(message || 'assertNull', 'got <?>', obj);
|
345
|
+
this.assertBlock(message, function() { return obj === null });
|
346
|
+
},
|
347
|
+
|
348
|
+
assertNotNull: function(obj, message) {
|
349
|
+
message = this.buildMessage(message || 'assertNotNull', 'got <?>', obj);
|
350
|
+
this.assertBlock(message, function() { return obj !== null });
|
351
|
+
},
|
352
|
+
|
353
|
+
assertUndefined: function(obj, message) {
|
354
|
+
message = this.buildMessage(message || 'assertUndefined', 'got <?>', obj);
|
355
|
+
this.assertBlock(message, function() { return typeof obj == "undefined" });
|
356
|
+
},
|
357
|
+
|
358
|
+
assertNotUndefined: function(obj, message) {
|
359
|
+
message = this.buildMessage(message || 'assertNotUndefined', 'got <?>', obj);
|
360
|
+
this.assertBlock(message, function() { return typeof obj != "undefined" });
|
361
|
+
},
|
362
|
+
|
363
|
+
assertNullOrUndefined: function(obj, message) {
|
364
|
+
message = this.buildMessage(message || 'assertNullOrUndefined', 'got <?>', obj);
|
365
|
+
this.assertBlock(message, function() { return obj == null });
|
366
|
+
},
|
367
|
+
|
368
|
+
assertNotNullOrUndefined: function(obj, message) {
|
369
|
+
message = this.buildMessage(message || 'assertNotNullOrUndefined', 'got <?>', obj);
|
370
|
+
this.assertBlock(message, function() { return obj != null });
|
371
|
+
},
|
372
|
+
|
373
|
+
assertMatch: function(expected, actual, message) {
|
374
|
+
message = this.buildMessage(message || 'assertMatch', 'regex <?> did not match <?>', expected, actual);
|
375
|
+
this.assertBlock(message, function() { return new RegExp(expected).exec(actual) });
|
376
|
+
},
|
377
|
+
|
378
|
+
assertNoMatch: function(expected, actual, message) {
|
379
|
+
message = this.buildMessage(message || 'assertNoMatch', 'regex <?> matched <?>', expected, actual);
|
380
|
+
this.assertBlock(message, function() { return !(new RegExp(expected).exec(actual)) });
|
381
|
+
},
|
382
|
+
|
383
|
+
assertHidden: function(element, message) {
|
384
|
+
message = this.buildMessage(message || 'assertHidden', '? isn\'t hidden.', element);
|
385
|
+
this.assertBlock(message, function() { return element.style.display == 'none' });
|
386
|
+
},
|
387
|
+
|
388
|
+
assertInstanceOf: function(expected, actual, message) {
|
389
|
+
message = this.buildMessage(message || 'assertInstanceOf', '<?> was not an instance of the expected type', actual);
|
390
|
+
this.assertBlock(message, function() { return actual instanceof expected });
|
391
|
+
},
|
392
|
+
|
393
|
+
assertNotInstanceOf: function(expected, actual, message) {
|
394
|
+
message = this.buildMessage(message || 'assertNotInstanceOf', '<?> was an instance of the expected type', actual);
|
395
|
+
this.assertBlock(message, function() { return !(actual instanceof expected) });
|
396
|
+
},
|
397
|
+
|
398
|
+
assertRespondsTo: function(method, obj, message) {
|
399
|
+
message = this.buildMessage(message || 'assertRespondsTo', 'object doesn\'t respond to <?>', method);
|
400
|
+
this.assertBlock(message, function() { return (method in obj && typeof obj[method] == 'function') });
|
401
|
+
},
|
402
|
+
|
403
|
+
assertRaise: function(exceptionName, method, message) {
|
404
|
+
message = this.buildMessage(message || 'assertRaise', '<?> exception expected but none was raised', exceptionName);
|
405
|
+
var block = function() {
|
406
|
+
try {
|
407
|
+
method();
|
408
|
+
return false;
|
409
|
+
} catch(e) {
|
410
|
+
if (e.name == exceptionName) return true;
|
411
|
+
else throw e;
|
412
|
+
}
|
413
|
+
};
|
414
|
+
this.assertBlock(message, block);
|
415
|
+
},
|
416
|
+
|
417
|
+
assertNothingRaised: function(method, message) {
|
418
|
+
try {
|
419
|
+
method();
|
420
|
+
this.assert(true, "Expected nothing to be thrown");
|
421
|
+
} catch(e) {
|
422
|
+
message = this.buildMessage(message || 'assertNothingRaised', '<?> was thrown when nothing was expected.', e);
|
423
|
+
this.flunk(message);
|
424
|
+
}
|
425
|
+
},
|
426
|
+
|
427
|
+
_isVisible: function(element) {
|
428
|
+
element = $(element);
|
429
|
+
if(!element.parentNode) return true;
|
430
|
+
this.assertNotNull(element);
|
431
|
+
if(element.style && Element.getStyle(element, 'display') == 'none')
|
432
|
+
return false;
|
433
|
+
|
434
|
+
return arguments.callee.call(this, element.parentNode);
|
435
|
+
},
|
436
|
+
|
437
|
+
assertVisible: function(element, message) {
|
438
|
+
message = this.buildMessage(message, '? was not visible.', element);
|
439
|
+
this.assertBlock(message, function() { return this._isVisible(element) });
|
440
|
+
},
|
441
|
+
|
442
|
+
assertNotVisible: function(element, message) {
|
443
|
+
message = this.buildMessage(message, '? was not hidden and didn\'t have a hidden parent either.', element);
|
444
|
+
this.assertBlock(message, function() { return !this._isVisible(element) });
|
445
|
+
},
|
446
|
+
|
447
|
+
assertElementsMatch: function() {
|
448
|
+
var pass = true, expressions = $A(arguments), elements = $A(expressions.shift());
|
449
|
+
if (elements.length != expressions.length) {
|
450
|
+
message = this.buildMessage('assertElementsMatch', 'size mismatch: ? elements, ? expressions (?).', elements.length, expressions.length, expressions);
|
451
|
+
this.flunk(message);
|
452
|
+
pass = false;
|
453
|
+
}
|
454
|
+
elements.zip(expressions).all(function(pair, index) {
|
455
|
+
var element = $(pair.first()), expression = pair.last();
|
456
|
+
if (element.match(expression)) return true;
|
457
|
+
message = this.buildMessage('assertElementsMatch', 'In index <?>: expected <?> but got ?', index, expression, element);
|
458
|
+
this.flunk(message);
|
459
|
+
pass = false;
|
460
|
+
}.bind(this))
|
461
|
+
|
462
|
+
if (pass) this.assert(true, "Expected all elements to match.");
|
463
|
+
},
|
464
|
+
|
465
|
+
assertElementMatches: function(element, expression, message) {
|
466
|
+
this.assertElementsMatch([element], expression);
|
467
|
+
}
|
468
|
+
};
|
469
|
+
|
470
|
+
Test.Unit.Testcase = Class.create(Test.Unit.Assertions, {
|
471
|
+
initialize: function(name, test, setup, teardown) {
|
472
|
+
this.name = name;
|
473
|
+
this.test = test || Prototype.emptyFunction;
|
474
|
+
this.setup = setup || Prototype.emptyFunction;
|
475
|
+
this.teardown = teardown || Prototype.emptyFunction;
|
476
|
+
this.messages = [];
|
477
|
+
this.actions = {};
|
478
|
+
},
|
479
|
+
|
480
|
+
isWaiting: false,
|
481
|
+
timeToWait: 1000,
|
482
|
+
assertions: 0,
|
483
|
+
failures: 0,
|
484
|
+
errors: 0,
|
485
|
+
isRunningFromRake: window.location.port == 4711,
|
486
|
+
|
487
|
+
wait: function(time, nextPart) {
|
488
|
+
this.isWaiting = true;
|
489
|
+
this.test = nextPart;
|
490
|
+
this.timeToWait = time;
|
491
|
+
},
|
492
|
+
|
493
|
+
run: function(rethrow) {
|
494
|
+
try {
|
495
|
+
try {
|
496
|
+
if (!this.isWaiting) this.setup();
|
497
|
+
this.isWaiting = false;
|
498
|
+
this.test();
|
499
|
+
} finally {
|
500
|
+
if(!this.isWaiting) {
|
501
|
+
this.teardown();
|
502
|
+
}
|
503
|
+
}
|
504
|
+
}
|
505
|
+
catch(e) {
|
506
|
+
if (rethrow) throw e;
|
507
|
+
this.error(e, this);
|
508
|
+
}
|
509
|
+
},
|
510
|
+
|
511
|
+
summary: function() {
|
512
|
+
var msg = '#{assertions} assertions, #{failures} failures, #{errors} errors\n';
|
513
|
+
return msg.interpolate(this) + this.messages.join("\n");
|
514
|
+
},
|
515
|
+
|
516
|
+
pass: function() {
|
517
|
+
this.assertions++;
|
518
|
+
},
|
519
|
+
|
520
|
+
fail: function(message) {
|
521
|
+
this.failures++;
|
522
|
+
var line = "";
|
523
|
+
try {
|
524
|
+
throw new Error("stack");
|
525
|
+
} catch(e){
|
526
|
+
line = (/\.html:(\d+)/.exec(e.stack || '') || ['',''])[1];
|
527
|
+
}
|
528
|
+
this.messages.push("Failure: " + message + (line ? " Line #" + line : ""));
|
529
|
+
},
|
530
|
+
|
531
|
+
info: function(message) {
|
532
|
+
this.messages.push("Info: " + message);
|
533
|
+
},
|
534
|
+
|
535
|
+
error: function(error, test) {
|
536
|
+
this.errors++;
|
537
|
+
this.actions['retry with throw'] = function() { test.run(true) };
|
538
|
+
this.messages.push(error.name + ": "+ error.message + "(" + Test.Unit.inspect(error) + ")");
|
539
|
+
},
|
540
|
+
|
541
|
+
status: function() {
|
542
|
+
if (this.failures > 0) return 'failed';
|
543
|
+
if (this.errors > 0) return 'error';
|
544
|
+
return 'passed';
|
545
|
+
},
|
546
|
+
|
547
|
+
benchmark: function(operation, iterations) {
|
548
|
+
var startAt = new Date();
|
549
|
+
(iterations || 1).times(operation);
|
550
|
+
var timeTaken = ((new Date())-startAt);
|
551
|
+
this.info((arguments[2] || 'Operation') + ' finished ' +
|
552
|
+
iterations + ' iterations in ' + (timeTaken/1000)+'s' );
|
553
|
+
return timeTaken;
|
554
|
+
}
|
555
|
+
});
|
556
|
+
|