[英]Asynchronous code in custom ESLint rules
故事和动机:
我们有一个相当庞大的端到端Protractor测试代码库。 有时,测试会等待实现特定修复 - 通常作为TDD方法的一部分,并演示如何重现问题以及预期的行为是什么。 我们目前正在做的是使用Jasmine的pending()
,里面有一个Jira问题编号。 例:
pending("Missing functionality (AP-1234)", function () {
// some testing is done here
});
现在,我们想知道何时可以将pending()
重命名为it()
并运行测试。 或者,换句话说,当问题AP-1234
被解决或发送到测试时。
目前的方法:
目前,我正在尝试使用自定义ESLint
规则 , jira
ESLint
模块和Q
来解决它。 自定义ESLint
规则使用至少一个参数搜索pending()
调用。 以AP-
格式提取票号,后跟4位数,并使用jira.findIssue()
检查其在Jira中的状态。 如果状态为Resolved
- 报告错误。
这是我到目前为止所得到的:
"use strict";
var JiraApi = require("jira").JiraApi,
Q = require('q');
var jira = new JiraApi("https",
"jira.url.com",
"443",
"user",
"password",
"2");
module.exports = function (context) {
var jiraTicketRegex = /AP\-\d+/g;
return {
CallExpression: function (node) {
if (node.callee.name === "pending" && node.arguments.length > 0) {
var match = node.arguments[0].value.match(jiraTicketRegex);
if (match) {
match.forEach(function(ticket) {
console.log(ticket); // I see the ticket numbers printed
getTicket(ticket).then(function (status) {
console.log(status); // I don't see statuses printed
if (status === "Resolved") {
context.report(node, 'Ticket {{ticket}} is already resolved.', {
ticket: ticket
})
}
});
});
}
}
}
}
};
其中getTicket()
定义为:
function getTicket(ticket) {
var deferred = Q.defer();
jira.findIssue(ticket, function(error, issue) {
if (error) {
deferred.reject(new Error(error));
} else {
deferred.resolve(issue.fields.status.name);
}
});
return deferred.promise;
}
问题是:目前,它成功从pending()
调用中提取票号,但不打印票证状态。 虽然没有错误。
问题:
我想,一般的问题是:我可以使用异步代码块,等待回调,解决自定义ESLint
规则中的ESLint
吗? 如果没有,我的选择是什么?
一个更具体的问题是:我做错了什么以及如何在ESLint
使用Node.js jira
模块?
将不胜感激任何见解或替代方法。
简短的回答是 - 不,你不能在规则中使用异步代码。 ESLint是同步的,并且在它行走AST时严重依赖于EventEmitter
。 将ESLint代码修改为异步非常困难,但同时保证事件将以正确的顺序发出。 我认为您唯一的选择可能是编写一个同步规则,将足够的信息输出到错误消息中,然后使用其中一个可解析的格式化程序(如JSON
或UNIX
,然后创建另一个应用程序,您可以将ESLint输出管道并执行异步查找Jira基于错误消息。
这些答案在2018年仍然有效。
有关eslint devs的一些见解,请参阅我们在其邮件列表中的对话 。
对于一个工作示例,在我的“伪eslint插件”中,我选择使用昂贵但同步的API,并警告用户如何最好地在其CI过程中使用“插件”。
注意:它不回答有关在ESLint自定义规则中支持异步代码的原始问题,但提供了该问题的替代解决方案。
在这种情况下,我个人不会使用ESLint ,它应该用于检查您的代码是否正确编写以及是否遵循样式指南; 从我的观点来看,缺少测试不是代码检查的一部分,它更像是团队内部流程。 此外,这种请求可能会显着减慢您的ESLint执行速度,如果有人在他们的编辑器中实时运行它,则会经常进行调用并且会减慢整个检查的速度。 我会将此JIRA检查作为Protractor流程的一部分,因此如果故障单已解决,您将获得一个失败的Protractor规范。 (从评论中复制以完成答案)
Jasmine允许使用xit()
将规范标记为挂起。 我不确定pending()
虽然在Protractor中很奇怪。 此外, Jasmine允许在规范中调用pending()
,因此它将被标记为pending,但它尚未针对Protractor实现( 请参阅问题 )。 知道这一点,我会使用自定义助手来定义“待定规范”,应该检查JIRA问题状态。 我猜你仍然可以使用Q来处理promises,我只是在没有外部依赖的情况下使用WebDriver promises发布替代方案。 以下是getTicket()
的修改版本:
function getTicketStatus(ticket) {
// Using WebDriver promises
var deferred = protractor.promise.defer();
jira.findIssue(ticket, function(error, issue) {
if (error) {
deferred.reject(new Error(error));
} else {
deferred.fulfill(issue.fields.status.name);
}
});
return deferred.promise;
}
然后有一个自定义帮助函数:
function jira(name) {
// Display as pending in reporter results, remove when pending() is supported
xit(name);
// Using Jasmine Async API because Jira request is not a part of Control Flow
it(name, function (done) {
getTicketStatus().then(function (status) {
if (status === 'Resolved') {
done.fail('Ticket "' + name + '" is already resolved.');
} else {
done();
// pending() is not supported yet https://github.com/angular/protractor/issues/2454
// pending();
}
}, function (error) {
done.fail(error);
});
});
}
用法示例:
jira('Missing functionality (AP-1234)', function () {
//
});
jira('Missing functionality (AP-1235)');
如果对JIRA的请求失败或问题已解决 ,则您将获得失败的规范(使用Jasmine 异步API )。 在所有情况下,您仍然会在报告结果中将此规范重复为待处理。 当希望实现规范中的pending()
功能时,我希望它可以得到改进。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.