浏览代码

Fix screenshots and continue implementing phantomas v2

Gaël Métais 4 年之前
父节点
当前提交
ac915e8973

+ 37 - 36
lib/screenshotHandler.js

@@ -1,6 +1,5 @@
 var debug       = require('debug')('ylt:screenshotHandler');
 var Jimp        = require('jimp');
-var tmp         = require('temporary');
 var Q           = require('q');
 var fs          = require('fs');
 var path        = require('path');
@@ -8,44 +7,22 @@ var path        = require('path');
 
 var screenshotHandler = function() {
 
-    this.getScreenshotTempFile = function() {
-        
-        var screenshotTmpFolder = new tmp.Dir();
-        var tmpFilePath = path.join(screenshotTmpFolder.path, 'screenshot.png');
-        var that = this;
-        
-        return {
-            
-            getTmpFolder: function() {
-                return screenshotTmpFolder;
-            },
-            
-            getTmpFilePath: function() {
-                return tmpFilePath;
-            },
-            
-            toThumbnail: function(width) {
-                return that.optimize(tmpFilePath, width);
-            },
-            
-            deleteTmpFile: function() {
-                return that.deleteTmpFileAndFolder(tmpFilePath, screenshotTmpFolder);
-            }
-        };
-    };
+    var tmpFolderPath = 'tmp';
+    var tmpFolderFullPath = path.join(__dirname, '..', tmpFolderPath);
+    var tmpFileName = 'temp-screenshot.png';
+    var tmpFileFullPath = path.join(tmpFolderFullPath, tmpFileName);
 
 
-    this.optimize = function(imagePath, width) {
+    this.findAndOptimizeScreenshot = function(width) {
         var that = this;
 
         debug('Starting screenshot transformation');
 
-        return this.openImage(imagePath)
+        return this.openImage(tmpFileFullPath)
 
             .then(function(image) {
-
+                that.deleteTmpFile(tmpFileFullPath);
                 return that.resizeImage(image, width);
-
             })
 
             .then(this.addWhiteBackground)
@@ -147,24 +124,48 @@ var screenshotHandler = function() {
     };
 
 
-    this.deleteTmpFileAndFolder = function(tmpFilePath, screenshotTmpFolder) {
+    this.deleteTmpFile = function(tmpFilePath) {
         var deferred = Q.defer();
 
         fs.unlink(tmpFilePath, function (err) {
             if (err) {
-                debug('Screenshot file not found, could not be deleted. But it is not a problem.');
+                debug('Screenshot temporary file not found, could not be deleted. But it is not a problem.');
             } else {
-                debug('Screenshot file deleted.');
+                debug('Screenshot temporary file deleted.');
             }
 
-            screenshotTmpFolder.rmdir();
-            debug('Screenshot temp folder deleted');
-
             deferred.resolve();
         });
 
         return deferred.promise;
     };
+
+    // Create a /tmp folder on the project's root directory
+    this.createTmpScreenshotFolder = function() {
+        var deferred = Q.defer();
+
+        // Create the folder if it doesn't exist
+        fs.exists(tmpFolderFullPath, function(exists) {
+            if (exists) {
+                deferred.resolve();
+            } else {
+                debug('Creating the tmp image folder', tmpFolderFullPath);
+                fs.mkdir(tmpFolderFullPath, function(err) {
+                    if (err) {
+                        deferred.reject(err);
+                    } else {
+                        deferred.resolve();
+                    }
+                });
+            }
+        });
+
+        return deferred.promise;
+    };
+
+    this.getTmpFileRelativePath = function() {
+        return tmpFolderPath + '/' + tmpFileName;
+    };
 };
 
 module.exports = new screenshotHandler();

+ 11 - 18
lib/server/controllers/apiController.js

@@ -51,11 +51,8 @@ var ApiController = function(app) {
             }
         };
 
-        // Create a temporary folder to save the screenshot
-        var screenshot;
-        if (run.params.screenshot) {
-            screenshot = ScreenshotHandler.getScreenshotTempFile();
-        }
+        // Create the tmp folder if it doesn't exist
+        ScreenshotHandler.createTmpScreenshotFolder(run.runId);
 
         // Add test to the testQueue
         debug('Adding test %s to the queue', run.runId);
@@ -78,7 +75,7 @@ var ApiController = function(app) {
             console.log('Launching test ' + run.runId + ' on ' + run.params.url);
 
             var runOptions = {
-                screenshot: run.params.screenshot ? screenshot.getTmpFilePath() : false,
+                screenshot: run.params.screenshot ? ScreenshotHandler.getTmpFileRelativePath() : false,
                 device: run.params.device,
                 proxy: run.params.proxy,
                 waitForSelector: run.params.waitForSelector,
@@ -95,40 +92,36 @@ var ApiController = function(app) {
 
         })
 
-        // Phantomas completed, let's save the screenshot if any
+        // Phantomas completed
         .then(function(data) {
 
             debug('Success');
             data.runId = run.runId;
 
             
-            // Some conditional steps are made if there is a screenshot
+            // Some conditional steps exist if there is a screenshot
             var screenshotPromise = Q.resolve();
 
             if (run.params.screenshot) {
-                
+
+                var screenshotSize = serverSettings.screenshotWidth ? serverSettings.screenshotWidth[run.params.device] : 400;
+
                 // Replace the empty promise created earlier with Q.resolve()
-                screenshotPromise = screenshot.toThumbnail(serverSettings.screenshotWidth || 400)
+                screenshotPromise = ScreenshotHandler.findAndOptimizeScreenshot(screenshotSize)
                 
                     // Read screenshot
                     .then(function(screenshotBuffer) {
-                        
                         if (screenshotBuffer) {
                             debug('Image optimized');
                             data.screenshotBuffer = screenshotBuffer;
-
-                            // Official path to get the image
-                            data.screenshotUrl = 'api/results/' + data.runId + '/screenshot.jpg';
+                            data.screenshotUrl = '/api/results/' + data.runId + '/screenshot.jpg'
                         }
-
                     })
-                    
-                    // Delete screenshot temporary file
-                    .then(screenshot.deleteTmpFile)
 
                     // Don't worry if there's an error
                     .fail(function(err) {
                         debug('An error occured while creating the screenshot\'s thumbnail. Ignoring and continuing...');
+                        debug(err);
                     });
 
             }

+ 24 - 11
lib/server/datastores/resultsDatastore.js

@@ -16,10 +16,13 @@ function ResultsDatastore() {
 
     this.saveResult = function(testResults) {
         
+        var screenshotFilePath = path.join(resultsDir, testResults.runId, resultScreenshotName);
+        var screenshotAPIPath = '/'
+
         return createResultFolder(testResults.runId)
 
             .then(function() {
-                return saveScreenshotIfExists(testResults);
+                return saveScreenshotIfExists(testResults, screenshotFilePath);
             })
 
             .then(function() {
@@ -56,10 +59,10 @@ function ResultsDatastore() {
 
 
     // The folder /results/folderName/
-    function createResultFolder(folderName) {
-        var folder = path.join(resultsDir, folderName);
+    function createResultFolder(runId) {
+        var folder = path.join(resultsDir, runId);
 
-        debug('Creating the folder %s', folderName);
+        debug('Creating the folder %s', runId);
 
         return createGlobalFolder().then(function() {
             return Q.nfcall(fs.mkdir, folder);
@@ -89,22 +92,32 @@ function ResultsDatastore() {
         return deferred.promise;
     }
 
+    this.getResultFolder = function(runId) {
+        return path.join(resultsDir, runId);
+    };
+
     // If there is a screenshot, save it as screenshot.jpg in the same folder as the results
-    function saveScreenshotIfExists(testResults) {
+    function saveScreenshotIfExists(testResults, path) {
         var deferred = Q.defer();
 
         if (testResults.screenshotBuffer) {
 
-            var screenshotFilePath = path.join(resultsDir, testResults.runId, resultScreenshotName);
-            fs.writeFile(screenshotFilePath, testResults.screenshotBuffer);
-
+            fs.writeFile(path, testResults.screenshotBuffer, function(err) {
+                if (err) {
+                    debug('Could not save final screenshot');
+                    debug(err);
+                    // But it is OK, we don't need to fail the run
+                    deferred.resolve();
+                } else {
+                    debug('Final screenshot saved: ' + path);
+                    deferred.resolve();
+                }
+            });
             delete testResults.screenshotBuffer;
 
-        } else {
-            deferred.resolve();
         }
 
-        return deferred;
+        return deferred.promise;
     }
 
     this.getScreenshot = function(runId) {

+ 47 - 5
lib/tools/phantomas/phantomasWrapper.js

@@ -17,7 +17,7 @@ var PhantomasWrapper = function() {
         var deferred = Q.defer();
         var task = data.params;
 
-        var options = {
+        /*var options = {
             
             // Cusomizable options
             'engine': task.options.phantomasEngine || 'webkit',
@@ -59,6 +59,51 @@ var PhantomasWrapper = function() {
             ].join(',')
         };
 
+        */
+
+        var options = {
+            
+            // Cusomizable options
+            'timeout': task.options.timeout || 60,
+            'user-agent': (task.options.device === 'desktop') ? 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) YLT Chrome/85.0.4183.121 Safari/537.36' : null,
+            'tablet': (task.options.device === 'tablet'),
+            'phone': (task.options.device === 'phone'),
+            'screenshot': task.options.screenshot || false,
+            'viewport': (task.options.device === 'desktop') ? '1280x800x1' : null,
+            'wait-for-network-idle': true,
+            //'wait-for-selector': task.options.waitForSelector,
+            'cookie': task.options.cookie,
+            'auth-user': task.options.authUser,
+            'auth-pass': task.options.authPass,
+            'block-domain': task.options.blockDomain,
+            'allow-domain': task.options.allowDomain,
+            'no-externals': task.options.noExternals,
+
+            // Mandatory
+            'analyze-css': true,
+            'ignore-ssl-errors': true,
+            /*'skip-modules': [
+                'ajaxRequests', // overridden
+                'domHiddenContent', // overridden
+                'domMutations', // not compatible with webkit
+                'domQueries', // overridden
+                'events', // overridden
+                'filmStrip', // not needed
+                'har', // not needed for the moment
+                'javaScriptBottlenecks', // needs to be launched after custom module scopeYLT
+                'jQuery', // overridden
+                'jserrors', // overridden
+                'lazyLoadableImages', //overridden
+                'pageSource', // not needed
+                'windowPerformance' // overridden
+            ].join(','),*/
+            /*'include-dirs': [
+                path.join(__dirname, 'custom_modules/core'),
+                path.join(__dirname, 'custom_modules/modules')
+            ].join(',')*/
+        };
+
+
         // Proxy option can't be set to null or undefined...
         // this is why it's set now and not in the object above
         if (task.options.proxy) {
@@ -67,10 +112,7 @@ var PhantomasWrapper = function() {
 
         // It's time to launch the test!!!
     
-        const promise = phantomas(task.url, {
-            'analyze-css': true,
-            'screenshot': true
-        });
+        const promise = phantomas(task.url, options);
 
         // handle the promise
         promise.

文件差异内容过多而无法显示
+ 14 - 0
server_config/settings-dareboost.json


文件差异内容过多而无法显示
+ 5 - 4
server_config/settings-prod.json


+ 5 - 1
server_config/settings.json

@@ -2,7 +2,11 @@
     "serverPort": 8383,
     "phantomasEngine": "webkit",
     "googleAnalyticsId": "",
-    "screenshotWidth": 400,
+    "screenshotWidth": {
+        "desktop": 600,
+        "tablet": 420,
+        "phone": 360
+    },
     "baseUrl": "/",
     "authorizedKeys": {
         

+ 10 - 60
test/api/screenshotHandlerTest.js

@@ -3,6 +3,7 @@ var ScreenshotHandler = require('../../lib/screenshotHandler');
 
 var fs = require('fs');
 var path = require('path');
+var rimraf = require('rimraf');
 
 describe('screenshotHandler', function() {
 
@@ -55,10 +56,14 @@ describe('screenshotHandler', function() {
     });
 
 
-    it('should optimize an image and return a buffered version', function(done) {
-        ScreenshotHandler.optimize(imagePath, 200)
+    it('should create the tmp folder if it doesn\'t exist', function(done) {
+        // Delete tmp folder if it exists
+        rimraf.sync("/some/directory");
+        
+        // The function we want to test
+        ScreenshotHandler.createTmpScreenshotFolder()
             .then(function(buffer) {
-                buffer.should.be.an.instanceof(Buffer);
+                fs.existsSync(path.join(__dirname, '../../tmp')).should.equal(true);
                 done();
             })
             .fail(function(err) {
@@ -66,63 +71,8 @@ describe('screenshotHandler', function() {
             });
     });
 
-
-    it('should provide a temporary file object', function() {
-        screenshot = ScreenshotHandler.getScreenshotTempFile();
-
-        screenshot.should.have.a.property('getTmpFolder').that.is.a('function');
-        screenshot.should.have.a.property('getTmpFilePath').that.is.a('function');
-        screenshot.should.have.a.property('toThumbnail').that.is.a('function');
-        screenshot.should.have.a.property('deleteTmpFile').that.is.a('function');
-    });
-
-
-    it('should have created the temporary folder', function() {
-        var folder = screenshot.getTmpFolder();
-        fs.existsSync(folder.path).should.equal(true);
-    });
-
-
-    it('should respond a temporary file', function() {
-        var file = screenshot.getTmpFilePath();
-        file.should.have.string('/screenshot.png');
+    it('should return the tmp folder path', function() {
+        ScreenshotHandler.getTmpFileRelativePath().should.equal('tmp/temp-screenshot.png');
     });
 
-
-    it('should delete the temp folder when there is no file', function(done) {
-        var tmpFolderPath = screenshot;
-
-        screenshot.deleteTmpFile()
-            .delay(1000)
-            .then(function() {
-                fs.existsSync(screenshot.getTmpFolder().path).should.equal(false);
-                done();
-            })
-            .fail(function(err) {
-                done(err);
-            });
-    });
-
-    it('should delete the temp folder with the screenshot inside', function(done) {
-        screenshot = ScreenshotHandler.getScreenshotTempFile();
-        var tmpFolderPath = screenshot.getTmpFolder().path;
-        var tmpImagePath = path.join(tmpFolderPath, 'screenshot.png');
-
-        // Copy image
-        var testImage = fs.readFileSync(imagePath);
-        fs.writeFileSync(tmpImagePath, testImage);
-
-        fs.existsSync(tmpImagePath).should.equal(true);
-
-        screenshot.deleteTmpFile()
-            .delay(1000)
-            .then(function() {
-                fs.existsSync(tmpImagePath).should.equal(false);
-                fs.existsSync(tmpFolderPath).should.equal(false);
-                done();
-            })
-            .fail(function(err) {
-                done(err);
-            });
-    });
 });

部分文件因为文件数量过多而无法显示