Browse Source

Merge pull request #71 from gmetais/advancedSettings

Advanced settings
Gaël Métais 10 years ago
parent
commit
33c6643388

+ 14 - 0
bin/cli.js

@@ -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 it is too large
+ 0 - 0
front/src/css/icons.css


+ 91 - 3
front/src/css/index.css

@@ -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 it is too large
+ 0 - 0
front/src/css/main.css


+ 22 - 3
front/src/js/services/apiService.js

@@ -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) {

+ 2 - 1
front/src/js/services/settingsService.js

@@ -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 it is too large
+ 0 - 0
front/src/less/icons.less


+ 106 - 3
front/src/less/index.less

@@ -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;
 

+ 63 - 3
front/src/views/index.html

@@ -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 &nbsp;✚</span>
+            <span ng-if="settings.showAdvanced">Hide advanced settings &nbsp;✖</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>

+ 10 - 2
lib/server/controllers/apiController.js

@@ -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);

+ 4 - 1
lib/tools/phantomas/phantomasWrapper.js

@@ -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
test/api/apiTest.js

@@ -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');

Some files were not shown because too many files changed in this diff