Fix screenshots and continue implementing phantomas v2
This commit is contained in:
+37
-36
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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.
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -2,7 +2,11 @@
|
||||
"serverPort": 8383,
|
||||
"phantomasEngine": "webkit",
|
||||
"googleAnalyticsId": "",
|
||||
"screenshotWidth": 400,
|
||||
"screenshotWidth": {
|
||||
"desktop": 600,
|
||||
"tablet": 420,
|
||||
"phone": 360
|
||||
},
|
||||
"baseUrl": "/",
|
||||
"authorizedKeys": {
|
||||
|
||||
|
||||
@@ -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 return the tmp folder path', function() {
|
||||
ScreenshotHandler.getTmpFileRelativePath().should.equal('tmp/temp-screenshot.png');
|
||||
});
|
||||
|
||||
|
||||
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 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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user