jspwiki-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From brus...@apache.org
Subject svn commit: r787361 [2/2] - in /incubator/jspwiki/trunk: ./ src/java/org/apache/wiki/ tests/JSSpec/ tests/JSSpec/Assets/ tests/JSSpec/Assets/Scripts/ tests/JSSpec/Assets/Styles/
Date Mon, 22 Jun 2009 19:23:30 GMT
Added: incubator/jspwiki/trunk/tests/JSSpec/Assets/Scripts/diff_match_patch.js
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/tests/JSSpec/Assets/Scripts/diff_match_patch.js?rev=787361&view=auto
==============================================================================
--- incubator/jspwiki/trunk/tests/JSSpec/Assets/Scripts/diff_match_patch.js (added)
+++ incubator/jspwiki/trunk/tests/JSSpec/Assets/Scripts/diff_match_patch.js Mon Jun 22 19:23:30 2009
@@ -0,0 +1 @@
+function diff_match_patch(){this.Diff_Timeout=1.0;this.Diff_EditCost=4;this.Diff_DualThreshold=32;this.Match_Balance=0.5;this.Match_Threshold=0.5;this.Match_MinLength=100;this.Match_MaxLength=1000;this.Patch_Margin=4;function getMaxBits(){var maxbits=0;var oldi=1;var newi=2;while(oldi!=newi){maxbits++;oldi=newi;newi=newi<<1}return maxbits}this.Match_MaxBits=getMaxBits()}var DIFF_DELETE=-1;var DIFF_INSERT=1;var DIFF_EQUAL=0;diff_match_patch.prototype.diff_main=function(text1,text2,opt_checklines){if(text1==text2){return[[DIFF_EQUAL,text1]]}if(typeof opt_checklines=='undefined'){opt_checklines=true}var checklines=opt_checklines;var commonlength=this.diff_commonPrefix(text1,text2);var commonprefix=text1.substring(0,commonlength);text1=text1.substring(commonlength);text2=text2.substring(commonlength);commonlength=this.diff_commonSuffix(text1,text2);var commonsuffix=text1.substring(text1.length-commonlength);text1=text1.substring(0,text1.length-commonlength);text2=text2.substring
 (0,text2.length-commonlength);var diffs=this.diff_compute(text1,text2,checklines);if(commonprefix){diffs.unshift([DIFF_EQUAL,commonprefix])}if(commonsuffix){diffs.push([DIFF_EQUAL,commonsuffix])}this.diff_cleanupMerge(diffs);return diffs};diff_match_patch.prototype.diff_compute=function(text1,text2,checklines){var diffs;if(!text1){return[[DIFF_INSERT,text2]]}if(!text2){return[[DIFF_DELETE,text1]]}var longtext=text1.length>text2.length?text1:text2;var shorttext=text1.length>text2.length?text2:text1;var i=longtext.indexOf(shorttext);if(i!=-1){diffs=[[DIFF_INSERT,longtext.substring(0,i)],[DIFF_EQUAL,shorttext],[DIFF_INSERT,longtext.substring(i+shorttext.length)]];if(text1.length>text2.length){diffs[0][0]=diffs[2][0]=DIFF_DELETE}return diffs}longtext=shorttext=null;var hm=this.diff_halfMatch(text1,text2);if(hm){var text1_a=hm[0];var text1_b=hm[1];var text2_a=hm[2];var text2_b=hm[3];var mid_common=hm[4];var diffs_a=this.diff_main(text1_a,text2_a,checklines);var diffs_b=this.diff_
 main(text1_b,text2_b,checklines);return diffs_a.concat([[DIFF_EQUAL,mid_common]],diffs_b)}if(checklines&&text1.length+text2.length<250){checklines=false}var linearray;if(checklines){var a=this.diff_linesToChars(text1,text2);text1=a[0];text2=a[1];linearray=a[2]}diffs=this.diff_map(text1,text2);if(!diffs){diffs=[[DIFF_DELETE,text1],[DIFF_INSERT,text2]]}if(checklines){this.diff_charsToLines(diffs,linearray);this.diff_cleanupSemantic(diffs);diffs.push([DIFF_EQUAL,'']);var pointer=0;var count_delete=0;var count_insert=0;var text_delete='';var text_insert='';while(pointer<diffs.length){if(diffs[pointer][0]==DIFF_INSERT){count_insert++;text_insert+=diffs[pointer][1]}else if(diffs[pointer][0]==DIFF_DELETE){count_delete++;text_delete+=diffs[pointer][1]}else{if(count_delete>=1&&count_insert>=1){var a=this.diff_main(text_delete,text_insert,false);diffs.splice(pointer-count_delete-count_insert,count_delete+count_insert);pointer=pointer-count_delete-count_insert;for(var j=a.length-1;j>=0
 ;j--){diffs.splice(pointer,0,a[j])}pointer=pointer+a.length}count_insert=0;count_delete=0;text_delete='';text_insert=''}pointer++}diffs.pop()}return diffs};diff_match_patch.prototype.diff_linesToChars=function(text1,text2){var linearray=[];var linehash={};linearray.push('');function diff_linesToCharsMunge(text){var chars='';while(text){var i=text.indexOf('\n');if(i==-1){i=text.length}var line=text.substring(0,i+1);text=text.substring(i+1);if(linehash.hasOwnProperty?linehash.hasOwnProperty(line):(linehash[line]!==undefined)){chars+=String.fromCharCode(linehash[line])}else{linearray.push(line);linehash[line]=linearray.length-1;chars+=String.fromCharCode(linearray.length-1)}}return chars}var chars1=diff_linesToCharsMunge(text1);var chars2=diff_linesToCharsMunge(text2);return[chars1,chars2,linearray]};diff_match_patch.prototype.diff_charsToLines=function(diffs,linearray){for(var x=0;x<diffs.length;x++){var chars=diffs[x][1];var text=[];for(var y=0;y<chars.length;y++){text.push(l
 inearray[chars.charCodeAt(y)])}diffs[x][1]=text.join('')}};diff_match_patch.prototype.diff_map=function(text1,text2){var ms_end=(new Date()).getTime()+this.Diff_Timeout*1000;var max_d=text1.length+text2.length-1;var doubleEnd=this.Diff_DualThreshold*2<max_d;var v_map1=[];var v_map2=[];var v1={};var v2={};v1[1]=0;v2[1]=0;var x,y;var footstep;var footsteps={};var done=false;var hasOwnProperty=!!(footsteps.hasOwnProperty);var front=(text1.length+text2.length)%2;for(var d=0;d<max_d;d++){if(this.Diff_Timeout>0&&(new Date()).getTime()>ms_end){return null}v_map1[d]={};for(var k=-d;k<=d;k+=2){if(k==-d||k!=d&&v1[k-1]<v1[k+1]){x=v1[k+1]}else{x=v1[k-1]+1}y=x-k;if(doubleEnd){footstep=x+','+y;if(front&&(hasOwnProperty?footsteps.hasOwnProperty(footstep):(footsteps[footstep]!==undefined))){done=true}if(!front){footsteps[footstep]=d}}while(!done&&x<text1.length&&y<text2.length&&text1.charAt(x)==text2.charAt(y)){x++;y++;if(doubleEnd){footstep=x+','+y;if(front&&(hasOwnProperty?footsteps.hasOw
 nProperty(footstep):(footsteps[footstep]!==undefined))){done=true}if(!front){footsteps[footstep]=d}}}v1[k]=x;v_map1[d][x+','+y]=true;if(x==text1.length&&y==text2.length){return this.diff_path1(v_map1,text1,text2)}else if(done){v_map2=v_map2.slice(0,footsteps[footstep]+1);var a=this.diff_path1(v_map1,text1.substring(0,x),text2.substring(0,y));return a.concat(this.diff_path2(v_map2,text1.substring(x),text2.substring(y)))}}if(doubleEnd){v_map2[d]={};for(var k=-d;k<=d;k+=2){if(k==-d||k!=d&&v2[k-1]<v2[k+1]){x=v2[k+1]}else{x=v2[k-1]+1}y=x-k;footstep=(text1.length-x)+','+(text2.length-y);if(!front&&(hasOwnProperty?footsteps.hasOwnProperty(footstep):(footsteps[footstep]!==undefined))){done=true}if(front){footsteps[footstep]=d}while(!done&&x<text1.length&&y<text2.length&&text1.charAt(text1.length-x-1)==text2.charAt(text2.length-y-1)){x++;y++;footstep=(text1.length-x)+','+(text2.length-y);if(!front&&(hasOwnProperty?footsteps.hasOwnProperty(footstep):(footsteps[footstep]!==undefined)))
 {done=true}if(front){footsteps[footstep]=d}}v2[k]=x;v_map2[d][x+','+y]=true;if(done){v_map1=v_map1.slice(0,footsteps[footstep]+1);var a=this.diff_path1(v_map1,text1.substring(0,text1.length-x),text2.substring(0,text2.length-y));return a.concat(this.diff_path2(v_map2,text1.substring(text1.length-x),text2.substring(text2.length-y)))}}}}return null};diff_match_patch.prototype.diff_path1=function(v_map,text1,text2){var path=[];var x=text1.length;var y=text2.length;var last_op=null;for(var d=v_map.length-2;d>=0;d--){while(1){if(v_map[d].hasOwnProperty?v_map[d].hasOwnProperty((x-1)+','+y):(v_map[d][(x-1)+','+y]!==undefined)){x--;if(last_op===DIFF_DELETE){path[0][1]=text1.charAt(x)+path[0][1]}else{path.unshift([DIFF_DELETE,text1.charAt(x)])}last_op=DIFF_DELETE;break}else if(v_map[d].hasOwnProperty?v_map[d].hasOwnProperty(x+','+(y-1)):(v_map[d][x+','+(y-1)]!==undefined)){y--;if(last_op===DIFF_INSERT){path[0][1]=text2.charAt(y)+path[0][1]}else{path.unshift([DIFF_INSERT,text2.charAt(y
 )])}last_op=DIFF_INSERT;break}else{x--;y--;if(last_op===DIFF_EQUAL){path[0][1]=text1.charAt(x)+path[0][1]}else{path.unshift([DIFF_EQUAL,text1.charAt(x)])}last_op=DIFF_EQUAL}}}return path};diff_match_patch.prototype.diff_path2=function(v_map,text1,text2){var path=[];var x=text1.length;var y=text2.length;var last_op=null;for(var d=v_map.length-2;d>=0;d--){while(1){if(v_map[d].hasOwnProperty?v_map[d].hasOwnProperty((x-1)+','+y):(v_map[d][(x-1)+','+y]!==undefined)){x--;if(last_op===DIFF_DELETE){path[path.length-1][1]+=text1.charAt(text1.length-x-1)}else{path.push([DIFF_DELETE,text1.charAt(text1.length-x-1)])}last_op=DIFF_DELETE;break}else if(v_map[d].hasOwnProperty?v_map[d].hasOwnProperty(x+','+(y-1)):(v_map[d][x+','+(y-1)]!==undefined)){y--;if(last_op===DIFF_INSERT){path[path.length-1][1]+=text2.charAt(text2.length-y-1)}else{path.push([DIFF_INSERT,text2.charAt(text2.length-y-1)])}last_op=DIFF_INSERT;break}else{x--;y--;if(last_op===DIFF_EQUAL){path[path.length-1][1]+=text1.charA
 t(text1.length-x-1)}else{path.push([DIFF_EQUAL,text1.charAt(text1.length-x-1)])}last_op=DIFF_EQUAL}}}return path};diff_match_patch.prototype.diff_commonPrefix=function(text1,text2){if(!text1||!text2||text1.charCodeAt(0)!==text2.charCodeAt(0)){return 0}var pointermin=0;var pointermax=Math.min(text1.length,text2.length);var pointermid=pointermax;var pointerstart=0;while(pointermin<pointermid){if(text1.substring(pointerstart,pointermid)==text2.substring(pointerstart,pointermid)){pointermin=pointermid;pointerstart=pointermin}else{pointermax=pointermid}pointermid=Math.floor((pointermax-pointermin)/2+pointermin)}return pointermid};diff_match_patch.prototype.diff_commonSuffix=function(text1,text2){if(!text1||!text2||text1.charCodeAt(text1.length-1)!==text2.charCodeAt(text2.length-1)){return 0}var pointermin=0;var pointermax=Math.min(text1.length,text2.length);var pointermid=pointermax;var pointerend=0;while(pointermin<pointermid){if(text1.substring(text1.length-pointermid,text1.len
 gth-pointerend)==text2.substring(text2.length-pointermid,text2.length-pointerend)){pointermin=pointermid;pointerend=pointermin}else{pointermax=pointermid}pointermid=Math.floor((pointermax-pointermin)/2+pointermin)}return pointermid};diff_match_patch.prototype.diff_halfMatch=function(text1,text2){var longtext=text1.length>text2.length?text1:text2;var shorttext=text1.length>text2.length?text2:text1;if(longtext.length<10||shorttext.length<1){return null}var dmp=this;function diff_halfMatchI(longtext,shorttext,i){var seed=longtext.substring(i,i+Math.floor(longtext.length/4));var j=-1;var best_common='';var best_longtext_a,best_longtext_b,best_shorttext_a,best_shorttext_b;while((j=shorttext.indexOf(seed,j+1))!=-1){var prefixLength=dmp.diff_commonPrefix(longtext.substring(i),shorttext.substring(j));var suffixLength=dmp.diff_commonSuffix(longtext.substring(0,i),shorttext.substring(0,j));if(best_common.length<suffixLength+prefixLength){best_common=shorttext.substring(j-suffixLength,
 j)+shorttext.substring(j,j+prefixLength);best_longtext_a=longtext.substring(0,i-suffixLength);best_longtext_b=longtext.substring(i+prefixLength);best_shorttext_a=shorttext.substring(0,j-suffixLength);best_shorttext_b=shorttext.substring(j+prefixLength)}}if(best_common.length>=longtext.length/2){return[best_longtext_a,best_longtext_b,best_shorttext_a,best_shorttext_b,best_common]}else{return null}}var hm1=diff_halfMatchI(longtext,shorttext,Math.ceil(longtext.length/4));var hm2=diff_halfMatchI(longtext,shorttext,Math.ceil(longtext.length/2));var hm;if(!hm1&&!hm2){return null}else if(!hm2){hm=hm1}else if(!hm1){hm=hm2}else{hm=hm1[4].length>hm2[4].length?hm1:hm2}var text1_a,text1_b,text2_a,text2_b;if(text1.length>text2.length){text1_a=hm[0];text1_b=hm[1];text2_a=hm[2];text2_b=hm[3]}else{text2_a=hm[0];text2_b=hm[1];text1_a=hm[2];text1_b=hm[3]}var mid_common=hm[4];return[text1_a,text1_b,text2_a,text2_b,mid_common]};diff_match_patch.prototype.diff_cleanupSemantic=function(diffs){var
  changes=false;var equalities=[];var lastequality=null;var pointer=0;var length_changes1=0;var length_changes2=0;while(pointer<diffs.length){if(diffs[pointer][0]==DIFF_EQUAL){equalities.push(pointer);length_changes1=length_changes2;length_changes2=0;lastequality=diffs[pointer][1]}else{length_changes2+=diffs[pointer][1].length;if(lastequality!==null&&(lastequality.length<=length_changes1)&&(lastequality.length<=length_changes2)){diffs.splice(equalities[equalities.length-1],0,[DIFF_DELETE,lastequality]);diffs[equalities[equalities.length-1]+1][0]=DIFF_INSERT;equalities.pop();equalities.pop();pointer=equalities.length?equalities[equalities.length-1]:-1;length_changes1=0;length_changes2=0;lastequality=null;changes=true}}pointer++}if(changes){this.diff_cleanupMerge(diffs)}this.diff_cleanupSemanticLossless(diffs)};diff_match_patch.prototype.diff_cleanupSemanticLossless=function(diffs){function diff_cleanupSemanticScore(one,two,three){var whitespace=/\s/;var score=0;if(one.charAt(o
 ne.length-1).match(whitespace)||two.charAt(0).match(whitespace)){score++}if(two.charAt(two.length-1).match(whitespace)||three.charAt(0).match(whitespace)){score++}return score}var pointer=1;while(pointer<diffs.length-1){if(diffs[pointer-1][0]==DIFF_EQUAL&&diffs[pointer+1][0]==DIFF_EQUAL){var equality1=diffs[pointer-1][1];var edit=diffs[pointer][1];var equality2=diffs[pointer+1][1];var commonOffset=this.diff_commonSuffix(equality1,edit);if(commonOffset){var commonString=edit.substring(edit.length-commonOffset);equality1=equality1.substring(0,equality1.length-commonOffset);edit=commonString+edit.substring(0,edit.length-commonOffset);equality2=commonString+equality2}var bestEquality1=equality1;var bestEdit=edit;var bestEquality2=equality2;var bestScore=diff_cleanupSemanticScore(equality1,edit,equality2);while(edit.charAt(0)===equality2.charAt(0)){equality1+=edit.charAt(0);edit=edit.substring(1)+equality2.charAt(0);equality2=equality2.substring(1);var score=diff_cleanupSemanticS
 core(equality1,edit,equality2);if(score>=bestScore){bestScore=score;bestEquality1=equality1;bestEdit=edit;bestEquality2=equality2}}if(diffs[pointer-1][1]!=bestEquality1){diffs[pointer-1][1]=bestEquality1;diffs[pointer][1]=bestEdit;diffs[pointer+1][1]=bestEquality2}}pointer++}};diff_match_patch.prototype.diff_cleanupEfficiency=function(diffs){var changes=false;var equalities=[];var lastequality='';var pointer=0;var pre_ins=false;var pre_del=false;var post_ins=false;var post_del=false;while(pointer<diffs.length){if(diffs[pointer][0]==DIFF_EQUAL){if(diffs[pointer][1].length<this.Diff_EditCost&&(post_ins||post_del)){equalities.push(pointer);pre_ins=post_ins;pre_del=post_del;lastequality=diffs[pointer][1]}else{equalities=[];lastequality=''}post_ins=post_del=false}else{if(diffs[pointer][0]==DIFF_DELETE){post_del=true}else{post_ins=true}if(lastequality&&((pre_ins&&pre_del&&post_ins&&post_del)||((lastequality.length<this.Diff_EditCost/2)&&(pre_ins+pre_del+post_ins+post_del)==3))){di
 ffs.splice(equalities[equalities.length-1],0,[DIFF_DELETE,lastequality]);diffs[equalities[equalities.length-1]+1][0]=DIFF_INSERT;equalities.pop();lastequality='';if(pre_ins&&pre_del){post_ins=post_del=true;equalities=[]}else{equalities.pop();pointer=equalities.length?equalities[equalities.length-1]:-1;post_ins=post_del=false}changes=true}}pointer++}if(changes){this.diff_cleanupMerge(diffs)}};diff_match_patch.prototype.diff_cleanupMerge=function(diffs){diffs.push([DIFF_EQUAL,'']);var pointer=0;var count_delete=0;var count_insert=0;var text_delete='';var text_insert='';var commonlength;while(pointer<diffs.length){if(diffs[pointer][0]==DIFF_INSERT){count_insert++;text_insert+=diffs[pointer][1];pointer++}else if(diffs[pointer][0]==DIFF_DELETE){count_delete++;text_delete+=diffs[pointer][1];pointer++}else{if(count_delete!==0||count_insert!==0){if(count_delete!==0&&count_insert!==0){commonlength=this.diff_commonPrefix(text_insert,text_delete);if(commonlength!==0){if((pointer-count_
 delete-count_insert)>0&&diffs[pointer-count_delete-count_insert-1][0]==DIFF_EQUAL){diffs[pointer-count_delete-count_insert-1][1]+=text_insert.substring(0,commonlength)}else{diffs.splice(0,0,[DIFF_EQUAL,text_insert.substring(0,commonlength)]);pointer++}text_insert=text_insert.substring(commonlength);text_delete=text_delete.substring(commonlength)}commonlength=this.diff_commonSuffix(text_insert,text_delete);if(commonlength!==0){diffs[pointer][1]=text_insert.substring(text_insert.length-commonlength)+diffs[pointer][1];text_insert=text_insert.substring(0,text_insert.length-commonlength);text_delete=text_delete.substring(0,text_delete.length-commonlength)}}if(count_delete===0){diffs.splice(pointer-count_delete-count_insert,count_delete+count_insert,[DIFF_INSERT,text_insert])}else if(count_insert===0){diffs.splice(pointer-count_delete-count_insert,count_delete+count_insert,[DIFF_DELETE,text_delete])}else{diffs.splice(pointer-count_delete-count_insert,count_delete+count_insert,[DIF
 F_DELETE,text_delete],[DIFF_INSERT,text_insert])}pointer=pointer-count_delete-count_insert+(count_delete?1:0)+(count_insert?1:0)+1}else if(pointer!==0&&diffs[pointer-1][0]==DIFF_EQUAL){diffs[pointer-1][1]+=diffs[pointer][1];diffs.splice(pointer,1)}else{pointer++}count_insert=0;count_delete=0;text_delete='';text_insert=''}}if(diffs[diffs.length-1][1]===''){diffs.pop()}var changes=false;pointer=1;while(pointer<diffs.length-1){if(diffs[pointer-1][0]==DIFF_EQUAL&&diffs[pointer+1][0]==DIFF_EQUAL){if(diffs[pointer][1].substring(diffs[pointer][1].length-diffs[pointer-1][1].length)==diffs[pointer-1][1]){diffs[pointer][1]=diffs[pointer-1][1]+diffs[pointer][1].substring(0,diffs[pointer][1].length-diffs[pointer-1][1].length);diffs[pointer+1][1]=diffs[pointer-1][1]+diffs[pointer+1][1];diffs.splice(pointer-1,1);changes=true}else if(diffs[pointer][1].substring(0,diffs[pointer+1][1].length)==diffs[pointer+1][1]){diffs[pointer-1][1]+=diffs[pointer+1][1];diffs[pointer][1]=diffs[pointer][1].s
 ubstring(diffs[pointer+1][1].length)+diffs[pointer+1][1];diffs.splice(pointer+1,1);changes=true}}pointer++}if(changes){this.diff_cleanupMerge(diffs)}};diff_match_patch.prototype.diff_addIndex=function(diffs){var i=0;for(var x=0;x<diffs.length;x++){diffs[x].push(i);if(diffs[x][0]!==DIFF_DELETE){i+=diffs[x][1].length}}};diff_match_patch.prototype.diff_xIndex=function(diffs,loc){var chars1=0;var chars2=0;var last_chars1=0;var last_chars2=0;var x;for(x=0;x<diffs.length;x++){if(diffs[x][0]!==DIFF_INSERT){chars1+=diffs[x][1].length}if(diffs[x][0]!==DIFF_DELETE){chars2+=diffs[x][1].length}if(chars1>loc){break}last_chars1=chars1;last_chars2=chars2}if(diffs.length!=x&&diffs[x][0]===DIFF_DELETE){return last_chars2}return last_chars2+(loc-last_chars1)};diff_match_patch.prototype.diff_prettyHtml=function(diffs){this.diff_addIndex(diffs);var html=[];for(var x=0;x<diffs.length;x++){var m=diffs[x][0];var t=diffs[x][1];var i=diffs[x][2];t=t.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace
 (/>/g,'&gt;');t=t.replace(/\n/g,'&para;<BR>');if(m===DIFF_DELETE){html.push('<DEL STYLE="background:#FFE6E6;" TITLE="i=',i,'">',t,'</DEL>')}else if(m===DIFF_INSERT){html.push('<INS STYLE="background:#E6FFE6;" TITLE="i=',i,'">',t,'</INS>')}else{html.push('<SPAN TITLE="i=',i,'">',t,'</SPAN>')}}return html.join('')};diff_match_patch.prototype.diff_text1=function(diffs){var txt=[];for(var x=0;x<diffs.length;x++){if(diffs[x][0]!==DIFF_INSERT){txt.push(diffs[x][1])}}return txt.join('')};diff_match_patch.prototype.diff_text2=function(diffs){var txt=[];for(var x=0;x<diffs.length;x++){if(diffs[x][0]!==DIFF_DELETE){txt.push(diffs[x][1])}}return txt.join('')};diff_match_patch.prototype.diff_toDelta=function(diffs){var txt=[];for(var x=0;x<diffs.length;x++){switch(diffs[x][0]){case DIFF_DELETE:txt.push('-',diffs[x][1].length,'\t');break;case DIFF_EQUAL:txt.push('=',diffs[x][1].length,'\t');break;case DIFF_INSERT:txt.push('+',encodeURI(diffs[x][1]),'\t');break;default:alert('Invalid diff
  operation in diff_toDelta()')}}return txt.join('').replace(/%20/g,' ')};diff_match_patch.prototype.diff_fromDelta=function(text1,delta){var diffs=[];var pointer=0;var tokens=delta.split(/\t/g);for(var x=0;x<tokens.length;x++){var param=tokens[x].substring(1);switch(tokens[x].charAt(0)){case'-':case'=':var n=parseInt(param,10);if(isNaN(n)||n<0){alert('Invalid number in diff_fromDelta()')}else{var text=text1.substring(pointer,pointer+=n);if(tokens[x].charAt(0)=='='){diffs.push([DIFF_EQUAL,text])}else{diffs.push([DIFF_DELETE,text])}}break;case'+':diffs.push([DIFF_INSERT,decodeURI(param)]);break;default:if(tokens[x]){alert('Invalid diff operation in diff_fromDelta()')}}}if(pointer!=text1.length){alert('Text length mismatch in diff_fromDelta()')}return diffs};diff_match_patch.prototype.match_main=function(text,pattern,loc){loc=Math.max(0,Math.min(loc,text.length-pattern.length));if(text==pattern){return 0}else if(text.length===0){return null}else if(text.substring(loc,loc+patter
 n.length)==pattern){return loc}else{return this.match_bitap(text,pattern,loc)}};diff_match_patch.prototype.match_bitap=function(text,pattern,loc){if(pattern.length>this.Match_MaxBits){return alert('Pattern too long for this browser.')}var s=this.match_alphabet(pattern);var score_text_length=text.length;score_text_length=Math.max(score_text_length,this.Match_MinLength);score_text_length=Math.min(score_text_length,this.Match_MaxLength);var dmp=this;function match_bitapScore(e,x){var d=Math.abs(loc-x);return(e/pattern.length/dmp.Match_Balance)+(d/score_text_length/(1.0-dmp.Match_Balance))}var score_threshold=this.Match_Threshold;var best_loc=text.indexOf(pattern,loc);if(best_loc!=-1){score_threshold=Math.min(match_bitapScore(0,best_loc),score_threshold)}best_loc=text.lastIndexOf(pattern,loc+pattern.length);if(best_loc!=-1){score_threshold=Math.min(match_bitapScore(0,best_loc),score_threshold)}var matchmask=1<<(pattern.length-1);best_loc=null;var bin_min,bin_mid;var bin_max=Math
 .max(loc+loc,text.length);var last_rd;for(var d=0;d<pattern.length;d++){var rd=Array(text.length);bin_min=loc;bin_mid=bin_max;while(bin_min<bin_mid){if(match_bitapScore(d,bin_mid)<score_threshold){bin_min=bin_mid}else{bin_max=bin_mid}bin_mid=Math.floor((bin_max-bin_min)/2+bin_min)}bin_max=bin_mid;var start=Math.max(0,loc-(bin_mid-loc)-1);var finish=Math.min(text.length-1,pattern.length+bin_mid);if(text.charAt(finish)==pattern.charAt(pattern.length-1)){rd[finish]=(1<<(d+1))-1}else{rd[finish]=(1<<d)-1}for(var j=finish-1;j>=start;j--){if(d===0){rd[j]=((rd[j+1]<<1)|1)&s[text.charAt(j)]}else{rd[j]=((rd[j+1]<<1)|1)&s[text.charAt(j)]|((last_rd[j+1]<<1)|1)|((last_rd[j]<<1)|1)|last_rd[j+1]}if(rd[j]&matchmask){var score=match_bitapScore(d,j);if(score<=score_threshold){score_threshold=score;best_loc=j;if(j>loc){start=Math.max(0,loc-(j-loc))}else{break}}}}if(match_bitapScore(d+1,loc)>score_threshold){break}last_rd=rd}return best_loc};diff_match_patch.prototype.match_alphabet=function(pa
 ttern){var s=Object();for(var i=0;i<pattern.length;i++){s[pattern.charAt(i)]=0}for(var i=0;i<pattern.length;i++){s[pattern.charAt(i)]|=1<<(pattern.length-i-1)}return s};diff_match_patch.prototype.patch_addContext=function(patch,text){var pattern=text.substring(patch.start2,patch.start2+patch.length1);var padding=0;while(text.indexOf(pattern)!=text.lastIndexOf(pattern)&&pattern.length<this.Match_MaxBits-this.Patch_Margin-this.Patch_Margin){padding+=this.Patch_Margin;pattern=text.substring(patch.start2-padding,patch.start2+patch.length1+padding)}padding+=this.Patch_Margin;var prefix=text.substring(patch.start2-padding,patch.start2);if(prefix!==''){patch.diffs.unshift([DIFF_EQUAL,prefix])}var suffix=text.substring(patch.start2+patch.length1,patch.start2+patch.length1+padding);if(suffix!==''){patch.diffs.push([DIFF_EQUAL,suffix])}patch.start1-=prefix.length;patch.start2-=prefix.length;patch.length1+=prefix.length+suffix.length;patch.length2+=prefix.length+suffix.length};diff_mat
 ch_patch.prototype.patch_make=function(text1,text2,opt_diffs){var diffs;if(typeof opt_diffs!='undefined'){diffs=opt_diffs}else{diffs=this.diff_main(text1,text2,true);if(diffs.length>2){this.diff_cleanupSemantic(diffs);this.diff_cleanupEfficiency(diffs)}}if(diffs.length===0){return[]}var patches=[];var patch=new patch_obj();var char_count1=0;var char_count2=0;var prepatch_text=text1;var postpatch_text=text1;for(var x=0;x<diffs.length;x++){var diff_type=diffs[x][0];var diff_text=diffs[x][1];if(patch.diffs.length===0&&diff_type!==DIFF_EQUAL){patch.start1=char_count1;patch.start2=char_count2}if(diff_type===DIFF_INSERT){patch.diffs.push(diffs[x]);patch.length2+=diff_text.length;postpatch_text=postpatch_text.substring(0,char_count2)+diff_text+postpatch_text.substring(char_count2)}else if(diff_type===DIFF_DELETE){patch.length1+=diff_text.length;patch.diffs.push(diffs[x]);postpatch_text=postpatch_text.substring(0,char_count2)+postpatch_text.substring(char_count2+diff_text.length)}el
 se if(diff_type===DIFF_EQUAL&&diff_text.length<=2*this.Patch_Margin&&patch.diffs.length!==0&&diffs.length!=x+1){patch.diffs.push(diffs[x]);patch.length1+=diff_text.length;patch.length2+=diff_text.length}if(diff_type===DIFF_EQUAL&&diff_text.length>=2*this.Patch_Margin){if(patch.diffs.length!==0){this.patch_addContext(patch,prepatch_text);patches.push(patch);patch=new patch_obj();prepatch_text=postpatch_text}}if(diff_type!==DIFF_INSERT){char_count1+=diff_text.length}if(diff_type!==DIFF_DELETE){char_count2+=diff_text.length}}if(patch.diffs.length!==0){this.patch_addContext(patch,prepatch_text);patches.push(patch)}return patches};diff_match_patch.prototype.patch_apply=function(patches,text){this.patch_splitMax(patches);var results=[];var delta=0;for(var x=0;x<patches.length;x++){var expected_loc=patches[x].start2+delta;var text1=this.diff_text1(patches[x].diffs);var start_loc=this.match_main(text,text1,expected_loc);if(start_loc===null){results.push(false)}else{results.push(true
 );delta=start_loc-expected_loc;var text2=text.substring(start_loc,start_loc+text1.length);if(text1==text2){text=text.substring(0,start_loc)+this.diff_text2(patches[x].diffs)+text.substring(start_loc+text1.length)}else{var diffs=this.diff_main(text1,text2,false);this.diff_cleanupSemanticLossless(diffs);var index1=0;var index2;for(var y=0;y<patches[x].diffs.length;y++){var mod=patches[x].diffs[y];if(mod[0]!==DIFF_EQUAL){index2=this.diff_xIndex(diffs,index1)}if(mod[0]===DIFF_INSERT){text=text.substring(0,start_loc+index2)+mod[1]+text.substring(start_loc+index2)}else if(mod[0]===DIFF_DELETE){text=text.substring(0,start_loc+index2)+text.substring(start_loc+this.diff_xIndex(diffs,index1+mod[1].length))}if(mod[0]!==DIFF_DELETE){index1+=mod[1].length}}}}}return[text,results]};diff_match_patch.prototype.patch_splitMax=function(patches){for(var x=0;x<patches.length;x++){if(patches[x].length1>this.Match_MaxBits){var bigpatch=patches[x];patches.splice(x,1);var patch_size=this.Match_MaxB
 its;var start1=bigpatch.start1;var start2=bigpatch.start2;var precontext='';while(bigpatch.diffs.length!==0){var patch=new patch_obj();var empty=true;patch.start1=start1-precontext.length;patch.start2=start2-precontext.length;if(precontext!==''){patch.length1=patch.length2=precontext.length;patch.diffs.push([DIFF_EQUAL,precontext])}while(bigpatch.diffs.length!==0&&patch.length1<patch_size-this.Patch_Margin){var diff_type=bigpatch.diffs[0][0];var diff_text=bigpatch.diffs[0][1];if(diff_type===DIFF_INSERT){patch.length2+=diff_text.length;start2+=diff_text.length;patch.diffs.push(bigpatch.diffs.shift());empty=false}else{diff_text=diff_text.substring(0,patch_size-patch.length1-this.Patch_Margin);patch.length1+=diff_text.length;start1+=diff_text.length;if(diff_type===DIFF_EQUAL){patch.length2+=diff_text.length;start2+=diff_text.length}else{empty=false}patch.diffs.push([diff_type,diff_text]);if(diff_text==bigpatch.diffs[0][1]){bigpatch.diffs.shift()}else{bigpatch.diffs[0][1]=bigpat
 ch.diffs[0][1].substring(diff_text.length)}}}precontext=this.diff_text2(patch.diffs);precontext=precontext.substring(precontext.length-this.Patch_Margin);var postcontext=this.diff_text1(bigpatch.diffs).substring(0,this.Patch_Margin);if(postcontext!==''){patch.length1+=postcontext.length;patch.length2+=postcontext.length;if(patch.diffs.length!==0&&patch.diffs[patch.diffs.length-1][0]===DIFF_EQUAL){patch.diffs[patch.diffs.length-1][1]+=postcontext}else{patch.diffs.push([DIFF_EQUAL,postcontext])}}if(!empty){patches.splice(x++,0,patch)}}}}};diff_match_patch.prototype.patch_toText=function(patches){var text=[];for(var x=0;x<patches.length;x++){text.push(patches[x])}return text.join('')};diff_match_patch.prototype.patch_fromText=function(textline){var patches=[];var text=textline.split('\n');while(text.length!==0){var m=text[0].match(/^@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@$/);if(!m){return alert('Invalid patch string:\n'+text[0])}var patch=new patch_obj();patches.push(patch);patch.st
 art1=parseInt(m[1],10);if(m[2]===''){patch.start1--;patch.length1=1}else if(m[2]=='0'){patch.length1=0}else{patch.start1--;patch.length1=parseInt(m[2],10)}patch.start2=parseInt(m[3],10);if(m[4]===''){patch.start2--;patch.length2=1}else if(m[4]=='0'){patch.length2=0}else{patch.start2--;patch.length2=parseInt(m[4],10)}text.shift();while(text.length!==0){var sign=text[0].charAt(0);var line=decodeURIComponent(text[0].substring(1));if(sign=='-'){patch.diffs.push([DIFF_DELETE,line])}else if(sign=='+'){patch.diffs.push([DIFF_INSERT,line])}else if(sign==' '){patch.diffs.push([DIFF_EQUAL,line])}else if(sign=='@'){break}else if(sign===''){}else{return alert('Invalid patch mode: "'+sign+'"\n'+line)}text.shift()}}return patches};function patch_obj(){this.diffs=[];this.start1=null;this.start2=null;this.length1=0;this.length2=0}patch_obj.prototype.toString=function(){var coords1,coords2;if(this.length1===0){coords1=this.start1+',0'}else if(this.length1==1){coords1=this.start1+1}else{coord
 s1=(this.start1+1)+','+this.length1}if(this.length2===0){coords2=this.start2+',0'}else if(this.length2==1){coords2=this.start2+1}else{coords2=(this.start2+1)+','+this.length2}var txt=['@@ -',coords1,' +',coords2,' @@\n'];for(var x=0;x<this.diffs.length;x++){switch(this.diffs[x][0]){case DIFF_DELETE:txt.push('-');break;case DIFF_EQUAL:txt.push(' ');break;case DIFF_INSERT:txt.push('+');break;default:alert('Invalid diff operation in patch_obj.toString()')}txt.push(encodeURI(this.diffs[x][1]),'\n')}return txt.join('').replace(/%20/g,' ')};
\ No newline at end of file

Propchange: incubator/jspwiki/trunk/tests/JSSpec/Assets/Scripts/diff_match_patch.js
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/jspwiki/trunk/tests/JSSpec/Assets/Styles/JSSpec-jspwiki.css
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/tests/JSSpec/Assets/Styles/JSSpec-jspwiki.css?rev=787361&view=auto
==============================================================================
--- incubator/jspwiki/trunk/tests/JSSpec/Assets/Styles/JSSpec-jspwiki.css (added)
+++ incubator/jspwiki/trunk/tests/JSSpec/Assets/Styles/JSSpec-jspwiki.css Mon Jun 22 19:23:30 2009
@@ -0,0 +1,235 @@
+@CHARSET "UTF-8";
+/* 
+File:JSSpec-jspwiki.css
+	Stylesheet for javascript spec.
+	Adjusted for JSPWiki by Dirk Frederickx, Dec 2008
+
+License:
+	todo
+ */
+
+/* refined global reset */
+/* inspired by http://meyerweb.com/eric/thoughts/2007/05/01/reset-reloaded/ and yui reset */
+html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var, dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td {
+	margin:0;
+	padding:0;
+	border:0;
+	outline:none;
+	/* vertical-align:baseline; seems to give printing errors in FF */
+}
+pre {
+	font:120% Monaco, Courier New, monospace;
+	overflow:auto;
+	clear:both;
+	white-space:pre;
+	padding:0.5em;
+	background:#f9f9f9;
+	border:1px solid #ddd;
+}
+ul {
+	list-style:none;
+}
+a {
+	text-decoration:none;
+}
+a:link, a:visited {
+	color:#666;
+}
+a:hover, a:active {
+	cursor:pointer !important;
+}
+
+html {
+	overflow:hidden;
+}
+
+body, #jsspec_container {
+	color:black; 
+	background:white; 
+	xxfont:11px/1.5 Lucida Grande, Arial, Helvetica, Sans-Serif;
+	font:11px/1.5 Verdana,Arial,Helvetica,sans-serif;
+
+	overflow:hidden;
+	width:100%;
+	height:100%;
+}
+
+
+#title {
+	position:absolute;	
+	top:0;    	
+	left:0;	
+	width:100%;	
+	height:30px;	
+	overflow:hidden;
+	background:grey;
+	padding:0.5em;
+	color:white;
+}
+
+#list {	
+	position:absolute;    	
+	top:40px;	
+	left:0;	
+	bottom:0;	
+	overflow:auto;    	
+	width:20%;
+	_height:expression(document.body.clientHeight-40);
+}
+
+#log {	
+	position:absolute;    	
+	top:40px;	
+	width:80%;
+	right:0;	
+	bottom:0;	
+	overflow:auto;	
+	_height:expression(document.body.clientHeight-40);
+	_width:expression(document.body.clientWidth-250);
+}
+
+
+/* hiding subtitles */
+h2 {
+	background:white;
+	margin-bottom:0.25em;
+	padding:0.25em 0.5em;
+}
+
+/* title section */
+
+div#title h1 {
+	font-size:2em;
+	float:left;
+}
+#title ul {
+	margin-right:1em;
+}
+div#title ul li {
+	font-weight:bold;
+	font-size:1.25em;
+	float:right;
+	padding:0.25em;
+}
+
+div#title p {
+	padding:1.5em;
+	float:left;
+}
+
+/* spec container */
+ul.specs {
+	margin:0.5em;
+}
+
+ul.specs li {
+	margin-bottom:0.1em;
+}
+
+/* spec title */
+ul.specs li h3 {
+	font-weight:bold;
+	padding:0.25em 1em;
+	cursor:pointer !important;
+}
+
+/* example container */
+ul.examples li {
+	border-style:solid;
+	margin:0.5em 0em 0.5em 2em;
+}
+
+/* example title */
+ul.examples li h4 {
+	padding:0.25em 0.5em;
+	margin-bottom:0.25em;
+}
+
+/* example explanation */
+ul.examples li div {
+	overflow:hidden;
+	padding:0.5em;
+}
+
+/* highlight clickable title blocks to collopse/hide spec examples */
+#log ul.specs li h3:hover {
+	padding-left:0.5em;
+	border-left:0.5em solid gray;
+	padding-right:0.5em;
+	border-right:0.5em solid gray;
+}
+
+/* styles for ongoing, success, failure, error */
+div.success, div.success a {
+	color:#9f9;
+}
+
+ul.specs li.success h3, ul.specs li.success h3 a {
+	background-color:#9f9;
+}
+
+ul.examples li.success, ul.examples li.success a {
+	background-color:#9f9;
+}
+
+div.exception, div.exception a {
+	color:#f93;
+}
+
+ul.specs li.exception h3, ul.specs li.exception h3 a {
+	background-color:#f93;
+}
+
+ul.examples li.exception, ul.examples li.exception a {
+	background-color:#f93;
+}
+
+div.ongoing, div.ongoing a {
+	color:#ffff80;
+}
+
+ul.specs li.ongoing h3, ul.specs li.ongoing h3 a {
+	background-color:#ffff80;
+} 
+
+ul.examples li.ongoing, ul.examples li.ongoing a {
+	background-color:#ffff80;
+}
+
+/* --------------------
+ * values
+ */
+
+.number_value, .string_value, .regexp_value, .boolean_value, .dom_value {
+	font-family: monospace;
+	color: blue;
+	white-space: pre;
+}
+
+.object_value, .array_value {
+}
+
+.date_value {
+	color:olive;
+}
+
+.undefined_value, .null_value {
+	color:blue;
+}
+
+.dom_attr_name {
+}
+
+.dom_attr_value {
+	color:red;
+}
+
+.dom_path {
+	color:gray;
+}
+
+strong {
+}
\ No newline at end of file

