i18n-js 0.1.6 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/test/i18n_js_test.rb DELETED
@@ -1,154 +0,0 @@
1
- require "test_helper"
2
-
3
- class I18nJSTest < ActiveSupport::TestCase
4
- setup do
5
- # Remove temporary directory if already present
6
- FileUtils.rm_r(Rails.root) if File.exist?(Rails.root)
7
-
8
- # Create temporary directory to test the files generation
9
- %w( config public/javascripts ).each do |path|
10
- FileUtils.mkdir_p Rails.root.join(path)
11
- end
12
-
13
- # Overwrite defaut locales path to use fixtures
14
- I18n.load_path = [File.dirname(__FILE__) + "/resources/locales.yml"]
15
- end
16
-
17
- teardown do
18
- # Remove temporary directory
19
- FileUtils.rm_r(Rails.root)
20
- end
21
-
22
- test "copy configuration file" do
23
- assert_equal false, File.file?(SimplesIdeias::I18n.config_file)
24
- SimplesIdeias::I18n.setup!
25
- assert File.file?(SimplesIdeias::I18n.config_file)
26
- end
27
-
28
- test "don't overwrite existing configuration file" do
29
- File.open(SimplesIdeias::I18n.config_file, "w+") {|f| f << "ORIGINAL"}
30
- SimplesIdeias::I18n.setup!
31
-
32
- assert_equal "ORIGINAL", File.read(SimplesIdeias::I18n.config_file)
33
- end
34
-
35
- test "copy JavaScript library" do
36
- path = Rails.root.join("public/javascripts/i18n.js")
37
-
38
- assert_equal false, File.file?(path)
39
- SimplesIdeias::I18n.setup!
40
- assert File.file?(path)
41
- end
42
-
43
- test "load configuration file" do
44
- SimplesIdeias::I18n.setup!
45
-
46
- assert SimplesIdeias::I18n.config?
47
- assert_kind_of HashWithIndifferentAccess, SimplesIdeias::I18n.config
48
- assert SimplesIdeias::I18n.config.any?
49
- end
50
-
51
- test "export messages to default path when configuration file doesn't exist" do
52
- SimplesIdeias::I18n.export!
53
- assert File.file?(Rails.root.join("public/javascripts/translations.js"))
54
- end
55
-
56
- test "export messages using the default configuration file" do
57
- set_config "default.yml"
58
- SimplesIdeias::I18n.expects(:save).with(translations, "public/javascripts/translations.js")
59
- SimplesIdeias::I18n.export!
60
- end
61
-
62
- test "export messages using custom output path" do
63
- set_config "custom_path.yml"
64
- SimplesIdeias::I18n.expects(:save).with(translations, "public/javascripts/translations/all.js")
65
- SimplesIdeias::I18n.export!
66
- end
67
-
68
- test "set default scope to * when not specified" do
69
- set_config "no_scope.yml"
70
- SimplesIdeias::I18n.expects(:save).with(translations, "public/javascripts/no_scope.js")
71
- SimplesIdeias::I18n.export!
72
- end
73
-
74
- test "export to multiple files" do
75
- set_config "multiple_files.yml"
76
- SimplesIdeias::I18n.export!
77
-
78
- assert File.file?(Rails.root.join("public/javascripts/all.js"))
79
- assert File.file?(Rails.root.join("public/javascripts/tudo.js"))
80
- end
81
-
82
- test "filtered translations using scope *.date.formats" do
83
- result = SimplesIdeias::I18n.filter(translations, "*.date.formats")
84
- assert_equal [:formats], result[:en][:date].keys
85
- assert_equal [:formats], result[:fr][:date].keys
86
- end
87
-
88
- test "filtered translations using scope [*.date.formats, *.number.currency.format]" do
89
- result = SimplesIdeias::I18n.scoped_translations(["*.date.formats", "*.number.currency.format"])
90
- assert_equal %w[ date number ], result[:en].keys.collect(&:to_s).sort
91
- assert_equal %w[ date number ], result[:fr].keys.collect(&:to_s).sort
92
- end
93
-
94
- test "filtered translations using multi-star scope" do
95
- result = SimplesIdeias::I18n.scoped_translations("*.*.formats")
96
-
97
- assert_equal %w[ date time ], result[:en].keys.collect(&:to_s).sort
98
- assert_equal %w[ date time ], result[:fr].keys.collect(&:to_s).sort
99
-
100
- assert_equal [:formats], result[:en][:date].keys
101
- assert_equal [:formats], result[:en][:time].keys
102
-
103
- assert_equal [:formats], result[:fr][:date].keys
104
- assert_equal [:formats], result[:fr][:time].keys
105
- end
106
-
107
- test "filtered translations using alternated stars" do
108
- result = SimplesIdeias::I18n.scoped_translations("*.admin.*.title")
109
-
110
- assert_equal %w[ edit show ], result[:en][:admin].keys.collect(&:to_s).sort
111
- assert_equal %w[ edit show ], result[:fr][:admin].keys.collect(&:to_s).sort
112
-
113
- assert_equal "Show", result[:en][:admin][:show][:title]
114
- assert_equal "Visualiser", result[:fr][:admin][:show][:title]
115
-
116
- assert_equal "Edit", result[:en][:admin][:edit][:title]
117
- assert_equal "Editer", result[:fr][:admin][:edit][:title]
118
- end
119
-
120
- test "deep merge" do
121
- target = {:a => {:b => 1}}
122
- result = SimplesIdeias::I18n.deep_merge(target, {:a => {:c => 2}})
123
-
124
- assert_equal result[:a], {:b => 1, :c => 2}
125
- end
126
-
127
- test "deep banged merge" do
128
- target = {:a => {:b => 1}}
129
- SimplesIdeias::I18n.deep_merge!(target, {:a => {:c => 2}})
130
-
131
- assert_equal target[:a], {:b => 1, :c => 2}
132
- end
133
-
134
- test "update javascript library" do
135
- FakeWeb.register_uri(:get, "http://github.com/fnando/i18n-js/raw/master/lib/i18n.js", :body => "UPDATED")
136
-
137
- SimplesIdeias::I18n.setup!
138
- SimplesIdeias::I18n.update!
139
- assert_equal "UPDATED", File.read(SimplesIdeias::I18n.javascript_file)
140
- end
141
-
142
- private
143
- # Set the configuration as the current one
144
- def set_config(path)
145
- config = HashWithIndifferentAccess.new(YAML.load_file(File.dirname(__FILE__) + "/resources/#{path}"))
146
- SimplesIdeias::I18n.expects(:config?).returns(true)
147
- SimplesIdeias::I18n.expects(:config).returns(config)
148
- end
149
-
150
- # Shortcut to SimplesIdeias::I18n.translations
151
- def translations
152
- SimplesIdeias::I18n.translations
153
- end
154
- end
@@ -1,1017 +0,0 @@
1
- /* Jsunittest, version 0.7.3
2
- * (c) 2008 Dr Nic Williams
3
- *
4
- * Jsunittest is freely distributable under
5
- * the terms of an MIT-style license.
6
- * For details, see the web site: http://jsunittest.rubyforge.org
7
- *
8
- *--------------------------------------------------------------------------*/
9
-
10
- var JsUnitTest = {
11
- Unit: {},
12
- inspect: function(object) {
13
- try {
14
- if (typeof object == "undefined") return 'undefined';
15
- if (object === null) return 'null';
16
- if (typeof object == "string") {
17
- var useDoubleQuotes = arguments[1];
18
- var escapedString = this.gsub(object, /[\x00-\x1f\\]/, function(match) {
19
- var character = String.specialChar[match[0]];
20
- return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
21
- });
22
- if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
23
- return "'" + escapedString.replace(/'/g, '\\\'') + "'";
24
- };
25
- return String(object);
26
- } catch (e) {
27
- if (e instanceof RangeError) return '...';
28
- throw e;
29
- }
30
- },
31
- $: function(element) {
32
- if (arguments.length > 1) {
33
- for (var i = 0, elements = [], length = arguments.length; i < length; i++)
34
- elements.push(this.$(arguments[i]));
35
- return elements;
36
- }
37
- if (typeof element == "string")
38
- element = document.getElementById(element);
39
- return element;
40
- },
41
- gsub: function(source, pattern, replacement) {
42
- var result = '', match;
43
- replacement = arguments.callee.prepareReplacement(replacement);
44
-
45
- while (source.length > 0) {
46
- if (match = source.match(pattern)) {
47
- result += source.slice(0, match.index);
48
- result += JsUnitTest.String.interpret(replacement(match));
49
- source = source.slice(match.index + match[0].length);
50
- } else {
51
- result += source, source = '';
52
- }
53
- }
54
- return result;
55
- },
56
- scan: function(source, pattern, iterator) {
57
- this.gsub(source, pattern, iterator);
58
- return String(source);
59
- },
60
- escapeHTML: function(data) {
61
- return data.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
62
- },
63
- arrayfromargs: function(args) {
64
- var myarray = new Array();
65
- var i;
66
-
67
- for (i=0;i<args.length;i++)
68
- myarray[i] = args[i];
69
-
70
- return myarray;
71
- },
72
- hashToSortedArray: function(hash) {
73
- var results = [];
74
- for (key in hash) {
75
- results.push([key, hash[key]]);
76
- }
77
- return results.sort();
78
- },
79
- flattenArray: function(array) {
80
- var results = arguments[1] || [];
81
- for (var i=0; i < array.length; i++) {
82
- var object = array[i];
83
- if (object != null && typeof object == "object" &&
84
- 'splice' in object && 'join' in object) {
85
- this.flattenArray(object, results);
86
- } else {
87
- results.push(object);
88
- }
89
- };
90
- return results;
91
- },
92
- selectorMatch: function(expression, element) {
93
- var tokens = [];
94
- var patterns = {
95
- // combinators must be listed first
96
- // (and descendant needs to be last combinator)
97
- laterSibling: /^\s*~\s*/,
98
- child: /^\s*>\s*/,
99
- adjacent: /^\s*\+\s*/,
100
- descendant: /^\s/,
101
-
102
- // selectors follow
103
- tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
104
- id: /^#([\w\-\*]+)(\b|$)/,
105
- className: /^\.([\w\-\*]+)(\b|$)/,
106
- pseudo:
107
- /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
108
- attrPresence: /^\[((?:[\w]+:)?[\w]+)\]/,
109
- attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
110
- };
111
-
112
- var assertions = {
113
- tagName: function(element, matches) {
114
- return matches[1].toUpperCase() == element.tagName.toUpperCase();
115
- },
116
-
117
- className: function(element, matches) {
118
- return Element.hasClassName(element, matches[1]);
119
- },
120
-
121
- id: function(element, matches) {
122
- return element.id === matches[1];
123
- },
124
-
125
- attrPresence: function(element, matches) {
126
- return Element.hasAttribute(element, matches[1]);
127
- },
128
-
129
- attr: function(element, matches) {
130
- var nodeValue = Element.readAttribute(element, matches[1]);
131
- return nodeValue && operators[matches[2]](nodeValue, matches[5] || matches[6]);
132
- }
133
- };
134
- var e = this.expression, ps = patterns, as = assertions;
135
- var le, p, m;
136
-
137
- while (e && le !== e && (/\S/).test(e)) {
138
- le = e;
139
- for (var i in ps) {
140
- p = ps[i];
141
- if (m = e.match(p)) {
142
- // use the Selector.assertions methods unless the selector
143
- // is too complex.
144
- if (as[i]) {
145
- tokens.push([i, Object.clone(m)]);
146
- e = e.replace(m[0], '');
147
- }
148
- }
149
- }
150
- }
151
-
152
- var match = true, name, matches;
153
- for (var i = 0, token; token = tokens[i]; i++) {
154
- name = token[0], matches = token[1];
155
- if (!assertions[name](element, matches)) {
156
- match = false; break;
157
- }
158
- }
159
-
160
- return match;
161
- },
162
- toQueryParams: function(query, separator) {
163
- var query = query || window.location.search;
164
- var match = query.replace(/^\s+/, '').replace(/\s+$/, '').match(/([^?#]*)(#.*)?$/);
165
- if (!match) return { };
166
-
167
- var hash = {};
168
- var parts = match[1].split(separator || '&');
169
- for (var i=0; i < parts.length; i++) {
170
- var pair = parts[i].split('=');
171
- if (pair[0]) {
172
- var key = decodeURIComponent(pair.shift());
173
- var value = pair.length > 1 ? pair.join('=') : pair[0];
174
- if (value != undefined) value = decodeURIComponent(value);
175
-
176
- if (key in hash) {
177
- var object = hash[key];
178
- var isArray = object != null && typeof object == "object" &&
179
- 'splice' in object && 'join' in object
180
- if (!isArray) hash[key] = [hash[key]];
181
- hash[key].push(value);
182
- }
183
- else hash[key] = value;
184
- }
185
- };
186
- return hash;
187
- },
188
-
189
- String: {
190
- interpret: function(value) {
191
- return value == null ? '' : String(value);
192
- }
193
- }
194
- };
195
-
196
- JsUnitTest.gsub.prepareReplacement = function(replacement) {
197
- if (typeof replacement == "function") return replacement;
198
- var template = new Template(replacement);
199
- return function(match) { return template.evaluate(match) };
200
- };
201
-
202
- JsUnitTest.Version = '0.7.3';
203
-
204
- JsUnitTest.Template = function(template, pattern) {
205
- this.template = template; //template.toString();
206
- this.pattern = pattern || JsUnitTest.Template.Pattern;
207
- };
208
-
209
- JsUnitTest.Template.prototype.evaluate = function(object) {
210
- if (typeof object.toTemplateReplacements == "function")
211
- object = object.toTemplateReplacements();
212
-
213
- return JsUnitTest.gsub(this.template, this.pattern, function(match) {
214
- if (object == null) return '';
215
-
216
- var before = match[1] || '';
217
- if (before == '\\') return match[2];
218
-
219
- var ctx = object, expr = match[3];
220
- var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
221
- match = pattern.exec(expr);
222
- if (match == null) return before;
223
-
224
- while (match != null) {
225
- var comp = (match[1].indexOf('[]') === 0) ? match[2].gsub('\\\\]', ']') : match[1];
226
- ctx = ctx[comp];
227
- if (null == ctx || '' == match[3]) break;
228
- expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
229
- match = pattern.exec(expr);
230
- }
231
-
232
- return before + JsUnitTest.String.interpret(ctx);
233
- });
234
- }
235
-
236
- JsUnitTest.Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
237
- JsUnitTest.Event = {};
238
- // written by Dean Edwards, 2005
239
- // with input from Tino Zijdel, Matthias Miller, Diego Perini
240
- // namespaced by Dr Nic Williams 2008
241
-
242
- // http://dean.edwards.name/weblog/2005/10/add-event/
243
- // http://dean.edwards.name/weblog/2005/10/add-event2/
244
- JsUnitTest.Event.addEvent = function(element, type, handler) {
245
- if (element.addEventListener) {
246
- element.addEventListener(type, handler, false);
247
- } else {
248
- // assign each event handler a unique ID
249
- if (!handler.$$guid) handler.$$guid = JsUnitTest.Event.addEvent.guid++;
250
- // create a hash table of event types for the element
251
- if (!element.events) element.events = {};
252
- // create a hash table of event handlers for each element/event pair
253
- var handlers = element.events[type];
254
- if (!handlers) {
255
- handlers = element.events[type] = {};
256
- // store the existing event handler (if there is one)
257
- if (element["on" + type]) {
258
- handlers[0] = element["on" + type];
259
- }
260
- }
261
- // store the event handler in the hash table
262
- handlers[handler.$$guid] = handler;
263
- // assign a global event handler to do all the work
264
- element["on" + type] = this.handleEvent;
265
- }
266
- };
267
- // a counter used to create unique IDs
268
- JsUnitTest.Event.addEvent.guid = 1;
269
-
270
- JsUnitTest.Event.removeEvent = function(element, type, handler) {
271
- if (element.removeEventListener) {
272
- element.removeEventListener(type, handler, false);
273
- } else {
274
- // delete the event handler from the hash table
275
- if (element.events && element.events[type]) {
276
- delete element.events[type][handler.$$guid];
277
- }
278
- }
279
- };
280
-
281
- JsUnitTest.Event.handleEvent = function(event) {
282
- var returnValue = true;
283
- // grab the event object (IE uses a global event object)
284
- event = event || JsUnitTest.Event.fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event);
285
- // get a reference to the hash table of event handlers
286
- var handlers = this.events[event.type];
287
- // execute each event handler
288
- for (var i in handlers) {
289
- this.$$handleEvent = handlers[i];
290
- if (this.$$handleEvent(event) === false) {
291
- returnValue = false;
292
- }
293
- }
294
- return returnValue;
295
- };
296
-
297
- JsUnitTest.Event.fixEvent = function(event) {
298
- // add W3C standard event methods
299
- event.preventDefault = this.fixEvent.preventDefault;
300
- event.stopPropagation = this.fixEvent.stopPropagation;
301
- return event;
302
- };
303
- JsUnitTest.Event.fixEvent.preventDefault = function() {
304
- this.returnValue = false;
305
- };
306
- JsUnitTest.Event.fixEvent.stopPropagation = function() {
307
- this.cancelBubble = true;
308
- };
309
-
310
- JsUnitTest.Unit.Logger = function(element) {
311
- this.element = JsUnitTest.$(element);
312
- if (this.element) this._createLogTable();
313
- };
314
-
315
- JsUnitTest.Unit.Logger.prototype.start = function(testName) {
316
- if (!this.element) return;
317
- var tbody = this.element.getElementsByTagName('tbody')[0];
318
-
319
- var tr = document.createElement('tr');
320
- var td;
321
-
322
- //testname
323
- td = document.createElement('td');
324
- td.appendChild(document.createTextNode(testName));
325
- tr.appendChild(td)
326
-
327
- tr.appendChild(document.createElement('td'));//status
328
- tr.appendChild(document.createElement('td'));//message
329
-
330
- tbody.appendChild(tr);
331
- };
332
-
333
- JsUnitTest.Unit.Logger.prototype.setStatus = function(status) {
334
- var logline = this.getLastLogLine();
335
- logline.className = status;
336
- var statusCell = logline.getElementsByTagName('td')[1];
337
- statusCell.appendChild(document.createTextNode(status));
338
- };
339
-
340
- JsUnitTest.Unit.Logger.prototype.finish = function(status, summary) {
341
- if (!this.element) return;
342
- this.setStatus(status);
343
- this.message(summary);
344
- };
345
-
346
- JsUnitTest.Unit.Logger.prototype.message = function(message) {
347
- if (!this.element) return;
348
- var cell = this.getMessageCell();
349
-
350
- // cell.appendChild(document.createTextNode(this._toHTML(message)));
351
- cell.innerHTML = this._toHTML(message);
352
- };
353
-
354
- JsUnitTest.Unit.Logger.prototype.summary = function(summary) {
355
- if (!this.element) return;
356
- var div = this.element.getElementsByTagName('div')[0];
357
- div.innerHTML = this._toHTML(summary);
358
- };
359
-
360
- JsUnitTest.Unit.Logger.prototype.getLastLogLine = function() {
361
- var tbody = this.element.getElementsByTagName('tbody')[0];
362
- var loglines = tbody.getElementsByTagName('tr');
363
- return loglines[loglines.length - 1];
364
- };
365
-
366
- JsUnitTest.Unit.Logger.prototype.getMessageCell = function() {
367
- var logline = this.getLastLogLine();
368
- return logline.getElementsByTagName('td')[2];
369
- };
370
-
371
- JsUnitTest.Unit.Logger.prototype._createLogTable = function() {
372
- var html = '<div class="logsummary">running...</div>' +
373
- '<table class="logtable">' +
374
- '<thead><tr><th>Status</th><th>Test</th><th>Message</th></tr></thead>' +
375
- '<tbody class="loglines"></tbody>' +
376
- '</table>';
377
- this.element.innerHTML = html;
378
- };
379
-
380
- JsUnitTest.Unit.Logger.prototype.appendActionButtons = function(actions) {
381
- // actions = $H(actions);
382
- // if (!actions.any()) return;
383
- // var div = new Element("div", {className: 'action_buttons'});
384
- // actions.inject(div, function(container, action) {
385
- // var button = new Element("input").setValue(action.key).observe("click", action.value);
386
- // button.type = "button";
387
- // return container.insert(button);
388
- // });
389
- // this.getMessageCell().insert(div);
390
- };
391
-
392
- JsUnitTest.Unit.Logger.prototype._toHTML = function(txt) {
393
- return JsUnitTest.escapeHTML(txt).replace(/\n/g,"<br/>");
394
- };
395
- JsUnitTest.Unit.MessageTemplate = function(string) {
396
- var parts = [];
397
- var str = JsUnitTest.scan((string || ''), /(?=[^\\])\?|(?:\\\?|[^\?])+/, function(part) {
398
- parts.push(part[0]);
399
- });
400
- this.parts = parts;
401
- };
402
-
403
- JsUnitTest.Unit.MessageTemplate.prototype.evaluate = function(params) {
404
- var results = [];
405
- for (var i=0; i < this.parts.length; i++) {
406
- var part = this.parts[i];
407
- var result = (part == '?') ? JsUnitTest.inspect(params.shift()) : part.replace(/\\\?/, '?');
408
- results.push(result);
409
- };
410
- return results.join('');
411
- };
412
- // A generic function for performming AJAX requests
413
- // It takes one argument, which is an object that contains a set of options
414
- // All of which are outline in the comments, below
415
- // From John Resig's book Pro JavaScript Techniques
416
- // published by Apress, 2006-8
417
- JsUnitTest.ajax = function( options ) {
418
-
419
- // Load the options object with defaults, if no
420
- // values were provided by the user
421
- options = {
422
- // The type of HTTP Request
423
- type: options.type || "POST",
424
-
425
- // The URL the request will be made to
426
- url: options.url || "",
427
-
428
- // How long to wait before considering the request to be a timeout
429
- timeout: options.timeout || 5000,
430
-
431
- // Functions to call when the request fails, succeeds,
432
- // or completes (either fail or succeed)
433
- onComplete: options.onComplete || function(){},
434
- onError: options.onError || function(){},
435
- onSuccess: options.onSuccess || function(){},
436
-
437
- // The data type that'll be returned from the server
438
- // the default is simply to determine what data was returned from the
439
- // and act accordingly.
440
- data: options.data || ""
441
- };
442
-
443
- // Create the request object
444
- var xml = window.ActiveXObject ? new ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest();
445
-
446
- // Open the asynchronous POST request
447
- xml.open(options.type, options.url, true);
448
-
449
- // We're going to wait for a request for 5 seconds, before giving up
450
- var timeoutLength = 5000;
451
-
452
- // Keep track of when the request has been succesfully completed
453
- var requestDone = false;
454
-
455
- // Initalize a callback which will fire 5 seconds from now, cancelling
456
- // the request (if it has not already occurred).
457
- setTimeout(function(){
458
- requestDone = true;
459
- }, timeoutLength);
460
-
461
- // Watch for when the state of the document gets updated
462
- xml.onreadystatechange = function(){
463
- // Wait until the data is fully loaded,
464
- // and make sure that the request hasn't already timed out
465
- if ( xml.readyState == 4 && !requestDone ) {
466
-
467
- // Check to see if the request was successful
468
- if ( httpSuccess( xml ) ) {
469
-
470
- // Execute the success callback with the data returned from the server
471
- options.onSuccess( httpData( xml, options.type ) );
472
-
473
- // Otherwise, an error occurred, so execute the error callback
474
- } else {
475
- options.onError();
476
- }
477
-
478
- // Call the completion callback
479
- options.onComplete();
480
-
481
- // Clean up after ourselves, to avoid memory leaks
482
- xml = null;
483
- }
484
- };
485
-
486
- // Establish the connection to the server
487
- xml.send(null);
488
-
489
- // Determine the success of the HTTP response
490
- function httpSuccess(r) {
491
- try {
492
- // If no server status is provided, and we're actually
493
- // requesting a local file, then it was successful
494
- return !r.status && location.protocol == "file:" ||
495
-
496
- // Any status in the 200 range is good
497
- ( r.status >= 200 && r.status < 300 ) ||
498
-
499
- // Successful if the document has not been modified
500
- r.status == 304 ||
501
-
502
- // Safari returns an empty status if the file has not been modified
503
- navigator.userAgent.indexOf("Safari") >= 0 && typeof r.status == "undefined";
504
- } catch(e){}
505
-
506
- // If checking the status failed, then assume that the request failed too
507
- return false;
508
- }
509
-
510
- // Extract the correct data from the HTTP response
511
- function httpData(r,type) {
512
- // Get the content-type header
513
- var ct = r.getResponseHeader("content-type");
514
-
515
- // If no default type was provided, determine if some
516
- // form of XML was returned from the server
517
- var data = !type && ct && ct.indexOf("xml") >= 0;
518
-
519
- // Get the XML Document object if XML was returned from
520
- // the server, otherwise return the text contents returned by the server
521
- data = type == "xml" || data ? r.responseXML : r.responseText;
522
-
523
- // If the specified type is "script", execute the returned text
524
- // response as if it was JavaScript
525
- if ( type == "script" )
526
- eval.call( window, data );
527
-
528
- // Return the response data (either an XML Document or a text string)
529
- return data;
530
- }
531
-
532
- };
533
- JsUnitTest.Unit.Assertions = {
534
- buildMessage: function(message, template) {
535
- var args = JsUnitTest.arrayfromargs(arguments).slice(2);
536
- return (message ? message + '\n' : '') +
537
- new JsUnitTest.Unit.MessageTemplate(template).evaluate(args);
538
- },
539
-
540
- flunk: function(message) {
541
- this.assertBlock(message || 'Flunked', function() { return false });
542
- },
543
-
544
- assertBlock: function(message, block) {
545
- try {
546
- block.call(this) ? this.pass() : this.fail(message);
547
- } catch(e) { this.error(e) }
548
- },
549
-
550
- assert: function(expression, message) {
551
- message = this.buildMessage(message || 'assert', 'got <?>', expression);
552
- this.assertBlock(message, function() { return expression });
553
- },
554
-
555
- assertEqual: function(expected, actual, message) {
556
- message = this.buildMessage(message || 'assertEqual', 'expected <?>, actual: <?>', expected, actual);
557
- this.assertBlock(message, function() { return expected == actual });
558
- },
559
-
560
- assertNotEqual: function(expected, actual, message) {
561
- message = this.buildMessage(message || 'assertNotEqual', 'expected <?>, actual: <?>', expected, actual);
562
- this.assertBlock(message, function() { return expected != actual });
563
- },
564
-
565
- assertEnumEqual: function(expected, actual, message) {
566
- message = this.buildMessage(message || 'assertEnumEqual', 'expected <?>, actual: <?>', expected, actual);
567
- var expected_array = JsUnitTest.flattenArray(expected);
568
- var actual_array = JsUnitTest.flattenArray(actual);
569
- this.assertBlock(message, function() {
570
- if (expected_array.length == actual_array.length) {
571
- for (var i=0; i < expected_array.length; i++) {
572
- if (expected_array[i] != actual_array[i]) return false;
573
- };
574
- return true;
575
- }
576
- return false;
577
- });
578
- },
579
-
580
- assertEnumNotEqual: function(expected, actual, message) {
581
- message = this.buildMessage(message || 'assertEnumNotEqual', '<?> was the same as <?>', expected, actual);
582
- var expected_array = JsUnitTest.flattenArray(expected);
583
- var actual_array = JsUnitTest.flattenArray(actual);
584
- this.assertBlock(message, function() {
585
- if (expected_array.length == actual_array.length) {
586
- for (var i=0; i < expected_array.length; i++) {
587
- if (expected_array[i] != actual_array[i]) return true;
588
- };
589
- return false;
590
- }
591
- return true;
592
- });
593
- },
594
-
595
- assertHashEqual: function(expected, actual, message) {
596
- message = this.buildMessage(message || 'assertHashEqual', 'expected <?>, actual: <?>', expected, actual);
597
- var expected_array = JsUnitTest.flattenArray(JsUnitTest.hashToSortedArray(expected));
598
- var actual_array = JsUnitTest.flattenArray(JsUnitTest.hashToSortedArray(actual));
599
- var block = function() {
600
- if (expected_array.length == actual_array.length) {
601
- for (var i=0; i < expected_array.length; i++) {
602
- if (expected_array[i] != actual_array[i]) return false;
603
- };
604
- return true;
605
- }
606
- return false;
607
- };
608
- this.assertBlock(message, block);
609
- },
610
-
611
- assertHashNotEqual: function(expected, actual, message) {
612
- message = this.buildMessage(message || 'assertHashNotEqual', '<?> was the same as <?>', expected, actual);
613
- var expected_array = JsUnitTest.flattenArray(JsUnitTest.hashToSortedArray(expected));
614
- var actual_array = JsUnitTest.flattenArray(JsUnitTest.hashToSortedArray(actual));
615
- // from now we recursively zip & compare nested arrays
616
- var block = function() {
617
- if (expected_array.length == actual_array.length) {
618
- for (var i=0; i < expected_array.length; i++) {
619
- if (expected_array[i] != actual_array[i]) return true;
620
- };
621
- return false;
622
- }
623
- return true;
624
- };
625
- this.assertBlock(message, block);
626
- },
627
-
628
- assertIdentical: function(expected, actual, message) {
629
- message = this.buildMessage(message || 'assertIdentical', 'expected <?>, actual: <?>', expected, actual);
630
- this.assertBlock(message, function() { return expected === actual });
631
- },
632
-
633
- assertNotIdentical: function(expected, actual, message) {
634
- message = this.buildMessage(message || 'assertNotIdentical', 'expected <?>, actual: <?>', expected, actual);
635
- this.assertBlock(message, function() { return expected !== actual });
636
- },
637
-
638
- assertNull: function(obj, message) {
639
- message = this.buildMessage(message || 'assertNull', 'got <?>', obj);
640
- this.assertBlock(message, function() { return obj === null });
641
- },
642
-
643
- assertNotNull: function(obj, message) {
644
- message = this.buildMessage(message || 'assertNotNull', 'got <?>', obj);
645
- this.assertBlock(message, function() { return obj !== null });
646
- },
647
-
648
- assertUndefined: function(obj, message) {
649
- message = this.buildMessage(message || 'assertUndefined', 'got <?>', obj);
650
- this.assertBlock(message, function() { return typeof obj == "undefined" });
651
- },
652
-
653
- assertNotUndefined: function(obj, message) {
654
- message = this.buildMessage(message || 'assertNotUndefined', 'got <?>', obj);
655
- this.assertBlock(message, function() { return typeof obj != "undefined" });
656
- },
657
-
658
- assertNullOrUndefined: function(obj, message) {
659
- message = this.buildMessage(message || 'assertNullOrUndefined', 'got <?>', obj);
660
- this.assertBlock(message, function() { return obj == null });
661
- },
662
-
663
- assertNotNullOrUndefined: function(obj, message) {
664
- message = this.buildMessage(message || 'assertNotNullOrUndefined', 'got <?>', obj);
665
- this.assertBlock(message, function() { return obj != null });
666
- },
667
-
668
- assertMatch: function(expected, actual, message) {
669
- message = this.buildMessage(message || 'assertMatch', 'regex <?> did not match <?>', expected, actual);
670
- this.assertBlock(message, function() { return new RegExp(expected).exec(actual) });
671
- },
672
-
673
- assertNoMatch: function(expected, actual, message) {
674
- message = this.buildMessage(message || 'assertNoMatch', 'regex <?> matched <?>', expected, actual);
675
- this.assertBlock(message, function() { return !(new RegExp(expected).exec(actual)) });
676
- },
677
-
678
- assertHasClass: function(element, klass, message) {
679
- element = JsUnitTest.$(element);
680
- message = this.buildMessage(message || 'assertHasClass', '? doesn\'t have class <?>.', element, klass);
681
- this.assertBlock(message, function() {
682
- var elementClassName = element.className;
683
- return (elementClassName.length > 0 && (elementClassName == klass ||
684
- new RegExp("(^|\\s)" + klass + "(\\s|$)").test(elementClassName)));
685
- // return !!element.className.match(new RegExp(klass))
686
- });
687
- },
688
-
689
- assertNotHasClass: function(element, klass, message) {
690
- element = JsUnitTest.$(element);
691
- message = this.buildMessage(message || 'assertNotHasClass', '? does have class <?>.', element, klass);
692
- this.assertBlock(message, function() {
693
- var elementClassName = element.className;
694
- return !(elementClassName.length > 0 && (elementClassName == klass ||
695
- new RegExp("(^|\\s)" + klass + "(\\s|$)").test(elementClassName)));
696
- });
697
- },
698
-
699
- assertHidden: function(element, message) {
700
- element = JsUnitTest.$(element);
701
- message = this.buildMessage(message || 'assertHidden', '? isn\'t hidden.', element);
702
- this.assertBlock(message, function() { return !element.style.display || element.style.display == 'none' });
703
- },
704
-
705
- assertInstanceOf: function(expected, actual, message) {
706
- message = this.buildMessage(message || 'assertInstanceOf', '<?> was not an instance of the expected type', actual);
707
- this.assertBlock(message, function() { return actual instanceof expected });
708
- },
709
-
710
- assertNotInstanceOf: function(expected, actual, message) {
711
- message = this.buildMessage(message || 'assertNotInstanceOf', '<?> was an instance of the expected type', actual);
712
- this.assertBlock(message, function() { return !(actual instanceof expected) });
713
- },
714
-
715
- assertRespondsTo: function(method, obj, message) {
716
- message = this.buildMessage(message || 'assertRespondsTo', 'object doesn\'t respond to <?>', method);
717
- this.assertBlock(message, function() { return (method in obj && typeof obj[method] == 'function') });
718
- },
719
-
720
- assertRaise: function(exceptionName, method, message) {
721
- message = this.buildMessage(message || 'assertRaise', '<?> exception expected but none was raised', exceptionName);
722
- var block = function() {
723
- try {
724
- method();
725
- return false;
726
- } catch(e) {
727
- if (e.name == exceptionName) return true;
728
- else throw e;
729
- }
730
- };
731
- this.assertBlock(message, block);
732
- },
733
-
734
- assertNothingRaised: function(method, message) {
735
- try {
736
- method();
737
- this.assert(true, "Expected nothing to be thrown");
738
- } catch(e) {
739
- message = this.buildMessage(message || 'assertNothingRaised', '<?> was thrown when nothing was expected.', e);
740
- this.flunk(message);
741
- }
742
- },
743
-
744
- _isVisible: function(element) {
745
- element = JsUnitTest.$(element);
746
- if(!element.parentNode) return true;
747
- this.assertNotNull(element);
748
- if(element.style && (element.style.display == 'none'))
749
- return false;
750
-
751
- return arguments.callee.call(this, element.parentNode);
752
- },
753
-
754
- assertVisible: function(element, message) {
755
- message = this.buildMessage(message, '? was not visible.', element);
756
- this.assertBlock(message, function() { return this._isVisible(element) });
757
- },
758
-
759
- assertNotVisible: function(element, message) {
760
- message = this.buildMessage(message, '? was not hidden and didn\'t have a hidden parent either.', element);
761
- this.assertBlock(message, function() { return !this._isVisible(element) });
762
- },
763
-
764
- assertElementsMatch: function() {
765
- var pass = true, expressions = JsUnitTest.arrayfromargs(arguments);
766
- var elements = expressions.shift();
767
- if (elements.length != expressions.length) {
768
- message = this.buildMessage('assertElementsMatch', 'size mismatch: ? elements, ? expressions (?).', elements.length, expressions.length, expressions);
769
- this.flunk(message);
770
- pass = false;
771
- }
772
- for (var i=0; i < expressions.length; i++) {
773
- var expression = expressions[i];
774
- var element = JsUnitTest.$(elements[i]);
775
- if (JsUnitTest.selectorMatch(expression, element)) {
776
- pass = true;
777
- break;
778
- }
779
- message = this.buildMessage('assertElementsMatch', 'In index <?>: expected <?> but got ?', index, expression, element);
780
- this.flunk(message);
781
- pass = false;
782
- };
783
- this.assert(pass, "Expected all elements to match.");
784
- },
785
-
786
- assertElementMatches: function(element, expression, message) {
787
- this.assertElementsMatch([element], expression);
788
- }
789
- };
790
- JsUnitTest.Unit.Runner = function(testcases) {
791
- var argumentOptions = arguments[1] || {};
792
- var options = this.options = {};
793
- options.testLog = ('testLog' in argumentOptions) ? argumentOptions.testLog : 'testlog';
794
- options.resultsURL = this.queryParams.resultsURL;
795
- options.testLog = JsUnitTest.$(options.testLog);
796
-
797
- this.tests = this.getTests(testcases);
798
- this.currentTest = 0;
799
- this.logger = new JsUnitTest.Unit.Logger(options.testLog);
800
-
801
- var self = this;
802
- JsUnitTest.Event.addEvent(window, "load", function() {
803
- setTimeout(function() {
804
- self.runTests();
805
- }, 0.1);
806
- });
807
- };
808
-
809
- JsUnitTest.Unit.Runner.prototype.queryParams = JsUnitTest.toQueryParams();
810
-
811
- JsUnitTest.Unit.Runner.prototype.portNumber = function() {
812
- if (window.location.search.length > 0) {
813
- var matches = window.location.search.match(/\:(\d{3,5})\//);
814
- if (matches) {
815
- return parseInt(matches[1]);
816
- }
817
- }
818
- return null;
819
- };
820
-
821
- JsUnitTest.Unit.Runner.prototype.getTests = function(testcases) {
822
- var tests = [], options = this.options;
823
- if (this.queryParams.tests) tests = this.queryParams.tests.split(',');
824
- else if (options.tests) tests = options.tests;
825
- else if (options.test) tests = [option.test];
826
- else {
827
- for (testname in testcases) {
828
- if (testname.match(/^test/)) tests.push(testname);
829
- }
830
- }
831
- var results = [];
832
- for (var i=0; i < tests.length; i++) {
833
- var test = tests[i];
834
- if (testcases[test])
835
- results.push(
836
- new JsUnitTest.Unit.Testcase(test, testcases[test], testcases.setup, testcases.teardown)
837
- );
838
- };
839
- return results;
840
- };
841
-
842
- JsUnitTest.Unit.Runner.prototype.getResult = function() {
843
- var results = {
844
- tests: this.tests.length,
845
- assertions: 0,
846
- failures: 0,
847
- errors: 0,
848
- warnings: 0
849
- };
850
-
851
- for (var i=0; i < this.tests.length; i++) {
852
- var test = this.tests[i];
853
- results.assertions += test.assertions;
854
- results.failures += test.failures;
855
- results.errors += test.errors;
856
- results.warnings += test.warnings;
857
- };
858
- return results;
859
- };
860
-
861
- JsUnitTest.Unit.Runner.prototype.postResults = function() {
862
- if (this.options.resultsURL) {
863
- // new Ajax.Request(this.options.resultsURL,
864
- // { method: 'get', parameters: this.getResult(), asynchronous: false });
865
- var results = this.getResult();
866
- var url = this.options.resultsURL + "?";
867
- url += "tests="+ this.tests.length + "&";
868
- url += "assertions="+ results.assertions + "&";
869
- url += "warnings=" + results.warnings + "&";
870
- url += "failures=" + results.failures + "&";
871
- url += "errors=" + results.errors;
872
- JsUnitTest.ajax({
873
- url: url,
874
- type: 'GET'
875
- })
876
- }
877
- };
878
-
879
- JsUnitTest.Unit.Runner.prototype.runTests = function() {
880
- var test = this.tests[this.currentTest], actions;
881
-
882
- if (!test) return this.finish();
883
- if (!test.isWaiting) this.logger.start(test.name);
884
- test.run();
885
- var self = this;
886
- if(test.isWaiting) {
887
- this.logger.message("Waiting for " + test.timeToWait + "ms");
888
- // setTimeout(this.runTests.bind(this), test.timeToWait || 1000);
889
- setTimeout(function() {
890
- self.runTests();
891
- }, test.timeToWait || 1000);
892
- return;
893
- }
894
-
895
- this.logger.finish(test.status(), test.summary());
896
- if (actions = test.actions) this.logger.appendActionButtons(actions);
897
- this.currentTest++;
898
- // tail recursive, hopefully the browser will skip the stackframe
899
- this.runTests();
900
- };
901
-
902
- JsUnitTest.Unit.Runner.prototype.finish = function() {
903
- this.postResults();
904
- this.logger.summary(this.summary());
905
- };
906
-
907
- JsUnitTest.Unit.Runner.prototype.summary = function() {
908
- return new JsUnitTest.Template('#{tests} tests, #{assertions} assertions, #{failures} failures, #{errors} errors, #{warnings} warnings').evaluate(this.getResult());
909
- };
910
- JsUnitTest.Unit.Testcase = function(name, test, setup, teardown) {
911
- this.name = name;
912
- this.test = test || function() {};
913
- this.setup = setup || function() {};
914
- this.teardown = teardown || function() {};
915
- this.messages = [];
916
- this.actions = {};
917
- };
918
- // import JsUnitTest.Unit.Assertions
919
-
920
- for (method in JsUnitTest.Unit.Assertions) {
921
- JsUnitTest.Unit.Testcase.prototype[method] = JsUnitTest.Unit.Assertions[method];
922
- }
923
-
924
- JsUnitTest.Unit.Testcase.prototype.isWaiting = false;
925
- JsUnitTest.Unit.Testcase.prototype.timeToWait = 1000;
926
- JsUnitTest.Unit.Testcase.prototype.assertions = 0;
927
- JsUnitTest.Unit.Testcase.prototype.failures = 0;
928
- JsUnitTest.Unit.Testcase.prototype.errors = 0;
929
- JsUnitTest.Unit.Testcase.prototype.warnings = 0;
930
- JsUnitTest.Unit.Testcase.prototype.isRunningFromRake = window.location.port;
931
-
932
- // JsUnitTest.Unit.Testcase.prototype.isRunningFromRake = window.location.port == 4711;
933
-
934
- JsUnitTest.Unit.Testcase.prototype.wait = function(time, nextPart) {
935
- this.isWaiting = true;
936
- this.test = nextPart;
937
- this.timeToWait = time;
938
- };
939
-
940
- JsUnitTest.Unit.Testcase.prototype.run = function(rethrow) {
941
- try {
942
- try {
943
- if (!this.isWaiting) this.setup();
944
- this.isWaiting = false;
945
- this.test();
946
- } finally {
947
- if(!this.isWaiting) {
948
- this.teardown();
949
- }
950
- }
951
- }
952
- catch(e) {
953
- if (rethrow) throw e;
954
- this.error(e, this);
955
- }
956
- };
957
-
958
- JsUnitTest.Unit.Testcase.prototype.summary = function() {
959
- var msg = '#{assertions} assertions, #{failures} failures, #{errors} errors, #{warnings} warnings\n';
960
- return new JsUnitTest.Template(msg).evaluate(this) +
961
- this.messages.join("\n");
962
- };
963
-
964
- JsUnitTest.Unit.Testcase.prototype.pass = function() {
965
- this.assertions++;
966
- };
967
-
968
- JsUnitTest.Unit.Testcase.prototype.fail = function(message) {
969
- this.failures++;
970
- var line = "";
971
- try {
972
- throw new Error("stack");
973
- } catch(e){
974
- line = (/\.html:(\d+)/.exec(e.stack || '') || ['',''])[1];
975
- }
976
- this.messages.push("Failure: " + message + (line ? " Line #" + line : ""));
977
- };
978
-
979
- JsUnitTest.Unit.Testcase.prototype.warning = function(message) {
980
- this.warnings++;
981
- var line = "";
982
- try {
983
- throw new Error("stack");
984
- } catch(e){
985
- line = (/\.html:(\d+)/.exec(e.stack || '') || ['',''])[1];
986
- }
987
- this.messages.push("Warning: " + message + (line ? " Line #" + line : ""));
988
- };
989
- JsUnitTest.Unit.Testcase.prototype.warn = JsUnitTest.Unit.Testcase.prototype.warning;
990
-
991
- JsUnitTest.Unit.Testcase.prototype.info = function(message) {
992
- this.messages.push("Info: " + message);
993
- };
994
-
995
- JsUnitTest.Unit.Testcase.prototype.error = function(error, test) {
996
- this.errors++;
997
- this.actions['retry with throw'] = function() { test.run(true) };
998
- this.messages.push(error.name + ": "+ error.message + "(" + JsUnitTest.inspect(error) + ")");
999
- };
1000
-
1001
- JsUnitTest.Unit.Testcase.prototype.status = function() {
1002
- if (this.failures > 0) return 'failed';
1003
- if (this.errors > 0) return 'error';
1004
- if (this.warnings > 0) return 'warning';
1005
- return 'passed';
1006
- };
1007
-
1008
- JsUnitTest.Unit.Testcase.prototype.benchmark = function(operation, iterations) {
1009
- var startAt = new Date();
1010
- (iterations || 1).times(operation);
1011
- var timeTaken = ((new Date())-startAt);
1012
- this.info((arguments[2] || 'Operation') + ' finished ' +
1013
- iterations + ' iterations in ' + (timeTaken/1000)+'s' );
1014
- return timeTaken;
1015
- };
1016
-
1017
- Test = JsUnitTest