+14
@@ -15,6 +15,10 @@ var cli = meow({
|
||||
' --device Use "phone" or "tablet" to simulate a mobile device (by user-agent and viewport size).',
|
||||
' --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.',
|
||||
' --wait-for-selector Once the page is loaded, Phantomas will wait until the given CSS selector matches some elements.',
|
||||
' --cookie Adds a cookie on the main domain.',
|
||||
' --auth-user Basic HTTP authentication username.',
|
||||
' --auth-pass Basic HTTP authentication password.',
|
||||
''
|
||||
].join('\n'),
|
||||
pkg: '../package.json'
|
||||
@@ -54,6 +58,16 @@ if (cli.flags.jsDeepAnalysis === true || cli.flags.jsDeepAnalysis === 'true') {
|
||||
// Device simulation
|
||||
options.device = cli.flags.device || 'desktop';
|
||||
|
||||
// Wait for CSS selector
|
||||
options.waitForSelector = cli.flags.waitForSelector || null;
|
||||
|
||||
// Cookie
|
||||
options.cookie = cli.flags.cookie || null;
|
||||
|
||||
// HTTP basic auth
|
||||
options.authUser = cli.flags.authUser || null;
|
||||
options.authPass = cli.flags.authPass || null;
|
||||
|
||||
|
||||
(function execute(url, options) {
|
||||
'use strict';
|
||||
|
||||
File diff suppressed because one or more lines are too long
+91
-3
@@ -13,11 +13,11 @@
|
||||
width: 50%;
|
||||
}
|
||||
.launchBtn {
|
||||
background: #e74c3c;
|
||||
background: #ffa319;
|
||||
color: #fff;
|
||||
}
|
||||
.launchBtn:focus {
|
||||
background: #ffa319;
|
||||
background: #e74c3c;
|
||||
}
|
||||
.launchBtn.disabled {
|
||||
background: #deaca6;
|
||||
@@ -25,6 +25,18 @@
|
||||
.launchBtn.disabled:focus {
|
||||
color: #ddd;
|
||||
}
|
||||
.settings {
|
||||
width: 50%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.settings input,
|
||||
.settings select {
|
||||
font-size: 1em;
|
||||
}
|
||||
.settings input[type=text] {
|
||||
width: 100%;
|
||||
min-width: 4em;
|
||||
}
|
||||
.device {
|
||||
margin-top: 3em;
|
||||
}
|
||||
@@ -53,10 +65,86 @@
|
||||
margin: 0.2em 0 0.1em;
|
||||
font-size: 3em;
|
||||
}
|
||||
.settingsTooltip {
|
||||
position: relative;
|
||||
}
|
||||
.settingsTooltip span {
|
||||
font-size: 0.8em;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
.settingsTooltip div {
|
||||
display: none;
|
||||
position: absolute;
|
||||
padding: 0.5em;
|
||||
width: 25em;
|
||||
background: #FFF;
|
||||
color: #000;
|
||||
font-size: 0.8em;
|
||||
border-radius: 1em;
|
||||
border: 2px solid #ffa319;
|
||||
white-space: normal;
|
||||
z-index: 2;
|
||||
}
|
||||
.settingsTooltip:hover div {
|
||||
display: block;
|
||||
}
|
||||
.showAdvanced {
|
||||
display: inline-block;
|
||||
margin-top: 2em;
|
||||
color: #FFF;
|
||||
text-decoration: none;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
.showAdvanced:hover {
|
||||
color: #ffa319;
|
||||
}
|
||||
.currentSettings {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
.currentSettings span {
|
||||
color: #ffa319;
|
||||
}
|
||||
.currentSettings span:after {
|
||||
color: #FFF;
|
||||
content: ",";
|
||||
}
|
||||
.currentSettings span:last-child:after {
|
||||
content: "";
|
||||
}
|
||||
.advanced {
|
||||
margin: 1em 0 0;
|
||||
display: table;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
border-spacing: 0.75em;
|
||||
}
|
||||
.advanced > div {
|
||||
display: table-row;
|
||||
}
|
||||
.advanced > div > div {
|
||||
display: table-cell;
|
||||
width: 75%;
|
||||
}
|
||||
.advanced > div > div.label {
|
||||
width: 25%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.advanced .subTable {
|
||||
display: table;
|
||||
border-spacing: 0;
|
||||
width: 100%;
|
||||
}
|
||||
.advanced .subTable > div {
|
||||
display: table-row;
|
||||
}
|
||||
.advanced .subTable > div > div {
|
||||
display: table-cell;
|
||||
padding: 0 0 0.75em;
|
||||
}
|
||||
.features {
|
||||
display: table;
|
||||
width: 50%;
|
||||
margin: 8em auto 0;
|
||||
margin: 6em auto 0;
|
||||
font-size: 0.9em;
|
||||
color: #413;
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -5,13 +5,32 @@ apiService.factory('API', ['$location', 'Runs', 'Results', function($location, R
|
||||
return {
|
||||
|
||||
launchTest: function(url, settings) {
|
||||
Runs.save({
|
||||
var runObject = {
|
||||
url: url,
|
||||
waitForResponse: false,
|
||||
screenshot: true,
|
||||
jsTimeline: true,
|
||||
device: settings.device
|
||||
}, function(data) {
|
||||
device: settings.device,
|
||||
waitForSelector: settings.waitForSelector,
|
||||
cookie: settings.cookie,
|
||||
authUser: settings.authUser,
|
||||
authPass: settings.authPass,
|
||||
};
|
||||
|
||||
if (settings.waitForSelector && settings.waitForSelector !== '') {
|
||||
runObject.waitForSelector = settings.waitForSelector;
|
||||
}
|
||||
|
||||
if (settings.cookie && settings.cookie !== '') {
|
||||
runObject.cookie = settings.cookie;
|
||||
}
|
||||
|
||||
if (settings.authUser && settings.authUser !== '' && settings.authPass && settings.authPass !== '') {
|
||||
runObject.authUser = settings.authUser;
|
||||
runObject.authPass = settings.authPass;
|
||||
}
|
||||
|
||||
Runs.save(runObject, function(data) {
|
||||
$location.path('/queue/' + data.runId);
|
||||
}, function(response) {
|
||||
if (response.status === 429) {
|
||||
|
||||
@@ -6,7 +6,8 @@ settingsService.factory('Settings', ['localStorageService', function(localStorag
|
||||
|
||||
getMergedSettings: function() {
|
||||
var defaultSettings = {
|
||||
device: 'desktop'
|
||||
device: 'desktop',
|
||||
showAdvanced: false
|
||||
};
|
||||
|
||||
var savedValues = localStorageService.get('settings');
|
||||
|
||||
File diff suppressed because one or more lines are too long
+106
-3
@@ -16,10 +16,10 @@
|
||||
}
|
||||
|
||||
.launchBtn {
|
||||
background: #e74c3c;
|
||||
background: #ffa319;
|
||||
color: #fff;
|
||||
&:focus {
|
||||
background: #ffa319;
|
||||
background: #e74c3c;
|
||||
}
|
||||
&.disabled {
|
||||
background: #deaca6;
|
||||
@@ -30,6 +30,20 @@
|
||||
|
||||
}
|
||||
|
||||
.settings {
|
||||
width: 50%;
|
||||
margin: 0 auto;
|
||||
|
||||
input, select {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
input[type=text] {
|
||||
width: 100%;
|
||||
min-width: 4em;
|
||||
}
|
||||
}
|
||||
|
||||
.device {
|
||||
margin-top: 3em;
|
||||
.item {
|
||||
@@ -62,10 +76,99 @@
|
||||
}
|
||||
}
|
||||
|
||||
.settingsTooltip {
|
||||
position: relative;
|
||||
span {
|
||||
font-size: 0.8em;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
|
||||
div {
|
||||
display: none;
|
||||
position: absolute;
|
||||
padding: 0.5em;
|
||||
width: 25em;
|
||||
background: #FFF;
|
||||
color: #000;
|
||||
font-size: 0.8em;
|
||||
border-radius: 1em;
|
||||
border: 2px solid #ffa319;
|
||||
white-space: normal;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
&:hover div {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.showAdvanced {
|
||||
display: inline-block;
|
||||
margin-top: 2em;
|
||||
color: #FFF;
|
||||
text-decoration: none;
|
||||
font-size: 0.9em;
|
||||
|
||||
&:hover {
|
||||
color: #ffa319;
|
||||
}
|
||||
}
|
||||
|
||||
.currentSettings {
|
||||
font-size: 0.9em;
|
||||
|
||||
span {
|
||||
color: #ffa319;
|
||||
&:after {
|
||||
color: #FFF;
|
||||
content: ",";
|
||||
}
|
||||
|
||||
&:last-child:after {
|
||||
content: "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.advanced {
|
||||
margin: 1em 0 0;
|
||||
display: table;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
border-spacing: 0.75em;
|
||||
|
||||
> div {
|
||||
display: table-row;
|
||||
|
||||
> div {
|
||||
display: table-cell;
|
||||
width: 75%;
|
||||
|
||||
&.label {
|
||||
width: 25%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.subTable {
|
||||
display: table;
|
||||
border-spacing: 0;
|
||||
width: 100%;
|
||||
> div {
|
||||
display: table-row;
|
||||
> div {
|
||||
display: table-cell;
|
||||
padding: 0 0 0.75em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.features {
|
||||
display: table;
|
||||
width: 50%;
|
||||
margin: 8em auto 0;
|
||||
margin: 6em auto 0;
|
||||
font-size: 0.9em;
|
||||
color: #413;
|
||||
|
||||
|
||||
@@ -7,9 +7,69 @@
|
||||
<div class="settings">
|
||||
<div class="device">
|
||||
<div>Choose the simulated device:</div>
|
||||
<div class="item" ng-class="{active: settings.device == 'desktop'}" ng-click="settings.device = 'desktop'"><div class="icon-screen"></div>Desktop</div>
|
||||
<div class="item" ng-class="{active: settings.device == 'tablet'}" ng-click="settings.device = 'tablet'"><div class="icon-tablet"></div>Tablet</div>
|
||||
<div class="item" ng-class="{active: settings.device == 'phone'}" ng-click="settings.device = 'phone'"><div class="icon-mobile"></div>Phone</div>
|
||||
<a href="" class="item" ng-class="{active: settings.device == 'desktop'}" ng-click="settings.device = 'desktop'"><div class="icon-screen"></div>Desktop</a>
|
||||
<a href="" class="item" ng-class="{active: settings.device == 'tablet'}" ng-click="settings.device = 'tablet'"><div class="icon-tablet"></div>Tablet</a>
|
||||
<a href="" class="item" ng-class="{active: settings.device == 'phone'}" ng-click="settings.device = 'phone'"><div class="icon-mobile"></div>Phone</a>
|
||||
</div>
|
||||
[ <a href="" class="showAdvanced" ng-click="settings.showAdvanced = !settings.showAdvanced">
|
||||
<span ng-if="!settings.showAdvanced">Advanced settings ✚</span>
|
||||
<span ng-if="settings.showAdvanced">Hide advanced settings ✖</span>
|
||||
</a> ]
|
||||
<span class="currentSettings" ng-if="!settings.showAdvanced && (settings.waitForSelector || settings.cookie || settings.authUser || settings.authPass)">
|
||||
Currently set:
|
||||
<span ng-if="settings.waitForSelector">wait for selector</span>
|
||||
<span ng-if="settings.cookie">cookie</span>
|
||||
<span ng-if="settings.authUser || settings.authPass">authentication</span>
|
||||
</span>
|
||||
<div class="advanced" ng-show="settings.showAdvanced">
|
||||
<!--<div>
|
||||
<div class="label">
|
||||
Wait selector
|
||||
<span class="settingsTooltip">
|
||||
<span class="icon-question"></span>
|
||||
<div><b>Wait for a CSS selector</b><br><br>Once the page is considered loaded, PhantomJS will repeatedly try to match the given CSS selector until it is found in the page. A 60 seconds timeout still applies anyway.<br><br>Example: "body.loaded"</div>
|
||||
</span>
|
||||
</div>
|
||||
<div><input type="text" name="waitForSelector" ng-model="settings.waitForSelector" /></div>
|
||||
</div>-->
|
||||
<div>
|
||||
<div class="label">
|
||||
Cookie
|
||||
<span class="settingsTooltip">
|
||||
<span class="icon-question"></span>
|
||||
<div><b>Cookie</b><br><br>Adds a cookie on the main domain.<br><br>Example: "bar=foo;domain=url"</div>
|
||||
</span>
|
||||
</div>
|
||||
<div><input type="text" name="cookie" ng-model="settings.cookie" /></div>
|
||||
</div>
|
||||
<!--<div>
|
||||
<div class="label">
|
||||
Authent
|
||||
<span class="settingsTooltip">
|
||||
<span class="icon-question"></span>
|
||||
<div><b>Basic HTTP authentication</b><br><br>Enter your credentials here if you need to bypass a basic authentication.<br><br><i>PS: if your authentication is not basic, you might be able to copy the session cookie from your browser, paste it in the "Cookie" setting and launch a run before your cookie expires.</i></div>
|
||||
</span>
|
||||
</div>
|
||||
<div class="subTable">
|
||||
<div>
|
||||
<div>username</div>
|
||||
<div><input type="text" class="authField" name="authUser" ng-model="settings.authUser" /></div>
|
||||
</div>
|
||||
<div>
|
||||
<div><span>password</div>
|
||||
<div><input type="text" class="authField" name="authPass" ng-model="settings.authPass" /></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>-->
|
||||
<!--<div>
|
||||
<div class="label">Blocked domains</div>
|
||||
<div>
|
||||
<div>
|
||||
Blacklist / Whitelist
|
||||
</div>
|
||||
<textarea name=""></textarea>
|
||||
</div>
|
||||
</div>-->
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -34,7 +34,11 @@ var ApiController = function(app) {
|
||||
partialResult: req.body.partialResult || null,
|
||||
screenshot: req.body.screenshot || false,
|
||||
jsTimeline: req.body.jsTimeline || false,
|
||||
device: req.body.device || 'desktop'
|
||||
device: req.body.device || 'desktop',
|
||||
waitForSelector: req.body.waitForSelector || null,
|
||||
cookie: req.body.cookie || null,
|
||||
authUser: req.body.authUser || null,
|
||||
authPass: req.body.authPass || null
|
||||
}
|
||||
};
|
||||
|
||||
@@ -68,7 +72,11 @@ var ApiController = function(app) {
|
||||
var runOptions = {
|
||||
screenshot: run.params.screenshot ? screenshot.getTmpFilePath() : false,
|
||||
jsDeepAnalysis: run.params.jsTimeline,
|
||||
device: run.params.device
|
||||
device: run.params.device,
|
||||
waitForSelector: run.params.waitForSelector,
|
||||
cookie: run.params.cookie,
|
||||
authUser: run.params.authUser,
|
||||
authPass: run.params.authPass
|
||||
};
|
||||
|
||||
return ylt(run.params.url, runOptions);
|
||||
|
||||
@@ -26,6 +26,10 @@ var PhantomasWrapper = function() {
|
||||
'tablet': (task.options.device === 'tablet'),
|
||||
'phone': (task.options.device === 'phone'),
|
||||
'screenshot': task.options.screenshot || false,
|
||||
'wait-for-selector': task.options.waitForSelector,
|
||||
'cookie': task.options.cookie,
|
||||
'auth-user': task.options.authUser,
|
||||
'auth-pass': task.options.authPass,
|
||||
|
||||
// Mandatory
|
||||
'reporter': 'json:pretty',
|
||||
@@ -42,7 +46,6 @@ var PhantomasWrapper = function() {
|
||||
'jQuery', // overridden
|
||||
'jserrors', // overridden
|
||||
'pageSource', // not needed
|
||||
'waitForSelector', // not needed
|
||||
'windowPerformance' // overriden
|
||||
].join(','),
|
||||
'include-dirs': [
|
||||
|
||||
+10
-2
@@ -97,7 +97,11 @@ describe('api', function() {
|
||||
url: wwwUrl + '/simple-page.html',
|
||||
waitForResponse: true,
|
||||
screenshot: true,
|
||||
device: 'tablet'
|
||||
device: 'tablet',
|
||||
//waitForSelector: '*',
|
||||
cookie: 'foo=bar',
|
||||
authUser: 'joe',
|
||||
authPass: 'secret'
|
||||
},
|
||||
json: true,
|
||||
headers: {
|
||||
@@ -165,8 +169,12 @@ describe('api', function() {
|
||||
body.should.have.a.property('javascriptExecutionTree').that.is.an('object');
|
||||
body.javascriptExecutionTree.should.deep.equal({});
|
||||
|
||||
// Check if the device is set to tablet
|
||||
// Check if settings are correctly sent and retrieved
|
||||
body.params.options.should.have.a.property('device').that.equals('tablet');
|
||||
//body.params.options.should.have.a.property('waitForSelector').that.equals('*');
|
||||
body.params.options.should.have.a.property('cookie').that.equals('foo=bar');
|
||||
body.params.options.should.have.a.property('authUser').that.equals('joe');
|
||||
body.params.options.should.have.a.property('authPass').that.equals('secret');
|
||||
|
||||
// Check if the screenshot temporary file was correctly removed
|
||||
body.params.options.should.not.have.a.property('screenshot');
|
||||
|
||||
Reference in New Issue
Block a user