Permalink
Browse files

This introduces new wrappers in automation extension to allow taking a

screenshot and comparing screenshots.

Developers taking screenshots can accomplish it using either the API
providing a path or using the "Take Screen Shot" button provided on the
whitel overlay shown by using "showOverlay()" on the automated spec
runner page.

If the button is used then developers can grab this newly taken screen
shot using new jake task. jake grab-image[ip,file-name] where file-name
is the name you want to name the file in the repo. The file is then
copied to test/data/automation/ReferenceImages.

For comparing images only the name of the image needs to passed in and
the current screenshot is compared against an image with that file name
on device under /accounts/1000/shared/misc/PuppetMaster/ReferenceImages.

To make this process more convinent for developers it augments new agents to the jake deploy-automation.
Namely automation-interface and PuppetMasterAgent have been added to the
jake task. It also copies all reference images from the repo to device.

Take away -
* use jake deploy-automation
* wait a few minutes and deploy your app and now you can take and compare
  screenshots.
* use jake upload-ssh-key to avoids crazy number of password prompts.
* Must restart the device the first installation of the agents.

Reviewed By: Bryan Higgins <bhiggins@rim.com>
Tested By: Brayan Higging <bhiggins@rim.com>
  • Loading branch information...
1 parent 8c5a3e4 commit aa83fdc4a100d4d76f8901ac6072a60726ede69c @nukulb nukulb committed Nov 16, 2012
View
@@ -20,6 +20,7 @@
"qnx",
"chrome",
"blackberry",
+ "internal",
"JNEXT",
"frameworkModules",
//Node
@@ -37,7 +38,10 @@
"iris",
//Browser
"DOMElement",
- "atob"
+ "atob",
+ //automated tests
+ "showOverlay",
+ "hideOverlay"
],
"node" : false,
View
@@ -41,6 +41,12 @@ task('test', [], function () {
require('./build/test')(null, process.argv.length >= 4 ? process.argv[3] : null);
});
+desc("Grabs the latest ScreenShot from the device located at /accounts/1000/shared/camera/WebWorksScreenShot.bmp " +
+ "/test/data/ReferenceImages/<name-of-file> [<ip address>,<name-of-file>]");
+task('grab-image', [], function () {
+ require('./build/grab-image')(Array.prototype.slice.call(arguments));
+});
+
/**
* Expected syntax is
* jake native-test[<device|simulator>,<IP Address of device>,<comma seperated extensions to ignore>..]
@@ -57,6 +63,7 @@ task('native-test', [], function () {
require('./build/native-test')(Array.prototype.slice.call(arguments));
});
+
/**
* Required jake native-test to avoid continous prompt of the password.
* Expected syntax is
@@ -81,9 +88,9 @@ task('lint', [], function () {
desc("show various codebase stats");
task('stats', [], require('./build/stats'));
-desc("Packages an app using the framework produced by this repo." + DESC_NEW_LINE +
- " This will replace the framework folder in the packager specified." + DESC_NEW_LINE +
- " This will replace webworks.js in the zip if you specify the path." + DESC_NEW_LINE +
+desc("Packages an app using the framework produced by this repo." + DESC_NEW_LINE +
+ " This will replace the framework folder in the packager specified." + DESC_NEW_LINE +
+ " This will replace webworks.js in the zip if you specify the path." + DESC_NEW_LINE +
" The packager path MUST be absolute (ie no ~)" + DESC_NEW_LINE +
" Expected usage - jake package[<pathToPackager>,<pathToAppZip>,<packagerOptions>,<{OPTIONAL}pathToWebWorks.js>]" + DESC_NEW_LINE +
" Example - jake package[/Users/jheifets/Downloads/BB10webworks-next-42/,test/test-app/wwTest.zip,-d,js/webworks.js]");
View
@@ -17,6 +17,7 @@ var path = require("path");
module.exports = {
ROOT: path.normalize(__dirname + "/../../"),
+ REFERENCE_IMAGES: path.normalize(__dirname + "/../../test/data/ReferenceImages/"),
TEMP: path.normalize(__dirname + "/../../temp/"),
DEPLOY: path.normalize(__dirname + "/../../target/zip/"),
DEPLOY_LIB: path.normalize(__dirname + "/../../target/zip/lib"),
@@ -0,0 +1,33 @@
+/*
+* Copyright 2012 Research In Motion Limited.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+var utils = require("./utils"),
+ jWorkflow = require("jWorkflow"),
+ _c = require("./conf");
+
+module.exports = function (ip, fileName) {
+ var cmd = "scp root@" + ip + ":/accounts/1000/shared/camera/WebWorksScreenShot.bmp test/data/automation/ReferenceImages/" + fileName;
+ return function (prev, baton) {
+ var build = jWorkflow.order();
+ baton.take();
+ build = build.andThen(utils.execCommandWithJWorkflow(cmd));
+
+ build.start(function (error) {
+ if (error) {
+ baton.drop(error);
+ }
+ });
+ };
+};
@@ -18,25 +18,46 @@ var childProcess = require('child_process'),
utils = require('./build/utils');
function getTestForAgentCmd(ip) {
- return "ssh root@" + ip + " '[ -f /var/automation/ui-agent ] && echo 1 || " +
- "(echo 0 ; mkdir -p /var/automation)'";
+ return "ssh root@" + ip + " '[ -f /var/automation/ui-agent ] && " +
+ "[ -f /var/automation/PuppetMasterAgent ] && [ -f /var/automation/automation-interface ] && echo 1 || " +
+ "(echo 0 ; mkdir -p /var/automation ; mkdir -p /accounts/1000/shared/misc/PuppetMaster/ReferenceImages/)'";
+}
+
+function getCopyReferenceImageCmd(ip, user) {
+ return "scp -r test/data/automation root@" + ip + ":/accounts/1000/shared/misc/PuppetMaster/ ";
}
function getCopyAgentCmd(ip, user) {
return "mkdir -p /Volumes/QNXAutomation && " +
"mount -t smbfs //'RIMNET;" + user + "'@javasrv50.devlab2k.testnet.rim.net/QNX%20Automation%20Agents /Volumes/QNXAutomation && " +
- "scp /Volumes/QNXAutomation/agents_v1.0.0.0/target/arm/agents/ui-agent root@" + ip + ":/var/automation/ui-agent || " +
+ "scp /Volumes/QNXAutomation/Trunk-Developer/target/arm/ui-agent root@" + ip + ":/var/automation/ui-agent && " +
+ "scp /Volumes/QNXAutomation/Trunk-Developer/target/arm/automation-interface root@" + ip + ":/var/automation/automation-interface && " +
+ "scp /Volumes/QNXAutomation/Trunk-Developer/target/arm/PuppetMasterAgent root@" + ip + ":/var/automation/PuppetMasterAgent && " +
"umount /Volumes/QNXAutomation";
}
function getRunAgentCmd(ip) {
- return ["root@" + ip,
+ return ["root@" + ip,
+ "rm -fr /accounts/1000/shared/misc/PuppetMaster ; " +
"if ! pidin | grep ui-agent > /dev/null; then " +
"/var/automation/ui-agent > /dev/null & " +
"sleep 2; " +
- "chmod 666 /pps/services/agent/ui-agent/control; " +
"else echo 'ui-agent is already running'; " +
- "fi;"];
+ "fi; " +
+ "if ! pidin | grep automation-interface > /dev/null; then " +
+ "/var/automation/automation-interface > /dev/null & " +
+ "sleep 2; " +
+ "else echo 'automation-interface is already running'; " +
+ "fi; " +
+ "if ! pidin | grep PuppetMasterAgent > /dev/null; then " +
+ "/var/automation/PuppetMasterAgent > /dev/null & " +
+ "sleep 10; " +
+ "else echo 'PuppetMasterAgent is already running'; " +
+ "fi;" +
+ "sleep 5;" +
+ "chmod 666 /pps/services/agent/ui-agent/control; " +
+ "chmod 666 /pps/services/agent/puppetmaster/control; "
+ ];
}
function onError(stderr) {
@@ -46,7 +67,7 @@ function onError(stderr) {
}
function execAgent(ip) {
- console.log('Starting ui-agent...');
+ console.log('Starting automation agents...');
childProcess.spawn('ssh', getRunAgentCmd(ip), [], { stdio: 'inherit', detached: true });
}
@@ -60,18 +81,27 @@ function execCopy(ip, user) {
});
}
+function execCopyReferenceImage(ip, user) {
+ childProcess.exec(getCopyReferenceImageCmd(ip, user), function (error, stdout, stderr) {
+ if (error) {
+ onError(stderr);
+ }
+ });
+}
+
function exec(ip, user) {
- console.log('Checking if ui-agent is installed...');
+ console.log('Checking if automation agents are installed...');
childProcess.exec(getTestForAgentCmd(ip), function (error, stdout, stderr) {
if (error) {
onError(stderr);
} else {
if (stdout.toString()[0] === "0") {
- console.log('ui-agent is not installed. Copying from shared drive...');
+ console.log('automation agents are not installed. Copying from shared drive...');
execCopy(ip, user);
} else {
execAgent(ip);
}
+ execCopyReferenceImage(ip, user);
}
});
}
View
@@ -0,0 +1,41 @@
+/*
+* Copyright 2012 Research In Motion Limited.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+var childProcess = require("child_process"),
+ util = require("util"),
+ jWorkflow = require("jWorkflow"),
+ conf = require("./build/conf"),
+ grabImage = require("./build/grab-image");
+
+function _done(error) {
+ if (error) {
+ util.puts("Grabbing image failed:\n" + error);
+ process.exit(1);
+ } else {
+ util.puts("Grabbing image successful");
+ process.exit();
+ }
+}
+
+module.exports = function () {
+ var args = Array.prototype.slice.call(arguments)[0],
+ ip = args[0] || conf.USB_IP,
+ fileName = args[1] || "TestCase.bmp",
+ build = jWorkflow.order(grabImage(ip, fileName));
+
+ build.start(function (error) {
+ _done(error);
+ });
+};
@@ -98,4 +98,42 @@ _self.rotate = function (orientation) {
);
};
+/*
+ * Takes the screenshot, path can be any path the application has write access.
+ */
+_self.takeScreenshot = function (path) {
+ internal.pps.syncWrite(
+ {
+ action : "Remote Call",
+ class : "ScreenApi",
+ method : "takeScreenshot",
+ parameter0 : path,
+ _src : "test-agent",
+ _dest : "puppetmaster"
+ },
+ "/pps/services/agent/puppetmaster/control"
+ );
+};
+
+/*
+ * Compares screenshot to a reference image located under /accounts/1000/shared/misc/PuppetMaster/ReferenceImages/
+ * name is the image name stored under.
+ */
+_self.compareCurrentScreen = function (name, callback) {
+ //should be converted to using delta mode on the output object but its hard due to subsequent calls
+ internal.pps.syncWrite(
+ {
+ action : "Remote Call",
+ class : "ScreenApi",
+ method : "compareScreenToReference",
+ parameter0 : name,
+ _src : "test-agent",
+ _dest : "puppetmaster"
+ },
+ "/pps/services/agent/puppetmaster/control"
+ );
+ setTimeout(function () {
+ callback(internal.pps.syncRead("/pps/services/agent/puppetmaster/output").output.response);
+ }, 1000);
+};
module.exports = _self;
@@ -3,7 +3,19 @@
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Jasmine Spec Runner</title>
+ <style type="text/css">
+ #overlay {
+ z-index:1000;
+ position:absolute;
+ top:0;
+ bottom:0;
+ left:0;
+ width:100%;
+ background:#fff;
+ visibility:hidden;
+ }
+ </style>
<link rel="stylesheet" type="text/css" href="../css/jasmine.css">
<script type="text/javascript" src="../js/jasmine.js"></script>
<script type="text/javascript" src="../js/jasmine-html.js"></script>
@@ -69,7 +81,21 @@
}
execJasmine();
};
- });
+ });
+
+ function showOverlay() {
+ var o = document.getElementById('overlay');
+ o.style.visibility = 'visible';
+ window.scrollTo(0,0);
+ }
+ function hideOverlay() {
+ var o = document.getElementById('overlay');
+ o.style.visibility = 'hidden';
+ }
+
+ function takeScreenshot() {
+ internal.automation.takeScreenshot("/accounts/1000/shared/camera/WebWorksScreenShot.bmp");
+ }
</script>
@@ -109,6 +135,9 @@
<input id="deselectAll" type="button" value="De-select All" />
<input id="addSpecs" type="button" value="Add Specs" />
<input id="start" type="button" value="Run Jasmine" /><br />
+ <div id="overlay">
+ <button onclick="takeScreenshot()" > Take ScreenShot </button>
+ </div>
</body>
</html>

0 comments on commit aa83fdc

Please sign in to comment.