Added: incubator/jspwiki/trunk/tests/JSSpec/Assets/Styles/JSSpec.css
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/tests/JSSpec/Assets/Styles/JSSpec.css?rev=787361&view=auto
==============================================================================
--- incubator/jspwiki/trunk/tests/JSSpec/Assets/Styles/JSSpec.css (added)
+++ incubator/jspwiki/trunk/tests/JSSpec/Assets/Styles/JSSpec.css Mon Jun 22 19:23:30 2009
@@ -0,0 +1,214 @@
+@CHARSET "UTF-8";
+/* --------------------
+ * @Layout
+ */
+ 
+html {
+	overflow: hidden;
+}
+
+body, #jsspec_container {
+	overflow: hidden;
+	padding: 0;
+	margin: 0;
+	width: 100%;
+	height: 100%;
+}
+
+#title {
+	padding: 0;
+	margin: 0;	
+	position: absolute;	
+	top: 0px;    	
+	left: 0px;	
+	width: 100%;	
+	height: 40px;	
+	overflow: hidden;
+}
+
+#list {	
+	padding: 0;	
+	margin: 0;	
+	position: absolute;    	
+	top: 40px;	
+	left: 0px;	
+	bottom: 0px;	
+	overflow: auto;    	
+	width: 250px;    	
+	_height:expression(document.body.clientHeight-40);
+}
+
+#log {	
+	padding: 0;	
+	margin: 0;	
+	position: absolute;    	
+	top: 40px;	
+	left: 250px;	
+	right: 0px;	
+	bottom: 0px;	
+	overflow: auto;	
+	_height:expression(document.body.clientHeight-40);
+	_width:expression(document.body.clientWidth-250);
+}
+
+/* --------------------
+ * @Decorations and colors
+ */
+* {	padding: 0;	margin: 0;	font-family: "Lucida Grande", Helvetica, sans-serif;
+}
+
+li {
+	list-style: none;
+}
+
+/* hiding subtitles */
+h2 {
+	display: none;
+}
+
+/* title section */
+div#title {
+	padding: 0em 0.5em;
+}
+
+div#title h1 {
+	font-size: 1.5em;
+	float: left;
+}
+
+div#title ul li {
+	float: left;
+	padding: 0.5em 0em 0.5em 0.75em;
+}
+
+div#title p {
+	float:right;
+	margin-right:1em;
+	font-size: 0.75em;
+}
+
+/* spec container */
+ul.specs {
+	margin: 0.5em;
+}
+
+ul.specs li {
+	margin-bottom: 0.1em;
+}
+
+/* spec title */
+ul.specs li h3 {
+	font-weight: bold;
+	font-size: 0.75em;
+	padding: 0.2em 1em;
+}
+
+/* example container */
+ul.examples li {
+	border-style: solid;
+	border-width: 1px 1px 1px 5px;
+	margin: 0.2em 0em 0.2em 1em;
+}
+
+/* example title */
+ul.examples li h4 {
+	font-weight: normal;
+	font-size: 0.75em;
+	margin-left: 1em;
+}
+
+/* example explaination */
+ul.examples li div {
+	padding: 1em 2em;
+	font-size: 0.75em;
+}
+
+/* styles for ongoing, success, failure, error */
+div.success, div.success a {
+	color: #FFFFFF;
+	background-color: #65C400;
+}
+
+ul.specs li.success h3, ul.specs li.success h3 a {
+	color: #FFFFFF;
+	background-color: #65C400;
+}
+
+ul.examples li.success, ul.examples li.success a {
+	color: #3D7700;
+	background-color: #DBFFB4;
+	border-color: #65C400;
+}
+
+div.exception, div.exception a {
+	color: #FFFFFF;	background-color: #C20000;
+}
+
+ul.specs li.exception h3, ul.specs li.exception h3 a {
+	color: #FFFFFF;
+	background-color: #C20000;
+}
+
+ul.examples li.exception, ul.examples li.exception a {
+	color: #C20000;
+	background-color: #FFFBD3;
+	border-color: #C20000;
+}
+
+div.ongoing, div.ongoing a {
+	color: #000000;
+	background-color: #FFFF80;
+}
+
+ul.specs li.ongoing h3, ul.specs li.ongoing h3 a {
+	color: #000000;
+	background-color: #FFFF80;
+} 
+
+ul.examples li.ongoing, ul.examples li.ongoing a {
+	color: #000000;
+	background-color: #FFFF80;
+	border-color: #DDDD00;
+}
+
+/* --------------------
+ * values
+ */
+
+.number_value, .string_value, .regexp_value, .boolean_value, .dom_value {
+	font-family: monospace;
+	color: blue;
+}
+
+.object_value, .array_value {
+	line-height: 2em;
+	padding: 0.1em 0.2em;
+	margin: 0.1em 0;
+}
+
+.date_value {
+	font-family: monospace;
+	color: olive;
+}
+
+.undefined_value, .null_value {
+	font-style: italic;
+	color: blue;
+}
+
+.dom_attr_name {
+}
+
+.dom_attr_value {
+	color: red;
+}
+
+.dom_path {
+	font-size: 0.75em;
+	color: gray;
+}
+
+strong {
+	font-weight: normal;
+	background-color: #FFC6C6;
+}
\ No newline at end of file

