如何在节点中使用 karma 并在 singleRun 为 true 时从 Server.start 返回 Promise

问题描述 投票:0回答:1

我正在尝试使用节点创建一个工具,该工具将根据我发送的配置信息通过 karma 多次运行 Jasmine。

我从调用一次 karma 开始,我在服务器上遇到了问题

Promise
即使我使用
singleRun: true
运行,也无法在测试运行的情况下解决问题。

如果我要在最终用户视为“单个”操作中多次调用 Jasmine,我需要编译

function doneCallback(exitCode)
行中的所有返回值,以查看是否有非 0。

也就是说,当使用

singleRun: true
时,我认为没有机会像 文档演示那样设置事件侦听器:

runner.run({port: 9876}).on('progress', function(data) {
  process.stdout.write(data)
})

我不是创建一个跑步者并运行它。我只是执行

server.start
并观察它在配置中运行一次测试,我需要获取结果。相反,当读取配置并且服务器启动时,所有
Promise
都会返回。当“隐式”运行器在 singleRun 期间完成时,没有
Promise
返回到调用上下文。 [关于监听事件] 就是一劳永逸。

这是我的代码的修改版本:

function startKarma(karmaConfig) {
    var karmaPromise = karma.config
        .parseConfig(
            null,
            karmaConfig,

            // http://karma-runner.github.io/6.3/dev/public-api.html
            { promiseConfig: true, throwErrors: true }
        )
        .then(
            (parsedKarmaConfig) => {
                // http://karma-runner.github.io/6.4/dev/public-api.html
                const server = new karma.Server(parsedKarmaConfig, function doneCallback(
                    exitCode
                ) {
                    console.log("Karma has exited with " + exitCode);    // <<<<<<< happens last. exitCode is defined.
                    return exitCode;
                });

                var serverPromise = server.start();
                return serverPromise.then(function (x) {
                    console.log("server promise", x); // <<<<<<<<<<<< happens first, x === undefined
                    return x;
                });
            },
            (rejectReason) => {
                console.log("Error", rejectReason);
                throw rejectReason;
            }
        );

    return karmaPromise;
}

我这样开始代码:

// leaving out config creation
startKarma(config).then(function (after) {
    console.log("after", after); // <<<<<<<<<<<< happens second, after === undefined
});

这是我的“基本配置”,它在代码中的其他地方覆盖了

files
preprocessors
basePath

var baseConfig = {
    files: [{ pattern: "**/*.js" }],
    preprocessors: {
        "**/!(*test).js": ["coverage"],
    },
    basePath: "./",

    frameworks: ["jasmine"],
    exclude: ["**/node_modules/**/"],
    reporters: ["coverage", "mocha"],
    coverageReporter: {
        reporters: [
            { type: "text-summary" },
            { type: "html", dir: "../coverage/" },
            { type: "text", dir: "coverage/", file: "coverage.txt" },
        ],
    },
    port: 9876,
    colors: true,
    logLevel: karma.config.LOG_DEBUG,
    autoWatch: true,
    browsers: ["Chrome"],
    singleRun: true,
    concurrency: Infinity,
};

我可以解释我想要做的事情的最好方法是,“我想在 singleRun Server.start 中获取运行程序的句柄,并通过

Promise
将其结果返回给调用代码。”不确定在哪里我应该访问“隐式”跑步者的结果。

换句话说,对于

singleRun: true
,我希望仅在测试运行后返回
Server.start
Promise
,而不是在服务器启动并运行后立即返回。既然没有,我想知道在哪里可以连接到必须正在运行的跑步者。

结果:

START:
server promise undefined
after undefined
01 05 2023 16:27:56.094:INFO [karma-server]: Karma v6.4.2 server started at http://localhost:9876/
01 05 2023 16:27:56.097:INFO [launcher]: Launching browsers Chrome with concurrency unlimited
01 05 2023 16:27:56.103:INFO [launcher]: Starting browser Chrome
01 05 2023 16:27:56.916:INFO [Chrome 112.0.0.0 (Windows 10)]: Connected on socket fLZkvHywy1zV36iIAAAB with id 22356421
  these are not real tests
    add2 function in global scope
      √ should return a value that is 2 greater than that which was pushed in  
    add2broken function in global scope
      × should return a value that is 2 greater than that which was pushed in  
    double function in global scope
      √ should return a value double that pushed in
    square function in global scope
      √ should return a value that squares that which was pushed in

