nitro 0.24.0 → 0.25.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/CHANGELOG +279 -0
  2. data/ProjectInfo +7 -7
  3. data/doc/AUTHORS +4 -2
  4. data/doc/RELEASES +96 -1
  5. data/lib/nitro.rb +5 -2
  6. data/lib/nitro/adapter/cgi.rb +1 -1
  7. data/lib/nitro/adapter/webrick.rb +7 -5
  8. data/lib/nitro/caching/output.rb +3 -2
  9. data/lib/nitro/cgi/utils.rb +8 -4
  10. data/lib/nitro/compiler.rb +9 -5
  11. data/lib/nitro/compiler/include.rb +42 -0
  12. data/lib/nitro/compiler/markup.rb +1 -1
  13. data/lib/nitro/compiler/morphing.rb +120 -50
  14. data/lib/nitro/compiler/squeeze.rb +2 -2
  15. data/lib/nitro/context.rb +9 -0
  16. data/lib/nitro/controller.rb +8 -4
  17. data/lib/nitro/dispatcher.rb +5 -5
  18. data/lib/nitro/dispatcher/nice.rb +16 -5
  19. data/lib/nitro/element.rb +30 -8
  20. data/lib/nitro/helper.rb +56 -0
  21. data/lib/nitro/{mixin → helper}/benchmark.rb +1 -1
  22. data/lib/nitro/{mixin → helper}/buffer.rb +1 -2
  23. data/lib/nitro/{mixin → helper}/debug.rb +1 -1
  24. data/lib/nitro/{mixin/helper.rb → helper/default.rb} +4 -4
  25. data/lib/nitro/{mixin → helper}/form.rb +3 -3
  26. data/lib/nitro/{mixin → helper}/javascript.rb +17 -1
  27. data/lib/nitro/{mixin → helper}/pager.rb +1 -1
  28. data/lib/nitro/{mixin → helper}/rss.rb +3 -3
  29. data/lib/nitro/{mixin → helper}/table.rb +1 -1
  30. data/lib/nitro/{mixin → helper}/xhtml.rb +2 -2
  31. data/lib/nitro/{mixin → helper}/xml.rb +1 -1
  32. data/lib/nitro/render.rb +16 -8
  33. data/lib/nitro/scaffold.rb +6 -6
  34. data/lib/nitro/server/runner.rb +12 -0
  35. data/lib/nitro/session/drbserver.rb +16 -1
  36. data/proto/public/js/builder.js +97 -0
  37. data/proto/public/js/controls.js +18 -5
  38. data/proto/public/js/dragdrop.js +8 -5
  39. data/proto/public/js/effects.js +185 -4
  40. data/proto/public/js/prototype.js +432 -178
  41. data/proto/public/js/scriptaculous.js +6 -2
  42. data/proto/public/js/slider.js +226 -0
  43. data/proto/public/js/unittest.js +363 -0
  44. data/proto/public/media/nitro.png +0 -0
  45. data/{script → proto/script}/scgi_ctl +0 -0
  46. data/{script → proto/script}/scgi_service +16 -8
  47. data/proto/src/skin.rb +24 -0
  48. data/{lib → src}/part/admin.rb +0 -0
  49. data/src/part/admin/controller.rb +47 -0
  50. data/{lib → src}/part/admin/skin.rb +0 -0
  51. data/src/part/admin/template/denied.xhtml +1 -0
  52. data/{lib → src}/part/admin/template/index.xhtml +0 -0
  53. data/test/nitro/{mixin → helper}/tc_pager.rb +2 -2
  54. data/test/nitro/{mixin → helper}/tc_rss.rb +3 -3
  55. data/test/nitro/{mixin → helper}/tc_table.rb +3 -3
  56. data/test/nitro/{mixin → helper}/tc_xhtml.rb +3 -3
  57. data/test/nitro/tc_caching.rb +4 -1
  58. data/test/nitro/tc_controller.rb +2 -2
  59. data/test/nitro/tc_element.rb +30 -0
  60. data/test/nitro/tc_helper.rb +36 -0
  61. data/test/nitro/tc_render.rb +1 -1
  62. metadata +70 -38
  63. data/lib/nitro/mixin/markup.rb +0 -122
  64. data/lib/part/admin/controller.rb +0 -28
  65. data/proto/README +0 -11
  66. data/proto/doc/README +0 -1
  67. data/proto/scgi.rb +0 -333
