Skip to content

Commit b8df1f9

Browse files
author
John Doherty
authored
Merge pull request #38 from Temi89/master
Integrate Applitools with selenium cucumber js .
2 parents 39f0657 + 4ef038d commit b8df1f9

File tree

4 files changed

+103
-20
lines changed

4 files changed

+103
-20
lines changed

README.MD

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,58 @@ module.exports = function () {
234234
};
235235
```
236236

237+
### Applitools Eyes!
238+
The Applitools Eyes Selenium JavaScript SDK allows you to easily add visual checkpoints to your JavaScript Selenium tests.
239+
It takes care of getting screenshots of your application from the underlying WebDriver, sending them to the Eyes server for validation and failing the test in case differences are found.
240+
To use Applitools Eyes specifying an ApiKey from Aplitools using a `selenium-cucumber-js.json` file at the root of your project
241+
242+
For example the following configuration could be used with an increased timeout which allows enough time for viusual checks:
243+
244+
```json
245+
{
246+
"eye_key": "Your_Api_Key",
247+
"timeout": 50000
248+
}
249+
```
250+
251+
And its usage within page Objects:
252+
253+
```js
254+
module.exports = {
255+
256+
url: 'https://applitools.com/helloworld',
257+
258+
elements: {
259+
clickme: by.tagName('button'),
260+
searchResultLink: by.css('div.g > h3 > a')
261+
},
262+
263+
264+
applitools_Eyes_Example: function () {
265+
266+
// Start the test and set the browser's viewport size to 800x600.
267+
eyes.open(driver, 'Hello World!', 'My first Javascript test!',
268+
{width: 800, height: 600});
269+
270+
// Navigate the browser to the "hello world!" web-site.
271+
driver.get(page.HelloWorld.elements.url);
272+
273+
// Visual checkpoint #1.
274+
eyes.checkWindow('Main Page');
275+
276+
// Click the "Click me!" button.
277+
driver.findElement(page.HelloWorld.elements.clickme).click();
278+
279+
// Visual checkpoint #2.
280+
eyes.checkWindow('Click!');
281+
282+
// End the test.
283+
eyes.close();
284+
}
285+
};
286+
```
287+
288+
237289
### Before/After hooks
238290

239291
You can register before and after handlers for features and scenarios:

index.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,19 +53,22 @@ program
5353
.option('-n, --noScreenshot [optional]', 'disable auto capturing of screenshots when an error is encountered')
5454
.parse(process.argv);
5555

56-
program.on('--help', function() {
56+
program.on('--help', function () {
5757
console.log(' For more details please visit https://github.com/john-doherty/selenium-cucumber-js#readme\n');
5858
});
5959

6060
// store browserName globally (used within world.js to build driver)
6161
global.browserName = program.browser;
6262

63+
// store Eyes Api globally (used within world.js to set Eyes)
64+
global.eyeskey = config.eye_key
65+
6366
// used within world.js to import page objects
6467
global.pageObjectPath = path.resolve(program.pageObjects);
6568

6669
// used within world.js to output reports
6770
global.reportsPath = path.resolve(program.reports);
68-
if (!fs.existsSync(program.reports)){
71+
if (!fs.existsSync(program.reports)) {
6972
fs.makeTreeSync(program.reports);
7073
}
7174

@@ -82,7 +85,7 @@ global.junitPath = path.resolve(program.junit || program.reports);
8285
global.DEFAULT_TIMEOUT = global.DEFAULT_TIMEOUT || program.timeOut || 10 * 1000;
8386

8487
// used within world.js to import shared objects into the shared namespace
85-
global.sharedObjectPaths = program.sharedObjects.map(function(item) {
88+
global.sharedObjectPaths = program.sharedObjects.map(function (item) {
8689
return path.resolve(item);
8790
});
8891

@@ -111,8 +114,8 @@ process.argv.push(path.resolve(program.steps));
111114
// add tag
112115
if (program.tags) {
113116
program.tags.forEach(function (tag) {
114-
process.argv.push('-t');
115-
process.argv.push(tag);
117+
process.argv.push('-t');
118+
process.argv.push(tag);
116119
})
117120
}
118121

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,14 @@
5252
"fs-plus": "2.9.1",
5353
"geckodriver": "1.1.2",
5454
"merge": "1.2.0",
55-
"phantomjs-prebuilt": "2.1.12",
5655
"require-dir": "0.3.2",
5756
"selenium-webdriver": "3.0.0"
5857
},
5958
"devDependencies": {
6059
"eslint": "^3.19.0",
6160
"eslint-config-airbnb-base": "^11.2.0",
62-
"eslint-plugin-import": "^2.2.0"
61+
"eslint-plugin-import": "^2.2.0",
62+
"eyes.selenium": "0.0.72"
6363
},
6464
"eslintConfig": {
6565
"extends": "airbnb-base",

runtime/world.js

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ var assert = require('chai').assert;
1616
var reporter = require('cucumber-html-reporter');
1717
var cucumberJunit = require('cucumber-junit');
1818

19+
// Initialize the eyes SDK and set your private API key.
20+
var Eyes = require('eyes.selenium').Eyes;
21+
1922
// drivers
2023
var FireFoxDriver = require('./firefoxDriver.js');
2124
var PhantomJSDriver = require('./phantomDriver.js');
@@ -34,19 +37,23 @@ function getDriverInstance() {
3437

3538
case 'firefox': {
3639
driver = new FireFoxDriver();
37-
} break;
40+
}
41+
break;
3842

3943
case 'phantomjs': {
4044
driver = new PhantomJSDriver();
41-
} break;
45+
}
46+
break;
4247

4348
case 'electron': {
4449
driver = new ElectronDriver();
45-
} break;
50+
}
51+
break;
4652

4753
case 'chrome': {
4854
driver = new ChromeDriver();
49-
} break;
55+
}
56+
break;
5057

5158
// try to load from file
5259
default: {
@@ -63,6 +70,21 @@ function getDriverInstance() {
6370
return driver;
6471
}
6572

73+
74+
/**
75+
* Initialize the eyes SDK and set your private API key via the config file.*/
76+
function getEyesInstance() {
77+
78+
var eyes = new Eyes();
79+
80+
//retrieve apikey from config file in the project root as defined by the user
81+
eyes.setApiKey(eyeskey);
82+
83+
return eyes;
84+
85+
86+
}
87+
6688
function consoleInfo() {
6789
var args = [].slice.call(arguments),
6890
output = chalk.bgBlue.white('\n>>>>> \n' + args + '\n<<<<<\n');
@@ -78,6 +100,7 @@ function createWorld() {
78100

79101
var runtime = {
80102
driver: null, // the browser object
103+
eyes: null,
81104
selenium: selenium, // the raw nodejs selenium driver
82105
By: selenium.By, // in keeping with Java expose selenium By
83106
by: selenium.By, // provide a javascript lowercase version
@@ -113,7 +136,7 @@ function importSupportObjects() {
113136

114137
if (fs.existsSync(itemPath)) {
115138

116-
var dir = requireDir(itemPath, { camelcase: true });
139+
var dir = requireDir(itemPath, {camelcase: true});
117140

118141
merge(allDirs, dir);
119142
}
@@ -131,7 +154,7 @@ function importSupportObjects() {
131154
if (global.pageObjectPath && fs.existsSync(global.pageObjectPath)) {
132155

133156
// require all page objects using camel case as object names
134-
global.page = requireDir(global.pageObjectPath, { camelcase: true });
157+
global.page = requireDir(global.pageObjectPath, {camelcase: true});
135158
}
136159

137160
// add helpers
@@ -150,12 +173,14 @@ module.exports = function () {
150173
// set the default timeout for all tests
151174
this.setDefaultTimeout(global.DEFAULT_TIMEOUT);
152175

153-
// create the driver before scenario if it's not instantiated
154-
this.registerHandler('BeforeScenario', function(scenario) {
176+
// create the driver and applitools eyes before scenario if it's not instantiated
177+
this.registerHandler('BeforeScenario', function (scenario) {
155178

156-
if (!global.driver) {
179+
if (!global.driver || !global.eyes) {
157180
global.driver = getDriverInstance();
181+
global.eyes = getEyesInstance();
158182
}
183+
159184
});
160185

161186
this.registerHandler('AfterFeatures', function (features, done) {
@@ -197,14 +222,17 @@ module.exports = function () {
197222

198223
scenario.attach(new Buffer(screenShot, 'base64'), 'image/png');
199224

200-
return driver.close().then(function() {
225+
return driver.close().then(function () {
201226
return driver.quit();
227+
}).then(function () {
228+
// If the test was aborted before eyes.close was called ends the test as aborted.
229+
return eyes.abortIfNotClosed();
202230
});
203-
});
231+
})
204232
}
205233

206-
return driver.close().then(function() {
234+
return driver.close().then(function () {
207235
return driver.quit();
208-
});
236+
})
209237
});
210238
};

0 commit comments

Comments
 (0)