|
阅读:4320回复:0
Firefox扩展SDK开发指南(四)
到目前为止,我们已经知道如何使用SDK去开发一个简单的扩展。您还可以使用SDK去创建一个可复用,接口定义清晰的CommonJS模块。这些模块随后可以用在其它遵循CommonJS规范的程序中,也包括其它使用SDK构建的扩展。
即便您不打算为其它开发人员提供可复用模块,使用模块化方法来结构化一个大型的或者复杂的扩展也是有意义的。这样会使得您的扩展更加容易理解,也为各个模块提供了一些封装,从而使得您可以随后修改它们的内部实现,而不担心破坏其使用。 如果您喜欢这个系列的文章,请访问盛夏莲花博客以获取最新内容更新及评论,以及更好的阅读体验。 点击此处,在线体验浏览、分享、导航工具-阳光宝盒 在这个例子中,我们仍然从translator扩展开始,并且将创建一个单独的模块来完成翻译任务。 translate.js的实现 在您的transloter工程的根目录下,创建一个名为translater.js的新文件,并且加入下面的代码: // Import the APIs we need. var request = require("request");
// Define the 'translate' function
using Request;
function translate(text, callback) {
if (text.length === 0) {
throw ("Text to translate must not be empty");
}
var req = request.Request({
url:"http://ajax.googleapis.com/ajax/services/language/translate",
content:{ v:"1.0", q:text, langpair:"|en" },
onComplete:function (response) {
callback(response.json.responseData.translatedText);
} });
req.get();
}
// Export the 'translate' function
exports.translate = translate;translate函数本质上与我们前面赋值给onMessage的消息处理函数完全一致,只不过它接受一个回调函数来处理翻译后的结果,而不是将它直接替换到被选择的文本原来的位置。 在代码的最后部分,我们通过把它加入到全局对象exports上,以完成对函数的导出。 编辑main.js 接下来,我们需要修改main.js,以使用我们的新模块,而不是原来的request模块。 // Import the APIs we need.
var contextMenu = require("context-menu");
var selection = require("selection");
var translate = require("translate");
exports.main = function (options, callbacks) {
console.log(options.loadReason);
// Create a new context menu item.
var menuItem = contextMenu.Item({ label:"Translate Selection",
// Show this item when a selection exists.
context:contextMenu.SelectionContext(),
// When this item is clicked, post a message to the item with the
// selected text and current URL.
contentScript:'self.on("click", function () {' + ' var text = window.getSelection().toString();' + ' self.postMessage(text);' + '});',
// When we receive the message, call the translator with the
//selected text and replace it with the translation.
onMessage:function (text) {
translate.translate(text, function (translation) {
selection.text = translation;
})
} });
};
exports.onUnload = function (reason) {
console.log(reason);
}接下来,再次运行cfx run,以测试我们的扩展。这次也应该跟上次的运行结果完全一致,只不过现在我们的核心功能还可以被其它模块使用。 测试 SDK提供了一个用于测试的框架。出于演示目的,我们加上一些简单的单元测试。 浏览至test目录,删除掉test-main.js文件。在同样的位置创建一个名为test-translate.js的文件,并加入下面的代码: var translate = require("translator/translate")
var testRunner;
var remainingTests;
function check_translation(translation) {
testRunner.assertEqual("Lizard", translation);
testRunner.done();
}
function test_languages(test, text) {
testRunner = test;
testRunner.waitUntilDone(2000);
translate.translate(text, check_translation);
}
exports.test_german = function (test) {
test_languages(test, "Eidechse");
}
exports.test_italian = function (test) {
test_languages(test, "Lucertola");
}
exports.test_finnish = function (test) {
test_languages(test, "Lisko");
}
exports.test_error = function (test) {
test.assertRaises(function () {
translate.translate("", check_translation);
}, "Text to translate must not be empty");
};该文件导出了4个函数,每个函数都有一个且惟有一个参数,即test对象。test对象由unit-test模块提供,它提供了一些简化单元测试的方法。在实现上,该文件导入了我们translator包里的模块。这里的PACKAGE/MODULE语法让您指定某个特定包里的特定模块,而不是在所有可用的包里去搜索它(比如通过使用require(“request”)。module-search的文档提供了更详细的说明。 前面三个函数调用translate方法并在回调函数里调用test.assertEqual来检查翻译结果是否正确。 第四个方法使用test.assertRaises检查被调用方法是否抛出了一个例外。 现在,您的包的结构应该如下图所示: ![]() 现在运行cfx –verbose test命令。您应该可以看到类似下面的输出: ![]() cfx test所做的工作: 在test目录中查找您的包。 加载任何以test开头的模块。 调用这些模块中导出函数,将test对象传递给这些函数。 下一节,我们将概述SDK提供的API。 |
|
