Подтвердить что ты не робот

Асинхронный код в пользовательских правилах ESLint

История и мотивация:

У нас есть довольно обширная сквозная тестовая кодовая страница Protractor. Иногда бывает, что тест ждет конкретного исправления, которое будет реализовано - как правило, в рамках подхода TDD и для демонстрации того, как проблема воспроизводится и каково предполагаемое поведение. В настоящее время мы используем Jasmine pending() с номером проблемы Jira внутри. Пример:

pending("Missing functionality (AP-1234)", function () {
    // some testing is done here
});

Теперь мы хотели бы знать, когда мы можем переименовать pending() обратно в it() и запустить тест. Или, другими словами, когда проблема AP-1234 разрешена или отправляется на тестирование.

Текущий подход:

В настоящий момент я пытаюсь решить его с помощью пользовательского правила ESLint, jira Модуль NodeJS и 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(), но не печатает статусы билетов. Ошибок нет.

Вопрос:

Общим вопросом является, я думаю, следующее: могу ли я использовать асинхронные блоки кода, ждать ответных запросов, разрешать promises в пользовательских правилах ESLint? И, если нет, каковы мои варианты?

Более конкретный вопрос: что я делаю неправильно и как я могу использовать модуль Node.js jira с ESLint?

Поблагодарили бы любые идеи или альтернативные подходы.

4b9b3361

Ответ 1

Короткий ответ - нет, вы не можете использовать асинхронный код внутри правил. ESLint является синхронным и в значительной степени полагается на EventEmitter, когда он ходит по AST. Было бы очень сложно изменить код ESLint, чтобы быть асинхронным, но в то же время гарантировать, что события будут выбрасываться в правильном порядке. Я думаю, что ваш единственный выбор состоит в том, чтобы написать правило синхронизации, которое выводит достаточное количество информации в сообщение об ошибке, затем используйте один из синтаксических форматов, например JSON или UNIX, а затем создайте другое приложение, которое вы можете подключить к выходу ESLint и сделать асинхронный поиск в Jira на основе сообщения об ошибке.

Ответ 2

Примечание: он не отвечает на оригинальный вопрос о поддержке асинхронного кода в пользовательских правилах ESLint, но предоставляет альтернативное решение проблемы.

В этом случае я лично не использовал бы ESLint, он должен использоваться для проверки правильности написания кода и последующего руководства стилями; с моей точки зрения, пропущенные тесты не являются частью проверки кода, это больше похоже на внутренние процессы вашей команды. Кроме того, такие запросы могут значительно замедлить выполнение ESLint, если кто-либо запускает его в режиме реального времени в своем редакторе, вызовы будут выполняться очень часто и будут замедлять весь чек. Я бы сделал эту JIRA-проверку частью потока Contractor, поэтому, если билет будет разрешен, вы получите неудачную спецификацию Protractor. (скопирован из comment, чтобы завершить ответ)

Жасмин позволяет отмечать спецификации как ожидающие использования xit(). Я не уверен в pending(), хотя он работает странно в Protractor. Кроме того, Jasmine позволяет вызывать 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() функциональность внутри спецификации реализована.