diff --git a/src/core/source/utils.js b/src/core/source/utils.js index 86c2030..16ffcca 100644 --- a/src/core/source/utils.js +++ b/src/core/source/utils.js @@ -192,8 +192,18 @@ function translateNode(node){ // function wrapSource(source, breakpointAt){ + function wrapToBlock(node){ + if (node.parentNode.type != 'BlockStatement' && node.parentNode.type != 'Program') + { + var tokens = getNodeRangeTokens(node); + tokens[0].value = '{\n' + tokens[0].value; + tokens[1].value = tokens[1].value + '\n}'; + } + } + var ast = parse(source); + if (breakpointAt == 'none') { traverseAst(ast, function(node){ @@ -230,10 +240,12 @@ function wrapSource(source, breakpointAt){ { var token = getNodeRangeTokens(node)[0]; var singleArg = node.arguments.length == 1 ? node.arguments[0] : null; - var isForCode = '__isFor(' + node.range + ',' + (node.loc.end.line - 1) + ')'; - var newValue = token.value.replace(/^__enterLine\(\d+\)/, isForCode); + var isForCode = 'if(__isFor(' + node.range + ',' + (node.loc.end.line - 1) + '))debugger;\n'; + var newValue = token.value.replace(/^__enterLine\(\d+\); /, isForCode); + + token.value = newValue != token.value ? newValue : isForCode + token.value; - token.value = newValue != token.value ? newValue : isForCode + ' || ' + token.value; + wrapToBlock(node.parentNode); if (singleArg && singleArg.type == 'BinaryExpression' && diff --git a/src/core/test.js b/src/core/test.js index b8192f2..245083b 100644 --- a/src/core/test.js +++ b/src/core/test.js @@ -218,10 +218,18 @@ var TestCase = AbstractTest.subclass({ this.testWrappedSources = {}; if (!this.testWrappedSources[breakpointAt]) + { + var sourceMap = ''; + // '\n//# sourceMappingURL=data:application/json;base64,' + + // require('basis.utils.base64').encode('{"version":3,"sources":["' + basis.path.origin + '/foo.js' + '"],"sourcesContent":[' + JSON.stringify(source) + '],' + + // '"mappings":"AAAA' + basis.string.repeat(';AACA', source.split('\n').length) + + // '"}', true) + '\n'; + this.testWrappedSources[breakpointAt] = 'function(' + sourceUtils.getFunctionInfo(this.data.test).args.concat('assert', '__isFor', '__enterLine', '__exception', '__wrapFunctionExpression', '__actual', '__expected').join(', ') + '){\n' + sourceUtils.getWrappedSource(source, breakpointAt) + - '\n}'; + '\n}' + sourceMap; + } return this.testWrappedSources[breakpointAt]; }, @@ -236,7 +244,7 @@ var TestCase = AbstractTest.subclass({ AbstractTest.prototype.reset.call(this); this.setState(STATE.UNDEFINED); }, - run: function(){ + run: function(breakAssert){ // var _warn = basis.dev.warn; // var _error = basis.dev.error; var warnMessages = []; @@ -247,6 +255,7 @@ var TestCase = AbstractTest.subclass({ var timeoutTimer; var async = this.data.async ? 1 : 0; var isNode = null; + var isForNum = 0; var sourceCode = this.getSourceCode(); var beforeAfterInfo = this.getBeforeAfterInfo(); @@ -328,6 +337,7 @@ var TestCase = AbstractTest.subclass({ errors.push({ num: report.testCount, + debug: isForNum, node: isNode, error: error, expected: utils.makeStaticCopy(expected), @@ -364,6 +374,7 @@ var TestCase = AbstractTest.subclass({ range: [start, end], line: line }; + return ++isForNum === breakAssert; }; var __enterLine = function(line){ diff --git a/src/reporter/app.js b/src/reporter/app.js index fe81b6a..f04c54e 100644 --- a/src/reporter/app.js +++ b/src/reporter/app.js @@ -44,18 +44,18 @@ toc.addHandler({ }); toc.selection.addHandler({ itemsChanged: function(selection){ - this.setDelegate(selection.pick()); + testDetails.setDelegate(selection.pick()); } -}, testDetails); +}); // content section setup testDetails.selection.addHandler({ itemsChanged: function(selection){ var selected = selection.pick(); if (selected) - this.setDelegate(selected.root); + toc.setDelegate(selected.root); } -}, toc); +}); var view = new Node({ template: resource('./template/view.tmpl'), diff --git a/src/reporter/app/check-debugger.js b/src/reporter/app/check-debugger.js new file mode 100644 index 0000000..775e327 --- /dev/null +++ b/src/reporter/app/check-debugger.js @@ -0,0 +1,31 @@ +var Node = require('basis.ui').Node; + +var timer; +var view = new Node({ + show: new basis.Token(false), + template: resource('./template/debugger-open.tmpl'), + binding: { + show: 'show' + } +}); + +basis.doc.body.ready(function(body){ + body.appendChild(view.element); +}); + +module.exports = function(){ + if (timer) + timer = clearTimeout(timer); + + var time = Date.now(); + view.show.set(false); + timer = setTimeout(function(){ + if (Date.now() - time < 200) + { + view.show.set(true); + timer = setTimeout(function(){ + view.show.set(false); + }, 3000); + } + }, 100); +}; diff --git a/src/reporter/app/template/debugger-open.css b/src/reporter/app/template/debugger-open.css new file mode 100644 index 0000000..4449097 --- /dev/null +++ b/src/reporter/app/template/debugger-open.css @@ -0,0 +1,17 @@ +.notify +{ + position: fixed; + top: 45px; + right: 5px; + padding: 8px; + background: rgba(0,0,0,.75); + color: white; + font-family: Tahoma, serif; + opacity: 0; + transition: opacity .25s; + z-index: 100; +} +.notify_show +{ + opacity: 1; +} diff --git a/src/reporter/app/template/debugger-open.tmpl b/src/reporter/app/template/debugger-open.tmpl new file mode 100644 index 0000000..bfb87bb --- /dev/null +++ b/src/reporter/app/template/debugger-open.tmpl @@ -0,0 +1,7 @@ + + + + +
+ To see effect, debugger should be opened. +
diff --git a/src/reporter/app/template/test-source.css b/src/reporter/app/template/test-source.css index 8fb373c..56adf9d 100644 --- a/src/reporter/app/template/test-source.css +++ b/src/reporter/app/template/test-source.css @@ -104,6 +104,24 @@ margin: 0; margin-top: 1px; overflow: hidden; + cursor: pointer; + position: relative; +} +.Basis-SyntaxHighlight .error-line-details-item:hover +{ + background: #F8F8F8; + box-shadow: 0 0 0px 1px white inset; +} +.Basis-SyntaxHighlight .error-line-details-item:hover:after +{ + content: 'pause before this assert'; + position: absolute; + top: 3px; + right: 3px; + padding: 2px 6px; + background: black; + background: rgba(0,0,0,.65); + color: white; } .Basis-SyntaxHighlight .error-line-details-item:first-child { diff --git a/src/reporter/app/template/test.css b/src/reporter/app/template/test.css index f7ee371..c313ad5 100644 --- a/src/reporter/app/template/test.css +++ b/src/reporter/app/template/test.css @@ -60,12 +60,14 @@ .loc-link { cursor: pointer; - border-bottom: 1px solid black; - border-color: rgba(0, 0, 0, .2); + /*border-bottom: 1px solid black; + border-color: rgba(0, 0, 0, .2);*/ + background: linear-gradient(to bottom, rgba(128, 128, 128, .25) 1px, transparent 1px) repeat-x 0 1.2em; } .loc-link:hover { color: #A00; - border-color: #A00; - border-color: rgba(160, 0, 0, .2); + /*border-color: #A00; + border-color: rgba(160, 0, 0, .2);*/ + background-image: linear-gradient(to bottom, rgba(160, 0, 0, .25) 1px, transparent 1px); } diff --git a/src/reporter/app/test.js b/src/reporter/app/test.js index 55e62ac..9b46b4c 100644 --- a/src/reporter/app/test.js +++ b/src/reporter/app/test.js @@ -9,6 +9,7 @@ var Node = require('basis.ui').Node; // var document = global.document; +var checkDebugger = require('./check-debugger.js'); var highlight = require('app.highlight'); var TestCase = require('core.test').TestCase; var strDiff = require('diff'); @@ -43,7 +44,7 @@ var CodeView = Node.subclass({ getter: function(node){ return node.getBeforeAfterInfo().afterCount; } - }, + }, afterCollapsed: 'afterCollapsed', hasParent: { events: 'ownerChanged', @@ -60,6 +61,14 @@ var CodeView = Node.subclass({ }, toggleAfter: function(){ this.afterCollapsed.set(!this.afterCollapsed.value); + }, + debug: function(event){ + var target = event.actionTarget; + var debug = Number(target.getAttribute('data-debug')); + var test = this.root instanceof TestCase ? this.root : this.data.test; + + checkDebugger(); + test.run(debug); } }, @@ -157,7 +166,7 @@ var CodeView = Node.subclass({ } return ( - '
' + + '
' + '' + (lineError.num + 1) + '' + 'Expected:' + '' + expected + '' + @@ -271,6 +280,7 @@ var TestSuiteNode = TestNode.subclass({ template: resource('./template/test-suite.tmpl'), + sorting: 'root.basisObjectId', childClass: TestNode, childFactory: function(config){ if (config.delegate.data.type == 'case')