newjs 1.1.0 → 1.2.0

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