Browse Source

Merge pull request #68 from gmetais/mobile

Fixes the first part of #14.
Gaël Métais 10 years ago
parent
commit
3d71454666
39 changed files with 263 additions and 132 deletions
  1. 13 16
      Gruntfile.js
  2. 4 0
      bin/cli.js
  3. 2 1
      bower.json
  4. 8 0
      front/src/css/dashboard.css
  5. 1 2
      front/src/css/icons.css
  6. 34 0
      front/src/css/index.css
  7. 1 2
      front/src/css/main.css
  8. BIN
      front/src/fonts/icons.woff
  9. 0 0
      front/src/fonts/svg-icons/arrow-left3.svg
  10. 0 0
      front/src/fonts/svg-icons/bars.svg
  11. 0 0
      front/src/fonts/svg-icons/lab.svg
  12. 0 0
      front/src/fonts/svg-icons/list.svg
  13. 0 0
      front/src/fonts/svg-icons/loop.svg
  14. 0 0
      front/src/fonts/svg-icons/mobile.svg
  15. 0 0
      front/src/fonts/svg-icons/question.svg
  16. 0 0
      front/src/fonts/svg-icons/screen.svg
  17. 0 0
      front/src/fonts/svg-icons/tablet.svg
  18. 0 0
      front/src/fonts/svg-icons/warning.svg
  19. 3 1
      front/src/js/app.js
  20. 1 1
      front/src/js/controllers/dashboardCtrl.js
  21. 7 2
      front/src/js/controllers/indexCtrl.js
  22. 1 1
      front/src/js/controllers/ruleCtrl.js
  23. 1 2
      front/src/js/controllers/screenshotCtrl.js
  24. 1 1
      front/src/js/controllers/timelineCtrl.js
  25. 7 4
      front/src/js/services/apiService.js
  26. 23 0
      front/src/js/services/settingsService.js
  27. 10 0
      front/src/less/dashboard.less
  28. 4 54
      front/src/less/icons.less
  29. 39 0
      front/src/less/index.less
  30. 67 29
      front/src/less/main.less
  31. 3 0
      front/src/main.html
  32. 1 1
      front/src/views/dashboard.html
  33. 8 0
      front/src/views/index.html
  34. 3 3
      front/src/views/resultSubHeader.html
  35. 1 1
      front/src/views/screenshot.html
  36. 4 2
      lib/server/controllers/apiController.js
  37. 10 7
      lib/tools/phantomas/phantomasWrapper.js
  38. 1 1
      package.json
  39. 5 1
      test/api/apiTest.js

+ 13 - 16
Gruntfile.js

