Skip to content
This repository has been archived by the owner on Sep 4, 2019. It is now read-only.

Commit

Permalink
This introduces new wrappers in automation extension to allow taking a
Browse files Browse the repository at this point in the history
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
nukulb committed Nov 17, 2012
1 parent 8c5a3e4 commit aa83fdc
Show file tree
Hide file tree
Showing 8 changed files with 197 additions and 14 deletions.
6 changes: 5 additions & 1 deletion .jshintrc
Expand Up @@ -20,6 +20,7 @@
"qnx",
"chrome",
"blackberry",
"internal",
"JNEXT",
"frameworkModules",
//Node
Expand All @@ -37,7 +38,10 @@
"iris",
//Browser
"DOMElement",
"atob"
"atob",
//automated tests
"showOverlay",
"hideOverlay"
],

"node" : false,
Expand Down
13 changes: 10 additions & 3 deletions Jakefile
Expand Up @@ -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>..]
Expand All @@ -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
Expand All @@ -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]");
Expand Down
1 change: 1 addition & 0 deletions build/build/conf.js
Expand Up @@ -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"),
Expand Down
33 changes: 33 additions & 0 deletions build/build/grab-image.js
@@ -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);
}
});
};
};
48 changes: 39 additions & 9 deletions build/deploy-automation.js
Expand Up @@ -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) {
Expand All @@ -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 });
}

Expand All @@ -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);
}
});
}
Expand Down
41 changes: 41 additions & 0 deletions build/grab-image.js
@@ -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);
});
};
38 changes: 38 additions & 0 deletions ext-internal/automation/client.js
Expand Up @@ -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;
31 changes: 30 additions & 1 deletion test/test-app/automatic/SpecRunner.htm
Expand Up @@ -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>
Expand Down Expand Up @@ -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>

Expand Down Expand Up @@ -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.