• mass Framework spec模块 v2


    对于一个框架的成长来说,测试是必不可少的,像用手来点来点去的测试基本不算测试,只有基于代码的单元测试才能让人安心。因此我不断地升级我的测试工具,从早期的abut到现在的spec模块。它不断地添加测试函数:eq, ok, same,contains, match...最近添加的方法是near,是专门用于测试CSS样式值,像width, height, opacity, border-top-width等值在各浏览器下总差1,2像素,更有甚者,webkit系的连浮点数也出来了。由于一个框架拥有许多模块,因此测试显示区也分为许多版块,如何处理同步与异步的关系非常重要,前一版本专门搞了个Deferred异步列队,但我发现其实mass的模块加载模块中的ready列队就是现成的异步列队,因此这版本就省下许多代码。本版本还处理了中文显示问题,这主要是因为FF私自对函体内的中文进行转码,我搞了uni2hanzi把它还原回来了。

    CSS部分

    
    @CHARSET "UTF-8";
     
    #dom-spec-result {
        border:5px solid #00a7ea;
        padding:10px;
        background:#03c9fa;
        list-style-type:none;
    }
    .dom-spec-summary {
        height: 2em;
        line-height: 2em;
        margin: 0;
        font-size: 13px;
        font-weight: bold;
        text-indent: 2em;
        background:#008000;
        color:#fff;
    }
    .dom-spec-detail{
        list-style: none;
        margin: 0;
        padding: 0;
    }
    .dom-spec-detail li{
        margin: 0;
        padding:0;
        border: 2px solid #03c9fa;
        text-indent: 1em;
    }
    .dom-spec-pass{
        background:#a9ea00;
    }
    .dom-spec-unpass{
        background:#cd0000;
        color:#fff;
    }
    .dom-spec-detail pre{
        margin: 1em;
        text-indent: 0;
        font-style: normal;
        background: #F0F8FF;
        padding: 2px;
        color:#000;
        border:2px outset #c0c0c0;
    }
    .dom-spec-error{
        background: #000;
        color:#fff;
    }
    .dom-spec-log{
        background: #cc9!important;
    }
    /*用于点击展开*/
    .dom-spec-slide {
        background:#a9ea00;
        text-indent: 2em;
        line-height: 1.4em;
        height: 1.4em;
        margin: 0;
    }
    .dom-spec-diff {
        background: red;
        margin: 1em;
    }
    .dom-spec-diff div{
        45%;
        float: left;
    }
    .dom-spec-diff pre{
        background: #00cc00;
    }
    /* new clearfix */
    .clearfix:after {
        visibility: hidden;
        display: block;
        font-size: 0;
        content: " ";
        clear: both;
        height: 0;
    }
    * html .clearfix             { zoom: 1; } /* IE6 */
    *:first-child+html .clearfix { zoom: 1; } /* IE7 */
    
    

    JS部分

    
    //==================================================
    // 测试模块
    //==================================================
    (function(global,DOC){
        var dom = global[DOC.URL.replace(/(#.+|\W)/g,'')];
        dom.define("first/spec", function(){
            dom.log("已加载spec模块")
            //模块为dom添加如下方法:
            //quote isEqual dump Deferred runTest addTestModule
            //在全局命名空间下多添加一个函数 expect
            dom.mix(dom,{
                //在字符串两端加上引号,并对其内部一些字符进行转义,用于JSON与引用
                quote :global.JSON && JSON.stringify || String.quote ||  (function(){
                    var meta = {
                        '\t':'t',
                        '\n':'n',
                        '\v':'v',
                        'f':'f',
                        '\r':'\r',
                        '\'':'\'',
                        '\"':'\"',
                        '\\':'\\'
                    },
                    reg = /[\x00-\x1F\'\"\\\u007F-\uFFFF]/g,
                    regFn = function(c){
                        if (c in meta) return '\\' + meta[c];
                        var ord = c.charCodeAt(0);
                        return ord < 0x20   ? '\\x0' + ord.toString(16)
                        :  ord < 0x7F   ? '\\'   + c
                        :  ord < 0x100  ? '\\x'  + ord.toString(16)
                        :  ord < 0x1000 ? '\\u0' + ord.toString(16)
                        : '\\u'  + ord.toString(16)
                    };
                    return function (str) {
                        return    '"' + str.replace(reg, regFn)+ '"';
                    }
                })(),
                //比较对象是否相等或相似
                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 "NodeList":
                            case "Arguments":
                            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 "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 + "}";
                    }
                }
    
            });
            //这里尽量不依赖其他核主模块
            var $ = function(id) {
                return DOC.getElementById(id);
            };
            var parseHTML = function() {//用于生成元素节点,注意第一层只能用一个元素
                var div = DOC.createElement("div");
                return function(html) {
                    div.innerHTML = html;
                    return div.firstChild;
                };
            }();
            //在字符串嵌入表达式 http://www.cnblogs.com/rubylouvre/archive/2011/03/06/1972176.html
            var reg_format = /\\?\#{([^{}]+)\}/gm;
            var format = function(str, object){
                var array = dom.slice(arguments,1);
                return str.replace(reg_format, function(match, name){
                    if (match.charAt(0) == '\\')
                        return match.slice(1);
                    var index = Number(name)
                    if(index >=0 )
                        return array[index];
                    if(object && object[name] !== void 0)
                        return  object[name];
                    return  '' ; ;
                });
            }
            var Expect = function(actual){
                return this instanceof Expect ? this.init(actual) : new Expect(actual);
            }
            function getUnpassExpect(str){
                var boolIndex = 1,ret = "error!",section = 0, qualifier = "("
                for(var j=1;j < str.length;j++){
                    if(str.charAt(j) == "("){
                        boolIndex++
                    }else if(str.charAt(j) == ")"){
                        boolIndex--
                    }else if(str.charAt(j) != qualifier && boolIndex == 0){
                        section++
                        if(section == 1){
                            qualifier = ")"//取得expect(...)中的部分
                            boolIndex = -1
                        }else if(section == 2){
                            boolIndex = 1;//取得ok,eq,match,log等函数名
                            qualifier = ")"
                        }else if(section == 3){//取得最后的函数体,并返回整个匹配项
                            ret = "expect" + str.slice(0,j)
                            break
                        }
                    }
                }
                return ret;
            }
        
            dom.require("ready",function(){
                var html = ['<div id="dom-spec-result"><p class="dom-spec-summary">',
                '<span id="dom-spec-failures" title="0">0</span> failures ',
                '<span id="dom-spec-errors" title="0">0</span> errors ',
                '<span id="dom-spec-done" title="0">0</span>% done ',
                '<span id="dom-spec-time" title="0">0</span>ms </p>',
                '<p class="dom-spec-summary">',global.navigator.userAgent,
                '</p><div id="dom-spec-cases"><div id="loading">正在加载测试数据中,请耐心等特</div></div></div>'];
                //div#dom-spec-result为整个系统的容器
                //div#dom-spec-summary用于放置各种统计
                //div#dom-spec-cases用于放置测试模块
                DOC.body.appendChild(parseHTML(html.join("")));
            });
    
            dom.mix(Expect,{
                refreshTime : function(){//刷新花费时间
                    var el = $("dom-spec-time");
                    var times = parseInt(el.title,10) + (new Date - Expect.now);
                    el.title = times;
                    el.innerHTML = times
                },
                addTestModule : function(title, cases) {   
                    dom.require("ready",function(){
                        var moduleId = "dom-spec-"+title, names = [];
                        if(!$(moduleId)){//在主显示区中添加一个版块
                            /**   =================每个模块大抵是下面的样子===============
                        <div class="dom-spec-case" id="dom-spec-dom.js">
                        <p><a href="javascript:void(0)">JS文件名字</a></p>
                        <ul style="display: none;" class="dom-spec-detail">
                        测试结果
                        </ul>
                        </div>
                         */
                            var html = ['<div id="#{0}" class="dom-spec-case">',
                            '<p class="dom-spec-slide"><a href="javascript:void(0)">#{1}</a></p>',
                            '<ul class="dom-spec-detail" style="display:none;"></ul></div>'].join('');
                            $("dom-spec-cases").appendChild(parseHTML(format(html, moduleId, title)));
                           
                        }
                        for(var name in cases){//取得describe第二个参数的那个对象所包含的所有函数,并放到异步列队中逐一执行它们
                            if(cases.hasOwnProperty(name)){
                                names.push(name);
                            }
                        };
                        (function runTest(){
                            if((name = names.shift())){
                                var suite = cases[name],//测试函数
                                caseId = "dom-spec-case-"+name.replace(/\./g,"-");
                                if(!Expect.removeLoading){
                                    var loading = $("loading");
                                    loading.parentNode.removeChild(loading);
                                    Expect.removeLoading = 1
                                }        
                                if(!$(caseId)){//对应一个方法
                                    var parentNode = $(moduleId).getElementsByTagName("ul")[0];
                                    //处理函数体的显示 
                                    var safe = (suite+"").replace(/</g,"<").replace(/>/g,">");
                                    //从函数体内分解出所有测试单元
                                    Expect.expectArray = safe.split("expect");
                                    //函数体本身
                                    var node = parseHTML(format('<li id="#{0}">#{1}<pre>#{2}</pre></li>',caseId,name,uni2hanzi(safe)));
                                    parentNode.appendChild(node);
                                }
                                Expect.Client = $(caseId);//对应一个LI元素
                                Expect.PASS = 1;//用于判定此测试套件有没有通过
                                Expect.boolIndex = 0;//用于记录当前是执行到第几条测试
                                Expect.totalIndex = 0;
                                Expect.now = new Date;
                                try{
                                    suite();//执行测试套件
                                }catch(err){
                                    Expect.PASS = 2;
                                    var htm = ["第",Expect.boolIndex,"行测试发生错误\n",Expect.Msgs[Expect.boolIndex],"\n"];
                                    for(var e in err){
                                        htm.push(e+" "+(err[e]+"").slice(0,100)+"\n");
                                    }
                                    htm = '<pre title="error">'+htm.join("").replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>')+"</pre>";
                                    Expect.Client.appendChild(parseHTML(htm));
                                    var errors = $("dom-spec-errors");
                                    errors.title++;
                                    errors.innerHTML = errors.title;
                                }
                                $(caseId).className = Expect.CLASS[Expect.PASS];
                                Expect.refreshTime();//更新测试所花的时间
                                setTimeout(runTest,16);
                            }
                        })();
                    });
                },
                CLASS : {
                    0:"dom-spec-unpass",
                    1:"dom-spec-pass",
                    2:"dom-spec-error"
                },
                Msgs:{},
                prototype:{
                    init:function(actual){//传入一个目标值以进行比较或打印
                        this.actual = actual;
                        return this;
                    },
                    ok:function(msg){//判定是否返回true
                        this._should("ok",void 0,msg);
                    },
                    ng:function(msg){//判定是否返回false
                        this._should("ng",void 0,msg);
                    },
                    log:function(msg){//不做判断,只打印结果,用于随机数等肉眼验证
                        this._should("log",msg);
                    },
                    eq:function(expected,msg){//判定目标值与expected是否全等
                        this._should("eq", expected, msg);
                    },
                    near:function(expected, msg){
                        this._should("near", expected, msg);
                    },
                    match:function(fn,msg){//判定目标值与expected是否全等
                        this._should("match", fn, msg);
                    },
                    not:function(expected,msg){//判定目标值与expected是否非全等
                        this._should("not", expected,msg);
                    },
                    has:function(prop,msg){//判定目标值是否包含prop属性
                        this._should("has", prop,msg);
                    },
                    contains:function(el,msg){//判定目标值是否包含el这个元素(用于数组或类数组)
                        this._should("contains", el,msg);
                    },
                    same: function(expected,msg){//判定结果是否与expected相似(用于数组或对象或函数等复合类型)
                        this._should("same", expected,msg);
                    },
                    _should:function(method,expected, msg){//上面方法的内部实现,比较真伪,并渲染结果到页面
                        var actual = this.actual,bool = false;
                        if(method != "log"){
                            Expect.Msgs[Expect.boolIndex] = msg;
                            Expect.boolIndex++;
                        }
                        Expect.totalIndex++
                        switch(method){
                            case "ok"://布尔真测试
                                bool = actual === true;
                                expected = true;
                                break;
                            case "ng"://布尔非测试
                                bool = actual === false;
                                expected = false;
                                break;
                            case "eq"://同一性真测试
                                bool = actual == expected;
                                break;
                            case "near":
                                var threshold = arguments[3] | 0;
                                return Math.abs(parseFloat(this.actual) - parseFloat(expected)) <= threshold;
                                break;
                            case "not"://同一性非测试
                                bool = actual != expected;
                                break;
                            case "same":
                                bool = dom.isEqual(actual, expected);
                                break
                            case "has":
                                bool = Object.prototype.hasOwnProperty.call(actual, expected);
                                break;
                            case "match":
                                bool = expected(actual);
                                break;
                            case "contains":
                                for(var i = 0,n = actual.length; i < n ;i++ ){
                                    if(actual === expected ){
                                        bool = true;
                                        break;
                                    }
                                }
                                break;
                            case "log":
                                bool = "";
                                Expect.Client.appendChild(parseHTML('<pre class="dom-spec-log" title="log">'+(expected||"")+"  "+dom.dump(actual)+'</pre>'));
                                break;
                        }
                        // Expect.Msgs[Expect.boolIndex] = msg;
                        //修改统计栏的数值
                        var done = $("dom-spec-done");
                        var errors = $("dom-spec-errors");
                        var failures = $("dom-spec-failures");
                        if(typeof bool === "boolean"){
                            Expect.PASS = ~~bool;
                            if(!bool){//如果没有通过
                                failures.title++;
                                failures.innerHTML = failures.title;
                                var statement = getUnpassExpect((Expect.expectArray[Expect.totalIndex] || ""))
                                var html = ['<div class="dom-spec-diff clearfix">'+(msg ? "<p>"+msg+"</p>" : "")+'<p>本测试套件中第',Expect.boolIndex,
                                '条测试出错: ',statement,'</p><div>actual:<pre title="actual">'+dom.type(actual)+" : "+dom.dump(actual)+'</pre></div>',
                                '<div>expected:<pre title="expected">'+dom.type(expected)+" : "+dom.dump(expected)+'</pre></div>',
                                '</div>'];
                                Expect.Client.appendChild(parseHTML(html.join('')));
                            }
                            done.title++;
                            done.innerHTML = (((done.title-errors.title-failures.title)/done.title)*100).toFixed(0);
                        }
                    }
                }
            });
            //用于收起或展开详细测试结果
            dom.bind(DOC,"click",function(e){
                var target = e && e.target || event.srcElement;
               
                if(target.tagName === "A"){
                    var parent = target.parentNode.parentNode;
                    if(parent.className== "dom-spec-case"){//用于切换详情面板
                        var ul = parent.getElementsByTagName("ul")[0];
                        var display = ul.style.display;
                        ul.style.display = display === "none" ? "" : "none";
                    }
                }
            });
            //shortcut
            //暴露到全局作用域
            global.expect = Expect;
            dom.addTestModule = Expect.addTestModule;
            //此函数是解决FF无法显示函数体内的汉字问题
            var uni2hanzi = global.netscape ? function(s){
                return  unescape(s.replace(/\\u/g,'%u'));
            }: function(s){
                return s
            }
            
        })
    })(this,this.document);
    //2011.8.9    增加getUnpassExpect函数,用于取得没有通过的expect并显示出来
    //2011.10.26  优化format与quote
    //2011.10.27   runTest添加参数,用于等特一定做量的测试模块都加载完毕才执行
    //2011.10.31 去掉deferred模块的依赖,依靠ready列队自行添加测试的模块
    

    用法:

    //主页面引用
               dom.require("ready,test/dom,test/lang", dom.noop);
    

    测试用的JS文件:

    //    test/dom.js
    
    dom.define("test/dom","first/spec",function(){
        dom.isWindow = function(obj){//单独提出来,专门用于测试对window的判定
            return dom.type(obj,"Window")
        };
        dom.addTestModule('模块加载模块-dom', {
            'type': function() {
                expect(dom.type("string")).eq("String");
                expect(dom.type(1)).eq("Number");
                expect(dom.type(!1)).eq("Boolean");
                expect(dom.type(NaN)).eq("NaN");
                expect(dom.type(/test/i)).eq("RegExp");
                expect(dom.type(dom.noop)).eq("Function");
                expect(dom.type(null)).eq("Null");
                expect(dom.type({})).eq("Object");
                expect(dom.type([])).eq("Array");
                expect(dom.type(new Date)).eq("Date");
                expect(dom.type(window)).eq("Window");
                expect(dom.type(document)).eq("Document");
                expect(dom.type(document.documentElement)).eq("HTML");
                expect(dom.type(document.body)).eq("BODY");
                expect(dom.type(document.childNodes)).eq("NodeList");
                expect(dom.type(document.getElementsByTagName("*"))).eq("NodeList");
                expect(dom.type(arguments)).eq("Arguments");
                expect(dom.type(1,"Number")).eq(true);
            },
            "isWindow" : function(){
                var test1 = {};
                test1.window = test1;
                test1.document = document;
                expect(dom.isWindow(test1)).ng();
                var test2 = {};
                test2.window = window;
                test2.document = document;
                expect(dom.isWindow(test1)).ng();
                expect(dom.isWindow(window)).ok();
                var iframe = document.createElement("iframe");
                document.body.appendChild(iframe);
                var iwin = iframe.contentWindow || iframe.contentDocument.parentWindow;
                expect(dom.isWindow(iwin)).ok();
                document.body.removeChild(iframe);
    
                var wg = {
                    document : {}
                }, wgdoc = wg.document;
                wg.window = wg;
                wgdoc.createElement = function(){
                    return wg;
                };
                wgdoc.getElementsByTagName = function(){
                    return [wg];
                };
                wgdoc.parentWindow = wg;
                wg.insertBefore = function(){};
                wg.firstChild = wg.firstChild;
                wg.removeChild = function(){};
                expect(dom.isWindow(wg)).ng();//false
            },
    
            "oneObject":function(){
                expect(dom.oneObject("aa,bb,cc")).same({
                    "aa":1,
                    "bb":1,
                    "cc":1
                });
                expect(dom.oneObject([1,2,3],false)).same({
                    "1":false,
                    "2":false,
                    "3":false
                });
            }
        });
    });
    
    //    test/lang.js
    
    dom.define("test/lang","lang,first/spec",function(dom, $$){
        dom.addTestModule("语言扩展模块-lang",{ 
            "dom.isPlainObject": function() {
                expect(dom.isPlainObject([])).ng();//false
                expect(dom.isPlainObject(1)).ng();//false
                expect(dom.isPlainObject(null)).ng();//false
                expect(dom.isPlainObject(void 0)).ng();//false
                expect(dom.isPlainObject(window)).ng();//false
                expect(dom.isPlainObject(document.body)).ng();//false
                expect(window.location).log();
                expect(dom.isPlainObject(window.location)).ng();//false
                var fn = function(){}
                expect(dom.isPlainObject(fn)).ng();//false
                fn.prototype = {
                    someMethod: function(){}
                };
                expect(dom.isPlainObject(new fn)).ng();//false
                expect(dom.isPlainObject({})).ok();//true
                expect(dom.isPlainObject({
                    aa:"aa",
                    bb:"bb",
                    cc:"cc"
                })).ok();//true
                expect(dom.isPlainObject(new Object)).ok();//true
            },
            "dom.isArrayLike":function(){
                expect(dom.isArrayLike(arguments)).ok();//1
                expect(dom.isArrayLike(document.links)).ok();//2
                expect(dom.isArrayLike(document.documentElement.childNodes)).ok();
                expect(dom.isArrayLike({
                    0:"a",
                    1:"b",
                    length:2
                })).ok();
                
                var tag = dom.tag
                var html = tag("select",tag("option","aaa") + tag("option","bbb")+ tag("option","ccc"))
                var div = document.createElement("div");
                div.innerHTML = html;
                var select = div.firstChild;
                expect(dom.isArrayLike(select)).ng();
    
            },
            "dom.isNative":function(){
                expect(dom.isNative(Array.prototype,"slice")).ok();
                expect(dom.isNative(Array.prototype,"indexOf")).log();
                expect(dom.isNative(Array.prototype,"forEach")).log();
                expect(dom.isNative(String.prototype,"quote")).log();
                expect(dom.isNative(String.prototype,"trim")).log();
                expect(dom.isNative(Function.prototype,"bind")).log();
            },
            "dom.range":function(){
                expect(dom.range(10)).same([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
                expect(dom.range(1, 11)).same([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
                expect(dom.range(0, 30, 5)).same([0, 5, 10, 15, 20, 25]);
                expect(dom.range(0, -10, -1)).same([0, -1, -2, -3, -4, -5, -6, -7, -8, -9]);
                expect(dom.range(0)).same([]);
            },
            "dom.format":function(){
                expect(dom.format("pi is #{0}", Math.PI)).eq("pi is 3.141592653589793");
                
                var a = dom.format("style.#{name}=((isEnd ? #{end} : adapter.#{type}( #{from}, #{change},'#{easing}',per ))|0)+'#{unit}';",{
                    name:"width",
                    end:"0",
                    type:"_default",
                    from:"200",
                    change:"200",
                    easing:"linear",
                    unit:"px"
                })   ;
               
                expect(a).eq("style.width=((isEnd ? 0 : adapter._default( 200, 200,'linear',per ))|0)+'px';");
    
            },
            "dom.tag":function(){
                var tag = dom.tag
                var html = tag("h1 title='aaa'","sss")
                ('a href=#' ,
                    tag("img src='http://www.google.com.hk/images/nav_logo83.png'")
                    ('br')
                    ('' ,"View larger image") );
                expect(html+"").eq("<h1 title='aaa'>sss</h1><a href=#><img src='http://www.google.com.hk/images/nav_logo83.png'><br>View larger image</a>");
            },
            "dom.parseXML":function(){
                var str = "<note><to>Tove</to><from>Jani</from><heading>Reminder</heading><body>Don't forget me this weekend!</body></note>"
                expect(dom.parseXML(str).nodeType).eq(9)//[object XMLDocument]
            },
            
            "String2":function(){
                expect($$("aaabbbcc").contains("bbb")).ok();
                expect($$('http://index').startsWith('http')).ok();
                expect($$('image.gif').endsWith('.gif')).ok();
                expect($$('image.gif').endsWith('.GIF')).ng();
                expect($$('image.gif').endsWith(".GIF",true)).ok();
    
                expect($$('司徒正美').byteLen()).eq(8);
    
                expect($$('').empty()).ok();
                expect($$(' ').empty()).ng();
    
                expect($$(' ').blank()).ok();
                expect($$('').blank()).ok();
                expect($$('\n').blank()).ok();
                expect($$(' a').blank()).ng();
    
                expect($$("this is a test test").truncate(10)).eq("this is...");
    
                expect($$("foo-bar").camelize()).eq("fooBar");
    
                expect($$("boo boo boo").capitalize()).eq("Boo boo boo");
    
                expect($$("fooBar").underscored()).eq("foo_bar");
                expect($$("foo-bar").underscored()).eq("foo_bar");
    
                expect($$("10.23").toInt()).eq(10);
                expect($$("1.23").toFloat()).eq(1.23);
    
                expect($$("animals.sheep[1]").escapeRegExp()).eq("animals\\.sheep\\[1\\]");
    
                expect($$("2").padLeft(4)).eq("0002");
    
                expect($$("2").padRight(4," ")).eq("2   ");
                expect($$("ruby").times(2)).eq("rubyruby");
            },
            "Array2":function(){
                var a = ["aaa",1,2,undefined,3,4,null,{
                    2:2
                }];
                //复制一个副本
                var b = $$(a).clone();
                expect(a).same(b);//1
                expect(a).not(b);//2
    
                expect($$(a).first()).eq('aaa');//3
                expect($$(a).first(function(el){//4
                    return el >1
                })).eq(2);
                expect($$(a).last()).same({//5
                    2:2
                });
                expect($$(a).last(function(el){//6
                    return el >1
                })).eq(4);
    
                expect($$(a).contains(2)).ok();//7
    
                expect($$(a).diff([1,2,3])).same(["aaa",undefined,4,null,{
                    2:2
                }]);
                expect($$(b).remove(1)).same([1]);
                expect($$(b).removeAt(1)).same([2]);
                expect($$(a).shuffle()).log();
                expect($$(a).random()).log();
                expect($$(a).compact()).same(["aaa",1,2,3,4,{
                    2:2
                }]);
                expect($$(a).ensure(3,4,5)).same(["aaa",1,2,undefined,3,4,null,{
                    2:2
                },5]);
                var c = [3,4,6,1,45,9,5,3,4,22,3];
                expect($$(c).min()).eq(1);
                expect($$(c).max()).eq(45);
                expect($$(c).unique()).same([6,1,45,9,5,4,22,3]);
                expect($$([1, 2, 1, 3, 1, 4]).unique()).same([2,3,1,4]);
    
                var d =['frank', ['bob', 'lisa'], ['jill', ['tom', 'sally']]];
                expect($$(d).flatten()).same(['frank', 'bob', 'lisa', 'jill', 'tom', 'sally']);
    
                var e = ['hello', 'world', 'this', 'is', 'nice'];
                expect($$(e).pluck("length")).same([5, 5, 4, 2, 4]);
                expect($$(e).sortBy(function(s) {
                    return s.length;
                })).same(["is","this","nice","hello","world"]);
    
                var f = [0,1,2,9];
                var g = [0,5,2];
                expect($$(f).diff(g)).same([1,9]);
    
                var h = [1,2,3];
                h = $$(h).union([2,3,4,5,6]);//取并集
                expect(h).same([1,2,3,4,5,6]);
                var j = [1, 2, 3, "a"];
                j = $$(j).intersect([1, "a", 2]);//取交集
                expect(j).same([1, 2, "a"]);
                
            },
            "Number2" : function(){
                var a = [];
                $$(8).downto(4, function(i) {
                    a.push(i);
                });
                expect(a).same([8,7,6,5,4]);
    
                expect($$(4.444).round(1)).eq(4.4);
                expect($$(4.444).round(2)).eq(4.44);
                expect($$(4.444).round(3)).eq(4.444);
                expect($$(7).constrain(3,5)).eq(5);
                expect($$(4).constrain(3,5)).eq(4);
                expect($$(4).nearer(3,9)).eq(3);
                expect($$(454).nearer(-4543,6576)).eq(-4543);
            },
            "Object2":function(){
    
                var a = {
                    a:"one",
                    b:"two",
                    c:"three"
                };
                expect($$(a).subset(["a","c"])).same({
                    a: 'one',
                    c: 'three'
                });
                a = {
                    first: 'Sunday',
                    second: 'Monday',
                    third: 'Tuesday'
                };
                var b = [];
                $$(a).forEach(function(value,key){
                    b.push(value);
                });
                expect(b).same(["Sunday","Monday","Tuesday"]);
                a = {
                    e:1,
                    b:"aaa",
                    c:[1,2,3],
                    d:{
                        bb:"bb"
                    }
                };
    
                expect($$(a).clone()).same(a);
                var obj1 = {
                    a: 0,
                    b: 1
                };
                var obj2 = {
                    c: 2,
                    d: 3
                };
                var obj3 = {
                    a: 4,
                    d: 5
                };
                var merged  = $$(obj1).merge(obj2, obj3);
                expect(obj1).same(merged);
                var nestedObj1 = {
                    a: {
                        b: 1,
                        c: 1
                    }
                };
                var nestedObj2 = {
                    a: {
                        b: 2
                    }
                };
                var nested  = $$(nestedObj1).merge(nestedObj2);
                expect(nested).same({
                    a: {
                        b: 2,
                        c: 1
                    }
                });
    
                a = {
                    a:1,
                    b:2,
                    c:3
                };
                expect($$(a).without("a")).same({
                    b:2,
                    c:3
                });
            }
        });
    });
       
    
    
    

    相关链接

    dom Framework spec模块

  • 相关阅读:
    【mybatis-SqlSession的方法总结】
    【项目中遇到的一点问题】
    【request获取用户请求ip】
    【Linux入门】
    【linux学习-centeros】
    java Map 映射
    Java Set接口
    Java 泛型
    Java集合框架---重构设计
    Java 数据结构之双链表
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/2230836.html
Copyright © 2020-2023  润新知