Propchange: incubator/jspwiki/trunk/tests/JSSpec/Assets/Styles/JSSpec.css
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/jspwiki/trunk/tests/JSSpec/JSSpec-dialog.js
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/tests/JSSpec/JSSpec-dialog.js?rev=787361&view=auto
==============================================================================
--- incubator/jspwiki/trunk/tests/JSSpec/JSSpec-dialog.js (added)
+++ incubator/jspwiki/trunk/tests/JSSpec/JSSpec-dialog.js Mon Jun 22 19:23:30 2009
@@ -0,0 +1,209 @@
+/*
+Script: SnipEditorSpecs.js
+	Test following classes: SnipEditor, Textarea, UndoRedo
+
+License:
+	xxx
+
+*/
+
+describe('Dialog & descendent Class specs', {
+
+	before_each : function() {
+		$$('body')[0].adopt( tst = new Element('p') );
+		tst.setHTML("empty");
+		dialog = null;	
+	},
+	after_each: function(){
+	
+		dialog = null;
+		tst.remove();
+	},
+	
+	//BASE DIALOG CLASS : test TODO
+
+
+	//SELECTION DIALOG
+	'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.setHTML( value ); }
+		});
+
+		var els = $ES("li",dialog.body), el = els[0];
+
+		value_of(els.length).should_be(3);
+		value_of(el.getText()).should_be('left');
+		value_of(el.getProperty('title')).should_be('left');
+
+		dialog.fireEvent('onSelect','newvalue');
+		value_of(tst.getText()).should_be('newvalue');		
+	},
+
+	'should turn a array into a selection dialog': function() {
+		var dialog = new SelectionDialog({
+			body:['left','center'],
+			caption:"select",
+			relativeTo:tst,
+			onSelect:function(value){ tst.setHTML( value ); }
+		});
+
+		var els = $ES("li",dialog.body), el = els[0];
+
+		value_of(els.length).should_be(2);
+		value_of(el.getText()).should_be('left');
+		value_of(el.getProperty('title')).should_be('left');
+	},
+
+	'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.setHTML( value ); }
+		});
+
+		var els = $ES("li",dialog.body), el = els[2];
+
+		value_of(els.length).should_be(3);
+		value_of(el.getText()).should_be('Right');
+		value_of(el.getProperty('title')).should_be('right');
+	},
+	
+	'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.toString(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.setHTML( value ); }
+		});
+
+		value_of(dialog.element.getStyle('display')).should_be('none'); 
+		
+		dialog.toggle();
+		value_of(dialog.element.getStyle('display')).should_not_be('none'); 
+
+		var el = $ES("li",dialog.body)[1];
+		dialog.onSelect({ 'type':'mousedown', target:el });
+		value_of(tst.getText()).should_be('center');
+
+		value_of(dialog.element.getStyle('display')).should_be('none');		
+	},
+
+	'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.setHTML( value ); }
+		});
+
+		//todo validate position on the dialog
+	},
+
+
+	//FONT DIALOG		
+	'should generate a standard Font Dialog': function() {
+
+		var dialog= new FontDialog({
+			caption:"font",
+			relativeTo:tst,
+			onSelect:function(value){ tst.setHTML( value ); }
+		});
+
+		var els = $ES("li",dialog.body), el = els[1];
+
+		value_of(els.length).should_be(9);
+		value_of(el.getText()).should_be('Comic Sans');
+		value_of(el.getProperty('title')).should_be('comic sans ms');
+
+		//funny browser 'dependency'
+		if(window.webkit){
+			value_of(el.getStyle('font-family')).should_be("'comic sans ms'");
+		} else {
+			value_of(el.getStyle('font-family')).should_be("comic sans ms");
+		}
+		dialog.fireEvent('onSelect','newvalue');
+		value_of(tst.getText()).should_be('newvalue');
+	},
+
+	'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.setHTML( value ); }
+		});
+
+		var els = $ES("li",dialog.body), el = els[1];
+
+		value_of(els.length).should_be(2);
+		value_of(el.getText()).should_be('Font name2');
+		value_of(el.getProperty('title')).should_be('font2');
+		value_of(el.getStyle('font-family')).should_be('font2');
+
+	},
+
+	//CHARS DIALOG
+	'should generate a standard Chars Dialog': function() {
+
+		var dialog= new CharsDialog({
+			caption:"special chars",
+			relativeTo:tst,
+			onSelect:function(value){ tst.setHTML( value ); }
+		});
+
+		var els = $ES("td",dialog.body), el = els[11];
+
+		value_of(els.length).should_be(9*11);
+		//value_of(el.getText()).should_be('&deg;');
+		value_of(el.getProperty('title')).should_be('&deg;');
+
+		dialog.fireEvent('onSelect','newvalue');
+		value_of(tst.getText()).should_be('newvalue');
+		
+	},
+	
+	//COLOR DIALOG
+
+	'should generate a standard Color Dialog': function() {
+
+		var dialog= new ColorDialog({
+			relativeTo:tst,
+			onChange:function(value){ tst.setHTML( value ); }
+		});
+
+		var img = $ES("img",dialog.body);
+
+		value_of(img.length).should_be(1);
+		value_of(img[0].getProperty('src')).should_be('images/circle-256.png');
+		value_of(dialog.color.getText()).should_be('#ffffff');
+		value_of(dialog.cursor).should_not_be( null );
+		value_of(dialog.hsv).should_be([0,0,100]);
+
+		dialog.fireEvent('onChange','newvalue');
+		value_of(tst.getText()).should_be('newvalue');
+	}
+
+});
+

