JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
1d32c5382e12bf1c5160589ecfd681cee6f2c6d4
[ckeditor.git] / _source / core / test.js
1 /*\r
2 Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.\r
3 For licensing, see LICENSE.html or http://ckeditor.com/license\r
4 */\r
5 \r
6 /**\r
7  * @fileOverview Defines the {@link CKEDITOR.test} object, which contains\r
8  *              functions used at our testing environment.\r
9  */\r
10 \r
11 /*jsl:import ../tests/yuitest.js*/\r
12 \r
13 /**\r
14  * Contains functions used at our testing environment. Currently,\r
15  * our testing system is based on the\r
16  * <a href="http://developer.yahoo.com/yui/yuitest/">YUI Test</a>.\r
17  * @namespace\r
18  * @example\r
19  */\r
20 CKEDITOR.test =\r
21 {\r
22         /**\r
23          * The assertion namespace, containing all assertion functions. Currently,\r
24          * this is an alias for\r
25          * <a href="http://developer.yahoo.com/yui/docs/YAHOO.util.Assert.html">YAHOO.util.Assert</a>.\r
26          * @example\r
27          * <b>CKEDITOR.test.assert</b>.areEqual( '10', 10 );        // "true"\r
28          * <b>CKEDITOR.test.assert</b>.areSame( '10', 10 );         // "false"\r
29          * <b>CKEDITOR.test.assert</b>.isUndefined( window.test );  // "true"\r
30          */\r
31         assert : YAHOO.util.Assert,\r
32 \r
33         runner : YAHOO.tool.TestRunner,\r
34 \r
35         /**\r
36          * Adds a test case to the test runner.\r
37          * @param {Object} testCase The test case object. See other tests for\r
38          *              examples.\r
39          * @example\r
40          * <b>CKEDITOR.test.addTestCase</b>((function()\r
41          * {\r
42          *     // Local reference to the "assert" object.\r
43          *     var assert = CKEDITOR.test.assert;\r
44          *\r
45          *     return {\r
46          *         test_example : function()\r
47          *         {\r
48          *             assert.areSame( '10', 10 );  // FAIL\r
49          *         }\r
50          *      };\r
51          * })());\r
52          */\r
53         addTestCase : function( testCase )\r
54         {\r
55                 YAHOO.tool.TestRunner.add( new YAHOO.tool.TestCase( testCase ) );\r
56         },\r
57 \r
58         /**\r
59          * Gets the inner HTML of an element, for testing purposes.\r
60          * @param {Boolean} stripLineBreaks Assign 'false' to avoid trimming line-breaks.\r
61          */\r
62         getInnerHtml : function( elementOrId , stripLineBreaks )\r
63         {\r
64                 var html;\r
65 \r
66                 if ( typeof elementOrId == 'string' )\r
67                         html = document.getElementById( elementOrId ).innerHTML;\r
68                 else if ( elementOrId.getHtml )\r
69                         html = elementOrId.getHtml();\r
70                 else\r
71                         html = elementOrId.innerHTML    // retrieve from innerHTML\r
72                                    || elementOrId.value;    // retrieve from value\r
73 \r
74                 return CKEDITOR.test.fixHtml( html, stripLineBreaks );\r
75         },\r
76 \r
77         fixHtml : function( html, stripLineBreaks )\r
78         {\r
79                 html = html.toLowerCase();\r
80 \r
81                 if ( stripLineBreaks !== false )\r
82                         html = html.replace( /[\n\r]/g, '' );\r
83                 else\r
84                         html = html.replace( /\r/g, '' );    // Normalize CRLF.\r
85 \r
86                 function sorter( a, b )\r
87                 {\r
88                         var nameA = a[ 0 ];\r
89                         var nameB = b[ 0 ];\r
90                         return nameA < nameB ? -1 : nameA > nameB ? 1 : 0;\r
91                 }\r
92 \r
93                 html = html.replace( /<\w[^>]*/g, function( match )\r
94                         {\r
95                                 var attribs = [];\r
96                                 var hasClass;\r
97 \r
98                                 match = match.replace( /\s([^\s=]+)=((?:"[^"]*")|(?:'[^']*')|(?:[^\s]+))/g, function( match, attName, attValue )\r
99                                         {\r
100                                                 if ( attName == 'style' )\r
101                                                 {\r
102                                                         // Reorganize the style rules so they are sorted by name.\r
103 \r
104                                                         var rules = [];\r
105 \r
106                                                         // Push all rules into an Array.\r
107                                                         attValue.replace( /(?:"| |;|^ )\s*([^ :]+?)\s*:\s*([^;"]+?)\s*(?=;|"|$)/g, function( match, name, value )\r
108                                                                 {\r
109                                                                         rules.push( [ name, value ] );\r
110                                                                 });\r
111 \r
112                                                         // Sort the Array.\r
113                                                         rules.sort( sorter );\r
114 \r
115                                                         // Transform each rule entry into a string name:value.\r
116                                                         for ( var i = 0 ; i < rules.length ; i++ )\r
117                                                                 rules[ i ] = rules[ i ].join( ':' );\r
118 \r
119                                                         // Join all rules with commas, removing spaces and adding an extra comma to the end.\r
120                                                         attValue = '"' + rules && ( rules.join( ';' ).replace( /\s+/g, '' ) + ';' );\r
121                                                 }\r
122 \r
123                                                 // IE may have 'class' more than once.\r
124                                                 if ( attName == 'class' )\r
125                                                 {\r
126                                                         if ( hasClass )\r
127                                                                 return '';\r
128 \r
129                                                         hasClass = true;\r
130                                                 }\r
131 \r
132                                                 if ( attName != '_cke_expando' )\r
133                                                         attribs.push( [ attName, attValue ] );\r
134 \r
135                                                 return '';\r
136                                         } );\r
137 \r
138                                 attribs.sort( sorter );\r
139 \r
140                                 var ret = match.replace( /\s{2,}/g, ' ' );\r
141 \r
142                                 for ( var i = 0 ; i < attribs.length ; i++ )\r
143                                 {\r
144                                         ret += ' ' + attribs[i][0] + '=';\r
145                                         ret += (/^["']/).test( attribs[i][1] ) ? attribs[i][1] : '"' + attribs[i][1] + '"';\r
146                                 }\r
147 \r
148                                 return ret;\r
149                         } );\r
150 \r
151                 return html;\r
152         },\r
153 \r
154         /**\r
155          * Wrapper of CKEDITOR.dom.element::getAttribute for style text normalization.\r
156          * @param element\r
157          * @param attrName\r
158          */\r
159         getAttribute : function( element, attrName )\r
160         {\r
161                 var retval = element.getAttribute( attrName );\r
162                 if ( attrName == 'style' )\r
163                 {\r
164                         // 1. Lower case property name.\r
165                         // 2. Add space after colon.\r
166                         // 3. Strip whitepsaces around semicolon.\r
167                         // 4. Always end with semicolon\r
168                         return retval.replace( /(?:^|;)\s*([A-Z-_]+)(:\s*)/ig,\r
169                                 function( match, property, colon )\r
170                                 {\r
171                                         return property.toLowerCase() + ': ';\r
172                                 } )\r
173                                 .replace( /\s+(?:;\s*|$)/g, ';' )\r
174                                 .replace( /([^;])$/g, '$1;' );\r
175                 }\r
176 \r
177                 return retval;\r
178         },\r
179 \r
180         /**\r
181          * Whether control the runner manually instead of running on window onload.\r
182          */\r
183         deferRunner : false\r
184 };\r