You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jspwiki.apache.org by br...@apache.org on 2009/09/26 15:22:32 UTC
svn commit: r819134 [2/2] - in /incubator/jspwiki/trunk/tests/javascript: ./
assets/ assets/images/
Added: incubator/jspwiki/trunk/tests/javascript/assets/json2.js
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/tests/javascript/assets/json2.js?rev=819134&view=auto
==============================================================================
--- incubator/jspwiki/trunk/tests/javascript/assets/json2.js (added)
+++ incubator/jspwiki/trunk/tests/javascript/assets/json2.js Sat Sep 26 13:22:31 2009
@@ -0,0 +1,478 @@
+/*
+ http://www.JSON.org/json2.js
+ 2008-11-19
+
+ Public Domain.
+
+ NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+
+ See http://www.JSON.org/js.html
+
+ This file creates a global JSON object containing two methods: stringify
+ and parse.
+
+ JSON.stringify(value, replacer, space)
+ value any JavaScript value, usually an object or array.
+
+ replacer an optional parameter that determines how object
+ values are stringified for objects. It can be a
+ function or an array of strings.
+
+ space an optional parameter that specifies the indentation
+ of nested structures. If it is omitted, the text will
+ be packed without extra whitespace. If it is a number,
+ it will specify the number of spaces to indent at each
+ level. If it is a string (such as '\t' or ' '),
+ it contains the characters used to indent at each level.
+
+ This method produces a JSON text from a JavaScript value.
+
+ When an object value is found, if the object contains a toJSON
+ method, its toJSON method will be called and the result will be
+ stringified. A toJSON method does not serialize: it returns the
+ value represented by the name/value pair that should be serialized,
+ or undefined if nothing should be serialized. The toJSON method
+ will be passed the key associated with the value, and this will be
+ bound to the object holding the key.
+
+ For example, this would serialize Dates as ISO strings.
+
+ Date.prototype.toJSON = function (key) {
+ function f(n) {
+ // Format integers to have at least two digits.
+ return n < 10 ? '0' + n : n;
+ }
+
+ return this.getUTCFullYear() + '-' +
+ f(this.getUTCMonth() + 1) + '-' +
+ f(this.getUTCDate()) + 'T' +
+ f(this.getUTCHours()) + ':' +
+ f(this.getUTCMinutes()) + ':' +
+ f(this.getUTCSeconds()) + 'Z';
+ };
+
+ You can provide an optional replacer method. It will be passed the
+ key and value of each member, with this bound to the containing
+ object. The value that is returned from your method will be
+ serialized. If your method returns undefined, then the member will
+ be excluded from the serialization.
+
+ If the replacer parameter is an array of strings, then it will be
+ used to select the members to be serialized. It filters the results
+ such that only members with keys listed in the replacer array are
+ stringified.
+
+ Values that do not have JSON representations, such as undefined or
+ functions, will not be serialized. Such values in objects will be
+ dropped; in arrays they will be replaced with null. You can use
+ a replacer function to replace those with JSON values.
+ JSON.stringify(undefined) returns undefined.
+
+ The optional space parameter produces a stringification of the
+ value that is filled with line breaks and indentation to make it
+ easier to read.
+
+ If the space parameter is a non-empty string, then that string will
+ be used for indentation. If the space parameter is a number, then
+ the indentation will be that many spaces.
+
+ Example:
+
+ text = JSON.stringify(['e', {pluribus: 'unum'}]);
+ // text is '["e",{"pluribus":"unum"}]'
+
+
+ text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
+ // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
+
+ text = JSON.stringify([new Date()], function (key, value) {
+ return this[key] instanceof Date ?
+ 'Date(' + this[key] + ')' : value;
+ });
+ // text is '["Date(---current time---)"]'
+
+
+ JSON.parse(text, reviver)
+ This method parses a JSON text to produce an object or array.
+ It can throw a SyntaxError exception.
+
+ The optional reviver parameter is a function that can filter and
+ transform the results. It receives each of the keys and values,
+ and its return value is used instead of the original value.
+ If it returns what it received, then the structure is not modified.
+ If it returns undefined then the member is deleted.
+
+ Example:
+
+ // Parse the text. Values that look like ISO date strings will
+ // be converted to Date objects.
+
+ myData = JSON.parse(text, function (key, value) {
+ var a;
+ if (typeof value === 'string') {
+ a =
+/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
+ if (a) {
+ return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
+ +a[5], +a[6]));
+ }
+ }
+ return value;
+ });
+
+ myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
+ var d;
+ if (typeof value === 'string' &&
+ value.slice(0, 5) === 'Date(' &&
+ value.slice(-1) === ')') {
+ d = new Date(value.slice(5, -1));
+ if (d) {
+ return d;
+ }
+ }
+ return value;
+ });
+
+
+ This is a reference implementation. You are free to copy, modify, or
+ redistribute.
+
+ This code should be minified before deployment.
+ See http://javascript.crockford.com/jsmin.html
+
+ USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
+ NOT CONTROL.
+*/
+
+/*jslint evil: true */
+
+/*global JSON */
+
+/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
+ call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
+ getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
+ lastIndex, length, parse, prototype, push, replace, slice, stringify,
+ test, toJSON, toString, valueOf
+*/
+
+// Create a JSON object only if one does not already exist. We create the
+// methods in a closure to avoid creating global variables.
+
+if (!this.JSON) {
+ JSON = {};
+}
+(function () {
+
+ function f(n) {
+ // Format integers to have at least two digits.
+ return n < 10 ? '0' + n : n;
+ }
+
+ if (typeof Date.prototype.toJSON !== 'function') {
+
+ Date.prototype.toJSON = function (key) {
+
+ return this.getUTCFullYear() + '-' +
+ f(this.getUTCMonth() + 1) + '-' +
+ f(this.getUTCDate()) + 'T' +
+ f(this.getUTCHours()) + ':' +
+ f(this.getUTCMinutes()) + ':' +
+ f(this.getUTCSeconds()) + 'Z';
+ };
+
+ String.prototype.toJSON =
+ Number.prototype.toJSON =
+ Boolean.prototype.toJSON = function (key) {
+ return this.valueOf();
+ };
+ }
+
+ var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+ escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+ gap,
+ indent,
+ meta = { // table of character substitutions
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '"' : '\\"',
+ '\\': '\\\\'
+ },
+ rep;
+
+
+ function quote(string) {
+
+// If the string contains no control characters, no quote characters, and no
+// backslash characters, then we can safely slap some quotes around it.
+// Otherwise we must also replace the offending characters with safe escape
+// sequences.
+
+ escapable.lastIndex = 0;
+ return escapable.test(string) ?
+ '"' + string.replace(escapable, function (a) {
+ var c = meta[a];
+ return typeof c === 'string' ? c :
+ '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+ }) + '"' :
+ '"' + string + '"';
+ }
+
+
+ function str(key, holder) {
+
+// Produce a string from holder[key].
+
+ var i, // The loop counter.
+ k, // The member key.
+ v, // The member value.
+ length,
+ mind = gap,
+ partial,
+ value = holder[key];
+
+// If the value has a toJSON method, call it to obtain a replacement value.
+
+ if (value && typeof value === 'object' &&
+ typeof value.toJSON === 'function') {
+ value = value.toJSON(key);
+ }
+
+// If we were called with a replacer function, then call the replacer to
+// obtain a replacement value.
+
+ if (typeof rep === 'function') {
+ value = rep.call(holder, key, value);
+ }
+
+// What happens next depends on the value's type.
+
+ switch (typeof value) {
+ case 'string':
+ return quote(value);
+
+ case 'number':
+
+// JSON numbers must be finite. Encode non-finite numbers as null.
+
+ return isFinite(value) ? String(value) : 'null';
+
+ case 'boolean':
+ case 'null':
+
+// If the value is a boolean or null, convert it to a string. Note:
+// typeof null does not produce 'null'. The case is included here in
+// the remote chance that this gets fixed someday.
+
+ return String(value);
+
+// If the type is 'object', we might be dealing with an object or an array or
+// null.
+
+ case 'object':
+
+// Due to a specification blunder in ECMAScript, typeof null is 'object',
+// so watch out for that case.
+
+ if (!value) {
+ return 'null';
+ }
+
+// Make an array to hold the partial results of stringifying this object value.
+
+ gap += indent;
+ partial = [];
+
+// Is the value an array?
+
+ if (Object.prototype.toString.apply(value) === '[object Array]') {
+
+// The value is an array. Stringify every element. Use null as a placeholder
+// for non-JSON values.
+
+ length = value.length;
+ for (i = 0; i < length; i += 1) {
+ partial[i] = str(i, value) || 'null';
+ }
+
+// Join all of the elements together, separated with commas, and wrap them in
+// brackets.
+
+ v = partial.length === 0 ? '[]' :
+ gap ? '[\n' + gap +
+ partial.join(',\n' + gap) + '\n' +
+ mind + ']' :
+ '[' + partial.join(',') + ']';
+ gap = mind;
+ return v;
+ }
+
+// If the replacer is an array, use it to select the members to be stringified.
+
+ if (rep && typeof rep === 'object') {
+ length = rep.length;
+ for (i = 0; i < length; i += 1) {
+ k = rep[i];
+ if (typeof k === 'string') {
+ v = str(k, value);
+ if (v) {
+ partial.push(quote(k) + (gap ? ': ' : ':') + v);
+ }
+ }
+ }
+ } else {
+
+// Otherwise, iterate through all of the keys in the object.
+
+ for (k in value) {
+ if (Object.hasOwnProperty.call(value, k)) {
+ v = str(k, value);
+ if (v) {
+ partial.push(quote(k) + (gap ? ': ' : ':') + v);
+ }
+ }
+ }
+ }
+
+// Join all of the member texts together, separated with commas,
+// and wrap them in braces.
+
+ v = partial.length === 0 ? '{}' :
+ gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
+ mind + '}' : '{' + partial.join(',') + '}';
+ gap = mind;
+ return v;
+ }
+ }
+
+// If the JSON object does not yet have a stringify method, give it one.
+
+ if (typeof JSON.stringify !== 'function') {
+ JSON.stringify = function (value, replacer, space) {
+
+// The stringify method takes a value and an optional replacer, and an optional
+// space parameter, and returns a JSON text. The replacer can be a function
+// that can replace values, or an array of strings that will select the keys.
+// A default replacer method can be provided. Use of the space parameter can
+// produce text that is more easily readable.
+
+ var i;
+ gap = '';
+ indent = '';
+
+// If the space parameter is a number, make an indent string containing that
+// many spaces.
+
+ if (typeof space === 'number') {
+ for (i = 0; i < space; i += 1) {
+ indent += ' ';
+ }
+
+// If the space parameter is a string, it will be used as the indent string.
+
+ } else if (typeof space === 'string') {
+ indent = space;
+ }
+
+// If there is a replacer, it must be a function or an array.
+// Otherwise, throw an error.
+
+ rep = replacer;
+ if (replacer && typeof replacer !== 'function' &&
+ (typeof replacer !== 'object' ||
+ typeof replacer.length !== 'number')) {
+ throw new Error('JSON.stringify');
+ }
+
+// Make a fake root object containing our value under the key of ''.
+// Return the result of stringifying the value.
+
+ return str('', {'': value});
+ };
+ }
+
+
+// If the JSON object does not yet have a parse method, give it one.
+
+ if (typeof JSON.parse !== 'function') {
+ JSON.parse = function (text, reviver) {
+
+// The parse method takes a text and an optional reviver function, and returns
+// a JavaScript value if the text is a valid JSON text.
+
+ var j;
+
+ function walk(holder, key) {
+
+// The walk method is used to recursively walk the resulting structure so
+// that modifications can be made.
+
+ var k, v, value = holder[key];
+ if (value && typeof value === 'object') {
+ for (k in value) {
+ if (Object.hasOwnProperty.call(value, k)) {
+ v = walk(value, k);
+ if (v !== undefined) {
+ value[k] = v;
+ } else {
+ delete value[k];
+ }
+ }
+ }
+ }
+ return reviver.call(holder, key, value);
+ }
+
+
+// Parsing happens in four stages. In the first stage, we replace certain
+// Unicode characters with escape sequences. JavaScript handles many characters
+// incorrectly, either silently deleting them, or treating them as line endings.
+
+ cx.lastIndex = 0;
+ if (cx.test(text)) {
+ text = text.replace(cx, function (a) {
+ return '\\u' +
+ ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+ });
+ }
+
+// In the second stage, we run the text against regular expressions that look
+// for non-JSON patterns. We are especially concerned with '()' and 'new'
+// because they can cause invocation, and '=' because it can cause mutation.
+// But just to be safe, we want to reject all unexpected forms.
+
+// We split the second stage into 4 regexp operations in order to work around
+// crippling inefficiencies in IE's and Safari's regexp engines. First we
+// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
+// replace all simple value tokens with ']' characters. Third, we delete all
+// open brackets that follow a colon or comma or that begin the text. Finally,
+// we look to see that the remaining characters are only whitespace or ']' or
+// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
+
+ if (/^[\],:{}\s]*$/.
+test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
+replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
+replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
+
+// In the third stage we use the eval function to compile the text into a
+// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
+// in JavaScript: it can begin a block or an object literal. We wrap the text
+// in parens to eliminate the ambiguity.
+
+ j = eval('(' + text + ')');
+
+// In the optional fourth stage, we recursively walk the new structure, passing
+// each name/value pair to a reviver function for possible transformation.
+
+ return typeof reviver === 'function' ?
+ walk({'': j}, '') : j;
+ }
+
+// If the text is not JSON parseable, then a SyntaxError is thrown.
+
+ throw new SyntaxError('JSON.parse');
+ };
+ }
+})();
Propchange: incubator/jspwiki/trunk/tests/javascript/assets/json2.js
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/jspwiki/trunk/tests/javascript/jasmine-runner.html
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/tests/javascript/jasmine-runner.html?rev=819134&view=auto
==============================================================================
--- incubator/jspwiki/trunk/tests/javascript/jasmine-runner.html (added)
+++ incubator/jspwiki/trunk/tests/javascript/jasmine-runner.html Sat Sep 26 13:22:31 2009
@@ -0,0 +1,44 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+Â Â <title>Jasmine Javascript Test Runner for JSPWiki</title>
+Â Â <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+
+Â Â <script type="text/javascript" src="./assets/jasmine-0.9.0.js"></script>
+ <script type="text/javascript" src="./assets/TrivialReporter.js"></script>
+
+ <!-- <script type="text/javascript" src="../../src/WebContent/scripts/mootools.js"></script> -->
+ <script src="../../src/WebContent/scripts/mootools-core.js"></script>
+ <script type="text/javascript" src="../../src/WebContent/scripts/mootools-more.js"></script>
+
+ <script type="text/javascript" src="../../src/WebContent/scripts/jspwiki-common.js"></script>
+ <script type="text/javascript" src="../../src/WebContent/scripts/jspwiki-edit.js"></script>
+ <script type="text/javascript" src="../../src/WebContent/scripts/dialog.js"></script>
+ <script type="text/javascript" src="../../src/WebContent/scripts/documoo/documoo.js"></script>
+
+ <script type="text/javascript">
+ jasmine.include('./spec-jspwiki-common.js', true);
+ jasmine.include('./spec-jspwiki-edit.js', true);
+ jasmine.include('./spec-dialog.js', true);
+ //jasmine.include('./spec-documoo.js', true);
+ </script>
+
+ <link href="./assets/jasmine-jspwiki.css" rel="stylesheet"/>
+</head>
+<body>
+<h1>Jasmine Javascript Test Runner <span>for JSPWiki</span></h1>
+<script type="text/javascript">
+
+ var jasmineEnv = jasmine.getEnv();
+ var trivialReporter = new jasmine.TrivialReporter();
+ jasmineEnv.addReporter(trivialReporter);
+ jasmineEnv.specFilter = function(spec) {
+ return trivialReporter.specFilter(spec);
+ };
+ window.onload = function() {
+ jasmineEnv.execute();
+ };
+
+</script>
+</body>
+</html>
\ No newline at end of file
Added: incubator/jspwiki/trunk/tests/javascript/spec-dialog.js
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/tests/javascript/spec-dialog.js?rev=819134&view=auto
==============================================================================
--- incubator/jspwiki/trunk/tests/javascript/spec-dialog.js (added)
+++ incubator/jspwiki/trunk/tests/javascript/spec-dialog.js Sat Sep 26 13:22:31 2009
@@ -0,0 +1,211 @@
+/*
+Script: spec-dialog.js
+ Test following classes: SnipEditor, Textarea, UndoRedo
+
+License:
+ xxx
+
+*/
+
+describe('Dialog & descendent Class specs', function(){
+
+ var tst, dialog;
+
+ beforeEach( function() {
+ $$('body')[0].adopt( tst = new Element('p') );
+ tst.set('html',"empty");
+ dialog = null;
+ });
+ afterEach( function(){
+
+ dialog = null; //fixme: remove Elements created by dialogs
+ tst.dispose();
+ });
+
+ //BASE DIALOG CLASS : test TODO
+
+
+ //SELECTION DIALOG
+ it('should turn a string into a selection dialog', function() {
+
+ var dialog = new SelectionDialog({
+ body:"left|center|right",
+ caption:"select",
+ relativeTo:tst,
+ onSelect:function(value){ tst.set('html', value ); }
+ });
+
+ var els = dialog.body.getElements('li'), el = els[0];
+
+ expect(els.length).toEqual(3);
+ expect(el.get('text')).toEqual('left');
+ expect(el.get('title')).toEqual('left');
+
+ dialog.fireEvent('onSelect','newvalue');
+ expect(tst.get('text')).toEqual('newvalue');
+ });
+
+ it('should turn a array into a selection dialog', function() {
+ var dialog = new SelectionDialog({
+ body:['left','center'],
+ caption:"select",
+ relativeTo:tst,
+ onSelect:function(value){ tst.set('html', value ); }
+ });
+
+ var els = dialog.body.getElements('li'), el = els[0];
+
+ expect(els.length).toEqual(2);
+ expect(el.get('text')).toEqual('left');
+ expect(el.get('title')).toEqual('left');
+ });
+
+ it('should turn an object into a selection dialog', function() {
+ var dialog= new SelectionDialog({
+ body:{Left:"left",Center:"center",Right:"right"},
+ caption:"select",
+ relativeTo:tst,
+ onSelect:function(value){ tst.set('html', value ); }
+ });
+
+ var els = dialog.body.getElements('li'), el = els[2];
+
+ expect(els.length).toEqual(3);
+ expect(el.get('text')).toEqual('Right');
+ expect(el.get('title')).toEqual('right');
+ });
+
+ it('should hide the dialog when the autoClose flag is set', function(){
+
+ //the mockup Event object allows testing with keyboard and mouse events
+ Event.implement({
+ initialize: function(e){
+ //alert(JSON.encode(e));
+ for(var ee in e ){ this[ee] = e[ee]; }
+ //this.event=''; //used by snipeditor to check the event.which flag
+ return this;
+ },
+ stop: function(){ return this; }
+ });
+
+ var dialog= new SelectionDialog({
+ body:"left|center|right",
+ caption:"select",
+ relativeTo:tst,
+ showNow:false,
+ autoClose:true,
+ onSelect:function(value){ tst.set('html', value ); }
+ });
+
+ expect(dialog.element.getStyle('display')).toEqual('none');
+
+ dialog.toggle();
+ expect(dialog.element.getStyle('display')).toNotEqual('none');
+
+ var el = dialog.body.getElements('li')[1];
+ dialog.onSelect({ 'type':'mousedown', target:el });
+ expect(tst.get('text')).toEqual('center');
+
+ expect(dialog.element.getStyle('display')).toEqual('none');
+ });
+
+ it('should make centered selection dialog', function(){
+ //fixme : getCoordinates seems not to run under JSSpec properly
+ var dialog= new SelectionDialog({
+ body:"left|center|right",
+ caption:"select",
+ relativeTo:tst, //should remove this line
+ autoClose:true,
+ onSelect:function(value){ tst.set('html', value ); }
+ });
+
+ //todo validate position on the dialog
+ });
+
+
+ //FONT DIALOG
+ it('should generate a standard Font Dialog', function() {
+
+ var dialog= new FontDialog({
+ caption:"font",
+ relativeTo:tst,
+ onSelect:function(value){ tst.set('html', value ); }
+ });
+
+ var els = dialog.body.getElements('li'), el = els[1];
+
+ expect(els.length).toEqual(9);
+ expect(el.get('text')).toEqual('Comic Sans');
+ expect(el.get('title')).toEqual('comic sans ms');
+
+ //grnch -- funny browser 'dependency'
+ if( Browser.Engine.webkit ){
+ expect(el.getStyle('font-family')).toEqual("'comic sans ms'");
+ } else {
+ expect(el.getStyle('font-family')).toEqual("comic sans ms");
+ }
+ dialog.fireEvent('onSelect','newvalue');
+ expect(tst.get('text')).toEqual('newvalue');
+ });
+
+ it('should generate a redefined Font Dialog', function() {
+
+ var dialog= new FontDialog({
+ fonts:{'Font name1':'font1', 'Font name2':'font2'},
+ caption:"font",
+ relativeTo:tst,
+ onSelect:function(value){ tst.set('html', value ); }
+ });
+
+ var els = dialog.body.getElements('li'), el = els[1];
+
+ expect(els.length).toEqual(2);
+ expect(el.get('text')).toEqual('Font name2');
+ expect(el.get('title')).toEqual('font2');
+ expect(el.getStyle('font-family')).toEqual('font2');
+
+ });
+
+ //CHARS DIALOG
+ it('should generate a standard Chars Dialog', function() {
+
+ var dialog= new CharsDialog({
+ caption:"special chars",
+ relativeTo:tst,
+ onSelect:function(value){ tst.set('html', value ); }
+ });
+
+ var els = dialog.body.getElements("td"), el = els[11];
+
+ expect(els.length).toEqual(9*11);
+ //expect(el.get('text')).toEqual('°');
+ expect(el.get('title')).toEqual('°');
+
+ dialog.fireEvent('onSelect','newvalue');
+ expect(tst.get('text')).toEqual('newvalue');
+
+ });
+
+ //COLOR DIALOG
+
+ it('should generate a standard Color Dialog', function() {
+
+ var dialog= new ColorDialog({
+ relativeTo:tst,
+ onChange:function(value){ tst.set('html', value ); }
+ });
+
+ var img = dialog.body.getElements("img");
+
+ expect(img.length).toEqual(1);
+ expect(img[0].get('src')).toEqual('images/circle-256.png');
+ expect(dialog.color.get('text')).toEqual('#ffffff');
+ expect(dialog.cursor).toNotEqual( null );
+ expect(dialog.hsv).toEqual([0,0,100]);
+
+ dialog.fireEvent('onChange','newvalue');
+ expect(tst.get('text')).toEqual('newvalue');
+ });
+
+});
+
Added: incubator/jspwiki/trunk/tests/javascript/spec-documoo.js
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/tests/javascript/spec-documoo.js?rev=819134&view=auto
==============================================================================
--- incubator/jspwiki/trunk/tests/javascript/spec-documoo.js (added)
+++ incubator/jspwiki/trunk/tests/javascript/spec-documoo.js Sat Sep 26 13:22:31 2009
@@ -0,0 +1,201 @@
+/*
+Script: spec-documoo.js
+ Test following classes: Jsdocs
+
+License:
+ xxx
+
+*/
+
+describe('Documoo Class', function(){
+
+ var test, documoo;
+
+ beforeEach( function() {
+ $$('body')[0].adopt( test = new Element('div',{id:"TEST"}) );
+ test.set('html',"empty");
+
+ documoo = new Documoo();
+ });
+ afterEach( function(){
+ test.dispose();
+ });
+
+ it('should retain text without markup', function() {
+
+ var s = [
+ "/* Some text without markup. ",
+ " End of text.*/"
+ ].join('\n');
+
+ test.set('html', documoo.formatDoc( 'test', s ) );
+
+ expect( test.get('text') ).toEqual( " Some text without markup. \n End of text." );
+
+ });
+
+ it('should format bold, italic and monospace text', function() {
+
+ var s = [
+ "/* First a *bold* word or __two__ ",
+ " More ''italic'' words are here",
+ " And finally some {{monospaced}} text",
+ " End of text.*/"
+ ].join('\n');
+ test.set('html', documoo.formatDoc( 'test', s ) );
+
+ expect( $$("#TEST b").length ).toEqual( 2 );
+ expect( $$("#TEST i").length ).toEqual(1);
+ expect( $$("#TEST tt").length ).toEqual(1);
+ expect( $$("#TEST b")[1].get('text') ).toMatch(/two/);
+ expect( $$("#TEST i")[0].get('text') ).toMatch(/italic/);
+ expect( $$("#TEST tt")[0].get('text') ).toMatch(/monospaced/);
+
+ });
+
+ it('should allow to escape markup with a tilde', function() {
+
+ var s = [
+ "/* This is not a ~*bold~* word",
+ " End of text.*/"
+ ].join('\n');
+ test.set('html', documoo.formatDoc( 'test', s ) );
+
+ expect( $$("#TEST b").length ).toEqual( 0 );
+ expect( $$("#TEST")[0].get('text') ).toMatch(/ \*bold\* /);
+
+ });
+
+ it('should format headings and sub-headings', function() {
+
+ var s = [
+ "/* ",
+ "Class: testClass",
+ " Documentation text comes here",
+ "Arguments:",
+ " This is a subheading",
+ "*/"
+ ].join('\n');
+ test.set('html', documoo.formatDoc( 'test', s ) );
+
+ expect( $$("#TEST h1").length ).toEqual( 1 );
+ expect( $$("#TEST h2").length ).toEqual( 1 );
+ expect( $$("#TEST h1")[0].get('text') ).toEqual("Class : testClass");
+ expect( $$("#TEST h1")[0].get('id') ).toMatch(/testClass/);
+ expect( $$("#TEST h2")[0].get('text') ).toEqual("Arguments:");
+ expect( $$("#TEST h2")[0].get('id') ).toEqual(null);
+
+ });
+
+ it('should format hyperlinks', function() {
+
+ var s = [
+ "/* First line",
+ " contains a http:www.google.com link",
+ " and some [internal1] and <internal2> links",
+ " End of text.*/"
+ ].join('\n');
+ test.set('html', documoo.formatDoc( 'test', s ) );
+
+ expect( $$("#TEST a").length ).toEqual( 3 );
+ expect( $$("#TEST a")[0].get('text') ).toMatch(/http:www.google.com/);
+ expect( $$("#TEST a")[0].get('href') ).toMatch(/http:www.google.com/);
+ expect( $$("#TEST a")[1].get('text') ).toMatch(/internal1/);
+ expect( $$("#TEST a")[1].get('href') ).toMatch(/#internal1/);
+ expect( $$("#TEST a")[2].get('text') ).toMatch(/internal2/);
+
+ });
+
+ it('should format unordered lists', function() {
+
+ var s = [
+ "/* First line.",
+ " * some list",
+ " * some list",
+ " continues on next line",
+ " * some list",
+ " This text is not part of the list",
+ " Second line",
+ " - some other list",
+ " - some other list",
+ " End of text.*/"
+ ].join('\n');
+ test.set('html', documoo.formatDoc( 'test', s ) );
+
+ expect( $$("#TEST ul").length ).toEqual( 2 );
+ expect( $$("#TEST ul > li").length ).toEqual(5);
+ expect( $$("#TEST ul li").length ).toEqual(5);
+ expect( $$("#TEST ul li")[1].get('text') ).toMatch(/continues/);
+ expect( $$("#TEST ul li")[2].get('text') ).toNotMatch(/continues/);
+ expect( $$("#TEST ol").length ).toEqual(0);
+
+ });
+
+ it('should format ordered lists', function(){
+
+ var s = [
+ "/* First line.",
+ " # some list",
+ " # some list",
+ " continues on next line",
+ " End of Text",
+ "*/"
+ ].join('\n');
+ test.set('html', documoo.formatDoc( 'test', s ) );
+
+ expect( $$("#TEST ol").length ).toEqual( 1 );
+ expect( $$("#TEST ol li").length ).toEqual(2);
+ expect( $$("#TEST ol li")[1].get('text') ).toMatch(/continues/);
+ expect( $$("#TEST ul").length ).toEqual(0);
+
+ });
+
+ it('should format definition lists', function(){
+
+ var s = [
+ "/* First line.",
+ " fruit - Apples, oranges and lemons are fruits",
+ " ;vegetables: Tomatoes, carrots etc.",
+ " and indented text continues on next line",
+ " this is not - a definition list",
+ " End of text.*/"
+ ].join('\n');
+ test.set('html', documoo.formatDoc( 'test', s ) );
+
+ expect( $$("#TEST dl").length ).toEqual( 1 );
+ expect( $$("#TEST dl dd").length ).toEqual(2);
+ expect( $$("#TEST dl dt").length ).toEqual(2);
+ expect( $$("#TEST dl dt")[0].get('text') ).toMatch(/fruit/);
+ expect( $$("#TEST dl dd")[0].get('text') ).toNotMatch(/continues/);
+ expect( $$("#TEST dl dt")[1].get('text') ).toMatch(/vegetables/);
+ expect( $$("#TEST dl dd")[1].get('text') ).toMatch(/continues/);
+ expect( $$("#TEST dl dd")[1].get('text') ).toNotMatch(/End of/);
+
+ });
+
+ it('should preserve preformatted ordered lists', function(){
+ var pre = "This is *preformatted* stuff";
+ var s = [
+ "/* First line.",
+ " > "+pre,
+ " > "+pre,
+ " > "+pre,
+ "",
+ " {{{"+pre+"}}}",
+ "",
+ "(start code)",
+ pre,
+ "(end)",
+ " End of text. */"
+ ].join('\n');
+ test.set('html', documoo.formatDoc( 'test', s ) );
+
+ expect( $$("#TEST pre").length ).toEqual( 3 );
+ expect( $$("#TEST pre")[0].get('text') ).toEqual( pre+'\n'+pre+'\n'+pre );
+ expect( $$("#TEST pre")[1].get('text') ).toEqual( pre );
+ expect( $$("#TEST pre")[2].get('text') ).toEqual( pre );
+
+ });
+
+});
+
Added: incubator/jspwiki/trunk/tests/javascript/spec-jspwiki-common.js
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/tests/javascript/spec-jspwiki-common.js?rev=819134&view=auto
==============================================================================
--- incubator/jspwiki/trunk/tests/javascript/spec-jspwiki-common.js (added)
+++ incubator/jspwiki/trunk/tests/javascript/spec-jspwiki-common.js Sat Sep 26 13:22:31 2009
@@ -0,0 +1,863 @@
+/*
+Script: spec-jspwiki-common.js
+
+License:
+ http://www.apache.org/licenses/LICENSE-2.0
+*/
+
+describe('Basic Javascript specs', function(){
+
+ it('shoud convert to lower-case', function(){
+ expect('Hello'.toLowerCase()).toEqual('hello');
+ });
+ it('should concatenate two strings', function(){
+ expect("Hello " + "World").toEqual("Hello World");
+ });
+ it('should add two numbers', function(){
+ expect(1 + 2).toEqual(3);
+ });
+ it('should match array literals', function(){
+ expect([1,2,3]).toEqual([1,2,3]);
+ });
+ it('should difference of array literals', function(){
+ expect([1,2,3]).toNotEqual([4,5,6]);
+ });
+ it('should match date literals', function(){
+ expect(new Date(1979,03,27)).toEqual(new Date(1979,03,27));
+ });
+ it('should retrieve the DOM firstChild', function(){
+ expect(document.body.firstChild).toEqual(document.body.firstChild);
+ });
+});
+
+describe('Common mootools extensions', function(){
+
+ it('should convert camel-case into space separated sentences', function(){
+
+ expect('thisIsCamelCase'.deCamelize()).toEqual('this Is Camel Case');
+ expect('thisIsACamelCase'.deCamelize()).toEqual('this Is ACamel Case');
+
+ });
+
+ it('should truncate a string to a maximum size', function(){
+
+ expect('test'.trunc(6)).toEqual('test');
+ expect('test a longer string'.trunc(6)).toEqual('test a...');
+ expect('test a longer string'.trunc(6,"---")).toEqual('test a---');
+
+ });
+
+ it('should return the text value of a DOM element', function(){
+
+ var a = new Element('div');
+ a.innerHTML= "test string";
+
+ expect( $getText(a) ).toEqual('test string');
+
+ });
+
+ it('should return the last item in the array', function(){
+
+Â Â Â Â expect([].getLast()).toEqual(null);
+Â Â Â Â expect([3].getLast()).toEqual(3);
+ Â Â Â Â expect([1,2,3,0,0,6].getLast()).toEqual(6);
+
+ });
+Â
+ it('should put an wrapper around a set of DOM elements', function(){
+ var html = "<div>some text</div>Some plain text<span>more text</span><p>And more text</p>";
+ var div = new Element('div').set('html',html);
+ var wrap = new Element('p').wrapContent(div);
+
+ expect(wrap.innerHTML).toEqual(html);
+ expect(div.innerHTML).toEqual("<p>"+html+"</p>");
+
+ });
+
+ it('should return the visibility of an DOM element, depending on the visibility of one of its parents', function(){
+
+ var span = new Element('span').set('html','Inside text');
+ var div = new Element('div',{'styles':{'display':'none'}}).adopt(span);
+ expect(span.visible()).toEqual(false);
+
+ div.setStyle('display','block');
+ expect(span.visible()).toEqual(true);
+ });
+
+ it('should return the default value of any form element', function(){
+
+ var form = new Element('form').set('html',[
+ "<input name='input' type='checkbox' checked='checked'></input>",
+ "<select name='select'>",
+ "<option value='volvo'>Volvo</option>",
+ "<option value='saab' selected='true'>Saab</option>",
+ "</select>",
+ "<textarea name='textarea'>textarea-value</textarea>"
+ ].join(''));
+ expect( form.input.getDefaultValue() ).toBeFalsy();
+ expect( form.select.getDefaultValue() ).toEqual('saab');
+ expect( form.textarea.getDefaultValue() ).toEqual('textarea-value');
+
+ //now change the value of the form elements
+ form.input.checked = true;
+ form.select.selectedIndex = 0;
+ form.textarea.value = "new textarea-value";
+
+ expect( form.input.get('value') ).toEqual('on'); //strange return value FIXME
+ expect( form.select.get('value') ).toEqual('volvo');
+ expect( form.textarea.get('value') ).toEqual('new textarea-value');
+
+ //the default values remain unchanged
+ expect( form.input.getDefaultValue() ).toBeFalsy();
+ expect( form.select.getDefaultValue() ).toEqual('saab');
+ expect( form.textarea.getDefaultValue() ).toEqual('textarea-value');
+ });
+
+ it('should return a localized string', function(){
+
+ LocalizedStrings = {
+ 'javascript.moreInfo' : 'More',
+ 'javascript.imageInfo' : 'Image {0} of {1}'
+ };
+
+ expect( "moreInfo".localize() ).toEqual('More');
+ expect( "imageInfo".localize(2) ).toEqual('Image 2 of ???1???');
+ expect( "imageInfo".localize(2,4) ).toEqual('Image 2 of 4');
+ expect( "imageInfo".localize(2,4,6) ).toEqual('Image 2 of 4');
+ expect( "funny string".localize() ).toEqual('???funny string???');
+ });
+
+});
+
+
+
+
+describe('Main WIKI class',function(){
+
+ it('should convert a pagename into a wiki url', function(){
+
+ Wiki.PageUrl = '/JSPWiki-pipo/Wiki.jsp?page=%23%24%25';
+
+ expect(Wiki.toUrl('test')).toEqual('/JSPWiki-pipo/Wiki.jsp?page=test');
+ });
+
+ it('should convert a wiki url into a pagename', function(){
+
+ Wiki.PageUrl = '/JSPWiki-pipo/Wiki.jsp?page=%23%24%25';
+
+ expect(Wiki.toPageName('/JSPWiki-pipo/Wiki.jsp?page=test')).toEqual('test');
+ expect(Wiki.toPageName('test')).toBeFalsy();
+ });
+
+ it('should remove funny chars to make a valid wiki pagename', function(){
+
+ expect(Wiki.cleanPageName(' ab cd ')).toEqual('ab cd');
+ expect(Wiki.cleanPageName('a1b2c3()&+,-=._$d4e5f6')).toEqual('a1b2c3()&+,-=._$d4e5f6');
+ expect(Wiki.cleanPageName('ab%@!\\?cd')).toEqual('abcd');
+ });
+
+});
+
+
+describe('WikiSlimbox class',function(){
+});
+
+describe('TabbedSection class',function(){
+});
+
+describe('Searchbox class',function(){
+});
+
+describe('Color class',function(){
+
+ it('hex constructor - should have the correct rgb', function(){
+ var myColor = new Color('#a2c240');
+ var myColor2 = new Color([162, 194, 64]);
+
+ //expect(myColor).toEqual([162, 194, 64]);
+ expect(myColor).toEqual(myColor2);
+ });
+
+ it('hex constructor - should have the correct hex', function(){
+ var myColor = new Color('#a2c240');
+ expect(myColor.hex).toEqual('#a2c240');
+
+ myColor = new Color('#666'); //short notation
+ expect(myColor.hex).toEqual('#666666');
+ });
+
+ it('rgb constructor - should have the correct rgb', function(){
+ var myColor = new Color([162, 194, 64],'rgb');
+ var myColor2 = new Color([162, 194, 64]);
+
+ expect(myColor).toEqual(myColor2);
+ });
+
+ it('rgb constructor - should have the correct hex', function(){
+ myColor = new Color([162, 194, 64],'rgb');
+ expect(myColor.hex).toEqual('#a2c240');
+
+ myColor = new Color([162, 194, 64]);
+ expect(myColor.hex).toEqual('#a2c240');
+ });
+
+ it('html-name constructor - should have the correct hex', function(){
+ var myColor = new Color('lime');
+
+ expect(myColor.hex).toEqual('#00ff00');
+ expect(myColor).toEqual(new Color([0, 255, 0]));
+ });
+
+ it('should mix two colors', function(){
+ var myColor = new Color('#000').mix('#fff', [255, 0, 255], 10);
+ expect(myColor.hex).toEqual('#311731');
+ });
+
+ it('should invert a color', function(){
+ var white = new Color('white');
+ var black = new Color('black');
+
+ expect(white.invert().hex).toEqual( black.hex );
+ });
+});
+
+
+describe('GraphBar class',function(){
+
+ var graph;
+
+ //helperfunction to build graphbars.
+ var buildTable = function(clazzname, markup){
+
+ var html = markup.map(function(row){
+ row = row.replace( /\|.[^|]*/g, function(match){
+ return (match.charAt(1)=='|') ? '<th>'+match.slice(2)+'</th>' : '<td>'+match.slice(1)+'</td>';
+ });
+ return '<tr>'+row+'</tr>';
+ });
+
+ graph.empty().removeClass('graphBars').addClass(clazzname)
+ .adopt( new Element('table',{'html':html}) );
+
+ new GraphBar(graph);
+ };
+
+ beforeEach( function(){
+
+ document.body.adopt( graph = new Element('div',{'class':'graphBars'}) );
+
+ });
+
+ afterEach( function(){
+
+ graph.dispose();
+
+ });
+
+ it('should generate inline horizontal bars',function(){
+// %%graphBars
+// * This is the 1st bar: %%gBar 100 /%
+// * This is the 2nd bar: %%gBar 120 /%
+// * This is the 3rd bar: %%gBar 140 /%
+// /%
+ graph.empty().adopt(
+ new Element('ul').adopt(
+ new Element('li',{html:"This is the 1st bar: <span class='gBar'>100</span>"}),
+ new Element('li',{html:"This is the 2nd bar: <span class='gBar'>120</span>"}),
+ new Element('li',{html:"This is the 3rd bar: <span class='gBar'>140</span>"})
+ )
+ );
+ //run render graphbar :
+ new GraphBar(graph);
+
+ expect( $$('span.graphBar').length).toEqual(3);
+ expect( $$('span.graphBar')[0].getStyle("border-left-width") ).toEqual("20px");
+ expect( $$('span.graphBar')[1].getStyle("border-left-width") ).toEqual("170px");
+ expect( $$('span.graphBar')[2].getStyle("border-left-width") ).toEqual("320px");
+
+ });
+
+ it('should parse data in tables, with %%gBar',function(){
+// %%graphBars
+// | apples | 20 kg
+// | pears | 40 kg
+// | bananas | 60 kg
+// /%
+ buildTable("graphBars", [
+ "| apples | <span class='gBar'>20 kg</span> ",
+ "| pears | <span class='gBar'>40 kg</span> ",
+ "| bananas | <span class='gBar'>60 kg</span> "]);
+
+ expect( $$('span.graphBar').length ).toEqual(3);
+ expect( $$('span.graphBar')[0].getStyle("border-left-width") ).toEqual("20px");
+ expect( $$('span.graphBar')[1].getStyle("border-left-width") ).toEqual("170px");
+ expect( $$('span.graphBar')[2].getStyle("border-left-width") ).toEqual("320px");
+
+ });
+
+ it('should parse column data in tables, with names',function(){
+// %%graphBarsWeight
+// || Name ||Weight
+// | apples | 20 kg
+// | pears | 40 kg
+// | bananas | 60 kg
+// /%
+ buildTable('graphBarsWeight', [
+ "|| Name || Weight ",
+ "| apples | 20 kg ",
+ "| pears | 40 kg ",
+ "| bananas | 60 kg "]);
+
+ expect( $$('span.graphBar').length ).toEqual(3);
+ expect( $$('span.graphBar')[0].getStyle("border-left-width") ).toEqual("20px");
+ expect( $$('span.graphBar')[1].getStyle("border-left-width") ).toEqual("170px");
+ expect( $$('span.graphBar')[2].getStyle("border-left-width") ).toEqual("320px");
+
+ });
+
+ it('should parse row data in tables, with names',function(){
+// %%graphBarsWeight
+// ||Name | apples | pears | bananas
+// ||Weight | 20 kg | 40 kg | 60
+// /%
+ buildTable('graphBarsWeight', [
+ "||Name | apples | pears | bananas",
+ "||Weight | 20 kg | 40 kg | 60 "
+ ]);
+
+ expect( $$('span.graphBar').length ).toEqual(3);
+ expect( $$('span.graphBar')[0].getStyle("border-left-width") ).toEqual("20px");
+ expect( $$('span.graphBar')[1].getStyle("border-left-width") ).toEqual("170px");
+ expect( $$('span.graphBar')[2].getStyle("border-left-width") ).toEqual("320px");
+
+
+ });
+
+ it('should do vertical bars',function(){
+// %%graphBars-vertical
+// | apples | %%gBar 20 kg /%
+// | pears | %%gBar 40 kg /%
+// | bananas | %%gBar 60 kg /%
+// /%
+
+ buildTable('graphBars-vertical', [
+ "| apples | <span class='gBar'>20 kg</span> ",
+ "| pears | <span class='gBar'>40 kg</span> ",
+ "| bananas | <span class='gBar'>60 kg</span> " ]);
+
+ expect( $$('span.graphBar').length ).toEqual(3);
+ expect( $$('span.graphBar')[0].getStyle("border-bottom-width") ).toEqual("20px");
+ expect( $$('span.graphBar')[0].getStyle("position") ).toEqual("absolute");
+ expect( $$('span.graphBar')[0].getStyle("width") ).toEqual("20px");
+ expect( $$('span.graphBar')[0].getStyle("bottom") ).toEqual("0px");
+ expect( $$('span.graphBar')[0].getParent().getStyle("position") ).toEqual("relative");
+ expect( $$('span.graphBar')[0].getNext().getStyle("position") ).toEqual("relative");
+ expect( $$('span.graphBar')[0].getNext().getStyle("top") ).toEqual("300px");
+
+
+ expect( $$('span.graphBar')[1].getStyle("border-bottom-width") ).toEqual("170px");
+ expect( $$('span.graphBar')[1].getStyle("position") ).toEqual("absolute");
+ expect( $$('span.graphBar')[1].getStyle("width") ).toEqual("20px");
+ expect( $$('span.graphBar')[1].getStyle("bottom") ).toEqual("0px");
+ expect( $$('span.graphBar')[1].getParent().getStyle("position") ).toEqual("relative");
+ expect( $$('span.graphBar')[1].getNext().getStyle("position") ).toEqual("relative");
+ expect( $$('span.graphBar')[1].getNext().getStyle("top") ).toEqual("150px");
+
+ expect( $$('span.graphBar')[2].getStyle("border-bottom-width") ).toEqual("320px");
+ expect( $$('span.graphBar')[2].getStyle("position") ).toEqual("absolute");
+ expect( $$('span.graphBar')[2].getStyle("width") ).toEqual("20px");
+ expect( $$('span.graphBar')[2].getStyle("bottom") ).toEqual("0px");
+ expect( $$('span.graphBar')[2].getParent().getStyle("position") ).toEqual("relative");
+ expect( $$('span.graphBar')[2].getNext().getStyle("position") ).toEqual("relative");
+ expect( $$('span.graphBar')[2].getNext().getStyle("top") ).toEqual("0px");
+
+ });
+
+ it('should generate date&time graph-bars',function(){
+// %%graphBars
+// || Name ||Weight
+// | apples | %%gBar 1 Jan 2006 /%
+// | pears | %%gBar 15 Feb 2006 /%
+// | bananas | %%gBar 1 Apr 2006 /%
+// /%
+ buildTable("graphBars", [
+ "| apples | <span class='gBar'>1 Jan 2006 </span> ",
+ "| pears | <span class='gBar'>20 Feb 2006</span> ",
+ "| bananas | <span class='gBar'>1 Apr 2006 </span> "]);
+
+ expect( $$('span.graphBar').length ).toEqual(3);
+ expect( $$('span.graphBar')[0].getStyle("border-left-width") ).toEqual("20px");
+ expect( $$('span.graphBar')[1].getStyle("border-left-width") ).toEqual("186px");
+ expect( $$('span.graphBar')[2].getStyle("border-left-width") ).toEqual("320px");
+
+ });
+
+ it('should accept single color input',function(){
+// %%graphBars-fuchsia
+// | apples | %%gBar 20 kg /%
+// | pears | %%gBar 40 kg /%
+// | bananas | %%gBar 60 kg /%
+// /%
+ buildTable("graphBars-fuchsia", [
+ "| apples | <span class='gBar'>20 kg</span> ",
+ "| pears | <span class='gBar'>40 kg</span> ",
+ "| bananas | <span class='gBar'>60 kg</span> "]);
+
+ expect( $$('span.graphBar').length ).toEqual(3);
+ expect( $$('span.graphBar')[0].getStyle("border-left-width") ).toEqual("20px");
+ expect( $$('span.graphBar')[0].getStyle("border-left-color") ).toEqual("#ff00ff");
+ expect( $$('span.graphBar')[1].getStyle("border-left-width") ).toEqual("170px");
+ expect( $$('span.graphBar')[1].getStyle("border-left-color") ).toEqual("#ff00ff");
+ expect( $$('span.graphBar')[2].getStyle("border-left-width") ).toEqual("320px");
+ expect( $$('span.graphBar')[2].getStyle("border-left-color") ).toEqual("#ff00ff");
+
+ });
+
+ it('should accept double color input to generate gradient colors for all bars',function(){
+// %%graphBars-ffff00-669900
+// | apples | %%gBar 20 kg /%
+// | pears | %%gBar 40 kg /%
+// | bananas | %%gBar 60 kg /%
+// /%
+ buildTable("graphBars-ffff00-669900", [
+ "| apples | <span class='gBar'>20 kg</span> ",
+ "| pears | <span class='gBar'>40 kg</span> ",
+ "| bananas | <span class='gBar'>60 kg</span> "]);
+
+ expect( $$('span.graphBar').length ).toEqual(3);
+ expect( $$('span.graphBar')[0].getStyle("border-left-width") ).toEqual("20px");
+ expect( $$('span.graphBar')[0].getStyle("border-left-color") ).toEqual("#ffff00");
+ expect( $$('span.graphBar')[1].getStyle("border-left-width") ).toEqual("170px");
+ expect( $$('span.graphBar')[1].getStyle("border-left-color") ).toEqual("#b3cc00");
+ expect( $$('span.graphBar')[2].getStyle("border-left-width") ).toEqual("320px");
+ expect( $$('span.graphBar')[2].getStyle("border-left-color") ).toEqual("#669900");
+
+ });
+
+ it('should invert color if progress bars specify only one color',function(){
+// %%graphBars-00ffff-progress
+// | apples | %%gBar 20 kg /%
+// | pears | %%gBar 40 kg /%
+// | bananas | %%gBar 60 kg /%
+// /%
+ buildTable("graphBars-red-progress", [
+ "| apples | <span class='gBar'>20 kg</span> ",
+ "| pears | <span class='gBar'>40 kg</span> ",
+ "| bananas | <span class='gBar'>60 kg</span> "]);
+
+ expect( $$('span.graphBar').length ).toEqual(6);
+ expect( $$('span.graphBar')[0].getStyle("border-left-width") ).toEqual("20px");
+ expect( $$('span.graphBar')[0].getStyle("border-left-color") ).toEqual("#00ffff");
+ expect( $$('span.graphBar')[1].getStyle("border-left-width") ).toEqual("300px");
+ expect( $$('span.graphBar')[1].getStyle("border-left-color") ).toEqual("#ff0000");
+ expect( $$('span.graphBar')[1].getStyle("margin-left") ).toEqual("-1ex");
+
+ expect( $$('span.graphBar')[2].getStyle("border-left-width") ).toEqual("170px");
+ expect( $$('span.graphBar')[2].getStyle("border-left-color") ).toEqual("#00ffff");
+ expect( $$('span.graphBar')[3].getStyle("border-left-width") ).toEqual("150px");
+ expect( $$('span.graphBar')[3].getStyle("border-left-color") ).toEqual("#ff0000");
+ expect( $$('span.graphBar')[3].getStyle("margin-left") ).toEqual("-1ex");
+
+ expect( $$('span.graphBar')[4].getStyle("border-left-width") ).toEqual("320px");
+ expect( $$('span.graphBar')[4].getStyle("border-left-color") ).toEqual("#00ffff");
+ expect( $$('span.graphBar')[5].getStyle("border-left-width") ).toEqual("0px");
+ expect( $$('span.graphBar')[5].getStyle("border-left-color") ).toEqual("#ff0000");
+ expect( $$('span.graphBar')[5].getStyle("margin-left") ).toEqual("-1ex");
+
+ });
+
+ it('should accept min and max bar size',function(){
+// %%graphBars-min48-max256
+// | apples | %%gBar 20 kg /%
+// | pears | %%gBar 40 kg /%
+// | bananas | %%gBar 60 kg /%
+// /%
+ buildTable("graphBars-min48-max256", [
+ "| apples | <span class='gBar'>20 kg</span> ",
+ "| pears | <span class='gBar'>40 kg</span> ",
+ "| bananas | <span class='gBar'>60 kg</span> "]);
+
+ expect( $$('span.graphBar').length ).toEqual(3);
+ expect( $$('span.graphBar')[0].getStyle("border-left-width") ).toEqual("48px");
+ expect( $$('span.graphBar')[1].getStyle("border-left-width") ).toEqual("152px");
+ expect( $$('span.graphBar')[2].getStyle("border-left-width") ).toEqual("256px");
+
+ });
+
+ it('should do progress bars, with 2 complementary bars reaching 100%',function(){
+// %%graphBars-fff00-669900-progress
+// || Name ||Weight
+// | apples | %%gBar 20 kg /%
+// | pears | %%gBar 40 kg /%
+// | bananas | %%gBar 60 kg /%
+// /%
+ buildTable("graphBars-ffff00-669900-progress", [
+ "| apples | <span class='gBar'>20 kg</span> ",
+ "| pears | <span class='gBar'>40 kg</span> ",
+ "| bananas | <span class='gBar'>60 kg</span> "]);
+
+ expect( $$('span.graphBar').length ).toEqual(6);
+ expect( $$('span.graphBar')[0].getStyle("border-left-width") ).toEqual("20px");
+ expect( $$('span.graphBar')[0].getStyle("border-left-color") ).toEqual("#669900");
+ expect( $$('span.graphBar')[1].getStyle("border-left-width") ).toEqual("300px");
+ expect( $$('span.graphBar')[1].getStyle("border-left-color") ).toEqual("#ffff00");
+ expect( $$('span.graphBar')[1].getStyle("margin-left") ).toEqual("-1ex");
+
+ expect( $$('span.graphBar')[2].getStyle("border-left-width") ).toEqual("170px");
+ expect( $$('span.graphBar')[2].getStyle("border-left-color") ).toEqual("#669900");
+ expect( $$('span.graphBar')[3].getStyle("border-left-width") ).toEqual("150px");
+ expect( $$('span.graphBar')[3].getStyle("border-left-color") ).toEqual("#ffff00");
+ expect( $$('span.graphBar')[3].getStyle("margin-left") ).toEqual("-1ex");
+
+ expect( $$('span.graphBar')[4].getStyle("border-left-width") ).toEqual("320px");
+ expect( $$('span.graphBar')[4].getStyle("border-left-color") ).toEqual("#669900");
+ expect( $$('span.graphBar')[5].getStyle("border-left-width") ).toEqual("0px");
+ expect( $$('span.graphBar')[5].getStyle("border-left-color") ).toEqual("#ffff00");
+ expect( $$('span.graphBar')[5].getStyle("margin-left") ).toEqual("-1ex");
+
+ });
+
+ it('should do gauge bars, with colors relative to the values',function(){
+// %%graphBars-fff00-669900-gauge
+// || Name ||Weight
+// | apples | %%gBar 20 kg /%
+// | pears | %%gBar 50 kg /%
+// | bananas | %%gBar 60 kg /%
+// /%
+ buildTable("graphBars-ffff00-669900-gauge", [
+ "| apples | <span class='gBar'>20 kg</span> ",
+ "| pears | <span class='gBar'>50 kg</span> ",
+ "| bananas | <span class='gBar'>60 kg</span> "]);
+
+ expect( $$('span.graphBar').length ).toEqual(3);
+ expect( $$('span.graphBar')[0].getStyle("border-left-width") ).toEqual("20px");
+ expect( $$('span.graphBar')[0].getStyle("border-left-color") ).toEqual("#ffff00");
+ expect( $$('span.graphBar')[1].getStyle("border-left-width") ).toEqual("245px");
+ expect( $$('span.graphBar')[1].getStyle("border-left-color") ).toEqual("#8cb300");
+ expect( $$('span.graphBar')[2].getStyle("border-left-width") ).toEqual("320px");
+ expect( $$('span.graphBar')[2].getStyle("border-left-color") ).toEqual("#669900");
+
+ });
+
+});
+
+describe('Collapsible class',function(){
+});
+
+describe('TableAdds class',function(){
+
+ var myTable,row,getcol,s;
+
+ beforeEach( function(){
+ document.body.adopt( myTable = new Element('table') );
+
+ //rowbuilder help function
+ row = function(r){
+ return ("<tr><td>"+r.split('|').join('</td><td>')+"</td></tr>");
+ };
+ //return column as js-array of values
+ getcol = function(column){
+ var result = [];
+ $A( myTable.rows ).each( function(r,i){
+ if( (i>0) && (r.style.display != 'none')) result.push( $(r.cells[column]).get('text').trim() );
+ });
+ return result;
+ };
+
+ var s = '';
+ s+= row('Title | Author | Published | Edition | Some IP@ | Expenses | Disk Memory|Float').replace(/td>/g,"th>");
+ s+= row('book1 | zappy | 25 Feb 2005 | 5 | 100.100.100.100 | â¬500 | 2Gb |0.01');
+ s+= row('book2 | happy | 25 Jan 2005 | 19 | 256.100.100.100 | â¬1500 | 4Kb |10e5');
+ s+= row('book3 | pappy | 23 Mar 2005 | 06 | 10.100.100.100 | â¬50 | 1.23TB |-1e3');
+ s+= row('book4 | dappy | 21 Apr 2005 | 199 | 1.100.100.100 | â¬0.500 | 2.73kb |0.443e-12');
+ s+= row('book5 | pappy | 25 Jul 2005 | 017 | 1.100.25.100 | â¬5500 | 0.4Tb |0.1e-99');
+
+ myTable.set('html',s);
+ });
+
+ afterEach( function(){
+ myTable.dispose();
+ });
+
+ it('should add default color zebra stripes to a table', function(){
+ new TableAdds(myTable, {zebra:['table']});
+
+ var rows = myTable.rows;
+ expect( rows[1].hasClass('odd') ).toBeFalsy();
+ expect( rows[2].hasClass('odd') ).toBeTruthy();
+ expect( rows[3].hasClass('odd') ).toBeFalsy();
+
+ });
+ it('should add one color zebra stripes to a table', function(){
+ new TableAdds(myTable, {zebra:['#fffff']});
+
+ var rows = myTable.rows;
+ expect( rows[1].getStyle('background-color') ).toEqual('transparent');
+ expect( rows[2].getStyle('background-color') ).toEqual('#ffffff');
+ expect( rows[3].getStyle('background-color') ).toEqual('transparent');
+
+ });
+
+ it('should add 2 color zebra stripes to a table', function(){
+ new TableAdds(myTable, {zebra:['#fffff','lime']});
+
+ var rows = myTable.rows;
+ expect( rows[1].getStyle('background-color') ).toEqual('#00ff00');
+ expect( rows[2].getStyle('background-color') ).toEqual('#ffffff');
+ expect( rows[3].getStyle('background-color') ).toEqual('#00ff00');
+
+ });
+
+ it('should sort integer numbers', function(){
+
+ var tt = new TableAdds(myTable, {sort:true});
+ var column = 3, data=[];
+
+ data = getcol(column);
+ expect(data).toEqual( ['5', '19', '06', '199', '017'] );
+
+ tt.sort(column); //ascending
+ data = getcol(column);
+ expect(data).toEqual( ['5', '06', '017', '19', '199'] );
+
+ tt.sort(column); //descending
+ data = getcol(column);
+ expect(data).toEqual( ['199', '19', '017', '06', '5' ] );
+
+ });
+
+ it('should sort dates', function(){
+
+ var tt = new TableAdds(myTable, {sort:true});
+ var column = 2, data=[];
+
+ data = getcol(column);
+ expect(data).toEqual( ['25 Feb 2005', '25 Jan 2005', '23 Mar 2005', '21 Apr 2005', '25 Jul 2005'] );
+
+ tt.sort(column); //ascending
+ data = getcol(column);
+ expect(data).toEqual( ['25 Jan 2005', '25 Feb 2005', '23 Mar 2005', '21 Apr 2005', '25 Jul 2005'] );
+
+ tt.sort(column); //descending
+ data = getcol(column);
+ expect(data).toEqual( ['25 Jul 2005', '21 Apr 2005', '23 Mar 2005', '25 Feb 2005', '25 Jan 2005'] );
+
+ });
+ it('should sort currency', function(){
+
+ var tt = new TableAdds(myTable, {sort:true});
+ var column = 5, data=[];
+
+ data = getcol(column);
+ expect(data).toEqual( ['â¬500', 'â¬1500', 'â¬50', 'â¬0.500', 'â¬5500'] );
+
+ tt.sort(column); //ascending
+ data = getcol(column);
+ expect(data).toEqual( ['â¬0.500', 'â¬50', 'â¬500', 'â¬1500', 'â¬5500'] );
+
+ tt.sort(column); //descending
+ data = getcol(column);
+ expect(data).toEqual( ['â¬5500', 'â¬1500', 'â¬500', 'â¬50', 'â¬0.500'] );
+
+ });
+ it('should sort ip@', function(){
+
+ var tt = new TableAdds(myTable, {sort:true});
+ var column = 4, data=[];
+
+ data = getcol(column);
+ expect(data).toEqual( ['100.100.100.100', '256.100.100.100', '10.100.100.100', '1.100.100.100', '1.100.25.100'] );
+
+ tt.sort(column); //ascending
+ data = getcol(column);
+ expect(data).toEqual( ['1.100.25.100', '1.100.100.100', '10.100.100.100', '100.100.100.100', '256.100.100.100'] );
+
+ tt.sort(column); //descending
+ data = getcol(column);
+ expect(data).toEqual( ['256.100.100.100', '100.100.100.100', '10.100.100.100', '1.100.100.100', '1.100.25.100'] );
+
+ });
+ it('should sort Tb, Gb, Mb, Kb memory values', function(){
+
+ var tt = new TableAdds(myTable, {sort:true});
+ var column = 6, data=[];
+
+ data = getcol(column);
+ expect(data).toEqual( ['2Gb', '4Kb', '1.23TB', '2.73kb', '0.4Tb'] );
+
+ tt.sort(column); //ascending
+ data = getcol(column);
+ expect(data).toEqual( ['2.73kb', '4Kb', '2Gb', '0.4Tb', '1.23TB'] );
+
+ tt.sort(column); //descending
+ data = getcol(column);
+ expect(data).toEqual( ['1.23TB', '0.4Tb', '2Gb', '4Kb', '2.73kb'] );
+
+ });
+
+ it('should sort floats', function(){
+
+ var tt = new TableAdds(myTable, {sort:true});
+ var column = 7, data=[];
+
+ data = getcol(column);
+ expect(data).toEqual( ['0.01', '10e5', '-1e3', '0.443e-12', '0.1e-99'] );
+
+ tt.sort(column); //ascending
+ data = getcol(column);
+ expect(data).toEqual( ['-1e3', '0.1e-99', '0.443e-12', '0.01', '10e5'] );
+
+ tt.sort(column); //descending
+ data = getcol(column);
+ expect(data).toEqual( ['10e5', '0.01', '0.443e-12', '0.1e-99', '-1e3' ] );
+
+ });
+
+ it('should sort strings', function(){
+
+ var tt = new TableAdds(myTable, {sort:true});
+ var column = 1, data=[];
+
+ data = getcol(column);
+ expect(data).toEqual( ['zappy', 'happy', 'pappy', 'dappy', 'pappy'] );
+
+ tt.sort(column); //ascending
+ data = getcol(column);
+ expect(data).toEqual( ['dappy', 'happy', 'pappy', 'pappy', 'zappy'] );
+
+ tt.sort(column); //descending
+ data = getcol(column);
+ expect(data).toEqual( ['zappy', 'pappy', 'pappy', 'happy', 'dappy'] );
+
+ });
+
+ it('should sort with "sortvalue" attributes', function(){
+
+ var tt = new TableAdds(myTable, {sort:true});
+ var column = 3, data=[];
+ var rows = myTable.rows;
+ rows[1].cells[column].setAttribute('jspwiki:sortvalue',0);
+ rows[2].cells[column].setAttribute('jspwiki:sortvalue',1);
+ rows[3].cells[column].setAttribute('jspwiki:sortvalue',2);
+ rows[4].cells[column].setAttribute('jspwiki:sortvalue',3);
+ rows[5].cells[column].setAttribute('jspwiki:sortvalue',4);
+
+
+ data = getcol(column);
+ expect(data).toEqual( ['5', '19', '06', '199', '017'] );
+
+ tt.sort(column); //ascending
+ data = getcol(column);
+ expect(data).toNotEqual( ['5', '06', '017', '19', '199'] );
+ expect(data).toEqual( ['5', '19', '06', '199', '017'] );
+
+ tt.sort(column); //descending
+ data = getcol(column);
+ expect(data).toNotEqual( ['199', '19', '017', '06', '5' ] );
+ expect(data).toEqual( ['017', '199', '06', '19', '5'] );
+
+ });
+
+ it('should filter a columns', function(){
+
+ var tt = new TableAdds(myTable, {filter:true});
+ var column = 3, data=[];
+
+ data = getcol(column);
+ expect(data).toEqual( ['5', '19', '06', '199', '017'] );
+
+ tt.filter(column, 6);
+ data = getcol(column);
+ expect(data).toEqual( ['06'] );
+
+
+ });
+
+ it('should filter a columns with more then 1 unique element', function(){
+
+ var tt = new TableAdds(myTable, {filter:true});
+ var tt = new TableAdds(myTable, {sort:true});
+ var column = 1, data=[];
+
+
+ data = getcol(column);
+ expect(data).toEqual( ['zappy', 'happy', 'pappy', 'dappy', 'pappy'] );
+
+ tt.filter(column, 'pappy');
+ data = getcol(column);
+ expect(data).toEqual( ['pappy','pappy'] );
+
+ data = getcol(0);
+ expect(data).toEqual( ['book3','book5'] );
+ });
+
+ it('should combine sorting and filtering to a table', function(){
+
+ var t1 = new TableAdds(myTable, {filter:true});
+
+ expect(t1.filters).toNotEqual(undefined);
+ expect(t1.sorted).toEqual(undefined);
+
+ var t2 = new TableAdds(myTable, {sort:true});
+ expect(t1).toEqual( t2 );
+ expect(t1.filters).toNotEqual(undefined);
+ expect(t1.sorted).toBeTruthy();
+
+ var column = 1, data=[];
+ data = getcol(column);
+ expect(data).toEqual( ['zappy', 'happy', 'pappy', 'dappy', 'pappy'] );
+
+ t1.sort(column);
+ t1.sort(column);
+ data = getcol(column);
+ expect(data).toEqual( ['zappy', 'pappy', 'pappy', 'happy', 'dappy'] );
+
+ t1.filter(column, 'pappy');
+ data = getcol(column);
+ expect(data).toEqual( ['pappy','pappy'] );
+
+ data = getcol(0);
+ expect(data).toEqual( ['book5','book3'] );
+
+
+ });
+
+ it('should combine sorting, filtering and zebra-stripes to a table', function(){
+
+ var t1 = new TableAdds(myTable, {filter:true, sort:true, zebra:['red'] });
+
+ expect(t1.filters).toNotEqual(undefined);
+ expect(t1.sorted).toBeTruthy();
+ expect(t1.zebra).toNotEqual(undefined);
+
+ var column = 1, data=[];
+ data = getcol(column);
+ expect(data).toEqual( ['zappy', 'happy', 'pappy', 'dappy', 'pappy'] );
+
+ t1.sort(column);
+ t1.sort(column);
+ data = getcol(column);
+ expect(data).toEqual( ['zappy', 'pappy', 'pappy', 'happy', 'dappy'] );
+
+ t1.filter(column, 'pappy');
+ data = getcol(column);
+ expect(data).toEqual( ['pappy','pappy'] );
+ data = getcol(0);
+ expect(data).toEqual( ['book5','book3'] );
+
+ var rows = myTable.rows;
+ expect( rows[0].getStyle('background-color') ).toEqual('transparent');
+ expect( rows[2].getStyle('background-color') ).toEqual('transparent');
+ expect( rows[3].getStyle('background-color') ).toEqual('#ff0000');
+
+ });
+
+});
+
+describe('Categories class',function(){
+});
+
+describe('HighlightWord class',function(){
+});
+
+
Added: incubator/jspwiki/trunk/tests/javascript/spec-jspwiki-edit.js
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/tests/javascript/spec-jspwiki-edit.js?rev=819134&view=auto
==============================================================================
--- incubator/jspwiki/trunk/tests/javascript/spec-jspwiki-edit.js (added)
+++ incubator/jspwiki/trunk/tests/javascript/spec-jspwiki-edit.js Sat Sep 26 13:22:31 2009
@@ -0,0 +1,773 @@
+/*
+Script: spec-jspwiki-edit.js
+
+License:
+ http://www.apache.org/licenses/LICENSE-2.0
+*/
+
+
+/*
+Script: snipeditorSpecs.js
+ Test following classes: WikiEditor, SnipEditor, Textarea, UndoRedo
+
+License:
+ xxx
+
+*/
+
+
+/*
+Native: StubEvent
+ Mockup Event object to allow simulation of keyboard and mouse events
+ (based on mootools v1.2.3)
+*/
+var StubEvent = new Native({
+
+ name: 'Event',
+
+ initialize: function(options){
+ return $extend(this, {
+ event: options.event||{},
+ type: options.type,
+
+ page: options.page,
+ client: options.client,
+ rightClick: options.rightClick,
+
+ wheel: options.wheel,
+
+ relatedTarget: options.relatedTarget,
+ target: options.target,
+
+ code: options.code,
+ key: options.key,
+
+ shift: options.shift,
+ control: options.control,
+ alt: options.alt,
+ meta: options.meta
+ });
+ }
+});
+
+StubEvent.Keys = Event.Keys;
+
+StubEvent.implement({
+ setKey: function(keystroke,shift){
+ this.type='keypress';
+ this.shift=shift||false,
+ this.code=keystroke.charCodeAt(0);
+ this.key=keystroke;
+ return this;
+ },
+ stop: function(){ return this; },
+ stopPropagation: function(){ return this; },
+ preventDefault: function(){ return this; }
+});
+
+
+
+describe('UndoRedo Class',function(){
+
+ var WORK, UndoElement, RedoElement, UNDOREDO;
+
+ beforeEach( function(){
+ WORK = {
+ state : 'testing',
+ getState: function(){ return this.state; },
+ putState: function(obj){ this.state = obj; }
+ }
+
+ $$('body')[0].adopt( UndoElement = new Element('a'), RedoElement = new Element('a') );
+
+ UNDOREDO = new UndoRedo(WORK, {redo:RedoElement, undo:UndoElement});
+
+ });
+
+ afterEach( function(){
+ WORK = null, UNDOREDO = null;
+ UndoElement.dispose();
+ RedoElement.dispose();
+ });
+
+ it('should initialize', function(){
+
+ expect(UNDOREDO.obj).toEqual(WORK);
+ expect(UNDOREDO.options.maxundo).toEqual(40);
+ expect(UNDOREDO.redo).toEqual([]);
+ expect(UNDOREDO.undo).toEqual([]);
+ expect(UNDOREDO.undoEL).toNotEqual(null);
+ expect(UNDOREDO.redoEL).toEqual(RedoElement);
+
+ UNDOREDO = new UndoRedo( WORK ,{maxundo:3});
+
+ expect(UNDOREDO.obj).toEqual(WORK);
+ expect(UNDOREDO.options.maxundo).toEqual(3);
+
+ });
+
+ it('should undo a single element', function(){
+
+ UNDOREDO.onChange();
+ WORK.state = "changed";
+
+ expect(UNDOREDO.undo).toEqual(['testing']);
+ expect(WORK.state).toEqual('changed');
+ expect(UndoElement.hasClass('disabled')).toBeFalsy();
+ expect(RedoElement.hasClass('disabled')).toBeTruthy();
+
+ UNDOREDO.onUndo();
+
+ expect(WORK.state).toEqual('testing');
+ expect(UNDOREDO.undo).toEqual([]);
+ expect(UNDOREDO.redo).toEqual(['changed']);
+ expect(UndoElement.hasClass('disabled')).toBeTruthy();
+ expect(RedoElement.hasClass('disabled')).toBeFalsy();
+
+ });
+
+ it('should undo multiple elements', function(){
+
+ UNDOREDO.onChange();
+ WORK.state = "changed1";
+ UNDOREDO.onChange();
+ WORK.state = "changed2";
+
+ expect(UNDOREDO.undo).toEqual(['testing','changed1']);
+ expect(WORK.state).toEqual('changed2');
+ expect(UndoElement.hasClass('disabled')).toBeFalsy();
+ expect(RedoElement.hasClass('disabled')).toBeTruthy();
+
+ UNDOREDO.onUndo();
+
+ expect(UndoElement.hasClass('disabled')).toBeFalsy();
+ expect(RedoElement.hasClass('disabled')).toBeFalsy();
+
+
+ UNDOREDO.onUndo();
+
+ expect(WORK.state).toEqual('testing');
+ expect(UNDOREDO.undo).toEqual([]);
+ expect(UNDOREDO.redo).toEqual(['changed2','changed1']);
+ expect(UndoElement.hasClass('disabled')).toBeTruthy();
+ expect(RedoElement.hasClass('disabled')).toBeFalsy();
+ });
+
+ it('should undo maximum "maxundo" elements', function(){
+
+ UNDOREDO = new UndoRedo( WORK ,{maxundo:3});
+
+ UNDOREDO.onChange();
+ WORK.state = "changed1";
+
+ expect(UNDOREDO.undo).toEqual(['testing']);
+
+ UNDOREDO.onChange();
+ WORK.state = "changed2";
+
+ expect(UNDOREDO.undo).toEqual(['testing','changed1']);
+
+ UNDOREDO.onChange();
+ WORK.state = "changed3";
+
+ expect(UNDOREDO.undo).toEqual(['testing','changed1','changed2']);
+
+ UNDOREDO.onChange();
+ WORK.state = "changed4";
+
+ expect(UNDOREDO.undo).toEqual(['changed1','changed2','changed3']);
+ expect(WORK.state).toEqual('changed4');
+
+ UNDOREDO.onUndo();
+ UNDOREDO.onUndo();
+ UNDOREDO.onUndo();
+ UNDOREDO.onUndo();
+
+ expect(WORK.state).toEqual('changed1');
+ expect(UNDOREDO.undo).toEqual([]);
+ expect(UNDOREDO.redo).toEqual(['changed4','changed3','changed2']);
+ });
+
+ it('should redo an element', function(){
+
+ UNDOREDO.onChange();
+ WORK.state = "changed1";
+ UNDOREDO.onChange();
+ WORK.state = "changed2";
+
+ expect(UNDOREDO.undo).toEqual(['testing','changed1']);
+ expect(WORK.state).toEqual('changed2');
+ expect(UndoElement.hasClass('disabled')).toBeFalsy();
+ expect(RedoElement.hasClass('disabled')).toBeTruthy();
+
+ UNDOREDO.onUndo();
+
+ expect(WORK.state).toEqual('changed1');
+ expect(UNDOREDO.undo).toEqual(['testing']);
+ expect(UNDOREDO.redo).toEqual(['changed2']);
+ expect(UndoElement.hasClass('disabled')).toBeFalsy();
+ expect(RedoElement.hasClass('disabled')).toBeFalsy();
+
+ UNDOREDO.onRedo();
+
+ expect(WORK.state).toEqual('changed2');
+ expect(UNDOREDO.undo).toEqual(['testing','changed1']);
+ expect(UNDOREDO.redo).toEqual([]);
+ expect(UndoElement.hasClass('disabled')).toBeFalsy();
+ expect(RedoElement.hasClass('disabled')).toBeTruthy();
+
+ });
+
+ it('should clear the redo stack when a new undo element is pushed', function(){
+
+ UNDOREDO.onChange();
+ WORK.state = "changed1";
+ UNDOREDO.onChange();
+ WORK.state = "changed2";
+
+ expect(UNDOREDO.undo).toEqual(['testing','changed1']);
+ expect(WORK.state).toEqual('changed2');
+ expect(UndoElement.hasClass('disabled')).toBeFalsy();
+ expect(RedoElement.hasClass('disabled')).toBeTruthy();
+
+ UNDOREDO.onUndo();
+
+ expect(WORK.state).toEqual('changed1');
+ expect(UNDOREDO.undo).toEqual(['testing']);
+ expect(UNDOREDO.redo).toEqual(['changed2']);
+ expect(UndoElement.hasClass('disabled')).toBeFalsy();
+ expect(RedoElement.hasClass('disabled')).toBeFalsy();
+
+ //no make a new change, this should clear the redo stack
+ WORK.state = "changed3";
+ UNDOREDO.onChange();
+
+ expect(WORK.state).toEqual('changed3');
+ expect(UNDOREDO.undo).toEqual(['testing','changed3']);
+ expect(UNDOREDO.redo).toEqual([]);
+ expect(UndoElement.hasClass('disabled')).toBeFalsy();
+ expect(RedoElement.hasClass('disabled')).toBeTruthy();
+
+ });
+
+
+});
+
+describe('Textarea Class', function(){
+
+ beforeEach( function() {
+ $$('body')[0].adopt( ta = new Element('textarea') );
+ ta.value = 'Example text';
+
+ txta = new Textarea( ta );
+ });
+
+ afterEach(function(){
+ ta.dispose();
+ });
+
+ it('should initialize Textarea class', function(){
+ expect(txta.getValue()).toEqual('Example text');
+ });
+
+ it('should set the caret', function(){
+ txta.setSelectionRange(2);
+ expect(txta.getSelection()).toEqual('');
+ expect(txta.getSelectionRange()).toEqual({start:2,end:2,thin:true})
+ });
+
+ it('should set a selection range', function(){
+ txta.setSelectionRange(2,4);
+ expect(txta.getSelection()).toEqual('am');
+ expect(txta.getSelectionRange()).toEqual({start:2,end:4,thin:false})
+ });
+
+ it('should set a selection range with a \\n included', function(){
+ ta.value = 'Example\ntext';
+ txta.setSelectionRange(6,9);
+ expect(txta.getSelection()).toEqual('e\nt');
+ expect(txta.getSelectionRange()).toEqual({start:6,end:9,thin:false})
+ });
+
+ it('should read a fragment from start to caret', function(){
+ txta.setSelectionRange(2);
+ expect(txta.getFromStart()).toEqual('Ex');
+ });
+
+ it('should read a fragment from caret till end', function(){
+ txta.setSelectionRange(2,4);
+ expect(txta.getTillEnd()).toEqual('ple text');
+ });
+
+ it('should replace the selection with another fragment', function(){
+ txta.setSelectionRange(2,4);
+ txta.setSelection('New Selection ');
+ expect(txta.getValue()).toEqual('ExNew Selection ple text');
+ expect(txta.getSelection()).toEqual('New Selection ');
+ expect(txta.getSelectionRange()).toEqual({start:2,end:16,thin:false})
+ });
+
+ it('should replace the selection with another fragment with a \\n', function(){
+ txta.setSelectionRange(2,4);
+ txta.setSelection('New\nSelection ');
+ expect(txta.getValue()).toEqual('ExNew\nSelection ple text');
+ expect(txta.getSelection()).toEqual('New\nSelection ');
+ expect(txta.getSelectionRange()).toEqual({start:2,end:16,thin:false})
+ });
+
+ it('should replace the selection with a \\n with another fragment', function(){
+ ta.value = 'Example\ntext';
+ txta.setSelectionRange(6,9);
+ txta.setSelection('New Selection ');
+ expect(txta.getValue()).toEqual('ExamplNew Selection ext');
+ expect(txta.getSelection()).toEqual('New Selection ');
+ expect(txta.getSelectionRange()).toEqual({start:6,end:20,thin:false})
+ });
+
+ it('should insert a fragment at the caret', function(){
+ txta.setSelectionRange(2);
+ txta.setSelection('New Selection ');
+ expect(txta.getValue()).toEqual('ExNew Selection ample text');
+ expect(txta.getSelection()).toEqual('New Selection ');
+ expect(txta.getSelectionRange()).toEqual({start:2,end:16,thin:false})
+ });
+
+ it('should insert a fragment after the selection', function(){
+ txta.setSelectionRange(2,4);
+ txta.insertAfter('Inserted Stuff ')
+ expect(txta.getValue()).toEqual('ExInserted Stuff ple text');
+ expect(txta.getSelection()).toEqual('');
+ expect(txta.getSelectionRange()).toEqual({start:17,end:17,thin:true})
+ });
+
+ it('should insert a set of fragments after the caret', function(){
+ txta.setSelectionRange(2);
+ txta.insertAfter('Inserted ','Stuff ')
+ expect(txta.getValue()).toEqual('ExInserted Stuff ample text');
+ expect(txta.getSelectionRange()).toEqual({start:17,end:17,thin:true})
+ });
+
+ it('should check if caret is at start of line', function(){
+ ta.value = 'Example\ntext';
+ txta.setSelectionRange(0);
+ expect(txta.isCaretAtStartOfLine()).toBeTruthy();
+ txta.setSelectionRange(2);
+ expect(txta.isCaretAtStartOfLine()).toBeFalsy();
+ txta.setSelectionRange(8);
+ expect(txta.isCaretAtStartOfLine()).toBeTruthy();
+ txta.setSelectionRange(9);
+ expect(txta.isCaretAtStartOfLine()).toBeFalsy();
+ txta.setSelectionRange(100);
+ expect(txta.isCaretAtStartOfLine()).toBeFalsy();
+ });
+
+});
+
+describe('Edit: SnipEditor Class', function(){
+
+ var KEY, TAB, main, next, snipe, txta, ta;
+
+ beforeEach( function(){
+
+ KEY = new StubEvent({'type':'keypress', 'shift':false}).setKey('a');
+ TAB = new StubEvent({ 'type':'keydown', 'shift':false, code:9, key:'tab' });
+
+ //initialise body with basic DOM elements to test the snip-editor
+ document.body
+ .adopt( main = new Element('textarea').set('html','Example text') )
+ .adopt( next = new Element('input') );
+ main.set('html','Example text');
+ next.value = "no-focus";
+
+ snipe = new SnipEditor( main, {
+ tabsnips: WikiEdit.tabSnippets,
+ directsnips: WikiEdit.directSnippets,
+ //buttons: $$('a.tool'),
+ next:next,
+ //suggest:$('suggestionMenu')
+ });
+
+ txta = snipe.get('textarea');
+ ta = txta.toElement();
+
+ snipe.options.findForm = {
+ findInput: {value: ''},
+ replaceInput: {value: ''},
+ isRegExp: {checked:false},
+ isMatchCase: {checked:false},
+ isReplaceGlobal: {checked:true},
+ msgNoMatchFound: function(){ }
+ };
+
+
+ });
+
+ afterEach(function(){
+ main.dispose(), ta.dispose(), next.dispose(), snipe=null, txta=null;
+ });
+
+ it('should initialize the SnipEditor class', function(){
+ expect(main.value).toEqual('Example text');
+ expect(ta.value).toEqual('Example text');
+ expect(txta.getValue()).toEqual('Example text');
+ });
+
+ //Special keys
+ it('shift-enter should jump to next form element', function(){
+ next.addEvent('focus',function(){ this.value="has-focus"});
+ txta.setSelectionRange(2);
+
+ expect(next.get('value')).toEqual('no-focus');
+
+ var SHIFTENTER = new StubEvent({ 'type':'keydown', 'shift':true, code:13, key:'enter' });
+
+ snipe.onKeystroke( SHIFTENTER );
+
+ //expect(txta.getValue()).toEqual('Example text');
+ //expect(txta.getSelectionRange()).toEqual({start:2,end:2,thin:true});
+ expect(next.get('value')).toEqual('has-focus');
+ });
+
+ //auto indentation on TAB
+ it('tab key should insert tab-spaces at the caret', function(){
+ txta.setSelectionRange(2);
+ snipe.onKeystroke( TAB );
+
+ expect(txta.getValue()).toEqual('Ex ample text');
+ expect(txta.getSelectionRange()).toEqual({start:6,end:6,thin:true})
+ });
+
+ it('selected text + tab key should replace the selection with tab-spaces', function(){
+ txta.setSelectionRange(2,4);
+ snipe.onKeystroke( TAB );
+
+ expect(txta.getValue()).toEqual('Ex ple text');
+ expect(txta.getSelectionRange()).toEqual({start:6,end:6,thin:true})
+ });
+
+ it('multi-line selection + tab key should insert tab-spaces at each line', function(){
+ txta.toElement().value="Example\ntext";
+ txta.setSelectionRange(0,12);
+ snipe.onKeystroke( TAB );
+
+ expect(txta.getValue()).toEqual(' Example\n text');
+ expect(txta.getSelectionRange()).toEqual({start:0,end:20,thin:false})
+ });
+
+ it('shift-tab key should remove tab-spaces to the left', function(){
+ txta.toElement().value="Ex ample text";
+ txta.setSelectionRange(6);
+
+ TAB.shift=true;
+ snipe.onKeystroke( TAB );
+
+ expect(txta.getValue()).toEqual('Example text');
+ expect(txta.getSelectionRange()).toEqual({start:2,end:2,thin:true})
+ });
+
+ it('multi-line selection + shift-tab key should remove the inserted tab-spaces at each line', function(){
+ txta.toElement().value=" Example\n text";
+ txta.setSelectionRange(0,20);
+ TAB.shift=true;
+ snipe.onKeystroke( TAB );
+
+ expect(txta.getValue()).toEqual('Example\ntext');
+ expect(txta.getSelectionRange()).toEqual({start:0,end:12,thin:false})
+ });
+
+ it('del key should remove tab-spaces to the right', function(){
+ txta.toElement().value="Ex ample text";
+ txta.setSelectionRange(2);
+ var DEL = new StubEvent({ 'type':'keydown', 'shift':false, code:46, key:'delete' });
+ snipe.onKeystroke( DEL );
+
+ expect(txta.getValue()).toEqual('Example text');
+ expect(txta.getSelectionRange()).toEqual({start:2,end:2,thin:true});
+ });
+
+
+ //direct snippets
+ it('Direct snippets, should insert a closing-bracket after the caret', function(){
+ txta.setSelectionRange(2);
+ snipe.onKeystroke( KEY.setKey('(') );
+
+ expect(txta.getValue()).toEqual('Ex()ample text');
+ expect(txta.getSelectionRange()).toEqual({start:3,end:3,thin:true}) ;
+ });
+
+ it('Direct snippets, should insert a bracket around the selection', function(){
+ txta.setSelectionRange(2,4);
+ snipe.onKeystroke( KEY.setKey('[') );
+
+ expect(txta.getValue()).toEqual('Ex[am]ple text');
+ expect(txta.getSelectionRange()).toEqual({start:3,end:5,thin:false});
+ });
+
+ it('should not expand direct snippets when deactivated', function(){
+ snipe.options.directsnips = {};
+ txta.setSelectionRange(2);
+
+ snipe.onKeystroke( KEY.setKey('a'));
+
+ //Warning: default key-stroke behaviour is not correct during Spec tests
+ // because the way it is simulated.
+ // Normally we would expect 'Ex[ample text'
+ expect(txta.getValue()).toEqual('Example text');
+ expect(txta.getSelectionRange()).toEqual({start:2,end:2,thin:true});
+ });
+
+ //Tab snippet, without parameters
+ it('Tab snippet - no parameters: should remove the leading \\n at the start of the first line of the textarea', function(){
+ snipe.options.tabsnips["toc"] = "\n[\\{TableOfContents }]\n";
+ txta.toElement().value="tocExample text";
+ txta.setSelectionRange(3);
+ snipe.onKeystroke( TAB );
+
+ expect(txta.getValue()).toEqual('[{TableOfContents }]\nExample text');
+ expect(txta.getSelectionRange()).toEqual({start:21,end:21,thin:true});
+
+ });
+ it('Tab snippet - no parameters: should remove the leading \\n at the start of the nth line the textarea', function(){
+ snipe.options.tabsnips["toc"] = "\n[\\{TableOfContents }]\n";
+ txta.toElement().value="Example\ntoc text";
+ txta.setSelectionRange(11);
+ snipe.onKeystroke( TAB );
+
+ expect(txta.getValue()).toEqual('Example\n[{TableOfContents }]\n text');
+ expect(txta.getSelectionRange()).toEqual({start:29,end:29,thin:true})
+ });
+ it('Tab snippet - no parameters: should keep a leading \\n in the middle of a line of the textarea', function(){
+ snipe.options.tabsnips["toc"] = "\n[\\{TableOfContents }]\n";
+ txta.toElement().value="Example toc text";
+ txta.setSelectionRange(11);
+ snipe.onKeystroke( TAB );
+
+ expect(txta.getValue()).toEqual('Example \n[{TableOfContents }]\n text');
+ expect(txta.getSelectionRange()).toEqual({start:30,end:30,thin:true})
+ });
+
+ it('Tab snippet: should only allow a tab snippet when in scope', function(){
+ snipe.options.tabsnips["toc"] = {
+ snippet:"\n[\\{TableOfContents }]\n",
+ scope:{
+ "test": "endtest",
+ "<p": "</p>"
+ }
+ }
+
+ //in scope
+ txta.toElement().value="Example <p>toc</p> text";
+ txta.setSelectionRange(14);
+ snipe.onKeystroke( TAB );
+
+ expect(txta.getValue()).toEqual("Example <p>\n[{TableOfContents }]\n</p> text");
+ expect(txta.getSelectionRange()).toEqual({start:33,end:33,thin:true})
+
+ //not in scope -- so just expands the tab to 4 spaces
+ txta.toElement().value="Example toc text";
+ txta.setSelectionRange(11);
+ snipe.onKeystroke( TAB );
+
+ expect(txta.getValue()).toEqual("Example toc text");
+ expect(txta.getSelectionRange()).toEqual({start:15,end:15,thin:true})
+
+ });
+
+ it('Tab snippet: should not expand tab snippets when deactivated', function(){
+ snipe.options.tabsnips = {}
+ txta.toElement().value="Example toc text";
+ txta.setSelectionRange(11);
+ snipe.onKeystroke( TAB );
+
+ expect(txta.getValue()).toEqual('Example toc text');
+ expect(txta.getSelectionRange()).toEqual({start:15,end:15,thin:true})
+ });
+
+ it('Tab snippet: should allow to undo the inserted tab snippet', function(){
+ snipe.options.tabsnips["toc"] = "\n[\\{TableOfContents }]\n";
+ txta.toElement().value="Example toc text";
+ txta.setSelectionRange(11);
+ snipe.onKeystroke( TAB );
+
+ expect(txta.getValue()).toEqual('Example \n[{TableOfContents }]\n text');
+ expect(txta.getSelectionRange()).toEqual({start:30,end:30,thin:true});
+
+ snipe.undoredo.onUndo();
+
+ expect(txta.getValue()).toEqual('Example toc text');
+ expect(txta.getSelectionRange()).toEqual({start:11,end:11,thin:true});
+
+ snipe.undoredo.onRedo();
+
+ expect(txta.getValue()).toEqual('Example \n[{TableOfContents }]\n text');
+ expect(txta.getSelectionRange()).toEqual({start:30,end:30,thin:true});
+ });
+
+ //Tab snippet, with a parameter
+ it('Tab snippet with parameter: should select the first parameter', function(){
+
+ });
+
+ it('Tab snippet with parameter: should allow to tab through all subsequent parameters', function(){
+
+ });
+
+ it('Tab snippet with parameter: should remove the active snippet when pressing esc/up/down', function(){
+
+ });
+
+ it('Tab snippet with parameter and parameter dialog: should display the parameter dialog', function(){
+
+ });
+
+ it('Tab snippet with font parameter: should display the font dialog', function(){
+
+ });
+
+ it('Tab snippet with color parameter: should display the color dialog', function(){
+
+ });
+
+ it('Tab snippet with special-charater parameter: should display the chars dialog', function(){
+
+ });
+
+ //Button snippets
+ it('Button snippet, should insert snippet text without parameters', function(){
+ });
+
+ it('Button snippet, should replace selected text by snippet without parameters', function(){
+ });
+
+ it('Button snippet, should insert snippet and tab through parameters without parameter dialog', function(){
+ });
+
+ it('Button snippet, should insert snippet and select first parameter with parameter dialog', function(){
+ });
+
+ it('Button snippet, should insert snippet and replace first free parameter with seleted text', function(){
+ //font snippet
+ });
+
+
+ //find and replace
+ it('should replace all occurences of a string', function(){
+
+ txta.toElement().value='Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.';
+ snipe.options.findForm.findInput.value='ipsum';
+ snipe.options.findForm.replaceInput.value='IPSUM'
+
+ snipe.onFindAndReplace();
+
+ expect(txta.getValue()).toEqual('Lorem IPSUM dolor sit amet. Lorem IPSUM dolor sit amet.');
+ });
+
+ it('should undo a replace operation', function(){
+
+ txta.toElement().value='Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.';
+ snipe.options.findForm.findInput.value='ipsum';
+ snipe.options.findForm.replaceInput.value='IPSUM'
+
+ snipe.onFindAndReplace();
+
+ expect(txta.getValue()).toEqual('Lorem IPSUM dolor sit amet. Lorem IPSUM dolor sit amet.');
+
+ snipe.undoredo.onUndo();
+
+ expect(txta.getValue()).toEqual('Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.');
+
+ snipe.undoredo.onRedo();
+
+ expect(txta.getValue()).toEqual('Lorem IPSUM dolor sit amet. Lorem IPSUM dolor sit amet.');
+
+ });
+
+ it('should return no-match found when replacing a string', function(){
+
+ txta.toElement().value='Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.';
+ snipe.options.findForm.findInput.value='cant find this string';
+ snipe.options.findForm.replaceInput.value='oops';
+ var error = '';
+ snipe.options.findForm.msgNoMatchFound=function(){ error = 'no match';}
+
+ snipe.onFindAndReplace();
+
+ expect(txta.getValue()).toEqual('Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.');
+ expect(error).toEqual('no match');
+ });
+
+ it('should replace all occurences of a string case sensitive', function(){
+
+ txta.toElement().value='Lorem ipsum dolor sit amet; lorem ipsum dolor sit amet.';
+ snipe.options.findForm.findInput.value='Lorem';
+ snipe.options.findForm.replaceInput.value='LOREM'
+ snipe.options.findForm.isMatchCase.checked=true;
+
+ snipe.onFindAndReplace();
+
+ expect(txta.getValue()).toEqual('LOREM ipsum dolor sit amet; lorem ipsum dolor sit amet.');
+ });
+
+ it('should replace all occurences of a string with a regular expression', function(){
+
+ txta.toElement().value='Lorem ipsum dolor sit amet. LOREM iPSUm dolor sit amet.';
+ snipe.options.findForm.findInput.value='i([psu]+)m';
+ snipe.options.findForm.replaceInput.value='I$1M'
+ snipe.options.findForm.isRegExp.checked=true;
+
+ snipe.onFindAndReplace();
+
+ expect(txta.getValue()).toEqual('Lorem IpsuM dolor sit amet. LOREM IPSUM dolor sit amet.');
+
+ //double $ in replace string acts as a single $
+ snipe.options.findForm.findInput.value='L([orem]+)m';
+ snipe.options.findForm.replaceInput.value='LL$$$1MM'
+
+ snipe.onFindAndReplace();
+
+ expect(txta.getValue()).toEqual('LL$oreMM IpsuM dolor sit amet. LL$OREMM IPSUM dolor sit amet.');
+ });
+
+ it('should replace the first occurences of a string', function(){
+
+ txta.toElement().value='Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.';
+ snipe.options.findForm.findInput.value='ipsum';
+ snipe.options.findForm.replaceInput.value='IPSUM'
+ snipe.options.findForm.isReplaceGlobal.checked=false;
+
+ snipe.onFindAndReplace();
+
+ expect(txta.getValue()).toEqual('Lorem IPSUM dolor sit amet. Lorem ipsum dolor sit amet.');
+ });
+
+ it('should replace all occurences of a string in a textarea selection', function(){
+
+ txta.toElement().value='Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.';
+ txta.setSelectionRange(6,27)
+ snipe.options.findForm.findInput.value='i';
+ snipe.options.findForm.replaceInput.value='III'
+
+ expect(txta.getSelection()).toEqual('ipsum dolor sit amet.');
+
+ snipe.onFindAndReplace();
+
+ expect(txta.getValue()).toEqual('Lorem IIIpsum dolor sIIIt amet. Lorem ipsum dolor sit amet.');
+ expect(txta.getSelection()).toEqual('IIIpsum dolor sIIIt amet.');
+ });
+
+
+});
+
+//todo
+describe('Edit: Wiki Editor Class', function(){
+
+ //test configuration dialog
+
+ //setting/reseting of smartpair and tabcompletion preferences
+
+ //test cookie get/set
+
+});
+
+
+