Added: incubator/jspwiki/trunk/tests/JSSpec/JSSpec-index.html
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/tests/JSSpec/JSSpec-index.html?rev=787361&view=auto
==============================================================================
--- incubator/jspwiki/trunk/tests/JSSpec/JSSpec-index.html (added)
+++ incubator/jspwiki/trunk/tests/JSSpec/JSSpec-index.html Mon Jun 22 19:23:30 2009
@@ -0,0 +1,31 @@
+<!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>Testing JSPWiki Javascript routines</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+
+  <link rel="stylesheet" type="text/css" media="screen" href="./Assets/Styles/JSSpec-jspwiki.css" />
+  <script type="text/javascript" src="./Assets/Scripts/JSSpec.js"></script>
+  <script type="text/javascript" src="./Assets/Scripts/diff_match_patch.js"></script>
+
+  <script type="text/javascript" src="../../src/WebContent/scripts/mootools.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="../documoo/documoo.js"></script>--!>
+
+  <script type="text/javascript" src="./JSSpec-jspwiki-common.js"></script>
+  <script type="text/javascript" src="./JSSpec-jspwiki-edit.js"></script>
+  <script type="text/javascript" src="./JSSpec-dialog.js"></script>
+  <!--<script type="text/javascript" src="./documoo/documooSpecs.js"></script>--!>
+
+</head>
+
+<body>
+
+</body>
+
+</html>
\ No newline at end of file