@@ -20,17 +20,21 @@
20
20
  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
21
 
22
22
  var Scriptaculous = {
23
- Version: '1.5_rc3',
23
+ Version: '1.5_rc4',
24
24
  require: function(libraryName) {
25
25
  // inserting via DOM fails in Safari 2.0, so brute force approach
26
26
  document.write('<script type="text/javascript" src="'+libraryName+'"></script>');
27
27
  },
28
28
  load: function() {
29
+ if((typeof Prototype=='undefined') ||
30
+ parseFloat(Prototype.Version.split(".")[0] + "." +
31
+ Prototype.Version.split(".")[1]) < 1.4)
32
+ throw("script.aculo.us requires the Prototype JavaScript framework >= 1.4.0");
29
33
  var scriptTags = document.getElementsByTagName("script");
30
34
  for(var i=0;i<scriptTags.length;i++) {
31
35
  if(scriptTags[i].src && scriptTags[i].src.match(/scriptaculous\.js(\?.*)?$/)) {
32
36
  var path = scriptTags[i].src.replace(/scriptaculous\.js(\?.*)?$/,'');
33
- this.require(path + 'util.js');
37
+ this.require(path + 'builder.js');
34
38
  this.require(path + 'effects.js');
35
39
  this.require(path + 'dragdrop.js');
36
40
  this.require(path + 'controls.js');
@@ -0,0 +1,226 @@
1
+ // Copyright (c) 2005 Marty Haught
2
+ //
3
+ // See scriptaculous.js for full license.
4
+
5
+ if(!Control) var Control = {};
6
+ Control.Slider = Class.create();
7
+
8
+ // options:
9
+ // axis: 'vertical', or 'horizontal' (default)
10
+ //
11
+ // callbacks:
12
+ // onChange(value)
13
+ // onSlide(value)
14
+ Control.Slider.prototype = {
15
+ initialize: function(handle, track, options) {
16
+ var slider = this;
17
+
18
+ if(handle instanceof Array) {
19
+ this.handles = handle.collect( function(e) { return $(e) });
20
+ } else {
21
+ this.handles = [$(handle)];
22
+ }
23
+
24
+ this.track = $(track);
25
+ this.options = options || {};
26
+
27
+ this.axis = this.options.axis || 'horizontal';
28
+ this.increment = this.options.increment || 1;
29
+ this.step = parseInt(this.options.step || '1');
30
+ this.range = this.options.range || $R(0,1);
31
+
32
+ this.value = 0; // assure backwards compat
33
+ this.values = this.handles.map( function() { return 0 });
34
+ this.spans = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
35
+ this.restricted = this.options.restricted || false;
36
+
37
+ this.maximum = this.options.maximum || this.range.end;
38
+ this.minimum = this.options.minimum || this.range.start;
39
+
40
+ // Will be used to align the handle onto the track, if necessary
41
+ this.alignX = parseInt(this.options.alignX || '0');
42
+ this.alignY = parseInt(this.options.alignY || '0');
43
+
44
+ this.trackLength = this.maximumOffset() - this.minimumOffset();
45
+
46
+ this.active = false;
47
+ this.dragging = false;
48
+ this.disabled = false;
49
+
50
+ if(this.options.disabled) this.setDisabled();
51
+
52
+ // Allowed values array
53
+ this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
54
+ if(this.allowedValues) {
55
+ this.minimum = this.allowedValues.min();
56
+ this.maximum = this.allowedValues.max();
57
+ }
58
+
59
+ this.eventMouseDown = this.startDrag.bindAsEventListener(this);
60
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
61
+ this.eventMouseMove = this.update.bindAsEventListener(this);
62
+
63
+ // Initialize handles
64
+ this.handles.each( function(h,i) {
65
+ slider.setValue(parseInt(slider.options.sliderValue || slider.range.start), i);
66
+ Element.makePositioned(h); // fix IE
67
+ Event.observe(h, "mousedown", slider.eventMouseDown);
68
+ });
69
+
70
+ Event.observe(document, "mouseup", this.eventMouseUp);
71
+ Event.observe(document, "mousemove", this.eventMouseMove);
72
+ },
73
+ dispose: function() {
74
+ var slider = this;
75
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
76
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
77
+ this.handles.each( function(h) {
78
+ Event.stopObserving(h, "mousedown", slider.eventMouseDown);
79
+ });
80
+ },
81
+ setDisabled: function(){
82
+ this.disabled = true;
83
+ },
84
+ setEnabled: function(){
85
+ this.disabled = false;
86
+ },
87
+ getNearestValue: function(value){
88
+ if(this.allowedValues){
89
+ if(value >= this.allowedValues.max()) return(this.allowedValues.max());
90
+ if(value <= this.allowedValues.min()) return(this.allowedValues.min());
91
+
92
+ var offset = Math.abs(this.allowedValues[0] - value);
93
+ var newValue = this.allowedValues[0];
94
+ this.allowedValues.each( function(v) {
95
+ var currentOffset = Math.abs(v - value);
96
+ if(currentOffset <= offset){
97
+ newValue = v;
98
+ offset = currentOffset;
99
+ }
100
+ });
101
+ return newValue;
102
+ }
103
+ if(value > this.range.end) return this.range.end;
104
+ if(value < this.range.start) return this.range.start;
105
+ return value;
106
+ },
107
+ setValue: function(sliderValue, handleIdx){
108
+ if(!this.active) {
109
+ this.activeHandle = this.handles[handleIdx];
110
+ this.activeHandleIdx = handleIdx;
111
+ }
112
+ handleIdx = handleIdx || this.activeHandleIdx || 0;
113
+ if(this.restricted) {
114
+ if((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
115
+ sliderValue = this.values[handleIdx-1];
116
+ if((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
117
+ sliderValue = this.values[handleIdx+1];
118
+ }
119
+ sliderValue = this.getNearestValue(sliderValue);
120
+ this.values[handleIdx] = sliderValue;
121
+ this.value = this.values[0]; // assure backwards compat
122
+
123
+ this.handles[handleIdx].style[ this.isVertical() ? 'top' : 'left'] =
124
+ this.translateToPx(sliderValue);
125
+
126
+ this.drawSpans();
127
+ this.updateFinished();
128
+ },
129
+ setValueBy: function(delta, handleIdx) {
130
+ this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
131
+ handleIdx || this.activeHandleIdx || 0);
132
+ },
133
+ translateToPx: function(value) {
134
+ return Math.round((this.trackLength / (this.range.end - this.range.start)) * (value - this.range.start)) + "px";
135
+ },
136
+ translateToValue: function(offset) {
137
+ return ((offset/this.trackLength) * (this.range.end - this.range.start)) + this.range.start;
138
+ },
139
+ getRange: function(range) {
140
+ var v = this.values.sortBy(Prototype.K);
141
+ range = range || 0;
142
+ return $R(v[range],v[range+1]);
143
+ },
144
+ minimumOffset: function(){
145
+ return(this.isVertical() ? this.alignY : this.alignX);
146
+ },
147
+ maximumOffset: function(){
148
+ return(this.isVertical() ?
149
+ this.track.offsetHeight - this.alignY : this.track.offsetWidth - this.alignX);
150
+ },
151
+ isVertical: function(){
152
+ return (this.axis == 'vertical');
153
+ },
154
+ drawSpans: function() {
155
+ var slider = this;
156
+ if(this.spans)
157
+ $R(0, this.spans.length-1).each(function(r) { slider.setSpan(r, slider.getRange(r)) });
158
+ },
159
+ setSpan: function(span, range) {
160
+ if(this.isVertical()) {
161
+ this.spans[span].style.top = this.translateToPx(range.start);
162
+ this.spans[span].style.height = this.translateToPx(range.end - range.start);
163
+ } else {
164
+ this.spans[span].style.left = this.translateToPx(range.start);
165
+ this.spans[span].style.width = this.translateToPx(range.end - range.start);
166
+ }
167
+ },
168
+ startDrag: function(event) {
169
+ if(Event.isLeftClick(event)) {
170
+ if(!this.disabled){
171
+ this.active = true;
172
+
173
+ // find the handle (prevents issues with Safari)
174
+ var handle = Event.element(event);
175
+ while((this.handles.indexOf(handle) == -1) && handle.parentNode)
176
+ handle = handle.parentNode;
177
+
178
+ this.activeHandle = handle;
179
+ this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
180
+
181
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
182
+ var offsets = Position.cumulativeOffset(this.activeHandle);
183
+ this.offsetX = (pointer[0] - offsets[0]);
184
+ this.offsetY = (pointer[1] - offsets[1]);
185
+
186
+ }
187
+ Event.stop(event);
188
+ }
189
+ },
190
+ update: function(event) {
191
+ if(this.active) {
192
+ if(!this.dragging) {
193
+ this.dragging = true;
194
+ if(this.activeHandle.style.position=="") style.position = "relative";
195
+ }
196
+ this.draw(event);
197
+ // fix AppleWebKit rendering
198
+ if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
199
+ Event.stop(event);
200
+ }
201
+ },
202
+ draw: function(event) {
203
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
204
+ var offsets = Position.cumulativeOffset(this.track);
205
+ pointer[0] -= this.offsetX + offsets[0];
206
+ pointer[1] -= this.offsetY + offsets[1];
207
+ this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
208
+ if(this.options.onSlide) this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
209
+ },
210
+ endDrag: function(event) {
211
+ if(this.active && this.dragging) {
212
+ this.finishDrag(event, true);
213
+ Event.stop(event);
214
+ }
215
+ this.active = false;
216
+ this.dragging = false;
217
+ },
218
+ finishDrag: function(event, success) {
219
+ this.active = false;
220
+ this.dragging = false;
221
+ this.updateFinished();
222
+ },
223
+ updateFinished: function() {
224
+ if(this.options.onChange) this.options.onChange(this.values.length>1 ? this.values : this.value, this);
225
+ }
226
+ }
@@ -0,0 +1,363 @@
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
+ // See scriptaculous.js for full license.
6
+
7
+ // experimental, Firefox-only
8
+ Event.simulateMouse = function(element, eventName) {
9
+ var options = Object.extend({
10
+ pointerX: 0,
11
+ pointerY: 0,
12
+ buttons: 0
13
+ }, arguments[2] || {});
14
+ var oEvent = document.createEvent("MouseEvents");
15
+ oEvent.initMouseEvent(eventName, true, true, document.defaultView,
16
+ options.buttons, options.pointerX, options.pointerY, options.pointerX, options.pointerY,
17
+ false, false, false, false, 0, $(element));
18
+
19
+ if(this.mark) Element.remove(this.mark);
20
+ this.mark = document.createElement('div');
21
+ this.mark.appendChild(document.createTextNode(" "));
22
+ document.body.appendChild(this.mark);
23
+ this.mark.style.position = 'absolute';
24
+ this.mark.style.top = options.pointerY + "px";
25
+ this.mark.style.left = options.pointerX + "px";
26
+ this.mark.style.width = "5px";
27
+ this.mark.style.height = "5px;";
28
+ this.mark.style.borderTop = "1px solid red;"
29
+ this.mark.style.borderLeft = "1px solid red;"
30
+
31
+ if(this.step)
32
+ alert('['+new Date().getTime().toString()+'] '+eventName+'/'+Test.Unit.inspect(options));
33
+
34
+ $(element).dispatchEvent(oEvent);
35
+ };
36
+
37
+ // 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.
38
+ // You need to downgrade to 1.0.4 for now to get this working
39
+ // See https://bugzilla.mozilla.org/show_bug.cgi?id=289940 for the fix that fixed too much
40
+ Event.simulateKey = function(element, eventName) {
41
+ var options = Object.extend({
42
+ ctrlKey: false,
43
+ altKey: false,
44
+ shiftKey: false,
45
+ metaKey: false,
46
+ keyCode: 0,
47
+ charCode: 0
48
+ }, arguments[2] || {});
49
+
50
+ var oEvent = document.createEvent("KeyEvents");
51
+ oEvent.initKeyEvent(eventName, true, true, window,
52
+ options.ctrlKey, options.altKey, options.shiftKey, options.metaKey,
53
+ options.keyCode, options.charCode );
54
+ $(element).dispatchEvent(oEvent);
55
+ };
56
+
57
+ Event.simulateKeys = function(element, command) {
58
+ for(var i=0; i<command.length; i++) {
59
+ Event.simulateKey(element,'keypress',{charCode:command.charCodeAt(i)});
60
+ }
61
+ };
62
+
63
+ var Test = {}
64
+ Test.Unit = {};
65
+
66
+ // security exception workaround
67
+ Test.Unit.inspect = function(obj) {
68
+ var info = [];
69
+
70
+ if(typeof obj=="string" ||
71
+ typeof obj=="number") {
72
+ return obj;
73
+ } else {
74
+ for(property in obj)
75
+ if(typeof obj[property]!="function")
76
+ info.push(property + ' => ' +
77
+ (typeof obj[property] == "string" ?
78
+ '"' + obj[property] + '"' :
79
+ obj[property]));
80
+ }
81
+
82
+ return ("'" + obj + "' #" + typeof obj +
83
+ ": {" + info.join(", ") + "}");
84
+ }
85
+
86
+ Test.Unit.Logger = Class.create();
87
+ Test.Unit.Logger.prototype = {
88
+ initialize: function(log) {
89
+ this.log = $(log);
90
+ if (this.log) {
91
+ this._createLogTable();
92
+ }
93
+ },
94
+ start: function(testName) {
95
+ if (!this.log) return;
96
+ this.testName = testName;
97
+ this.lastLogLine = document.createElement('tr');
98
+ this.statusCell = document.createElement('td');
99
+ this.nameCell = document.createElement('td');
100
+ this.nameCell.appendChild(document.createTextNode(testName));
101
+ this.messageCell = document.createElement('td');
102
+ this.lastLogLine.appendChild(this.statusCell);
103
+ this.lastLogLine.appendChild(this.nameCell);
104
+ this.lastLogLine.appendChild(this.messageCell);
105
+ this.loglines.appendChild(this.lastLogLine);
106
+ },
107
+ finish: function(status, summary) {
108
+ if (!this.log) return;
109
+ this.lastLogLine.className = status;
110
+ this.statusCell.innerHTML = status;
111
+ this.messageCell.innerHTML = this._toHTML(summary);
112
+ },
113
+ message: function(message) {
114
+ if (!this.log) return;
115
+ this.messageCell.innerHTML = this._toHTML(message);
116
+ },
117
+ summary: function(summary) {
118
+ if (!this.log) return;
119
+ this.logsummary.innerHTML = this._toHTML(summary);
120
+ },
121
+ _createLogTable: function() {
122
+ this.log.innerHTML =
123
+ '<div id="logsummary"></div>' +
124
+ '<table id="logtable">' +
125
+ '<thead><tr><th>Status</th><th>Test</th><th>Message</th></tr></thead>' +
126
+ '<tbody id="loglines"></tbody>' +
127
+ '</table>';
128
+ this.logsummary = $('logsummary')
129
+ this.loglines = $('loglines');
130
+ },
131
+ _toHTML: function(txt) {
132
+ return txt.escapeHTML().replace(/\n/g,"<br/>");
133
+ }
134
+ }
135
+
136
+ Test.Unit.Runner = Class.create();
137
+ Test.Unit.Runner.prototype = {
138
+ initialize: function(testcases) {
139
+ this.options = Object.extend({
140
+ testLog: 'testlog'
141
+ }, arguments[1] || {});
142
+ this.options.resultsURL = this.parseResultsURLQueryParameter();
143
+ if (this.options.testLog) {
144
+ this.options.testLog = $(this.options.testLog) || null;
145
+ }
146
+ if(this.options.tests) {
147
+ this.tests = [];
148
+ for(var i = 0; i < this.options.tests.length; i++) {
149
+ if(/^test/.test(this.options.tests[i])) {
150
+ this.tests.push(new Test.Unit.Testcase(this.options.tests[i], testcases[this.options.tests[i]], testcases["setup"], testcases["teardown"]));
151
+ }
152
+ }
153
+ } else {
154
+ if (this.options.test) {
155
+ this.tests = [new Test.Unit.Testcase(this.options.test, testcases[this.options.test], testcases["setup"], testcases["teardown"])];
156
+ } else {
157
+ this.tests = [];
158
+ for(var testcase in testcases) {
159
+ if(/^test/.test(testcase)) {
160
+ this.tests.push(new Test.Unit.Testcase(testcase, testcases[testcase], testcases["setup"], testcases["teardown"]));
161
+ }
162
+ }
163
+ }
164
+ }
165
+ this.currentTest = 0;
166
+ this.logger = new Test.Unit.Logger(this.options.testLog);
167
+ setTimeout(this.runTests.bind(this), 1000);
168
+ },
169
+ parseResultsURLQueryParameter: function() {
170
+ return window.location.search.parseQuery()["resultsURL"];
171
+ },
172
+ // Returns:
173
+ // "ERROR" if there was an error,
174
+ // "FAILURE" if there was a failure, or
175
+ // "SUCCESS" if there was neither
176
+ getResult: function() {
177
+ var hasFailure = false;
178
+ for(var i=0;i<this.tests.length;i++) {
179
+ if (this.tests[i].errors > 0) {
180
+ return "ERROR";
181
+ }
182
+ if (this.tests[i].failures > 0) {
183
+ hasFailure = true;
184
+ }
185
+ }
186
+ if (hasFailure) {
187
+ return "FAILURE";
188
+ } else {
189
+ return "SUCCESS";
190
+ }
191
+ },
192
+ postResults: function() {
193
+ if (this.options.resultsURL) {
194
+ new Ajax.Request(this.options.resultsURL,
195
+ { method: 'get', parameters: 'result=' + this.getResult(), asynchronous: false });
196
+ }
197
+ },
198
+ runTests: function() {
199
+ var test = this.tests[this.currentTest];
200
+ if (!test) {
201
+ // finished!
202
+ this.postResults();
203
+ this.logger.summary(this.summary());
204
+ return;
205
+ }
206
+ if(!test.isWaiting) {
207
+ this.logger.start(test.name);
208
+ }
209
+ test.run();
210
+ if(test.isWaiting) {
211
+ this.logger.message("Waiting for " + test.timeToWait + "ms");
212
+ setTimeout(this.runTests.bind(this), test.timeToWait || 1000);
213
+ } else {
214
+ this.logger.finish(test.status(), test.summary());
215
+ this.currentTest++;
216
+ // tail recursive, hopefully the browser will skip the stackframe
217
+ this.runTests();
218
+ }
219
+ },
220
+ summary: function() {
221
+ var assertions = 0;
222
+ var failures = 0;
223
+ var errors = 0;
224
+ var messages = [];
225
+ for(var i=0;i<this.tests.length;i++) {
226
+ assertions += this.tests[i].assertions;
227
+ failures += this.tests[i].failures;
228
+ errors += this.tests[i].errors;
229
+ }
230
+ return (
231
+ this.tests.length + " tests, " +
232
+ assertions + " assertions, " +
233
+ failures + " failures, " +
234
+ errors + " errors");
235
+ }
236
+ }
237
+
238
+ Test.Unit.Assertions = Class.create();
239
+ Test.Unit.Assertions.prototype = {
240
+ initialize: function() {
241
+ this.assertions = 0;
242
+ this.failures = 0;
243
+ this.errors = 0;
244
+ this.messages = [];
245
+ },
246
+ summary: function() {
247
+ return (
248
+ this.assertions + " assertions, " +
249
+ this.failures + " failures, " +
250
+ this.errors + " errors" + "\n" +
251
+ this.messages.join("\n"));
252
+ },
253
+ pass: function() {
254
+ this.assertions++;
255
+ },
256
+ fail: function(message) {
257
+ this.failures++;
258
+ this.messages.push("Failure: " + message);
259
+ },
260
+ error: function(error) {
261
+ this.errors++;
262
+ this.messages.push(error.name + ": "+ error.message + "(" + Test.Unit.inspect(error) +")");
263
+ },
264
+ status: function() {
265
+ if (this.failures > 0) return 'failed';
266
+ if (this.errors > 0) return 'error';
267
+ return 'passed';
268
+ },
269
+ assert: function(expression) {
270
+ var message = arguments[1] || 'assert: got "' + Test.Unit.inspect(expression) + '"';
271
+ try { expression ? this.pass() :
272
+ this.fail(message); }
273
+ catch(e) { this.error(e); }
274
+ },
275
+ assertEqual: function(expected, actual) {
276
+ var message = arguments[2] || "assertEqual";
277
+ try { (expected == actual) ? this.pass() :
278
+ this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
279
+ '", actual "' + Test.Unit.inspect(actual) + '"'); }
280
+ catch(e) { this.error(e); }
281
+ },
282
+ assertNotEqual: function(expected, actual) {
283
+ var message = arguments[2] || "assertNotEqual";
284
+ try { (expected != actual) ? this.pass() :
285
+ this.fail(message + ': got "' + Test.Unit.inspect(actual) + '"'); }
286
+ catch(e) { this.error(e); }
287
+ },
288
+ assertNull: function(obj) {
289
+ var message = arguments[1] || 'assertNull'
290
+ try { (obj==null) ? this.pass() :
291
+ this.fail(message + ': got "' + Test.Unit.inspect(obj) + '"'); }
292
+ catch(e) { this.error(e); }
293
+ },
294
+ assertHidden: function(element) {
295
+ var message = arguments[1] || 'assertHidden';
296
+ this.assertEqual("none", element.style.display, message);
297
+ },
298
+ assertNotNull: function(object) {
299
+ var message = arguments[1] || 'assertNotNull';
300
+ this.assert(object != null, message);
301
+ },
302
+ assertInstanceOf: function(expected, actual) {
303
+ var message = arguments[2] || 'assertInstanceOf';
304
+ try {
305
+ (actual instanceof expected) ? this.pass() :
306
+ this.fail(message + ": object was not an instance of the expected type"); }
307
+ catch(e) { this.error(e); }
308
+ },
309
+ assertNotInstanceOf: function(expected, actual) {
310
+ var message = arguments[2] || 'assertNotInstanceOf';
311
+ try {
312
+ !(actual instanceof expected) ? this.pass() :
313
+ this.fail(message + ": object was an instance of the not expected type"); }
314
+ catch(e) { this.error(e); }
315
+ },
316
+ _isVisible: function(element) {
317
+ element = $(element);
318
+ if(!element.parentNode) return true;
319
+ this.assertNotNull(element);
320
+ if(element.style && Element.getStyle(element, 'display') == 'none')
321
+ return false;
322
+
323
+ return this._isVisible(element.parentNode);
324
+ },
325
+ assertNotVisible: function(element) {
326
+ this.assert(!this._isVisible(element), Test.Unit.inspect(element) + " was not hidden and didn't have a hidden parent either. " + ("" || arguments[1]));
327
+ },
328
+ assertVisible: function(element) {
329
+ this.assert(this._isVisible(element), Test.Unit.inspect(element) + " was not visible. " + ("" || arguments[1]));
330
+ }
331
+ }
332
+
333
+ Test.Unit.Testcase = Class.create();
334
+ Object.extend(Object.extend(Test.Unit.Testcase.prototype, Test.Unit.Assertions.prototype), {
335
+ initialize: function(name, test, setup, teardown) {
336
+ Test.Unit.Assertions.prototype.initialize.bind(this)();
337
+ this.name = name;
338
+ this.test = test || function() {};
339
+ this.setup = setup || function() {};
340
+ this.teardown = teardown || function() {};
341
+ this.isWaiting = false;
342
+ this.timeToWait = 1000;
343
+ },
344
+ wait: function(time, nextPart) {
345
+ this.isWaiting = true;
346
+ this.test = nextPart;
347
+ this.timeToWait = time;
348
+ },
349
+ run: function() {
350
+ try {
351
+ try {
352
+ if (!this.isWaiting) this.setup.bind(this)();
353
+ this.isWaiting = false;
354
+ this.test.bind(this)();
355
+ } finally {
356
+ if(!this.isWaiting) {
357
+ this.teardown.bind(this)();
358
+ }
359
+ }
360
+ }
361
+ catch(e) { this.error(e); }
362
+ }
363
+ });