Finished in 0.018 secs / 0.002 secs @ 16:27:56 GMT-0400 (Eastern Daylight Time)

SUMMARY:
√ 3 tests completed
× 1 test failed

FAILED TESTS:
  these are not real tests
    add2broken function in global scope
      × should return a value that is 2 greater than that which was pushed in  
        Chrome 112.0.0.0 (Windows 10)
      Expected 27 to be 7.
          at <Jasmine>
          at UserContext.<anonymous> (fakeTests/testSubdir/add2.test.js:26:28) 
          at <Jasmine>


=============================== Coverage summary ===============================
Statements   : 76.47% ( 13/17 )
Branches     : 50% ( 8/16 )
Functions    : 80% ( 4/5 )
Lines        : 81.25% ( 13/16 )
================================================================================

需要明确的是,我认为设置

singleRun: false
并“手动”处理服务器生命周期将允许我做我想做的事情,但如果可能的话,我想 KISS 并挂钩到
singleRun: true
版本。

node.js karma-jasmine karma-runner karma-mocha
1个回答
0
投票

我相信,正确的做法是将所有这些逻辑包装到我自己的

Promise
中。也就是说,karma 不为单次运行提供事件挂钩。这种方法(在原始问题中描述)是浪费精力。

要卷起自己的

Promise
包装纸,这样做(关键是
return new Promise(function (resolve, reject) //...
):

function startKarma(karmaRunId, overrides) {
    return new Promise(function (resolve, reject) {
        overrides = Object.assign(
            {},
            karmaConfigTools.overridesForMochaTestingRun,
            overrides
        );
        var karmaConfig = karmaConfigTools.createKarmaConfig(overrides);

        karma.config
            .parseConfig(
                null,
                karmaConfig,

                // In most cases, parseOptions.throwErrors = true should also be set.
                // This disables process exiting and allows errors to result in rejected promises.
                // http://karma-runner.github.io/6.3/dev/public-api.html
                { promiseConfig: true, throwErrors: true }
            )
            .then(
                (parsedKarmaConfig) => {
                    // fwiw
                    // http://karma-runner.github.io/6.4/dev/public-api.html
                    // I'm not sure why it names the callback function doneCallback.
                    const server = new karma.Server(
                        parsedKarmaConfig,
                        function doneCallback(exitCode) {
                            // 0 is success/no test failure.
                            // Anything else is bad. Usually 1 afaict.
                            utils.debugLog("Wrapped karma has exited with " + exitCode);
                            karmaRunResults[karmaRunId] = exitCode;

                            resolve(exitCode);
                        }
                    ).on("progress", function (data) {
                        process.stdout.write(data);
                    });

                    server.start().then(function (x) {
                        utils.debugLog("server started", x);
                    });
                },
                (rejectReason) => {
                    utils.debugLog("Error", rejectReason);
                    throw rejectReason;
                }
            );
    });
}

现在我可以等到到达我最初想要的部分:

const server = new karma.Server(parsedKarmaConfig, function doneCallback(
    exitCode
) {
    console.log("Karma has exited with " + exitCode);    // <<<<<<< happens last. exitCode is defined.
    return exitCode;
});

我补充说,

Promise
不是通过业力来监听,而是表现得惊人😏,就像一个
Promise
,允许调用者等待,直到获得它想要的信息。如果我需要调用大量的 singleRun 测试套件,我会将这些调用分组到一个数组中并
Promise.all
它们。再说一遍,典型的
Promise
东西

TL;博士

最重要的是,业力似乎不允许您收听单次运行中的事件。如果您想通过 karma 的处理程序使用类似

runner.run({port: 9876}).on('progress', function(data) { // ...

的代码进行监听,则必须设置一个开放式生命周期 (!singleRun) karma 运行器

但是,您可以使用基于“多个 singleRun”的逻辑设置自己的异步(基于

Promise
)管理来完成相同的事情,如上所示。

© www.soinside.com 2019 - 2024. All rights reserved.