Added: incubator/jspwiki/trunk/tests/JSSpec/JSSpec-jspwiki-common.js
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/tests/JSSpec/JSSpec-jspwiki-common.js?rev=787361&view=auto
==============================================================================
--- incubator/jspwiki/trunk/tests/JSSpec/JSSpec-jspwiki-common.js (added)
+++ incubator/jspwiki/trunk/tests/JSSpec/JSSpec-jspwiki-common.js Mon Jun 22 19:23:30 2009
@@ -0,0 +1,507 @@
+/*
+Script: jspwiki-commonSpecs.js
+
+License:
+	http://www.apache.org/licenses/LICENSE-2.0
+*/
+
+describe('Basic Javascript specs', {
+
+	'toLowerCase()': function() {
+		value_of('Hello'.toLowerCase()).should_be('hello');
+	},
+	'Match array literals': function() {
+		value_of([1,2,3]).should_be([1,2,3]);
+	},
+	'Difference of array literals': function() {
+		value_of([1,2,3]).should_not_be([4,5,6]);
+	},
+	'Match date literals': function() {
+		value_of(new Date(1979,03,27)).should_be(new Date(1979,03,27));
+	},
+	'DOM firstChild operator': function() {
+		value_of(document.body.firstChild).should_be(document.body.firstChild);
+	}
+});
+
+describe('Common mootools extensions',{
+
+	'should convert camel-case into space separated sentences': function(){
+
+		value_of('thisIsCamelCase'.deCamelize()).should_be('this Is Camel Case');
+		value_of('thisIsACamelCase'.deCamelize()).should_be('this Is ACamel Case');
+
+	},
+	
+	'should truncate a string to a maximum size': function(){
+	
+		value_of('test'.trunc(6)).should_be('test');
+		value_of('test a longer string'.trunc(6)).should_be('test a...');
+		value_of('test a longer string'.trunc(6,"---")).should_be('test a---');
+	
+	},
+	
+	'should return the text value of a DOM element': function(){
+	
+		var a = new Element('div');
+		a.innerHTML= "test string";
+
+		value_of( $getText(a) ).should_be('test string');	
+	
+	},
+
+	'should return the last item in the array': function(){
+
+    	value_of([].getLast()).should_be(null);
+    	value_of([3].getLast()).should_be(3);
+	    value_of([1,2,3,0,0,6].getLast()).should_be(6);
+
+	},
+ 
+	'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').setHTML(html);
+		var wrap = new Element('p').wraps(div);
+		
+		value_of(wrap.innerHTML).should_be(html);
+		value_of(div.innerHTML).should_be("<p>"+html+"</p>");
+
+	},
+	
+	'should return the visibility of an DOM element, depending on the visibility of one of its parents': function() {
+
+		var span = new Element('span').setHTML('Inside text');
+		var div = new Element('div',{'styles':{'display':'none'}}).adopt(span);		
+		value_of(span.visible()).should_be(false);
+
+		div.setStyle('display','block');
+		value_of(span.visible()).should_be(true);
+	},
+
+	'should return the default value of any form element': function(){
+
+		var form = new Element('form').setHTML([
+			"<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(''));
+
+		value_of( form.input.getDefaultValue() ).should_be(false);
+		value_of( form.select.getDefaultValue() ).should_be('saab');
+		value_of( form.textarea.getDefaultValue() ).should_be('textarea-value');
+
+		//now change the value of the form elements
+		form.input.checked = true;
+		form.select.selectedIndex = 0;
+		form.textarea.value = "new textarea-value";
+
+		value_of( form.input.getValue() ).should_be('on'); //strange return value FIXME
+		value_of( form.select.getValue() ).should_be('volvo');
+		value_of( form.textarea.getValue() ).should_be('new textarea-value');
+
+		//the default values remain unchanged
+		value_of( form.input.getDefaultValue() ).should_be(false);
+		value_of( form.select.getDefaultValue() ).should_be('saab');
+		value_of( form.textarea.getDefaultValue() ).should_be('textarea-value');
+	},
+	
+	'should return a localized string': function(){
+
+		LocalizedStrings = {
+			'javascript.moreInfo' : 'More',
+			'javascript.imageInfo' : 'Image {0} of {1}'
+		};
+		
+		value_of( "moreInfo".localize() ).should_be('More');
+		value_of( "imageInfo".localize(2) ).should_be('Image 2 of ???1???');
+		value_of( "imageInfo".localize(2,4) ).should_be('Image 2 of 4');
+		value_of( "imageInfo".localize(2,4,6) ).should_be('Image 2 of 4');
+		value_of( "funny string".localize() ).should_be('???funny string???');
+	}
+
+});
+
+
+describe('Main WIKI class',{
+
+	'should convert a pagename into a wiki url':function(){
+
+		Wiki.PageUrl = '/JSPWiki-pipo/Wiki.jsp?page=%23%24%25';
+		
+		value_of(Wiki.toUrl('test')).should_be('/JSPWiki-pipo/Wiki.jsp?page=test');		
+	},
+	
+	'should convert a wiki url into a pagename':function(){
+
+		Wiki.PageUrl = '/JSPWiki-pipo/Wiki.jsp?page=%23%24%25';
+		
+		value_of(Wiki.toPageName('/JSPWiki-pipo/Wiki.jsp?page=test')).should_be('test');
+		value_of(Wiki.toPageName('test')).should_be(false);
+	},
+	
+	'should remove funny chars to make a valid wiki pagename':function(){
+		
+		value_of(Wiki.cleanPageName('  ab    cd  ')).should_be('ab cd');
+		value_of(Wiki.cleanPageName('a1b2c3()&+,-=._$d4e5f6')).should_be('a1b2c3()&+,-=._$d4e5f6');
+		value_of(Wiki.cleanPageName('ab%@!\\?cd')).should_be('abcd');	
+	}
+
+});
+
+
+describe('WikiSlimbox class',{
+});
+
+describe('TabbedSection class',{
+});
+
+describe('Searchbox class',{
+});
+
+describe('Color class',{
+
+	'hex constructor - should have the correct rgb': function(){
+		var myColor = new Color('#a2c240');
+		value_of(myColor).should_be([162, 194, 64]);
+	},
+	
+	'hex constructor - should have the correct hex': function(){
+		var myColor = new Color('#a2c240');
+		value_of(myColor.hex).should_be('#a2c240');
+
+		myColor = new Color('#666');  //short notation
+		value_of(myColor.hex).should_be('#666666');
+	},
+
+	'rgb constructor - should have the correct rgb': function(){
+		//var myColor = new Color('rgb(162, 194, 64)');
+		//value_of(myColor).should_be([162, 194, 64]);
+
+		var myColor = new Color([162, 194, 64]);
+		value_of(myColor).should_be([162, 194, 64]);
+	},
+
+	'rgb constructor - should have the correct hex': function(){
+		//var myColor = new Color('rgb(162, 194, 64)');
+		//value_of(myColor.hex).should_be('#a2c240');
+
+		myColor = new Color([162, 194, 64]);
+		value_of(myColor.hex).should_be('#a2c240');
+	},
+
+	'html-name constructor - should have the correct hex': function(){
+		var myColor = new Color('lime');
+		value_of(myColor.hex).should_be('#00ff00');
+		value_of(myColor).should_be([0, 255, 0]);
+	},
+	
+	'should mix two colors': function(){
+		var myColor = new Color('#000').mix('#fff', [255, 0, 255], 10);
+		value_of(myColor.hex).should_be('#311731');
+	},
+	
+	'should invert a color': function(){
+		var white = new Color('white');
+		var black = new Color('black');
+
+		value_of(white.invert().hex).should_be( black.hex );		
+	}
+});
+
+
+describe('GraphBar class',{
+});
+
+describe('Collapsible class',{
+});
+
+describe('TableAdds class',{
+
+	before_each : 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]).getText().trim() );
+			});
+			return result;
+		};
+
+		var s = '';
+		s+= row('Title  | Author  | Published    | Edition  | Some IP@         | Expenses  | Disk Memory').replace(/td>/g,"th>");
+		s+= row('book1  |  zappy  |  25 Feb 2005 |  5       |  100.100.100.100 |  €500     |  2Gb ');
+		s+= row('book2  |  happy  |  25 Jan 2005 |  19      |  256.100.100.100 |  €1500    |  4Kb');
+		s+= row('book3  |  pappy  |  23 Mar 2005 |  06      |  10.100.100.100  |  €50      |  1.23TB');
+		s+= row('book4  |  dappy  |  21 Apr 2005 |  199     |  1.100.100.100   |  €0.500   |  2.73kb');
+		s+= row('book5  |  pappy  |  25 Jul 2005 |  017     |  1.100.25.100    |  €5500    |  0.4Tb');
+
+		myTable.setHTML(s);		
+	},
+	after_each: function(){
+		myTable.remove();
+	},
+
+	'should add default color zebra stripes to a table': function(){
+		new TableAdds(myTable, {zebra:['table']});
+
+		var rows = myTable.rows;
+		value_of( rows[1].hasClass('odd') ).should_be(false);
+		value_of( rows[2].hasClass('odd') ).should_be(true);
+		value_of( rows[3].hasClass('odd') ).should_be(false);
+		
+	},
+	'should add one color zebra stripes to a table': function(){
+		new TableAdds(myTable, {zebra:['#fffff']});
+
+		var rows = myTable.rows;
+		value_of( rows[1].getStyle('background-color') ).should_be('transparent');
+		value_of( rows[2].getStyle('background-color') ).should_be('#ffffff');
+		value_of( rows[3].getStyle('background-color') ).should_be('transparent');
+		
+	},
+
+	'should add 2 color zebra stripes to a table': function(){
+		new TableAdds(myTable, {zebra:['#fffff','lime']});
+
+		var rows = myTable.rows;
+		value_of( rows[1].getStyle('background-color') ).should_be('#00ff00');
+		value_of( rows[2].getStyle('background-color') ).should_be('#ffffff');
+		value_of( rows[3].getStyle('background-color') ).should_be('#00ff00');
+		
+	},
+
+	'should sort numbers': function(){
+	
+		var tt = new TableAdds(myTable, {sort:true});
+		var column = 3, data=[];
+
+		data = getcol(column);
+		value_of(data).should_be( ['5', '19', '06', '199', '017'] );
+		
+		tt.sort(column); //ascending
+		data = getcol(column);
+		value_of(data).should_be( ['5', '06', '017', '19', '199'] );
+
+		tt.sort(column); //descending
+		data = getcol(column);
+		value_of(data).should_be( ['199', '19', '017', '06', '5' ] );		
+	
+	},
+	'should sort dates': function(){
+
+		var tt = new TableAdds(myTable, {sort:true});
+		var column = 2, data=[];
+
+		data = getcol(column);
+		value_of(data).should_be( ['25 Feb 2005', '25 Jan 2005', '23 Mar 2005', '21 Apr 2005', '25 Jul 2005'] );
+		
+		tt.sort(column); //ascending
+		data = getcol(column);
+		value_of(data).should_be( ['25 Jan 2005',  '25 Feb 2005', '23 Mar 2005', '21 Apr 2005', '25 Jul 2005'] );
+
+		tt.sort(column); //descending
+		data = getcol(column);
+		value_of(data).should_be( ['25 Jul 2005', '21 Apr 2005', '23 Mar 2005', '25 Feb 2005', '25 Jan 2005'] );		
+	
+	},
+	'should sort currency': function(){
+
+		var tt = new TableAdds(myTable, {sort:true});
+		var column = 5, data=[];
+
+		data = getcol(column);
+		value_of(data).should_be( ['€500', '€1500', '€50', '€0.500', '€5500'] );
+		
+		tt.sort(column); //ascending
+		data = getcol(column);
+		value_of(data).should_be( ['€0.500', '€50', '€500', '€1500', '€5500'] );
+
+		tt.sort(column); //descending
+		data = getcol(column);
+		value_of(data).should_be( ['€5500', '€1500', '€500', '€50', '€0.500'] );
+	
+	},
+	'should sort ip@': function(){
+
+		var tt = new TableAdds(myTable, {sort:true});
+		var column = 4, data=[];
+
+		data = getcol(column);
+		value_of(data).should_be( ['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);
+		value_of(data).should_be( ['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);
+		value_of(data).should_be( ['256.100.100.100', '100.100.100.100', '10.100.100.100', '1.100.100.100', '1.100.25.100'] );
+	
+	},
+	'should sort Tb, Gb, Mb, Kb memory values': function(){
+
+		var tt = new TableAdds(myTable, {sort:true});
+		var column = 6, data=[];
+
+		data = getcol(column);
+		value_of(data).should_be( ['2Gb', '4Kb', '1.23TB', '2.73kb', '0.4Tb'] );
+		
+		tt.sort(column); //ascending
+		data = getcol(column);
+		value_of(data).should_be( ['2.73kb', '4Kb', '2Gb', '0.4Tb', '1.23TB'] );
+
+		tt.sort(column); //descending
+		data = getcol(column);
+		value_of(data).should_be( ['1.23TB', '0.4Tb', '2Gb', '4Kb', '2.73kb'] );
+	
+	},
+	'should sort strings': function(){
+
+		var tt = new TableAdds(myTable, {sort:true});
+		var column = 1, data=[];
+
+		data = getcol(column);
+		value_of(data).should_be( ['zappy', 'happy', 'pappy', 'dappy', 'pappy'] );
+		
+		tt.sort(column); //ascending
+		data = getcol(column);
+		value_of(data).should_be( ['dappy', 'happy', 'pappy', 'pappy', 'zappy'] );
+
+		tt.sort(column); //descending
+		data = getcol(column);
+		value_of(data).should_be( ['zappy', 'pappy', 'pappy', 'happy', 'dappy'] );
+	
+	},
+	'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);
+		value_of(data).should_be( ['5', '19', '06', '199', '017'] );
+		
+		tt.sort(column); //ascending
+		data = getcol(column);
+		value_of(data).should_not_be( ['5', '06', '017', '19', '199'] );
+		value_of(data).should_be( ['5', '19', '06', '199', '017'] );
+
+		tt.sort(column); //descending
+		data = getcol(column);
+		value_of(data).should_not_be( ['199', '19', '017', '06', '5' ] );		
+		value_of(data).should_be( ['017', '199', '06', '19', '5'] );
+	
+	},
+	'should filter a columns': function(){
+
+		var tt = new TableAdds(myTable, {filter:true});
+		var column = 3, data=[];
+
+		data = getcol(column);
+		value_of(data).should_be( ['5', '19', '06', '199', '017'] );
+		
+		tt.filter(column, 6);
+		data = getcol(column);
+		value_of(data).should_be( ['06'] );
+
+
+	},
+	'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);
+		value_of(data).should_be( ['zappy', 'happy', 'pappy', 'dappy', 'pappy'] );
+		
+		tt.filter(column, 'pappy');
+		data = getcol(column);
+		value_of(data).should_be( ['pappy','pappy'] );
+	
+		data = getcol(0);
+		value_of(data).should_be( ['book3','book5'] );
+	},
+	'should combine sorting and filtering to a table': function(){
+
+		var t1 = new TableAdds(myTable, {filter:true});
+
+		value_of(t1.filters).should_not_be(undefined);
+		value_of(t1.sorted).should_be(undefined);
+
+		var t2 = new TableAdds(myTable, {sort:true});
+		value_of(t1).should_be( t2 );
+		value_of(t1.filters).should_not_be(undefined);
+		value_of(t1.sorted).should_be(true);		
+
+		var column = 1, data=[];
+		data = getcol(column);
+		value_of(data).should_be( ['zappy', 'happy', 'pappy', 'dappy', 'pappy'] );
+		
+		t1.sort(column);
+		t1.sort(column);
+		data = getcol(column);
+		value_of(data).should_be( ['zappy', 'pappy', 'pappy', 'happy', 'dappy'] );
+
+		t1.filter(column, 'pappy');
+		data = getcol(column);
+		value_of(data).should_be( ['pappy','pappy'] );
+	
+		data = getcol(0);
+		value_of(data).should_be( ['book5','book3'] );
+
+
+	},
+	'should combine sorting, filtering and zebra-stripes to a table': function(){
+
+		var t1 = new TableAdds(myTable, {filter:true, sort:true, zebra:['red'] });
+
+		value_of(t1.filters).should_not_be(undefined);
+		value_of(t1.sorted).should_be(true);		
+		value_of(t1.zebra).should_not_be(undefined);
+		
+		var column = 1, data=[];
+		data = getcol(column);
+		value_of(data).should_be( ['zappy', 'happy', 'pappy', 'dappy', 'pappy'] );
+		
+		t1.sort(column);
+		t1.sort(column);
+		data = getcol(column);
+		value_of(data).should_be( ['zappy', 'pappy', 'pappy', 'happy', 'dappy'] );
+
+		t1.filter(column, 'pappy');
+		data = getcol(column);
+		value_of(data).should_be( ['pappy','pappy'] );	
+		data = getcol(0);
+		value_of(data).should_be( ['book5','book3'] );
+
+		var rows = myTable.rows;
+		value_of( rows[0].getStyle('background-color') ).should_be('transparent');
+		value_of( rows[2].getStyle('background-color') ).should_be('transparent');
+		value_of( rows[3].getStyle('background-color') ).should_be('#ff0000');
+
+	}
+
+});
+
+describe('Categories class',{
+});
+
+describe('HighlightWord class',{
+});

