Skip to content

Commit

Permalink
visitor implemented
Browse files Browse the repository at this point in the history
  • Loading branch information
lahmatiy committed Jul 13, 2016
1 parent 4d7e2dd commit abd27c5
Show file tree
Hide file tree
Showing 7 changed files with 282 additions and 70 deletions.
67 changes: 66 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,72 @@ module.exports = {
setTimeout(function(){
resolve();
}, 10);
})
});
}
};
```

### Визитер

В некоторых тестах необходимо определять, что были пройдены определенные точки кода, а некоторые не были. Для этого можно использовать специальную функцию `visit()` для запоминания пройденных точек и метод `assert.visited()` для проверки.

```js
module.exports = {
name: 'Visited points',
test: function(){
visit('foo');
visit({ bar: true });

assert.visited(['foo', { bar: true }]);
}
};
```

Метод `visit.list()` позволяет получить текущий копию списка точек, а `visit.reset()` очищает этот список.

```js
module.exports = {
name: 'visit.list() and visit.reset()',
test: function(){
visit({ foo: 'test' });
assert.deep([{ foo: 'test' }], visit.list()); // эквивалентно assert.visited({ foo: 'test' });

visit.reset();
assert.deep([], visit.list());
}
};
```

Для того, чтобы отметить некоторую точку, что она не должна посещаться используется метод `visit.wrong()`.

```js
module.exports = {
name: 'visit.wrong()',
test: function(){
visit.wrong(); // эффект тот же, что и assert(false), но в данном случае
// будет выведено более говорящее сообщение
}
};
```

Метод `visit.wrap()` позволяет обернуть метод, чтобы записывать его вызовы. В список точек будет сохраняться первый аргумент:

```js
module.exports = {
name: 'visit.wrap()',
test: function(){
var obj = {
foo: function(obj){
return obj;
}
};

visit.wrap(obj, 'foo'); // перед выполнением метода в список точек сохранится первый аргумент

obj.foo(1, 2);
obj.foo({ bar: 1 });

assert.visited([1, { bar: 1 }]);
}
};
```
Expand Down
89 changes: 89 additions & 0 deletions example/showcase.html
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,95 @@
}
}
]
},
{
name: 'visitor',
test: [
{
name: 'should collect and check collected points',
test: function(){
function bar(){
visit('bar');
}
function baz(){
visit('baz');
}

visit('foo');
baz();

assert.visited(['foo', 'baz']);
}
},
{
name: 'reset visit points',
test: function(){
visit('foo');
assert.visited(['foo']);

visit.reset();
assert.visited([]);
}
},
{
name: 'assert on wrong visit',
test: function(){
function foo(){
visit.wrong();
}

foo();

return new Promise(function(resolve, reject){
reject(new Error('ok'));
}).then(function(){
assert(true);
}, function(){
visit.wrong();
});
}
},
{
name: 'assert on wrong visit as function',
test: function(){
var obj = {
method: visit.wrong
};

obj.method();
}
},
{
name: 'visit as event listener',
test: function(){
var obj = {
foo: function(obj){
return obj;
}
};

visit.wrap(obj, 'foo');

assert(obj.foo(1) === 1);
assert({ bar: 1 }, obj.foo({ bar: 1 }));

assert.visited([1, { bar: 1 }]);
}
},
{
name: 'visit.list() and visit.reset()',
test: function(){
visit({ foo: 'test' });
assert.deep([{ foo: 'test' }], visit.list());

visit.reset();
assert.deep([], visit.list());

assert.deep([1,2], [1,2]);
assert([1,2], [1,2]);
}
}
]
}
]
});
Expand Down
64 changes: 64 additions & 0 deletions src/app/reporters/default/module/test-tree/annotations.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
var strDiff = require('diff');

function htmlEscape(str){
return str
.replace(/&/g, '&')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;');
}

var annotationByType = {
unknown: function(annotation){
return '<div>Unknown annotation type: ' + annotation.type + '</div>';
},
compare: function(annotation){
var diffType =
typeof annotation.expected == 'string' &&
typeof annotation.actual == 'string'
? 'diffChars'
: 'diffWords';

var diff = strDiff[diffType](annotation.expectedStr, annotation.actualStr);
var expected = '';
var actual = '';

for (var i = 0, chunk; chunk = diff[i]; i++)
{
if (chunk.removed)
{
expected += '<span class="diff-removed">' + htmlEscape(chunk.value) + '</span>';
continue;
}

if (chunk.added)
{
actual += '<span class="diff-added">' + htmlEscape(chunk.value) + '</span>';
continue;
}

expected += htmlEscape(chunk.value);
actual += htmlEscape(chunk.value);
}

return (
'<div class="error-line-details-item" event-click="debug" data-debug="' + annotation.debug + '">' +
'<span class="num">' + (annotation.num + 1) + '</span>' +
'<span class="caption">Expected:</span>' +
'<span class="expected">' + expected + '</span>' +
'<span class="caption">Actual:</span>' +
'<span class="actual">' + actual + '</span>' +
'</div>'
);
},
message: function(annotation){
return '<div class="error-line-details-item" event-click="debug" data-debug="' + annotation.debug + '">' +
'<span>' + annotation.message + '</span>' +
'</div>';
}
};

module.exports = function processAnnotation(annotation){
var fn = annotationByType[annotation.type] || annotationByType.unknown;

return fn(annotation);
};
55 changes: 8 additions & 47 deletions src/app/reporters/default/module/test-tree/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,12 @@ var document = global.document;
var checkDebugger = require('./check-debugger.js');
var highlight = require('./highlight.js');
var TestCase = require('runner.test').TestCase;
var strDiff = require('diff');

var processAnnotation = require('./annotations.js');

//
// Test source code view
//

function htmlEscape(str){
return str
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;');
}

var CodeView = Node.subclass({
className: 'CodeView',
Expand Down Expand Up @@ -168,50 +161,18 @@ var CodeView = Node.subclass({
else
{
var errorLines = this.data.errorLines;
var noLine = document.createElement('div');

// no line annotations
noLine.className = 'line';
lines.push(noLine);

for (var lineNum in errorLines)
{
lines[lineNum].className += ' error-line';
lines[lineNum].innerHTML +=
'<div class="error-line-details">' +
errorLines[lineNum].map(function(lineError){
var diffType =
typeof lineError.expected == 'string' &&
typeof lineError.actual == 'string'
? 'diffChars'
: 'diffWords';

var diff = strDiff[diffType](lineError.expectedStr, lineError.actualStr);
var expected = '';
var actual = '';

for (var i = 0, chunk; chunk = diff[i]; i++)
{
if (chunk.removed)
{
expected += '<span class="diff-removed">' + htmlEscape(chunk.value) + '</span>';
continue;
}

if (chunk.added)
{
actual += '<span class="diff-added">' + htmlEscape(chunk.value) + '</span>';
continue;
}

expected += htmlEscape(chunk.value);
actual += htmlEscape(chunk.value);
}

return (
'<div class="error-line-details-item" event-click="debug" data-debug="' + lineError.debug + '">' +
'<span class="num">' + (lineError.num + 1) + '</span>' +
'<span class="caption">Expected:</span>' +
'<span class="expected">' + expected + '</span>' +
'<span class="caption">Actual:</span>' +
'<span class="actual">' + actual + '</span>' +
'</div>'
);
}).join('') +
errorLines[lineNum].map(processAnnotation).join('') +
'</div>';
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/runner/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ var TestCase = AbstractTest.subclass({

if (this.testWrappedSource === null)
this.testWrappedSource =
'function __yatra_test__(' + sourceUtils.getFunctionInfo(this.data.test).args.concat('assert', '__isFor', '__enterLine', '__exception', '__wrapFunctionExpression', '__actual', '__expected').join(', ') + '){\n' +
'function __yatra_test__(' + sourceUtils.getFunctionInfo(this.data.test).args.concat('assert', 'visit', '__isFor', '__enterLine', '__exception', '__wrapFunctionExpression', '__actual', '__expected').join(', ') + '){\n' +
'window.onerror = function(m,_,_,_,e){if(!e)try{throw new Error(m)}catch(ex){e=ex};__exception(e);return true};\n' +
'// ' + this.data.name.replace(/\r\n?|\n/g, '\\n') + '\n' +
sourceUtils.getWrappedSource(source) +
Expand Down
Loading

0 comments on commit abd27c5

Please sign in to comment.