Merge pull request #50 from gmetais/subqueries
Show subqueries in timeline
This commit is contained in:
+6
-1
@@ -12,7 +12,8 @@ var cli = meow({
|
||||
' yellowlabtools <url> <options>',
|
||||
'',
|
||||
'Options:',
|
||||
' --screenshot Will take a screenshot and use this value as the output path. It needs to end with ".png".',
|
||||
' --screenshot Will take a screenshot and use this value as the output path. It needs to end with ".png".',
|
||||
' --js-deep-analysis When activated, the javascriptExecutionTree will contain sub-requests.',
|
||||
''
|
||||
].join('\n'),
|
||||
pkg: '../package.json'
|
||||
@@ -44,6 +45,10 @@ if (screenshot) {
|
||||
options.screenshot = cli.flags.screenshot;
|
||||
}
|
||||
|
||||
// Deep JS analysis option
|
||||
if (cli.flags.jsDeepAnalysis === true || cli.flags.jsDeepAnalysis === 'true') {
|
||||
options.jsDeepAnalysis = true;
|
||||
}
|
||||
|
||||
|
||||
(function execute(url, options) {
|
||||
|
||||
@@ -177,6 +177,46 @@ input.textFilter {
|
||||
.table > div > .type {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.table .children {
|
||||
margin-top: 0.2em;
|
||||
font-size: 0.8em;
|
||||
line-height: 1.6em;
|
||||
}
|
||||
.table .child {
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
.table .child > .child {
|
||||
margin-left: 1em;
|
||||
}
|
||||
.table .child:before {
|
||||
content: "↳";
|
||||
}
|
||||
.table .child .childArgs {
|
||||
display: none;
|
||||
}
|
||||
.table .child span {
|
||||
position: relative;
|
||||
}
|
||||
.table .child span:hover {
|
||||
background: #EBD8E2;
|
||||
}
|
||||
.table .child span:hover .childArgs {
|
||||
display: block;
|
||||
position: absolute;
|
||||
padding: 0 1em 0 2em;
|
||||
left: 100%;
|
||||
top: 0;
|
||||
background: #EBD8E2;
|
||||
line-height: 1.3em;
|
||||
height: 1.3em;
|
||||
z-index: 1;
|
||||
}
|
||||
.table .showingDetails .child span:hover {
|
||||
background: inherit;
|
||||
}
|
||||
.table .showingDetails .child span:hover .childArgs {
|
||||
display: none;
|
||||
}
|
||||
.table > div > .value {
|
||||
width: 70%;
|
||||
word-break: break-all;
|
||||
|
||||
@@ -12,6 +12,7 @@ var yltApp = angular.module('YellowLabTools', [
|
||||
'apiService',
|
||||
'menuService',
|
||||
'gradeDirective',
|
||||
'jsChildrenDirective',
|
||||
'offendersDirectives'
|
||||
]);
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
var jsChildrenDirective = angular.module('jsChildrenDirective', []);
|
||||
|
||||
jsChildrenDirective.directive('jsChildren', function() {
|
||||
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
node: '=node'
|
||||
},
|
||||
template: '<div class="children"></div>',
|
||||
replace: true,
|
||||
link: function(scope, element, attrs) {
|
||||
|
||||
function recursiveHtmlBuilder(node) {
|
||||
var html = '';
|
||||
|
||||
if (node.children) {
|
||||
node.children.forEach(function(child) {
|
||||
|
||||
var childArgs = '';
|
||||
if (child.data.callDetails && child.data.callDetails.arguments && child.data.callDetails.arguments.length > 0) {
|
||||
childArgs = child.data.callDetails.arguments.join(' : ');
|
||||
if (childArgs.length > 100) {
|
||||
childArgs = childArgs.substr(0, 98) + '...';
|
||||
}
|
||||
}
|
||||
|
||||
html += '<div class="child"><span>' + child.data.type + '<div class="childArgs">' + childArgs + '</div></span>' + recursiveHtmlBuilder(child) + '</div>';
|
||||
});
|
||||
}
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
element.append(recursiveHtmlBuilder(scope.node));
|
||||
|
||||
// Bind a very special behavior:
|
||||
// We want to display something in the next table-cell, at the same hight.
|
||||
element.find('span').on('mouseenter', function() {
|
||||
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -8,7 +8,8 @@ apiService.factory('API', ['$location', 'Runs', 'Results', function($location, R
|
||||
Runs.save({
|
||||
url: url,
|
||||
waitForResponse: false,
|
||||
screenshot: true
|
||||
screenshot: true,
|
||||
jsTimeline: true
|
||||
}, function(data) {
|
||||
$location.path('/queue/' + data.runId);
|
||||
}, function(response) {
|
||||
|
||||
@@ -197,6 +197,56 @@ input.textFilter {
|
||||
white-space:nowrap;
|
||||
}
|
||||
|
||||
.table .children {
|
||||
margin-top: 0.2em;
|
||||
font-size: 0.8em;
|
||||
line-height: 1.6em;
|
||||
}
|
||||
|
||||
.table .child {
|
||||
margin-left: 0.5em;
|
||||
|
||||
> .child {
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
&:before {
|
||||
content: "↳";
|
||||
}
|
||||
|
||||
.childArgs {
|
||||
display: none;
|
||||
}
|
||||
|
||||
span {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
span:hover {
|
||||
background: #EBD8E2;
|
||||
|
||||
.childArgs {
|
||||
display: block;
|
||||
position: absolute;
|
||||
padding: 0 1em 0 2em;
|
||||
left: 100%;
|
||||
top: 0;
|
||||
background: #EBD8E2;
|
||||
line-height: 1.3em;
|
||||
height: 1.3em;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.table .showingDetails .child span:hover {
|
||||
background: inherit;
|
||||
|
||||
.childArgs {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.table > div > .value {
|
||||
width: 70%;
|
||||
word-break: break-all;
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
<script src="/js/services/apiService.js"></script>
|
||||
<script src="/js/services/menuService.js"></script>
|
||||
<script src="/js/directives/gradeDirective.js"></script>
|
||||
<script src="/js/directives/jsChildrenDirective.js"></script>
|
||||
<script src="/js/directives/offendersDirectives.js"></script>
|
||||
<!-- endbuild -->
|
||||
<head>
|
||||
|
||||
@@ -78,7 +78,10 @@
|
||||
}">
|
||||
|
||||
<div class="index">{{$index + 1}}</div>
|
||||
<div class="type">{{node.data.type}}</div>
|
||||
<div class="type">
|
||||
{{node.data.type}}
|
||||
<js-children node="node"></js-children>
|
||||
</div>
|
||||
|
||||
<div class="value">
|
||||
{{node.data.callDetails.arguments[0]}}
|
||||
|
||||
@@ -32,7 +32,8 @@ var ApiController = function(app) {
|
||||
url: req.body.url,
|
||||
waitForResponse: req.body.waitForResponse !== false && req.body.waitForResponse !== 'false' && req.body.waitForResponse !== 0,
|
||||
partialResult: req.body.partialResult || null,
|
||||
screenshot: req.body.screenshot || false
|
||||
screenshot: req.body.screenshot || false,
|
||||
jsTimeline: req.body.jsTimeline || false
|
||||
}
|
||||
};
|
||||
|
||||
@@ -64,7 +65,8 @@ var ApiController = function(app) {
|
||||
debug('Launching test %s on %s', run.runId, run.params.url);
|
||||
|
||||
var runOptions = {
|
||||
screenshot: run.params.screenshot ? screenshot.getTmpFilePath() : false
|
||||
screenshot: run.params.screenshot ? screenshot.getTmpFilePath() : false,
|
||||
jsDeepAnalysis: run.params.jsTimeline
|
||||
};
|
||||
|
||||
return ylt(run.params.url, runOptions);
|
||||
@@ -107,7 +109,16 @@ var ApiController = function(app) {
|
||||
|
||||
// Save results
|
||||
.then(function() {
|
||||
// Remove uneeded temp screenshot path
|
||||
delete data.params.options.screenshot;
|
||||
|
||||
// Empty javascriptExecutionTree if not needed
|
||||
if (!run.params.jsTimeline) {
|
||||
data.javascriptExecutionTree = {};
|
||||
}
|
||||
|
||||
// Remove tools results if not needed
|
||||
|
||||
return resultsDatastore.saveResult(data);
|
||||
})
|
||||
|
||||
|
||||
+5
-1
@@ -159,7 +159,10 @@ describe('api', function() {
|
||||
body.should.have.a.property('scoreProfiles').that.is.an('object');
|
||||
body.should.have.a.property('rules').that.is.an('object');
|
||||
body.should.have.a.property('toolsResults').that.is.an('object');
|
||||
|
||||
// javascriptExecutionTree should only be filled if option jsTimeline is true
|
||||
body.should.have.a.property('javascriptExecutionTree').that.is.an('object');
|
||||
body.javascriptExecutionTree.should.deep.equal({});
|
||||
|
||||
// Check if the screenshot temporary file was correctly removed
|
||||
body.params.options.should.not.have.a.property('screenshot');
|
||||
@@ -188,7 +191,8 @@ describe('api', function() {
|
||||
url: serverUrl + '/api/runs',
|
||||
body: {
|
||||
url: wwwUrl + '/simple-page.html',
|
||||
waitForResponse: false
|
||||
waitForResponse: false,
|
||||
jsTimeline: true
|
||||
},
|
||||
json: true,
|
||||
headers: {
|
||||
|
||||
Reference in New Issue
Block a user