编写自定义Commands
大多数情况下,你需要扩展Nightwatch commands以满足自己的应用程序需求。这样做只需要创建一个单独的文件夹并在其中定义自己的commands。
然后在nightwatch.json文件中设置custom__commands__path属性,command名是文件本身的名字。
有两种主要的方法来定义一个custom command:
Function-style commands(函数式命令)
这是命令commands的最简单的形式,但是它们也非常有限。你的command模块需要导出一个command函数,这需要至少调用一个夜Nightwatch api方法( 例如 .execute() ),这是由于commands的异步排队系统工作原理所限制,你还可以将所有内容封装在 .perform() 中来调用。诸如 execute 和 perform 的客户端命令可以通过 this 实现。
exports.command = function(file, callback) {
var self = this;
var imageData;
var fs = require('fs');
try {
var originalData = fs.readFileSync(file);
var base64Image = new Buffer(originalData, 'binary').toString('base64');
imageData = 'data:image/jpeg;base64,' + base64Image;
} catch (err) {
console.log(err);
throw "Unable to open file: " + file;
}
this.execute(
function(data) { // execute application specific code
App.resizePicture(data);
return true;
},
[imageData], // arguments array to be passed
function(result) {
if (typeof callback === "function") {
callback.call(self, result);
}
}
);
return this;
};
上面的例子定义了一个command(例如:resizePicture.js),它加载一个图像文件作为data-URI,并调用一个名为resizePicture的方法,在应用程序中定义。
有了这个command,测试就可以变成这样:
module.exports = {
"testing resize picture" : function (browser) {
browser
.url("http://app.host")
.waitForElementVisible("body")
.resizePicture("/var/www/pics/moon.jpg")
.assert.element(".container .picture-large")
.end();
}
};
Class-style commands(类方式命令)
这就是Nightwatch的大部分commands的编写方式。你的command模块需要使用一个command实例方法导出一个类构造函数,该方法表示command函数。像这样编写的command应该从EventEmitter继承,并手动发出完整的事件,以指示命令完成。
基于类的command方法在类实例的上下文中运行(this的值)。这个测试api对象提供了this.api或this.client.api,这个this.client是Nightwatch实例本身。
下面的例子是.pause()命令:
var util = require('util');
var events = require('events');
function Pause() {
events.EventEmitter.call(this);
}
util.inherits(Pause, events.EventEmitter);
Pause.prototype.command = function(ms, cb) {
var self = this;
// If we don't pass the milliseconds, the client will
// be suspended indefinitely
if (!ms) {
return this;
}
setTimeout(function() {
// if we have a callback, call it right before the complete event
if (cb) {
cb.call(self.client.api);
}
self.emit('complete');
}, ms);
return this;
};
module.exports = Pause;
complete事件
需要在异步操作中完成对complete事件的信令 (例如:调用setTimeout),不扩展EventEmitter的command类将被视为与命令功能类似,要求command方法至少调用一个Nightwatch api方法才能完成。
目前还不支持使用ES6类作为自定义command。有关更多细节,请参见Nightwatch#1199。
编写自定义Assertions
Nightwatch允许你甚至定义你自己的断言,扩展可用的断言 .assert 和 .verify 名称空间。
Assertions实现了一个简单的接口,该接口在内置assertions和自定义assertions之间共享:
exports.assertion = function() {
/**
* The message which will be used in the test output and
* inside the XML reports
* @type {string}
*/
this.message;
/**
* A value to perform the assertion on. If a function is
* defined, its result will be used.
* @type {function|*}
*/
this.expected;
/**
* The method which performs the actual assertion. It is
* called with the result of the value method as the argument.
* @type {function}
*/
this.pass = function(value) {
};
/**
* The method which returns the value to be used on the
* assertion. It is called with the result of the command's
* callback as argument.
* @type {function}
*/
this.value = function(result) {
};
/**
* Performs a protocol command/action and its result is
* passed to the value method via the callback argument.
* @type {function}
*/
this.command = function(callback) {
return this;
};
};
自定义断言也继承了EventEmitter。请在Github上查看更多的断言模块示例
自定义Reporter
如果你想要定义自己的repoter,除了内置的(stdout和junit-xml),你可以通过两种方式来实现:
--reporter命令行参数
接口
module.exports = {
write : function(results, options, done) {
done();
}
};
reporter方法在你的外部全局文件里
参看globalsMobule.js文件,例如:
module.exports = {
reporter : function(results, done) {
console.log(results);
done();
}
};