Added: incubator/jspwiki/trunk/tests/JSSpec/JSSpec-jspwiki-edit.js
URL: http://svn.apache.org/viewvc/incubator/jspwiki/trunk/tests/JSSpec/JSSpec-jspwiki-edit.js?rev=787361&view=auto
==============================================================================
--- incubator/jspwiki/trunk/tests/JSSpec/JSSpec-jspwiki-edit.js (added)
+++ incubator/jspwiki/trunk/tests/JSSpec/JSSpec-jspwiki-edit.js Mon Jun 22 19:23:30 2009
@@ -0,0 +1,734 @@
+/*
+Script: jspwiki-editSpecs.js
+
+License:
+	xxx
+
+*/
+
+
+describe('JSPWiki-commonstyles: ...',{
+});
+
+
+
+describe('JSPWiki-prefs',{
+});
+
+
+
+
+/*
+Script: snipeditorSpecs.js
+	Test following classes: WikiEditor, SnipEditor, Textarea, UndoRedo
+
+License:
+	xxx
+
+*/
+
+describe('Edit: UndoRedo Class',{
+
+	before_each: 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});
+
+	},
+
+	after_each: function(){
+		WORK = null, UNDOREDO = null;
+		UndoElement.remove();
+		RedoElement.remove();
+	},
+
+	'should initialize': function(){
+
+		value_of(UNDOREDO.obj).should_be(WORK);				
+		value_of(UNDOREDO.options.maxundo).should_be(40);
+		value_of(UNDOREDO.redo).should_be_empty();
+		value_of(UNDOREDO.undo).should_be_empty();
+		value_of(UNDOREDO.undoEL).should_not_be(null);
+		value_of(UNDOREDO.redoEL).should_be(RedoElement);
+
+		UNDOREDO = new UndoRedo( WORK ,{maxundo:3});
+
+		value_of(UNDOREDO.obj).should_be(WORK);				
+		value_of(UNDOREDO.options.maxundo).should_be(3);
+		
+	},
+	
+	'should undo a single element': function(){
+
+		UNDOREDO.onChange();
+		WORK.state = "changed";
+		
+		value_of(UNDOREDO.undo).should_be(['testing']);		
+		value_of(WORK.state).should_be(['changed']);
+		value_of(UndoElement.hasClass('disabled')).should_be_false();
+		value_of(RedoElement.hasClass('disabled')).should_be_true();
+		
+		UNDOREDO.onUndo();
+
+		value_of(WORK.state).should_be(['testing']);
+		value_of(UNDOREDO.undo).should_be_empty();
+		value_of(UNDOREDO.redo).should_be(['changed']);
+		value_of(UndoElement.hasClass('disabled')).should_be_true();
+		value_of(RedoElement.hasClass('disabled')).should_be_false();
+		
+	},
+	
+	'should undo multiple elements': function(){
+
+		UNDOREDO.onChange();
+		WORK.state = "changed1";
+		UNDOREDO.onChange();
+		WORK.state = "changed2";
+		
+		value_of(UNDOREDO.undo).should_be(['testing','changed1']);		
+		value_of(WORK.state).should_be(['changed2']);
+		value_of(UndoElement.hasClass('disabled')).should_be_false();
+		value_of(RedoElement.hasClass('disabled')).should_be_true();
+		
+		UNDOREDO.onUndo();
+
+		value_of(UndoElement.hasClass('disabled')).should_be_false();
+		value_of(RedoElement.hasClass('disabled')).should_be_false();
+
+
+		UNDOREDO.onUndo();
+
+		value_of(WORK.state).should_be(['testing']);
+		value_of(UNDOREDO.undo).should_be_empty();
+		value_of(UNDOREDO.redo).should_be(['changed2','changed1']);
+		value_of(UndoElement.hasClass('disabled')).should_be_true();
+		value_of(RedoElement.hasClass('disabled')).should_be_false();
+	},
+	
+	'should undo maximum "maxundo" elements': function(){
+
+		UNDOREDO = new UndoRedo( WORK ,{maxundo:3});
+
+		UNDOREDO.onChange();
+		WORK.state = "changed1";
+
+		value_of(UNDOREDO.undo).should_be(['testing']);		
+
+		UNDOREDO.onChange();
+		WORK.state = "changed2";
+
+		value_of(UNDOREDO.undo).should_be(['testing','changed1']);		
+
+		UNDOREDO.onChange();
+		WORK.state = "changed3";
+
+		value_of(UNDOREDO.undo).should_be(['testing','changed1','changed2']);		
+
+		UNDOREDO.onChange();
+		WORK.state = "changed4";
+		
+		value_of(UNDOREDO.undo).should_be(['changed1','changed2','changed3']);		
+		value_of(WORK.state).should_be(['changed4']);
+		
+		UNDOREDO.onUndo();
+		UNDOREDO.onUndo();
+		UNDOREDO.onUndo();
+		UNDOREDO.onUndo();
+
+		value_of(WORK.state).should_be(['changed1']);
+		value_of(UNDOREDO.undo).should_be_empty();
+		value_of(UNDOREDO.redo).should_be(['changed4','changed3','changed2']);
+	},
+	
+	'should redo an element': function(){
+	
+		UNDOREDO.onChange();
+		WORK.state = "changed1";
+		UNDOREDO.onChange();
+		WORK.state = "changed2";
+		
+		value_of(UNDOREDO.undo).should_be(['testing','changed1']);		
+		value_of(WORK.state).should_be(['changed2']);
+		value_of(UndoElement.hasClass('disabled')).should_be_false();
+		value_of(RedoElement.hasClass('disabled')).should_be_true();
+		
+		UNDOREDO.onUndo();
+
+		value_of(WORK.state).should_be(['changed1']);
+		value_of(UNDOREDO.undo).should_be(['testing']);		
+		value_of(UNDOREDO.redo).should_be(['changed2']);
+		value_of(UndoElement.hasClass('disabled')).should_be_false();
+		value_of(RedoElement.hasClass('disabled')).should_be_false();
+
+		UNDOREDO.onRedo();
+
+		value_of(WORK.state).should_be(['changed2']);
+		value_of(UNDOREDO.undo).should_be(['testing','changed1']);		
+		value_of(UNDOREDO.redo).should_be_empty();
+		value_of(UndoElement.hasClass('disabled')).should_be_false();
+		value_of(RedoElement.hasClass('disabled')).should_be_true();
+
+	},
+	
+	'should clear the redo stack when a new undo element is pushed': function(){
+	
+		UNDOREDO.onChange();
+		WORK.state = "changed1";
+		UNDOREDO.onChange();
+		WORK.state = "changed2";
+		
+		value_of(UNDOREDO.undo).should_be(['testing','changed1']);		
+		value_of(WORK.state).should_be(['changed2']);
+		value_of(UndoElement.hasClass('disabled')).should_be_false();
+		value_of(RedoElement.hasClass('disabled')).should_be_true();
+		
+		UNDOREDO.onUndo();
+
+		value_of(WORK.state).should_be(['changed1']);
+		value_of(UNDOREDO.undo).should_be(['testing']);		
+		value_of(UNDOREDO.redo).should_be(['changed2']);
+		value_of(UndoElement.hasClass('disabled')).should_be_false();
+		value_of(RedoElement.hasClass('disabled')).should_be_false();
+
+		//no make a new change, this should clear the redo stack
+		WORK.state = "changed3";
+		UNDOREDO.onChange();
+
+		value_of(WORK.state).should_be(['changed3']);
+		value_of(UNDOREDO.undo).should_be(['testing','changed3']);		
+		value_of(UNDOREDO.redo).should_be_empty();
+		value_of(UndoElement.hasClass('disabled')).should_be_false();
+		value_of(RedoElement.hasClass('disabled')).should_be_true();
+
+	}
+
+
+});
+
+describe('Edit: Textarea Class', {
+
+	before_each : function() {
+		$$('body')[0].adopt( ta = new Element('textarea') );
+		ta.value = 'Example text';			
+		
+		txta = new Textarea( ta );
+	},
+	after_each: function(){
+		ta.remove();
+	},
+	
+	'should initialize Textarea class': function(){			
+		value_of(txta.getValue()).should_be('Example text');
+	},
+	
+	'should set the caret':function(){
+		txta.setSelectionRange(2);
+		value_of(txta.getSelection()).should_be('');
+		value_of(txta.getSelectionRange()).should_be({start:2,end:2,thin:true})
+	},
+
+	'should set a selection range':function(){
+		txta.setSelectionRange(2,4); 
+		value_of(txta.getSelection()).should_be('am');
+		value_of(txta.getSelectionRange()).should_be({start:2,end:4,thin:false})
+	},
+
+	'should set a selection range with a \\n included':function(){
+		ta.value = 'Example\ntext';
+		txta.setSelectionRange(6,9); 
+		value_of(txta.getSelection()).should_be('e\nt');
+		value_of(txta.getSelectionRange()).should_be({start:6,end:9,thin:false})
+	},
+
+	'should read a fragment from start to caret':function(){
+		txta.setSelectionRange(2);
+		value_of(txta.getFromStart()).should_be('Ex');
+	},
+
+	'should read a fragment from caret till end':function(){
+		txta.setSelectionRange(2,4);
+		value_of(txta.getTillEnd()).should_be('ple text');
+	},
+	
+	'should replace the selection with another fragment':function(){
+		txta.setSelectionRange(2,4);
+		txta.setSelection('New Selection ');
+		value_of(txta.getValue()).should_be('ExNew Selection ple text');
+		value_of(txta.getSelection()).should_be('New Selection ');
+		value_of(txta.getSelectionRange()).should_be({start:2,end:16,thin:false})			
+	},
+	
+	'should replace the selection with another fragment with a \\n':function(){
+		txta.setSelectionRange(2,4);
+		txta.setSelection('New\nSelection ');
+		value_of(txta.getValue()).should_be('ExNew\nSelection ple text');
+		value_of(txta.getSelection()).should_be('New\nSelection ');
+		value_of(txta.getSelectionRange()).should_be({start:2,end:16,thin:false})			
+	},
+	
+	'should replace the selection with a \\n with another fragment':function(){
+		ta.value = 'Example\ntext';			
+		txta.setSelectionRange(6,9); 
+		txta.setSelection('New Selection ');
+		value_of(txta.getValue()).should_be('ExamplNew Selection ext');
+		value_of(txta.getSelection()).should_be('New Selection ');
+		value_of(txta.getSelectionRange()).should_be({start:6,end:20,thin:false})
+	},
+	
+	'should insert a fragment at the caret':function(){
+		txta.setSelectionRange(2);
+		txta.setSelection('New Selection ');
+		value_of(txta.getValue()).should_be('ExNew Selection ample text');
+		value_of(txta.getSelection()).should_be('New Selection ');
+		value_of(txta.getSelectionRange()).should_be({start:2,end:16,thin:false})			
+	},
+	
+	'should insert a fragment after the selection':function(){
+		txta.setSelectionRange(2,4);
+		txta.insertAfter('Inserted Stuff ')
+		value_of(txta.getValue()).should_be('ExInserted Stuff ple text');
+		value_of(txta.getSelection()).should_be('');
+		value_of(txta.getSelectionRange()).should_be({start:17,end:17,thin:true})			
+	},
+	
+	'should insert a set of fragments after the caret':function(){
+		txta.setSelectionRange(2);
+		txta.insertAfter('Inserted ','Stuff ')
+		value_of(txta.getValue()).should_be('ExInserted Stuff ample text');
+		value_of(txta.getSelectionRange()).should_be({start:17,end:17,thin:true})			
+	},
+	
+	'should check if caret is at start of line':function(){
+		ta.value = 'Example\ntext';			
+		txta.setSelectionRange(0);
+		value_of(txta.isCaretAtStartOfLine()).should_be_true();
+		txta.setSelectionRange(2);
+		value_of(txta.isCaretAtStartOfLine()).should_be_false();
+		txta.setSelectionRange(8);
+		value_of(txta.isCaretAtStartOfLine()).should_be_true();
+		txta.setSelectionRange(9);
+		value_of(txta.isCaretAtStartOfLine()).should_be_false();
+		txta.setSelectionRange(100);
+		value_of(txta.isCaretAtStartOfLine()).should_be_false();
+	}
+
+});
+
+describe('Edit: SnipEditor Class', {
+
+	before_each : function() {
+
+		/* Mockup Event object to allow simulation of keyboard and mouse events*/
+		Event.implement({ 
+			initialize: function(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(){ }
+		});
+
+		KEY = new Event({ 'type':'keypress', 'shift':false, code:'a'.charCodeAt(0), key:'a' });
+		TAB = new Event({ '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').setHTML('Example text') )
+			.adopt( next = new Element('input') );
+		main.setHTML('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(){ }
+		};
+
+
+	},
+
+	after_each: function(){
+		main.remove(), ta.remove(), next.remove(), snipe=null, txta=null;
+	},
+	
+	'should initialize the SnipEditor class': function(){
+		value_of(main.value).should_be('Example text');
+		value_of(ta.value).should_be('Example text');
+		value_of(txta.getValue()).should_be('Example text');
+	},
+	
+	//Special keys
+	'shift-enter should jump to next form element': function(){
+		next.addEvent('focus',function(){ this.value="has-focus"});
+		txta.setSelectionRange(2);
+
+		value_of(next.getValue()).should_be('no-focus');
+
+		var SHIFTENTER = new Event({ 'type':'keydown', 'shift':true, code:13, key:'enter' });
+		snipe.onKeystroke( SHIFTENTER );
+
+		//value_of(txta.getValue()).should_be('Example text');
+		//value_of(txta.getSelectionRange()).should_be({start:2,end:2,thin:true});
+		value_of(next.getValue()).should_be('has-focus');
+	},
+
+	//auto indentation on TAB
+	'tab key should insert tab-spaces at the caret': function(){
+		txta.setSelectionRange(2);
+		snipe.onKeystroke( TAB );
+
+		value_of(txta.getValue()).should_be('Ex    ample text');
+		value_of(txta.getSelectionRange()).should_be({start:6,end:6,thin:true})
+	},
+
+	'selected text + tab key should replace the selection with tab-spaces': function(){
+		txta.setSelectionRange(2,4);
+		snipe.onKeystroke( TAB );
+
+		value_of(txta.getValue()).should_be('Ex    ple text');
+		value_of(txta.getSelectionRange()).should_be({start:6,end:6,thin:true})
+	},
+
+	'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 );
+
+		value_of(txta.getValue()).should_be('    Example\n    text');
+		value_of(txta.getSelectionRange()).should_be({start:0,end:20,thin:false})		
+	},
+
+	'shift-tab key should remove tab-spaces to the left': function(){
+		txta.toElement().value="Ex    ample text";
+		txta.setSelectionRange(6);
+		snipe.onKeystroke( $merge(TAB,{shift:true}) );
+
+		value_of(txta.getValue()).should_be('Example text');
+		value_of(txta.getSelectionRange()).should_be({start:2,end:2,thin:true})		
+	},
+	
+	'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);
+		snipe.onKeystroke( $merge(TAB,{shift:true}) );
+
+		value_of(txta.getValue()).should_be('Example\ntext');
+		value_of(txta.getSelectionRange()).should_be({start:0,end:12,thin:false})		
+	},
+
+	'del key should remove tab-spaces to the right': function(){
+		txta.toElement().value="Ex    ample text";
+		txta.setSelectionRange(2);
+		var DEL = new Event({ 'type':'keydown', 'shift':false, code:46, key:'delete' });
+		snipe.onKeystroke( DEL );
+
+		value_of(txta.getValue()).should_be('Example text');
+		value_of(txta.getSelectionRange()).should_be({start:2,end:2,thin:true});		
+	},
+
+
+	//direct snippets
+	'Direct snippets, should insert a closing-bracket after the caret': function(){
+		txta.setSelectionRange(2);
+		snipe.onKeystroke( $merge(KEY, {code:'('.charCodeAt(0), key:'('}) );
+
+		value_of(txta.getValue()).should_be('Ex()ample text');
+		value_of(txta.getSelectionRange()).should_be({start:3,end:3,thin:true})	;		
+	},
+	
+	'Direct snippets, should insert a bracket around the selection': function(){
+		txta.setSelectionRange(2,4);
+		snipe.onKeystroke( $merge(KEY, {code:'['.charCodeAt(0), key:'['}) );
+ 
+		value_of(txta.getValue()).should_be('Ex[am]ple text');
+		value_of(txta.getSelectionRange()).should_be({start:3,end:5,thin:false});
+	},
+
+	'should not expand direct snippets when deactivated': function(){
+		snipe.options.directsnips = {};
+		txta.setSelectionRange(2);
+
+		snipe.onKeystroke( $merge(KEY, {code:'a'.charCodeAt(0), key:'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'
+		value_of(txta.getValue()).should_be('Example text');
+		value_of(txta.getSelectionRange()).should_be({start:2,end:2,thin:true});
+	},
+
+	//Tab snippet, without parameters 
+	'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 );
+
+		value_of(txta.getValue()).should_be('[{TableOfContents }]\nExample text');
+		value_of(txta.getSelectionRange()).should_be({start:21,end:21,thin:true});
+
+	},
+	'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 );
+
+		value_of(txta.getValue()).should_be('Example\n[{TableOfContents }]\n text');
+		value_of(txta.getSelectionRange()).should_be({start:29,end:29,thin:true})
+	},
+	'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 );
+
+		value_of(txta.getValue()).should_be('Example \n[{TableOfContents }]\n text');
+		value_of(txta.getSelectionRange()).should_be({start:30,end:30,thin:true})
+	},
+
+	'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 );
+
+		value_of(txta.getValue()).should_be("Example <p>\n[{TableOfContents }]\n</p> text");
+		value_of(txta.getSelectionRange()).should_be({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 );
+
+		value_of(txta.getValue()).should_be("Example toc     text");
+		value_of(txta.getSelectionRange()).should_be({start:15,end:15,thin:true})
+
+	},
+
+	'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 );
+
+		value_of(txta.getValue()).should_be('Example toc     text');
+		value_of(txta.getSelectionRange()).should_be({start:15,end:15,thin:true})
+	},
+
+	'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 );
+
+		value_of(txta.getValue()).should_be('Example \n[{TableOfContents }]\n text');
+		value_of(txta.getSelectionRange()).should_be({start:30,end:30,thin:true});
+
+		snipe.undoredo.onUndo();
+		
+		value_of(txta.getValue()).should_be('Example toc text');
+		value_of(txta.getSelectionRange()).should_be({start:11,end:11,thin:true});
+
+		snipe.undoredo.onRedo();
+		
+		value_of(txta.getValue()).should_be('Example \n[{TableOfContents }]\n text');
+		value_of(txta.getSelectionRange()).should_be({start:30,end:30,thin:true});
+	},
+
+	//Tab snippet, with a parameter 
+	'Tab snippet with parameter: should select the first parameter': function(){
+		
+	},
+
+	'Tab snippet with parameter: should allow to tab through all subsequent parameters': function(){
+		
+	},
+
+	'Tab snippet with parameter: should remove the active snippet when pressing esc/up/down': function(){
+		
+	},
+
+	'Tab snippet with parameter and parameter dialog: should display the parameter dialog': function(){
+
+	},
+
+	'Tab snippet with font parameter: should display the font dialog': function(){
+
+	},
+
+	'Tab snippet with color parameter: should display the color dialog': function(){
+
+	},
+
+	'Tab snippet with special-charater parameter: should display the chars dialog': function(){
+
+	},
+
+	//Button snippets
+	'Button snippet, should insert snippet text without parameters': function(){
+	},
+
+	'Button snippet, should replace selected text by snippet without parameters': function(){
+	},
+
+	'Button snippet, should insert snippet and tab through parameters without parameter dialog': function(){
+	},
+
+	'Button snippet, should insert snippet and select first parameter with parameter dialog': function(){
+	},
+	
+	'Button snippet, should insert snippet and replace first free parameter with seleted text': function(){
+		//font snippet
+	},
+	
+
+	//find and replace 
+	'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();
+
+		value_of(txta.getValue()).should_be('Lorem IPSUM dolor sit amet. Lorem IPSUM dolor sit amet.');
+	},
+
+	'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();
+
+		value_of(txta.getValue()).should_be('Lorem IPSUM dolor sit amet. Lorem IPSUM dolor sit amet.');
+
+		snipe.undoredo.onUndo();
+		
+		value_of(txta.getValue()).should_be('Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.');
+		
+		snipe.undoredo.onRedo();
+
+		value_of(txta.getValue()).should_be('Lorem IPSUM dolor sit amet. Lorem IPSUM dolor sit amet.');
+
+	},
+
+	'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();
+
+		value_of(txta.getValue()).should_be('Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.');
+		value_of(error).should_be('no match');
+	},
+
+	'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();
+
+		value_of(txta.getValue()).should_be('LOREM ipsum dolor sit amet; lorem ipsum dolor sit amet.');
+	},
+	
+	'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();
+
+		value_of(txta.getValue()).should_be('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();
+
+		value_of(txta.getValue()).should_be('LL$oreMM IpsuM dolor sit amet. LL$OREMM IPSUM dolor sit amet.');
+	},
+	
+	'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();
+
+		value_of(txta.getValue()).should_be('Lorem IPSUM dolor sit amet. Lorem ipsum dolor sit amet.');
+	},
+	
+	'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'
+
+		value_of(txta.getSelection()).should_be('ipsum dolor sit amet.');
+
+		snipe.onFindAndReplace();
+
+		value_of(txta.getValue()).should_be('Lorem IIIpsum dolor sIIIt amet. Lorem ipsum dolor sit amet.');
+		value_of(txta.getSelection()).should_be('IIIpsum dolor sIIIt amet.');
+	}
+
+
+});
+
+//todo
+describe('Edit: Wiki Editor Class', {
+
+	//test configuration dialog
+	
+	//setting/reseting of smartpair and tabcompletion preferences
+	
+	//test cookie get/set 
+
+});
+
+
+



Mime
View raw message