您的位置:首页 > Web前端 > JavaScript

javascript 测试工具abut v3

2011-03-06 14:39 267 查看
新版本并没有添加新功能,只是修bug与进行代码重构!详细用法请看abut v2的介绍。

//abut v3 annotations-based unit testing,基于注释的单元测试工具 by 司徒正美
//http://www.cnblogs.com/rubylouvre/archive/2011/03/06/1972250.html
(function(WIN,DOM){
var addEvent = (function () {
if (DOM.addEventListener) {
return function (el, type, fn) {
el.addEventListener(type, fn, false);
};
} else {
return function (el, type, fn) {
el.attachEvent('on' + type, function () {
return fn.call(el, WIN.event);
});
}
}
})();
////////////////////////////////////////////////////////////////////////////////////////////////
var A_slice = Array.prototype.slice;
var metaOne = {
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'\\': '\\\\'
}
WIN.dom = WIN.dom || {
mix: function(target, source ,override) {
var i, ride = (override === void 0) || override;
for (i in source) {
if (ride || !(i in target)) {
target[i] = source[i];
}
}
return target;
}
}
dom.mix(dom,{
// http://www.cnblogs.com/rubylouvre/archive/2010/01/20/1652646.html type : (function(){
var reg = /^(\w)/,
regFn = function($,$1){
return $1.toUpperCase()
},
to_s = Object.prototype.toString;
return function(obj,str){
var result = (typeof obj).replace(reg,regFn);
if(result === 'Object' || (result === 'Function' && obj.exec) ){//safari chrome中 type /i/ 为function
if(obj===null) result = 'Null';//Object,Function,Null,Undefined,Window,Arguments等等都为其构造器名称
else if(obj.window==obj) result = 'Window';
else if(obj.callee) result = 'Arguments';
else if(obj.nodeType === 9) result = 'Document';
else if(obj.nodeName) result = (obj.nodeName+'').replace('#',''); //处理元素节点
else if(!obj.constructor || !(obj instanceof Object)){
if("send" in obj && "setRequestHeader" in obj){//处理IE5-8的宿主对象与节点集合
result = "XMLHttpRequest"
}else if("length" in obj && "item" in obj){
result = "namedItem" in obj ?  'HTMLCollection' :'NodeList';
}else{
result = 'Unknown';
}
}else result = to_s.call(obj).slice(8,-1);
}
if(result === "Number" && isNaN(obj))  result = "NaN";
//safari chrome中 对 HTMLCollection与NodeList的to_s都为 "NodeList",此bug暂时无解
if(str){
return str === result;
}
return result;
}
})(),
oneObject : function(array,val){
var result = {},value = val !== void 0 ? val :1;
for(var i=0,n=array.length;i < n;i++)
result[array[i]] = value;
return result;
},
quote : String.quote || function (str) {
str = str.replace(/[\x00-\x1f\\]/g, function (chr) {
var special = metaOne[chr];
return special ? special : '\\u' + ('0000'+chr.charCodeAt(0).toString(16)).slice(-4);
});
return '"' + str.replace(/"/g, '\\"') + '"';
}
},false);

//http://www.cnblogs.com/rubylouvre/archive/2010/04/20/1716486.html
(function(w,s){
s = ["XMLHttpRequest",
"ActiveXObject('Msxml2.XMLHTTP.6.0')",
"ActiveXObject('Msxml2.XMLHTTP.3.0')",
"ActiveXObject('Msxml2.XMLHTTP')",
"ActiveXObject('Microsoft.XMLHTTP')"];
if( !-[1,] && w.ScriptEngineMinorVersion() === 7 && location.protocol === "file:"){
s.shift();
}
for(var i = 0 ,el;el=s[i++];){
try{
if(eval("new "+el)){
dom.xhr = new Function( "return new "+el);
break;
}
}catch(e){}
}
})(WIN);
///////////////////////////////////////////////////////////////////////////
var rcomments = /\/\/([^\r\n]+)|\/\*([\s\S]+?)\*\//g;
var rltrim = /^\s+/
var rsign  = /(\$|#){4}(\w*)\(([\s\S]+)\);?/
if ( rltrim.test( "\xA0" ) ) {
rltrim = /^[\s\xA0]+/;
}
var rstar = /^\*+/;//多行注释中的前置*号
var rlt4  = /<<<</
var rgt4  = />>>>/
var rtest = /try{dom._should/
var rCRFL = /\r?\n/ //回车符与换行符
var ropacity = /opacity:\s*(\d?\.\d+)/g;
var trimCode = function(source){
var results = [],  flag_mul , flag_push, line, m, num = 0
while((m = rcomments.exec(source))){//取得所有注释
var comment =  m[1] || m[2] , lines = comment.split(rCRFL) , result = []
for(var i=0, n = lines.length; i < n ;i++){
line = lines[i].replace(rltrim,'').replace(rstar,' ');
if(rlt4.test(line)){//在使用了夹具的情况,使用<<<<作为左界定符
line = "try{"
flag_mul = flag_push = true;
}
if( flag_mul){//夹具
flag_push = true
}
if( rgt4.test(line)){//在使用了夹具的情况,使用>>>>作为左界定符
flag_mul = false;
line = "}catch(e){};"
flag_push = true;
}
if(rtest.test(line)){//用于统计一共有多少个测试样例
num++
flag_push = true
}
if( flag_push ){
result.push(line)
}
flag_push = false;
}
if(/\S+/.test(result.join("")))
results = results.concat(result)
}
return  {
code:results.join("\n"),
num:num
}
}
//将源码分行并添加上行号
var cleanCode = function (source) {
var lines = source.split(rCRFL) ,line
for(var i=0,n = lines.length; i < n ;i++){
line = lines[i].replace(rltrim, '');
lines[i] = line.replace(rsign,function(code,$1,$2,$3){
if($1 == "####")
dom.abut.isModify = true;
code = window.uneval && uneval(code) || dom.quote(code)
return "try{dom._should("+$3+","+i+","
+ dom.quote($2 || "ok") +","+ code
+')}catch(e){dom.abut.render("dom-abut-error","第'+i+'行测试代码发生错误",'+code+'+"<br/>"+ e)};'

});
}
return lines.join('\n');
};

dom.mix(dom,{
abut:function(str,appendTo,text){
appendTo = appendTo || DOM.body
if(str.indexOf("url(")=== 0){
var url = str.slice(4,-1),
xhr = dom.xhr();
xhr.open("GET",url+"?"+(new Date-0),false);
xhr.send(null);
text = xhr.responseText || "";
if (!text) throw "the target file does not exist";
}else{
var el = DOM.getElementById(str);
if (!el) throw "can not find the target element";
text = el.text;
}
var self = arguments.callee;
self.isModify = false;
var purified_code = cleanCode(text);
var obj = trimCode(purified_code);
if(!self._first){//保证这里的代码只执行一次
self._first = true;
el = self.componentElement = DOM.createElement("ul");
el.className = "dom-abut-result";
self.render("dom-abut-title",'<span>一共有'+obj.num+'个测试</span> <span id=dom-abut-pass>0</span>done  <span id=dom-abut-unpass>0</span>errors');
appendTo.appendChild(el);
dom.addSheet(".dom-abut-result {\
border:5px solid #00a7ea;padding:10px;background:#03c9fa;list-style-type:none;\
}\
.dom-abut-result li{\
padding:5px ;margin-bottom:1px;font-size:14px;\
}\
.dom-abut-result li blockquote{\
padding:5px;display:none;\
}\
.dom-abut-title{\
background:#008000;\
}\
.dom-abut-pass{\
background:#a9ea00;\
}\
.dom-abut-unpass{\
background:red;color:#fff;\
}\
.dom-abut-error{\
background:#000;color:#fff;\
}\
.dom-abut-log{\
background:#c0c0c0;\
}\
.dom-abut-log blockquote{\
font-weight: normal;background:#808080;\
}");
addEvent(el,"click",function(e){
e = e || WIN.event;
var target = e.target || e.srcElement;
var blockquote =  target.getElementsByTagName("blockquote")[0];
if(blockquote){
blockquote.style.display =  !!(blockquote.offsetHeight || blockquote.offestWidth) ? "none": "block";
}
});
}
try {
self.isModify && eval(purified_code);
eval(obj.code);
} catch (e) {
self.render("dom-abut-error","解析编译测试代码失败!");
}
},
addSheet : function(css,appendTo){
var self = arguments.callee,style ,el = appendTo || dom.insertion || DOM.body
if(!self.style){
var styles = DOM.getElementsByTagName("style"), i = 0, reg = /screen|all/i, media
while(style = styles[i++]){
media = style.getAttribute("media");
if(media === null || reg.test(media)){
self.style = style;
break;
}
}
if(!self.style){
style = DOM.createElement('style');
el.parentNode.insertBefore(style,el);
self.style = style;
}
}
if(!-[1,] && el.filters){//IE6-8
css = css.replace(ropacity,function($,$1){
$1 = parseFloat($1) * 100;
if($1 < 0 || $1 > 100)
return "";
return "filter:alpha(opacity="+ $1 +");"
});
}
css += "\n";//增加末尾的换行符,方便在firebug下的查看。
if(style.styleSheet){    //ie
style.styleSheet.cssText += css;//添加新的内部样式
}else if(WIN.Components){
style.innerHTML += css;//火狐支持直接innerHTML添加样式表字串
}else{
style.appendChild(DOM.createTextNode(css))
}
},

_should:function(actual, expected, line, method, source){
var args = Array.apply([],arguments);
source = args.pop();
method = args.pop();
line   = args.pop();
if(args.length === 1){
expected = void 0;
}
var bool, context
switch(method){
case "ok"://布尔真测试
bool = !!actual
break;
case "ng"://布尔非测试
bool = !!!actual
break;
case "eq"://同一性真测试
bool = actual == expected;
break;
case "not"://同一性非测试
bool = actual != expected;
break;
case "same":
bool = dom.isEqual(actual, expected)
break
case "log":
bool = "<pre>"+dom.dump(actual)+"</pre>";
break;
}

if(typeof bool === "string"){
context = '第' + line+"行日志记录";
dom.abut.render("dom-abut-log",context,bool);
}else{
context =  '第'+ line+'行测试代码: '+(bool ? '通过' :'不通过' ) ;
var id = bool ? 'dom-abut-pass' : 'dom-abut-unpass';
var el = DOM.getElementById(id);
var count = ~~el.innerHTML
el.innerHTML = ++count;
source = "actual    :   "+actual+"<br/> expected :   "+expected+"<hr/>"+source
dom.abut.render(id,context,source);
}
},
//比较对象是否相等或相似
isEqual: function(a, b) {
if (a === b) {
return true;
} else if (a === null || b === null || typeof a === "undefined" || typeof b === "undefined" || dom.type(a) !== dom.type(b)) {
return false; // don't lose time with error prone cases
} else {
switch(dom.type(a)){
case "String":
case "Boolean":
case "Number":
case "Null":
case "Undefined":
//处理简单类型的伪对象与字面值相比较的情况,如1 v new Number(1)
if (b instanceof a.constructor || a instanceof b.constructor) {
return a == b;
}
return a === b;
case "NaN":
return isNaN(b);
case "Date":
return  a.valueOf() === b.valueOf();
case "Array":
var len = a.length;
if (len !== b.length)
return false;
for (var i = 0; i < len; i++) {
if (!this.isEqual(a[i], b[i])) {
return false;
}
}
return true;
default:
for (var key in b) {
if (!this.isEqual(a[key], b[key])) {
return false
}
}
return true;
}
}
},
dump : function(obj, indent) {
indent = indent || "";
if (obj === null)
return indent + "null";
if (obj === void 0)
return indent + "undefined";
if (obj.nodeType === 9)
return indent + "[object Document]";
if (obj.nodeType)
return indent + "[object " + (obj.tagName || "Node") +"]";
var arr = [],type = dom.type(obj),self = arguments.callee,next = indent +  "\t";
switch (type) {
case "Boolean":
case "Number":
case "NaN":
case "RegExp":
return indent + obj;
case "String":
return indent + dom.quote(obj);
case "Function":
return (indent + obj).replace(/\n/g, "\n" + indent);
case "Date":
return indent + '(new Date(' + obj.valueOf() + '))';
case "Unknown":
case "XMLHttpRequest" :
case "Window" :
return indent + "[object "+type +"]";
case "NodeList":
case "HTMLCollection":
case "Arguments":
case "Array":
for (var i = 0, n = obj.length; i < n; ++i)
arr.push(self(obj[i], next).replace(/^\s* /g, next));
return indent + "[\n" + arr.join(",\n") + "\n" + indent + "]";
default:
for (var i in obj) {
arr.push(next + self(i) + ": " + self(obj[i], next).replace(/^\s+/g, "") );
}
return indent + "{\n" + arr.join(",\n") + "\n" + indent + "}";
}
}
});

dom.mix(dom.abut,{
render : function(className,context,code){
var li = DOM.createElement("li");
li.className = className;
this.componentElement.appendChild(li);
var blockquote = DOM.createElement("blockquote")
li.innerHTML = context;
if(code){
li.appendChild(blockquote);
blockquote.innerHTML = code;
}
}
});

})(this,this.document);


比如我页面上有一个id为test3的script元素节点,其innerHTML如下:

var Person = function(name,sex){
this.name = name;
this.sex = sex;
//####log(this.name);
//####log(this.sex);
}
var p = new Person("ruby","louvre");

var Person = function(name,sex){ this.name = name; this.sex = sex; //####log(this.name); //####log(this.sex); } var p = new Person("ruby","louvre");
运行代码

想对其测试,只要引用abut.js,在页面上运行如下脚本即可:

dom.abut("test3",document.body);
//v2的使用方法,太笨重,已废弃
// dom.abut({selector:"test3", target:document.body });

如果我们想对远程的JS文件(只限于同域,因为使用XMLHttpRequest对象),则使用方法如下:

dom.abut("url(http://aaa.js)",document.body);
//v2的使用方法,太笨重,已废弃
// dom.abut({url:"http://aaa.js", target:document.body });

另,第二个参数是可以,默认就是把测试结果添加到document.body的底部!

var runJS = function(id){
dom.abut(id,document.getElementById("dombody"))
}

对复杂对象的查看:

/*<<<<
var h = {
a : {
x : 10,
y : "hoge",
z : [ { hoge : "fuga"} , { hoge : "foo" }, { hoge : "bar" } ]
},
b : {
x : "piyo"
}
};
$$$$log(h)
>>>>
*/

/*<<<< var h = { a : { x : 10, y : "hoge", z : [ { hoge : "fuga"} , { hoge : "foo" }, { hoge : "bar" } ] }, b : { x : "piyo" } }; $$$$log(h) >>>> */
运行代码

var flatten = function(arr) {

var result = [],self = arguments.callee;

for(var i=0,n=arr.length,el;i< n;i++){

el = arr[i];

if (dom.type(el,"Array")) {

result = result.concat(self(el));

} else {

result.push(el);

}

}

return result;

}

/*<<<<

* var a =['frank', ['bob', 'lisa'], ['jill', ['tom', 'sally']]];

* $$$$same(flatten(a),['frank', 'bob', 'lisa', 'jill', 'tom', 'sally']);

* >>>>

*/

var flatten = function(arr) {
var result = [],self = arguments.callee;
for(var i=0,n=arr.length,el;i < n;i++){
el = arr[i];
if (dom.type(el,"Array")) {
result = result.concat(self(el));
} else {
result.push(el);
}
}
return result;
}

/*<<<<
* var a =['frank', ['bob', 'lisa'], ['jill', ['tom', 'sally']]];
* $$$$same(flatten(a),['frank', 'bob', 'lisa', 'jill', 'tom', 'sally']);
* >>>>
*/


运行代码

例子5(截取自我框架的base模块)

var
PROTO = "prototype",
CTOR = "constructor",
hasOwn = Object[PROTO].hasOwnProperty;
//用于取得数据的类型或判定数据的类型
// $$$$(dom.type(1,"Number"));
// $$$$(dom.type(NaN,"NaN"));
// $$$$(dom.type(void(0),"Undefined"));
// $$$$(dom.type("aaa","String"));
// $$$$(dom.type([1,2,3],"Array"));
// $$$$(dom.type(/i/,"RegExp"));
// $$$$(dom.type({},"Object"));
// $$$$(dom.type(document,"Document"));
// $$$$(dom.type(document.body,"BODY"));
// $$$$(dom.type(window,"Window"));
// $$$$(dom.type(true,"Boolean"));
// $$$$(dom.type(document.getElementsByTagName('script'),"HTMLCollection"));

dom.type = (function(){
var reg = /^(\w)/,
regFn = function($,$1){
return $1.toUpperCase()
},
to_s = Object[PROTO].toString;
return function(obj,str){
var result = (typeof obj).replace(reg,regFn);
if(result === 'Object' || (result === 'Function' && obj.exec) ){//safari chrome中 type /i/ 为function
if(obj===null) result = 'Null';
else if(obj.window==obj) result = 'Window'; //返回Window的构造器名字
else if(obj.callee) result = 'Arguments';
else if(obj.nodeType === 9) result = 'Document';
else if(obj.nodeName) result = (obj.nodeName+'').replace('#',''); //处理元素节点
else if(!obj.constructor || !(obj instanceof Object)){
if("send" in obj && "setRequestHeader" in obj){//处理IE5-8的宿主对象与节点集合
result = "XMLHttpRequest"
}else if("length" in obj && "item" in obj){
result = "namedItem" in obj ?  'HTMLCollection' :'NodeList';
}else{
result = 'Unknown';
}
}else result = to_s.call(obj).slice(8,-1);
}
if(result === "Number" && isNaN(obj))  result = "NaN";
//safari chrome中 对 HTMLCollection与NodeList的to_s都为 "NodeList",此bug暂时无解
if(str){
return str === result;
}
return result;
}
})()

//生成键值统一的对象,用于高速化判定
// $$$$same(dom.oneObject(["aa","bb","cc"]),{"aa":1,"bb":1,"cc":1})
dom.oneObject = function(array,val){
var result = {},value = val !== void 0 ? val :1;
for(var i=0,n=array.length;i < n;i++)
result[array[i]] = value;
return result;

}


// $$$$(dom.type(1,"Number"));
// $$$$(dom.type(NaN,"NaN"));
// $$$$(dom.type(void(0),"Undefined"));
// $$$$(dom.type("aaa","String"));
// $$$$(dom.type([1,2,3],"Array"));
// $$$$(dom.type(/i/,"RegExp"));
// $$$$(dom.type({},"Object"));
// $$$$(dom.type(document,"Document"));
// $$$$(dom.type(document.body,"BODY"));
// $$$$(dom.type(window,"Window"));
// $$$$(dom.type(true,"Boolean"));
// $$$$(dom.type(document.getElementsByTagName('script'),"HTMLCollection"));

// $$$$same(dom.oneObject(["aa","bb","cc"]),{"aa":1,"bb":1,"cc":1})

运行代码

//abut v3 annotations-based unit testing,基于注释的单元测试工具
(function(WIN,DOM){

//http://tech.kayac.com/archive/javascript-test-framework-sweets.html
var dom = WIN[escape(DOM.URL.split("#")[0])];
dom.declare("abut", ["lang","xhr"],function(){
try{
var reg_comments = /\/\/([^\r\n]+)|\/\*([\s\S]+?)\*\//g;
var reg_ltrim = /^\s+/;
var reg_sign = /(\$|#){4}(\w*)\(([\s\S]+)\);?/;
if ( reg_ltrim.test( "\xA0" ) ) {
reg_ltrim = /^[\s\xA0]+/;
}
var reg_star = /^\*+/;//多行注释中的前置*号
var reg_lt4 = /<<<var reg_gt4 = />>>>/;
var reg_test = /try{dom._should/;
var reg_CRFL = /\r?\n/; //回车符与换行符
var reg_opacity = /opacity:\s*(\d?\.\d+)/g;
var trimCode = function(source){
var results = [], flag_mul , flag_push, line, m, num = 0;
while((m = reg_comments.exec(source))){//取得所有注释
var comment = m[1] || m[2] , lines = comment.split(reg_CRFL) , result = [];
for(var i=0, n = lines.length; i < n ;i++){
line = lines[i].replace(reg_ltrim,'').replace(reg_star,' ');
if(reg_lt4.test(line)){//在使用了夹具的情况,使用<<<<作为左界定符
line = "try{";
flag_mul = flag_push = true;
}
if( flag_mul){//夹具
flag_push = true;
}
if( reg_gt4.test(line)){//在使用了夹具的情况,使用>>>>作为左界定符
flag_mul = false;
line = "}catch(e){dom.log(e)};"
flag_push = true;
}
if(reg_test.test(line)){//用于统计一共有多少个测试样例
num++;
flag_push = true;
}
if( flag_push ){
result.push(line);
}
flag_push = false;
}
if(/\S+/.test(result.join(""))){
results = results.concat(result);
}
}
return {
code:results.join("\n"),
num:num
}
}
//将源码分行并添加上行号
var cleanCode = function (source) {
var lines = source.split(reg_CRFL) ,line;
for(var i=0,n = lines.length; i < n ;i++){
line = lines[i].replace(reg_ltrim, '');
lines[i] = line.replace(reg_sign,function(code,$1,$2,$3){
if($1 == "####"){
dom.abut.isModify = true;
}
code = window.uneval && uneval(code) || dom.quote(code);
return "try{dom._should("+$3+","+i+","
+ dom.quote($2 || "ok") +","+ code
+')}catch(e){dom.abut.render("dom-abut-error","第'+i+'行测试代码发生错误",'+code+'+"
"+ e)};'

});
}
return lines.join('\n');
};

//使用方法 : dom.abut("url(/dom/lang.js)")
dom.mix(dom,{
abut:function(str,appendTo,/*private*/text){
appendTo = appendTo || DOM.body;
if(str.indexOf("url(")=== 0){
var url = str.slice(4,-1);
var xhr = dom.xhr();
xhr.open("GET",url+"?"+(new Date-0),false);
xhr.send(null);
text = xhr.responseText || "";
if (!text) throw "the target file does not exist";
}else{
var el = DOM.getElementById(str);
if (!el) throw "can not find the target element";
text = el.text;
}
var self = arguments.callee;
self.isModify = false;
var purified_code = cleanCode(text);
var obj = trimCode(purified_code);
if(!self._first){//保证这里的代码只执行一次
self._first = true;
el = self.componentElement = DOM.createElement("ul");
el.className = "dom-abut-result";
self.render("dom-abut-title",'一共有'+obj.num+'个测试 0done  0errors');
appendTo.appendChild(el);
dom.addSheet(".dom-abut-result {\
border:5px solid #00a7ea;padding:10px;background:#03c9fa;list-style-type:none;\
}\
.dom-abut-result li{\
padding:5px ;margin-bottom:1px;font-size:14px;\
}\
.dom-abut-result li blockquote{\
padding:5px;display:none;\
}\
.dom-abut-title{\
background:#008000;\
}\
.dom-abut-pass{\
background:#a9ea00;\
}\
.dom-abut-unpass{\
background:red;color:#fff;\
}\
.dom-abut-error{\
background:#000;color:#fff;\
}\
.dom-abut-log{\
background:#c0c0c0;\
}\
.dom-abut-log blockquote{\
font-weight: normal;background:#808080;\
}");
dom.bind(el,"click",function(e){
e = e || WIN.event;
var target = e.target || e.srcElement;
var blockquote = target.getElementsByTagName("blockquote")[0];
if(blockquote){
blockquote.style.display = !!(blockquote.offsetHeight || blockquote.offestWidth) ? "none": "block";
}
});
}
try {
self.isModify && eval(purified_code);
eval(obj.code);
} catch (e) {
self.render("dom-abut-error","解析编译测试代码失败!");
}

},
addSheet : function(css,appendTo){
var self = arguments.callee,style ,el = appendTo || dom.insertion || DOM.body;
if(!self.style){
var styles = DOM.getElementsByTagName("style"), i = 0, reg = /screen|all/i, media;
while(style = styles[i++]){
media = style.getAttribute("media");
if(media === null || reg.test(media)){
self.style = style;
break;
}
}
if(!self.style){
style = DOM.createElement('style');
el.parentNode.insertBefore(style,el);
self.style = style;
}
}
if(!+"\v1" && el.filters){//IE6-8
css = css.replace(reg_opacity,function($,$1){
$1 = parseFloat($1) * 100;
if($1 < 0 || $1 > 100){
return "";
}
return "filter:alpha(opacity="+ $1 +");";
});
}
css += "\n";//增加末尾的换行符,方便在firebug下的查看。
if(style.styleSheet){ //ie
style.styleSheet.cssText += css;//添加新的内部样式
}else if(WIN.Components){
style.innerHTML += css;//火狐支持直接innerHTML添加样式表字串
}else{
style.appendChild(DOM.createTextNode(css));
}
},
_should:function(actual, expected, line, method, source){
var args = Array.apply([],arguments);
source = args.pop();
method = args.pop();
line = args.pop();
if(args.length === 1){
expected = void 0;
}
var bool, context;
switch(method){
case "ok"://布尔真测试
bool = !!actual;
expected = actual;
break;
case "ng"://布尔非测试
bool = !!!actual;
expected = actual;
break;
case "eq"://同一性真测试
bool = actual == expected;
break;
case "not"://同一性非测试
bool = actual != expected;
break;
case "same":
bool = dom.isEqual(actual, expected);
break
case "log":
bool = "
"+dom.dump(actual)+"
";
break;
}
if(typeof bool === "string"){
context = '第' + line+"行日志记录";
dom.abut.render("dom-abut-log",context,bool);
}else{
context = '第'+ line+'行测试代码: '+(bool ? '通过' :'不通过' ) ;
var id = bool ? 'dom-abut-pass' : 'dom-abut-unpass';
var el = DOM.getElementById(id);
var count = ~~el.innerHTML;
el.innerHTML = ++count;
source = "actual : "+actual+"
expected : "+ expected+""+source;
dom.abut.render(id,context,source);
}
},
//比较对象是否相等或相似
isEqual: function(a, b) {
if (a === b) {
return true;
} else if (a === null || b === null || typeof a === "undefined" || typeof b === "undefined" || dom.type(a) !== dom.type(b)) {
return false; // don't lose time with error prone cases
} else {
switch(dom.type(a)){
case "String":
case "Boolean":
case "Number":
case "Null":
case "Undefined":
//处理简单类型的伪对象与字面值相比较的情况,如1 v new Number(1)
if (b instanceof a.constructor || a instanceof b.constructor) {
return a == b;
}
return a === b;
case "NaN":
return isNaN(b);
case "Date":
return a.valueOf() === b.valueOf();
case "Array":
var len = a.length;
if (len !== b.length)
return false;
for (var i = 0; i < len; i++) {
if (!this.isEqual(a[i], b[i])) {
return false;
}
}
return true;
default:
for (var key in b) {
if (!this.isEqual(a[key], b[key])) {
return false;
}
}
return true;
}
}
},
dump : function(obj, indent) {
indent = indent || "";
if (obj === null)
return indent + "null";
if (obj === void 0)
return indent + "undefined";
if (obj.nodeType === 9)
return indent + "[object Document]";
if (obj.nodeType)
return indent + "[object " + (obj.tagName || "Node") +"]";
var arr = [],type = dom.type(obj),self = arguments.callee,next = indent + "\t";
switch (type) {
case "Boolean":
case "Number":
case "NaN":
case "RegExp":
return indent + obj;
case "String":
return indent + dom.quote(obj);
case "Function":
return (indent + obj).replace(/\n/g, "\n" + indent);
case "Date":
return indent + '(new Date(' + obj.valueOf() + '))';
case "Unknown":
case "XMLHttpRequest" :
case "Window" :
return indent + "[object "+type +"]";
case "NodeList":
case "Arguments":
case "Array":
for (var i = 0, n = obj.length; i < n; ++i)
arr.push(self(obj[i], next).replace(/^\s* /g, next));
return indent + "[\n" + arr.join(",\n") + "\n" + indent + "]";
default:
for ( i in obj) {
arr.push(next + self(i) + ": " + self(obj[i], next).replace(/^\s+/g, "") );
}
return indent + "{\n" + arr.join(",\n") + "\n" + indent + "}";
}
}
});
dom.mix(dom.abut,{
render : function(className,context,code){
var li = DOM.createElement("li");
li.className = className;
this.componentElement.appendChild(li);
var blockquote = DOM.createElement("blockquote")
li.innerHTML = context;
if(code){
li.appendChild(blockquote);
blockquote.innerHTML = code;
}
}
});
}catch(e){
alert(e+" abut");
}
});

})(this,this.document);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: