/* Tree.js v0.6.2 https://github.com/Wizek/Tree */ void function() { function _virgoTreeInstance() { // Heart of the framework var tree = function(act, forgot) { tree._act = act typeof forgot=='function'&&console.warn("Didn't you forget about .branch() somewhere?") return tree } tree._virgoTreeInstance = oneTimeSetUp // Host objects tree.not = {_not:true} tree._asserts = {} tree._helpers = {} tree.config = tree.cfg = function (obj, val) { // might be needed later var defaults = {} // if it is called on the .heritable. path, this._heritable is true // otherwise false or undefined var heritable = this._heritable // spec(ific) is false if called simply by tree.config, true if taking other path var spec = this._spec // taming the input var obj = tree.cfg._morph(obj, val) if (obj == null || typeof obj == 'string') { return read(obj) } else if (typeof obj == 'object') { return write(obj) } function write (obj) { if (heritable) { for (key in obj) if (obj.hasOwnProperty(key)) { tree.config.heritable[key] = obj[key] } } else { for (key in obj) if (obj.hasOwnProperty(key)) { tree.config.oneLevel[key] = obj[key] } } return read() } function read (str) { if (!spec) { return getMixed(str) } else { if (str) { return getProper()[str] } else { return getProper() } } function getProper () { if (heritable) { return tree.config.heritable } else { return tree.config.oneLevel } } // combine HER and ONE, in case of conflict the latter wins function getMixed (str) { var her = tree.config.heritable var one = tree.config.oneLevel if (str) { // single query return (typeof one[str] !== 'undefined' ? one[str] : her[str]) } else { // general query var out = {} for (key in her) if (her.hasOwnProperty(key)) { out[key] = her[key] } for (key in one) if (one.hasOwnProperty(key)) { out[key] = one[key] } return out } } } } // tame the input tree.config._morph = function(obj, val) { if (typeof obj == 'object' && obj) { // we do not care about val, obj alone does it return obj } else if (typeof obj == 'string') { // we can either have a read request if (typeof val == 'undefined') { // all exact read calls are in string form return obj } else { // or a write request // all write calls are in object form var o = {} o[obj] = val return o } } else { // general read is null return null } } tree.config.oneLevel = {} tree.config.heritable = {} tree.oneLevel = { _heritable: false , _spec: true , config: tree.cfg , cfg: tree.cfg } tree.heritable = { _heritable: true , _spec: true , cfg: tree.cfg , config: tree.cfg } tree._helpers.getCallerLine = function(l) { var t = new Error().stack return t? t.split('\n')[l?l:4].match(/\(?(\S+\w)\)?$/)[1] : '(unknown)' } var tpl = tree._helpers._templater = function(tplstr, vars) { if (typeof vars != 'object') var vars = {} if (typeof tplstr != 'string') throw new Error('Template string is not a string!') var RE_ifTruthy = /\{{\s*#\s*(.*?)\s*}}(.*?){{\s*\/\s*\1\s*}}/g var RE_ifFalsy = /\{{\s*\^\s*(.*?)\s*}}(.*?){{\s*\/\s*\1\s*}}/g while (tplstr.match(RE_ifTruthy)) { tplstr = tplstr.replace(RE_ifTruthy , function(full, varName, content, pos, oStr) { if (vars[varName]) { return content }else{ return '' } }) } while (tplstr.match(RE_ifFalsy)) { tplstr = tplstr.replace(RE_ifFalsy , function(full, varName, content, pos, oStr) { if (vars[varName]) { return '' }else{ return content } }) } return tplstr.replace(/\{{\s*([^}]*?)\s*}}/g , function(match, group, pos, oStr) { if (group in vars) { return vars[group] }else{ return '' } }) } tree._helpers._formateer = function(input, long) { var output = '' var type = typeof input if (type == 'number') { output = input.toString() } else if (type == 'string') { var single = input.match(/'/g) var double = input.match(/"/g) var sgl = "'" var dbl = '"' var esc = '\\' if (single && double) { if (double.length < single.length) { // more single than doulbe output = dbl+input.replace(/"/g, esc+dbl)+dbl } else { // more or equal count of doulbe than count of single output = sgl+input.replace(/'/g, esc+sgl)+sgl } } else if (single) { // if there are singles inside output = dbl+input+dbl } else { // wheter there are doubles or not output = sgl+input+sgl } } else if (type == 'function') { if (long) { output = input.toString() } else { output = 'fn(){...}' } } else if (Array.isArray(input)) { if (long) { output = JSON.stringify(input, null, 2) } else { output = '[...]' } } else if (type == 'object' && input && input.toString() === '[object Object]') { if (long) { output = JSON.stringify(input, null, 2) } else { output = '{...}' } } else if (type == 'boolean') { output = input.toString() } else if (type == 'undefined') { output = 'undefined' } else if (input == null) { output = 'null' } else { output = '[unknown type: '+input+']' } return output } tree._announcer = {} tree._announcer.registerBranch = function(newBranch) { var $pe = $(tree._domElem) var html = tree._htmlTpl if (newBranch.commented) { var name = newBranch.name.match('(// *)(.*)')[2] $pe.children('ul').append( tpl(html.branch,{comm:true,gut: tpl(html.branchGut,{ summary:htmlEncode(name+' ('+tree._helpers.getCallerLine()+')') }) }) ) } else { if (!tree._global.inited) { tree._initDom() tree._global.inited = true } newBranch._domElem = $( tpl(html.branch,{gut: tpl(html.branchGut,{ summary:htmlEncode(newBranch.cfg('name')) }) }) ).get(0) $(tree._domElem).children('ul').append(newBranch._domElem) } this.updateTreeTop(this.getStatusString('running')) if ($pe.hasClass('no-children')) { $pe.removeClass('no-children').addClass('collapsed') } function htmlEncode (value) { return String(value) .replace(/&/g, '&') .replace(/"/g, '"') .replace(/'/g, ''') .replace(//g, '>') } } tree._announcer.branchDone = function(obj) { var $el = $(tree._domElem) if ($el.has('ul li:not(.passed):not(.commented)').length == 0) { $el.removeClass('await').addClass('passed') if (tree._parent) { tree._parent._announcer.branchDone() } } } tree._announcer.branchFail = function() { var $el = $(tree._domElem) $el .removeClass('await') //.removeClass('no-children') .removeClass('collapsed') .removeClass('passed') // needed because of double .done() .addClass('failed') .addClass('expanded') if (tree._parent) { tree._parent._announcer.branchFail() } } tree._announcer.updateTreeTop = function(txt) { $(tree._global.$treeTop).children('.summary').html(txt) } tree._announcer.registerAssert = function(obj) { if (!tree._global.inited) { tree._initDom() tree._global.inited = true } this.updateTreeTop(this.getStatusString('running')) var $el = $(tree._domElem) if ($el.hasClass('no-children')) { $el.removeClass('no-children').addClass('collapsed') } if (!obj.pass) { tree._announcer.branchFail() } obj.path = obj.path || tree._helpers.getCallerLine() if (obj.act) { obj.actType = typeof obj.act } if (obj.exp) { obj.expType = typeof obj.exp } $el.children('ul').append( $(tpl(tree._htmlTpl.assert, obj)) ) } tree._initDom = function($elem) { if (typeof jQuery === 'undefined' || !jQuery ) { throw new Error('jQuery dependency not found') } if (tree._global.inited) { return 'inited already' } else { tree._global.inited = true } var bp = tree._global.baseUrl ? tree._global.baseUrl : '' var cssFilePath = bp+'tree.css' var html = tree._htmlTpl var tpl = tree._helpers._templater if (isDomElem($elem)) { var $elem = $($elem) var $head = $elem.parents('html').children('head') } else { if (typeof $elem == 'string') { var id = $elem } var $elem = $('body') var $head = $('head') } var cssAsString = 'article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}[hidden]{display:none}html{font-size:100%;overflow-y:scroll;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}body,button,input,select,textarea{font-family:sans-serif}a:focus{outline:thin dotted}a:hover,a:active{outline:0}h1{font-size:2em}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}blockquote{margin:1em 40px}dfn{font-style:italic}mark{background:#ff0;color:#000}pre,code,kbd,samp{font-family:monospace,serif;_font-family:\'courier new\',monospace;font-size:1em}pre{white-space:pre;white-space:pre-wrap;word-wrap:break-word}q{quotes:none}q:before,q:after{content:\'\';content:none}small{font-size:75%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}ul,ol{margin-left:0;padding:0 0 0 40px}dd{margin:0 0 0 40px}nav ul,nav ol{list-style:none;list-style-image:none}img{border:0;-ms-interpolation-mode:bicubic}svg:not(:root){overflow:hidden}figure{margin:0}form{margin:0}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em}legend{border:0;*margin-left:-7px}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button;*overflow:visible}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}div.tree-top{background:#eee;color:#201f1d;font:12pt \'Consolas\';padding:10px 10px 0;box-shadow:0 2px 10px 0 rgba(0,0,0,.50);padding-left:85px}div.tree-top>li>.summary em{font-style:normal;font-weight:700}div.tree-top .stamp{border:3px solid #008000;border-radius:5px;padding:0 2px}div.tree-top .stamp.await{border-color:#afdbf0;color:#9dde8a;color:#0d3446}div.tree-top .stamp.failed{border-color:#ff483c;color:#3f0400}div.tree-top .stamp.passed{border-color:#9dde8a;color:#193810}div.tree-top .stamp.comment{border-color:#ddd}div.tree-top ul{margin-top:0}div.tree-top li{list-style-type:none;margin-top:8px}div.tree-top li:not(.no-children)>span{cursor:pointer}div.tree-top li.branch.commented{color:#808080}div.tree-top li.branch.commented>.stamp{border-color:#ddd}div.tree-top li.assert .stamp.failed{background:#ff483c}div.tree-top li.assert .stamp.passed{background:#9dde8a}div.tree-top li.assert.failed table{border-left:4px #ff483c solid}div.tree-top li.assert.passed table{border-left:4px #9dde8a solid}div.tree-top li.assert table{font-size:80%;margin:6px 0 12px 40px;border-collapse:separate;border-spacing:5px}div.tree-top li.assert table th{border-right:2px rgba(0,0,0,.12) solid;vertical-align:top;font-weight:400;text-align:right;padding-right:5px}div.tree-top li.assert table td li{white-space:pre}div.tree-top .type.number,div.tree-top .type.string{color:#667bef}div.tree-top .collapsed>ul,div.tree-top .collapsed>table,div.tree-top .collapsed>.handle:not(.plus),div.tree-top .expanded>.handle:not(.minus),div.tree-top .no-children>.handle:not(.dot),div.tree-top .await>.stamp:not(.await),div.tree-top .failed>.stamp:not(.failed),div.tree-top .passed>.stamp:not(.passed),div.tree-top .commented>.stamp:not(.comment){display:none}div.tree-top .handle{color:#808080;font:bold 120% \'Lucidia Console\',monospace}div.tree-top *{-webkit-user-select:none;-khtml-user-select:none;-o-user-select:none;user-select:none}div.tree-top .summary,div.tree-top table,div.tree-top .summary *,div.tree-top table *{-webkit-user-select:initial;-khtml-user-select:initial;-o-user-select:initial;user-select:initial}div.tree-top div.logo,div.tree-top div.logo img{height:52.5px;width:60px;*zoom:1}div.tree-top div.logo img{opacity:.4;position:absolute;right:10px}div.tree-top li{text-indent:-75px}div.tree-top table{text-indent:0;margin-left:-35px!important}' var cssWrapperA = '' if ($head.find('link#tree, style#tree').length == 0) { (cssAsString ? $(cssWrapperA+cssAsString+cssWrapperB) : $('') ).appendTo($head) $('.tree-top').find('.collapsed>span, .expanded>span') .live('click', function() { $(this).siblings('ul, table').toggle().parent('li') .toggleClass('collapsed expanded') }) } var summary = 'Empty' var $init = $(tpl(html.init, {id:id, path:html.logo, gut: tpl(html.branch, {gut: tpl(html.branchGut, {summary:summary}) }) })) var $treeTop = $init.children('li.branch').get(0) tree._global.$treeTop = $treeTop tree._domElem = $treeTop $elem.append($init) //Returns true if it is a DOM element function isDomElem(o) { return ( typeof HTMLElement === "object" ? o instanceof HTMLElement : // DOM2 typeof o === "object" && o.nodeType === 1 && typeof o.nodeName==="string" ) } } tree._announcer.EFD = function() { tree._announcer.updateTreeTop(this.getStatusString('done')) } tree._announcer.getStatusString = function(type) { var g = tree._global g.time = Date.now()-g.tree_start var tpl = tree._helpers._templater return tpl(tree._htmlTpl['status_'+type], g) } //tree.note = function(str) { // this._note = str //} tree._htmlTpl = { init: '' + '\n
Note | This assert passes |
---|---|
Result | ' + '{{actS}} |
Expected | ' + '{{expS}} |
Path | {{path}} |