@@ -11,17 +11,18 @@ module.exports = function(grunt) {
         pkg: grunt.file.readJSON('package.json'),
         pkg: grunt.file.readJSON('package.json'),
         settings: grunt.file.readJSON('./server_config/settings.json'),
         settings: grunt.file.readJSON('./server_config/settings.json'),
         
         
-        font: {
+        webfont: {
             icons: {
             icons: {
-                src: ['front/src/fonts/svg-icons/*.svg'],
-                destCss: 'front/src/less/icons.less',
-                destFonts: 'front/src/fonts/icons.woff',
-
-                // Optional: Custom routing of font filepaths for CSS
-                cssRouter: function (fontpath) {
-                    var pathArray = fontpath.split('/');
-                    var fileName = pathArray[pathArray.length - 1];
-                    return '/fonts/' + fileName;
+                src: 'front/src/fonts/svg-icons/*.svg',
+                dest: 'tmp',
+                destCss: 'front/src/less',
+                options: {
+                    engine: 'node',
+                    types: 'woff',
+                    stylesheet: 'less',
+                    embed: true,
+                    htmlDemo: false,
+                    syntax: 'bootstrap'
                 }
                 }
             }
             }
         },
         },
@@ -102,7 +103,6 @@ module.exports = function(grunt) {
             },
             },
             build: {
             build: {
                 files: [
                 files: [
-                    {src: ['./front/src/fonts/icons.woff'], dest: './front/build/fonts/icons.woff'},
                     {src: ['./front/src/img/favicon.png'], dest: './front/build/img/favicon.png'},
                     {src: ['./front/src/img/favicon.png'], dest: './front/build/img/favicon.png'},
                     {src: ['./front/src/img/logo-large.png'], dest: './front/build/img/logo-large.png'},
                     {src: ['./front/src/img/logo-large.png'], dest: './front/build/img/logo-large.png'},
                 ]
                 ]
@@ -211,10 +211,7 @@ module.exports = function(grunt) {
             html: './front/build/main.html',
             html: './front/build/main.html',
             css: './front/build/css/*.css',
             css: './front/build/css/*.css',
             options: {
             options: {
-                assetsDirs: ['front/build'],
-                patterns: {
-                    css: [[/(\/fonts\/icons\.woff)/gm, 'Replacing reference to icons.woff']]
-                }
+                assetsDirs: ['front/build']
             }
             }
         },
         },
         htmlmin: {
         htmlmin: {
@@ -294,7 +291,7 @@ module.exports = function(grunt) {
 
 
 
 
     grunt.registerTask('icons', [
     grunt.registerTask('icons', [
-        'font:icons',
+        'webfont:icons',
         'less',
         'less',
         'clean:tmp'
         'clean:tmp'
     ]);
     ]);

+ 4 - 0
bin/cli.js

@@ -12,6 +12,7 @@ var cli = meow({
         '  yellowlabtools <url> <options>',
         '  yellowlabtools <url> <options>',
         '',
         '',
         'Options:',
         'Options:',
+        '  --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".',
         '  --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.',
         '  --js-deep-analysis   When activated, the javascriptExecutionTree will contain sub-requests.',
         ''
         ''
@@ -50,6 +51,9 @@ if (cli.flags.jsDeepAnalysis === true || cli.flags.jsDeepAnalysis === 'true') {
     options.jsDeepAnalysis = true;
     options.jsDeepAnalysis = true;
 }
 }
 
 
+// Device simulation
+options.device = cli.flags.device || 'desktop';
+
 
 
 (function execute(url, options) {
 (function execute(url, options) {
     'use strict';
     'use strict';

+ 2 - 1
bower.json

@@ -5,7 +5,8 @@
     "angular-route": "~1.3.14",
     "angular-route": "~1.3.14",
     "angular-resource": "~1.3.14",
     "angular-resource": "~1.3.14",
     "angular-sanitize": "~1.3.14",
     "angular-sanitize": "~1.3.14",
-    "angular-animate": "~1.3.14"
+    "angular-animate": "~1.3.14",
+    "angular-local-storage": "~0.1.5"
   },
   },
   "resolutions": {
   "resolutions": {
     "angular": "~1.3.8"
     "angular": "~1.3.8"

+ 8 - 0
front/src/css/dashboard.css

@@ -46,6 +46,14 @@
   content: "+";
   content: "+";
   opacity: 0.85;
   opacity: 0.85;
 }
 }
+.summary .globalScore .screenshotWrapper.phone:hover:after {
+  top: 1.7em;
+  left: 0.64em;
+}
+.summary .globalScore .screenshotWrapper.tablet:hover:after {
+  top: 1.5em;
+  left: 0.9em;
+}
 .summary .notations {
 .summary .notations {
   display: table;
   display: table;
   width: 80%;
   width: 80%;

File diff suppressed because it is too large
+ 1 - 2
front/src/css/icons.css


+ 34 - 0
front/src/css/index.css

@@ -16,9 +16,43 @@
   background: #e74c3c;
   background: #e74c3c;
   color: #fff;
   color: #fff;
 }
 }
+.launchBtn:focus {
+  background: #ffa319;
+}
 .launchBtn.disabled {
 .launchBtn.disabled {
   background: #deaca6;
   background: #deaca6;
 }
 }
+.launchBtn.disabled:focus {
+  color: #ddd;
+}
+.device {
+  margin-top: 3em;
+}
+.device .item {
+  display: inline-block;
+  margin: 1em 0.75em;
+  width: 5.5em;
+  height: 5.5em;
+  color: #FFF;
+  border: 1px solid #FFF;
+  padding: 1px;
+  border-radius: 0.5em;
+  cursor: pointer;
+  text-decoration: none;
+  font-size: 0.8em;
+}
+.device .item.active {
+  color: #ffa319;
+  border: 2px solid #ffa319;
+  padding: 0;
+}
+.device .item:hover {
+  color: #ffa319;
+}
+.device .item > div {
+  margin: 0.2em 0 0.1em;
+  font-size: 3em;
+}
 .features {
 .features {
   display: table;
   display: table;
   width: 50%;
   width: 50%;

File diff suppressed because it is too large
+ 1 - 2
front/src/css/main.css


BIN
front/src/fonts/icons.woff


File diff suppressed because it is too large
+ 0 - 0
front/src/fonts/svg-icons/arrow-left3.svg


File diff suppressed because it is too large
+ 0 - 0
front/src/fonts/svg-icons/bars.svg


File diff suppressed because it is too large
+ 0 - 0
front/src/fonts/svg-icons/lab.svg


File diff suppressed because it is too large
+ 0 - 0
front/src/fonts/svg-icons/list.svg


File diff suppressed because it is too large
+ 0 - 0
front/src/fonts/svg-icons/loop.svg


File diff suppressed because it is too large
+ 0 - 0
front/src/fonts/svg-icons/mobile.svg


File diff suppressed because it is too large
+ 0 - 0
front/src/fonts/svg-icons/question.svg


File diff suppressed because it is too large
+ 0 - 0
front/src/fonts/svg-icons/screen.svg


File diff suppressed because it is too large
+ 0 - 0
front/src/fonts/svg-icons/tablet.svg


File diff suppressed because it is too large
+ 0 - 0
front/src/fonts/svg-icons/warning.svg


+ 3 - 1
front/src/js/app.js

@@ -12,8 +12,10 @@ var yltApp = angular.module('YellowLabTools', [
     'resultsFactory',
     'resultsFactory',
     'apiService',
     'apiService',
     'menuService',
     'menuService',
+    'settingsService',
     'gradeDirective',
     'gradeDirective',
-    'offendersDirectives'
+    'offendersDirectives',
+    'LocalStorageModule'
 ]);
 ]);
 
 
 yltApp.run(['$rootScope', '$location', function($rootScope, $location) {
 yltApp.run(['$rootScope', '$location', function($rootScope, $location) {

+ 1 - 1
front/src/js/controllers/dashboardCtrl.js

@@ -34,7 +34,7 @@ dashboardCtrl.controller('DashboardCtrl', ['$scope', '$rootScope', '$routeParams
     };
     };
 
 
     $scope.testAgain = function() {
     $scope.testAgain = function() {
-        API.launchTest($scope.result.params.url);
+        API.relaunchTest($scope.result);
     };
     };
 
 
     /// When comming from a social shared link, the user needs to click on "See full report" button to display the full dashboard.
     /// When comming from a social shared link, the user needs to click on "See full report" button to display the full dashboard.

+ 7 - 2
front/src/js/controllers/indexCtrl.js

@@ -1,9 +1,14 @@
 var indexCtrl = angular.module('indexCtrl', []);
 var indexCtrl = angular.module('indexCtrl', []);
 
 
-indexCtrl.controller('IndexCtrl', ['$scope', '$location', 'API', function($scope, $location, API) {
+indexCtrl.controller('IndexCtrl', ['$scope', 'Settings', 'API', function($scope, Settings, API) {
+    
+    $scope.settings = Settings.getMergedSettings();
+    console.log($scope.settings);
+
     $scope.launchTest = function() {
     $scope.launchTest = function() {
         if ($scope.url) {
         if ($scope.url) {
-            API.launchTest($scope.url);
+            Settings.saveSettings($scope.settings);
+            API.launchTest($scope.url, $scope.settings);
         }
         }
     };
     };
 }]);
 }]);

+ 1 - 1
front/src/js/controllers/ruleCtrl.js

@@ -29,7 +29,7 @@ ruleCtrl.controller('RuleCtrl', ['$scope', '$rootScope', '$routeParams', '$locat
     };
     };
 
 
     $scope.testAgain = function() {
     $scope.testAgain = function() {
-        API.launchTest($scope.result.params.url);
+        API.relaunchTest($scope.result);
     };
     };
 
 
     loadResults();
     loadResults();

+ 1 - 2
front/src/js/controllers/screenshotCtrl.js

@@ -10,7 +10,6 @@ screenshotCtrl.controller('ScreenshotCtrl', ['$scope', '$rootScope', '$routePara
             Results.get({runId: $routeParams.runId}, function(result) {
             Results.get({runId: $routeParams.runId}, function(result) {
                 $rootScope.loadedResult = result;
                 $rootScope.loadedResult = result;
                 $scope.result = result;
                 $scope.result = result;
-                init();
             }, function(err) {
             }, function(err) {
                 $scope.error = true;
                 $scope.error = true;
             });
             });
@@ -24,7 +23,7 @@ screenshotCtrl.controller('ScreenshotCtrl', ['$scope', '$rootScope', '$routePara
     };
     };
 
 
     $scope.testAgain = function() {
     $scope.testAgain = function() {
-        API.launchTest($scope.result.params.url);
+        API.relaunchTest($scope.result);
     };
     };
 
 
     loadResults();
     loadResults();

+ 1 - 1
front/src/js/controllers/timelineCtrl.js

@@ -141,7 +141,7 @@ timelineCtrl.controller('TimelineCtrl', ['$scope', '$rootScope', '$routeParams',
     };
     };
 
 
     $scope.testAgain = function() {
     $scope.testAgain = function() {
-        API.launchTest($scope.result.params.url);
+        API.relaunchTest($scope.result);
     };
     };
 
 
     loadResults();
     loadResults();

+ 7 - 4
front/src/js/services/apiService.js

@@ -4,12 +4,13 @@ apiService.factory('API', ['$location', 'Runs', 'Results', function($location, R
 
 
     return {
     return {
 
 
-        launchTest: function(url) {
+        launchTest: function(url, settings) {
             Runs.save({
             Runs.save({
                 url: url,
                 url: url,
                 waitForResponse: false,
                 waitForResponse: false,
                 screenshot: true,
                 screenshot: true,
-                jsTimeline: true
+                jsTimeline: true,
+                device: settings.device
             }, function(data) {
             }, function(data) {
                 $location.path('/queue/' + data.runId);
                 $location.path('/queue/' + data.runId);
             }, function(response) {
             }, function(response) {
@@ -19,9 +20,11 @@ apiService.factory('API', ['$location', 'Runs', 'Results', function($location, R
                     alert('An error occured...');
                     alert('An error occured...');
                 }
                 }
             });
             });
-        }
-
+        },
 
 
+        relaunchTest: function(result) {
+            this.launchTest(result.params.url, result.params.options);
+        }
     };
     };
 
 
 }]);
 }]);

+ 23 - 0
front/src/js/services/settingsService.js

@@ -0,0 +1,23 @@
+var settingsService = angular.module('settingsService', []);
+
+settingsService.factory('Settings', ['localStorageService', function(localStorageService) {
+
+    return {
+
+        getMergedSettings: function() {
+            var defaultSettings = {
+                device: 'desktop'
+            };
+            
+            var savedValues = localStorageService.get('settings');
+
+            return angular.extend(defaultSettings, savedValues);
+        },
+
+        saveSettings: function(settings) {
+            localStorageService.set('settings', settings);
+        }
+
+    };
+
+}]);

+ 10 - 0
front/src/less/dashboard.less

@@ -51,6 +51,16 @@
             opacity: 0.85;
             opacity: 0.85;
         }
         }
     }
     }
+
+    .screenshotWrapper.phone:hover:after {
+        top: 1.7em;
+        left: 0.64em;
+    }
+
+    .screenshotWrapper.tablet:hover:after {
+        top: 1.5em;
+        left: 0.9em;
+    }
 }
 }
 
 
 .summary .notations {
 .summary .notations {

File diff suppressed because it is too large
+ 4 - 54
front/src/less/icons.less


+ 39 - 0
front/src/less/index.less

@@ -18,8 +18,47 @@
 .launchBtn {
 .launchBtn {
     background: #e74c3c;
     background: #e74c3c;
     color: #fff;
     color: #fff;
+    &:focus {
+        background: #ffa319;
+    }
     &.disabled {
     &.disabled {
         background: #deaca6;
         background: #deaca6;
+        &:focus {
+            color: #ddd;
+        }
+    }
+    
+}
+
+.device {
+    margin-top: 3em;
+    .item {
+        display: inline-block;
+        margin: 1em 0.75em;
+        width: 5.5em;
+        height: 5.5em;
+        color: #FFF;
+        border: 1px solid #FFF;
+        padding: 1px;
+        border-radius: 0.5em;
+        cursor: pointer;
+        text-decoration: none;
+        font-size: 0.8em;
+
+        &.active {
+            color: #ffa319;
+            border: 2px solid #ffa319;
+            padding: 0;
+        }
+
+        &:hover {
+            color: #ffa319;
+        }
+
+        > div {
+            margin: 0.2em 0 0.1em;
+            font-size: 3em;
+        }
     }
     }
 }
 }
 
 

+ 67 - 29
front/src/less/main.less

@@ -126,11 +126,23 @@ a.linkButton {
 }
 }
 
 
 
 
-.screenshotWrapper.desktop {
+.screenshotWrapper {
     display: inline-block;
     display: inline-block;
     position: relative;
     position: relative;
-    border: 0.2em solid #AAA;
     background: #000;
     background: #000;
+
+    > div {
+        overflow: scroll;
+        position: relative;
+    }
+
+    .screenshotImage {
+        width: 100%;
+    }
+}
+
+.screenshotWrapper.desktop {
+    border: 0.2em solid #AAA;
     padding: 0.5em;
     padding: 0.5em;
     border-top-left-radius: 0.4em;
     border-top-left-radius: 0.4em;
     border-top-right-radius: 0.4em;
     border-top-right-radius: 0.4em;
@@ -160,12 +172,61 @@ a.linkButton {
     > div {
     > div {
         width: 12em;
         width: 12em;
         height: 6.75em;
         height: 6.75em;
-        overflow: scroll;
-        position: relative;
     }
     }
+}
 
 
-    .screenshotImage {
-        width: 100%;
+.screenshotWrapper.phone {
+    border: 0.07em solid #CCC;
+    padding: 1em 0.3em 1.5em;
+    border-radius: 0.6em;
+
+    &:before {
+        position: absolute;
+        width: 0.8em;
+        height: 0.8em;
+        bottom: 0.3em;
+        left: 3.3em;
+        border: 0.07em solid #CCC;
+        border-radius: 0.5em;
+        content: " ";
+    }
+
+    &:after {
+        position: absolute;
+        width: 1em;
+        height: 0.1em;
+        bottom: 13.9em;
+        left: 3.2em;
+        background: #555;
+        border-radius: 0.05em;
+        content: " ";
+    }
+
+    > div {
+        width: 6.75em;
+        height: 12em;
+    }
+}
+
+.screenshotWrapper.tablet {
+    border: 0.07em solid #CCC;
+    padding: 0.8em 0.5em 0.9em;
+    border-radius: 0.6em;
+
+    &:before {
+        position: absolute;
+        width: 0.5em;
+        height: 0.5em;
+        bottom: 0.15em;
+        left: 4.35em;
+        border: 0.07em solid #CCC;
+        border-radius: 0.4em;
+        content: " ";
+    }
+
+    > div {
+        width: 8.25em;
+        height: 11em;
     }
     }
 }
 }
 
 
@@ -186,27 +247,4 @@ a.linkButton {
     .version {
     .version {
         font-size: 0.7em;
         font-size: 0.7em;
     }
     }
-}
-
-/* Icons */
-.icon-lab {
-    .icon(@lab);
-}
-.icon-question {
-    .icon(@question);
-}
-.icon-warning {
-    .icon(@warning);
-}
-.icon-back {
-    .icon(@arrow-left3);
-}
-.icon-summary {
-    .icon(@list);
-}
-.icon-spaghetti {
-    .icon(@bars);
-}
-.icon-loop {
-    .icon(@loop);
 }
 }

+ 3 - 0
front/src/main.html

@@ -24,6 +24,7 @@
     <script src="/bower_components/angular-resource/angular-resource.min.js"></script>
     <script src="/bower_components/angular-resource/angular-resource.min.js"></script>
     <script src="/bower_components/angular-sanitize/angular-sanitize.min.js"></script>
     <script src="/bower_components/angular-sanitize/angular-sanitize.min.js"></script>
     <script src="/bower_components/angular-animate/angular-animate.min.js"></script>
     <script src="/bower_components/angular-animate/angular-animate.min.js"></script>
+    <script src="/bower_components/angular-local-storage/dist/angular-local-storage.min.js"></script>
     <script src="/js/app.js"></script>
     <script src="/js/app.js"></script>
     <script src="/js/controllers/indexCtrl.js"></script>
     <script src="/js/controllers/indexCtrl.js"></script>
     <script src="/js/controllers/dashboardCtrl.js"></script>
     <script src="/js/controllers/dashboardCtrl.js"></script>
@@ -35,6 +36,8 @@
     <script src="/js/models/runsFactory.js"></script>
     <script src="/js/models/runsFactory.js"></script>
     <script src="/js/services/apiService.js"></script>
     <script src="/js/services/apiService.js"></script>
     <script src="/js/services/menuService.js"></script>
     <script src="/js/services/menuService.js"></script>
+    <script src="/js/services/settingsService.js"></script>
+
     <script src="/js/directives/gradeDirective.js"></script>
     <script src="/js/directives/gradeDirective.js"></script>
     <script src="/js/directives/offendersDirectives.js"></script>
     <script src="/js/directives/offendersDirectives.js"></script>
     <!-- endbuild -->
     <!-- endbuild -->

+ 1 - 1
front/src/views/dashboard.html

@@ -11,7 +11,7 @@
         </div>
         </div>
         <div>
         <div>
             <a href="/result/{{result.runId}}/screenshot">
             <a href="/result/{{result.runId}}/screenshot">
-                <div class="screenshotWrapper desktop">
+                <div class="screenshotWrapper" ng-class="result.params.options.device">
                     <div>
                     <div>
                         <img class="screenshotImage" ng-src="{{result.screenshotUrl}}"/>
                         <img class="screenshotImage" ng-src="{{result.screenshotUrl}}"/>
                     </div>
                     </div>

+ 8 - 0
front/src/views/index.html

@@ -4,6 +4,14 @@
 <form ng-submit="launchTest()" >
 <form ng-submit="launchTest()" >
     <input type="text" name="url" ng-model="url" placeholder="http://www.mysite.com" class="url" />
     <input type="text" name="url" ng-model="url" placeholder="http://www.mysite.com" class="url" />
     <input type="submit" value="Launch test" class="launchBtn" ng-class="{disabled: !url}" />
     <input type="submit" value="Launch test" class="launchBtn" ng-class="{disabled: !url}" />
+    <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>
+        </div>
+    </div>
 </form>
 </form>
 
 
 
 

+ 3 - 3
front/src/views/resultSubHeader.html

@@ -1,8 +1,8 @@
 <div>Tested url: &nbsp; <a href="{{result.params.url}}" target="_blank" class="testedUrl">{{result.params.url}}</a></div>
 <div>Tested url: &nbsp; <a href="{{result.params.url}}" target="_blank" class="testedUrl">{{result.params.url}}</a></div>
 
 
 <div class="resultsMenu">
 <div class="resultsMenu">
-    <a class="menuItem back" href="/"><div class="icon-back"></div><span>New test<span></a>
+    <a class="menuItem back" href="/"><div class="icon-arrow-left3"></div><span>New test<span></a>
     <a class="menuItem restart" href="" ng-click="testAgain()"><div class="icon-loop"></div><span>Test again<span></a>
     <a class="menuItem restart" href="" ng-click="testAgain()"><div class="icon-loop"></div><span>Test again<span></a>
-    <div class="menuItem" ng-class="{active: Menu.getCurrentPage() == 'dashboard'}" ng-click="Menu.changePage('dashboard')"><div class="icon-summary"></div><span>Dashboard</span></div>
-    <div class="menuItem" ng-class="{active: Menu.getCurrentPage() == 'timeline'}" ng-click="Menu.changePage('timeline')"><div class="icon-spaghetti"></div><span>JS Timeline</span></div>
+    <div class="menuItem" ng-class="{active: Menu.getCurrentPage() == 'dashboard'}" ng-click="Menu.changePage('dashboard')"><div class="icon-list"></div><span>Dashboard</span></div>
+    <div class="menuItem" ng-class="{active: Menu.getCurrentPage() == 'timeline'}" ng-click="Menu.changePage('timeline')"><div class="icon-bars"></div><span>JS Timeline</span></div>
 </div>
 </div>

+ 1 - 1
front/src/views/screenshot.html

@@ -2,7 +2,7 @@
 <div class="screenshot board">
 <div class="screenshot board">
     <h2>Screenshot</h2>
     <h2>Screenshot</h2>
 
 
-    <div class="screenshotWrapper desktop">
+    <div class="screenshotWrapper" ng-class="result.params.options.device">
         <div>
         <div>
             <img class="screenshotImage" ng-src="{{result.screenshotUrl}}"/>
             <img class="screenshotImage" ng-src="{{result.screenshotUrl}}"/>
         </div>
         </div>

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

@@ -33,7 +33,8 @@ var ApiController = function(app) {
                 waitForResponse: req.body.waitForResponse !== false && req.body.waitForResponse !== 'false' && req.body.waitForResponse !== 0,
                 waitForResponse: req.body.waitForResponse !== false && req.body.waitForResponse !== 'false' && req.body.waitForResponse !== 0,
                 partialResult: req.body.partialResult || null,
                 partialResult: req.body.partialResult || null,
                 screenshot: req.body.screenshot || false,
                 screenshot: req.body.screenshot || false,
-                jsTimeline: req.body.jsTimeline || false
+                jsTimeline: req.body.jsTimeline || false,
+                device: req.body.device || 'desktop'
             }
             }
         };
         };
 
 
@@ -66,7 +67,8 @@ var ApiController = function(app) {
 
 
             var runOptions = {
             var runOptions = {
                 screenshot: run.params.screenshot ? screenshot.getTmpFilePath() : false,
                 screenshot: run.params.screenshot ? screenshot.getTmpFilePath() : false,
-                jsDeepAnalysis: run.params.jsTimeline
+                jsDeepAnalysis: run.params.jsTimeline,
+                device: run.params.device
             };
             };
 
 
             return ylt(run.params.url, runOptions);
             return ylt(run.params.url, runOptions);

+ 10 - 7
lib/tools/phantomas/phantomasWrapper.js

@@ -11,11 +11,6 @@ var PhantomasWrapper = function() {
 
 
     /**
     /**
      * This is the phantomas launcher. It merges user chosen options into the default options
      * This is the phantomas launcher. It merges user chosen options into the default options
-     * Available options :
-     *
-     * - timeout : in seconds (default 60)
-     * - jsDeepAnalysis : should we inspect subrequests in the javascript execution tree?
-     *
      */
      */
     this.execute = function(data) {
     this.execute = function(data) {
 
 
@@ -27,7 +22,9 @@ var PhantomasWrapper = function() {
             // Cusomizable options
             // Cusomizable options
             'timeout': task.options.timeout || 60,
             'timeout': task.options.timeout || 60,
             'js-deep-analysis': task.options.jsDeepAnalysis || false,
             'js-deep-analysis': task.options.jsDeepAnalysis || false,
-            'user-agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.110 Safari/537.36',
+            'user-agent': (task.options.device === 'desktop') ? 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.110 Safari/537.36' : null,
+            'tablet': (task.options.device === 'tablet'),
+            'phone': (task.options.device === 'phone'),
             'screenshot': task.options.screenshot || false,
             'screenshot': task.options.screenshot || false,
 
 
             // Mandatory
             // Mandatory
@@ -64,7 +61,13 @@ var PhantomasWrapper = function() {
                 value = '"' + value + '"';
                 value = '"' + value + '"';
             }
             }
 
 
-            optionsString += ' ' + '--' + opt + '=' + value;
+            if (value === true) {
+                optionsString += ' ' + '--' + opt;
+            } else if (value === false || value === null) {
+                // Nothing
+            } else {
+                optionsString += ' ' + '--' + opt + '=' + value;
+            }
 
 
         }
         }
         debug('node node_modules/phantomas/bin/phantomas.js --url=' + task.url + optionsString + ' --verbose');
         debug('node node_modules/phantomas/bin/phantomas.js --url=' + task.url + optionsString + ' --verbose');

+ 1 - 1
package.json

@@ -40,12 +40,12 @@
     "grunt-env": "^0.4.4",
     "grunt-env": "^0.4.4",
     "grunt-express": "^1.4.1",
     "grunt-express": "^1.4.1",
     "grunt-filerev": "^2.1.2",
     "grunt-filerev": "^2.1.2",
-    "grunt-fontsmith": "^0.9.1",
     "grunt-inline-angular-templates": "^0.1.5",
     "grunt-inline-angular-templates": "^0.1.5",
     "grunt-line-remover": "^0.0.2",
     "grunt-line-remover": "^0.0.2",
     "grunt-mocha-test": "^0.12.7",
     "grunt-mocha-test": "^0.12.7",
     "grunt-replace": "^0.8.0",
     "grunt-replace": "^0.8.0",
     "grunt-usemin": "^3.0.0",
     "grunt-usemin": "^3.0.0",
+    "grunt-webfont": "^0.5.2",
     "matchdep": "^0.3.0",
     "matchdep": "^0.3.0",
     "mocha": "^2.2.1",
     "mocha": "^2.2.1",
     "request": "^2.53.0",
     "request": "^2.53.0",

+ 5 - 1
test/api/apiTest.js

@@ -96,7 +96,8 @@ describe('api', function() {
             body: {
             body: {
                 url: wwwUrl + '/simple-page.html',
                 url: wwwUrl + '/simple-page.html',
                 waitForResponse: true,
                 waitForResponse: true,
-                screenshot: true
+                screenshot: true,
+                device: 'tablet'
             },
             },
             json: true,
             json: true,
             headers: {
             headers: {
@@ -164,6 +165,9 @@ describe('api', function() {
                 body.should.have.a.property('javascriptExecutionTree').that.is.an('object');
                 body.should.have.a.property('javascriptExecutionTree').that.is.an('object');
                 body.javascriptExecutionTree.should.deep.equal({});
                 body.javascriptExecutionTree.should.deep.equal({});
 
 
+                // Check if the device is set to tablet
+                body.params.options.should.have.a.property('device').that.equals('tablet');
+
                 // Check if the screenshot temporary file was correctly removed
                 // Check if the screenshot temporary file was correctly removed
                 body.params.options.should.not.have.a.property('screenshot');
                 body.params.options.should.not.have.a.property('screenshot');
                 // Check if the screenshot buffer was correctly removed
                 // Check if the screenshot buffer was correctly removed

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