如何在 mocha 测试中测试模板是否为 iron:router 路由呈现?

How to test if a template has rendered for a iron:router route in a mocha test?

在我的流星应用程序中,我希望能够测试某个模板是否已针对特定 route/path 呈现。我当前的设置包括以下内容:iron:router、practicalmeteor:mocha,我正在使用 Blaze 进行渲染。

有两个问题我无法开始工作:

调用 Router.go() 后如何测试模板是否已呈现?

import { Router } from 'meteor/iron:router';
import { Template } from 'meteor/templating';
import { chai } from 'meteor/practicalmeteor:chai';

Router.route('/example', { name: 'exampleTemp' });

describe('example route', function() {
    it('renders template exampleTemp', function() {
        Router.go('/example');
        // not sure what to put here to wait for route to finish

        // don't know how to achieve the function below
        chai.assert.isTrue(Template.exampleTemp.isRendered());
    });
});

这不是一个完美的解决方案,因为如果您定义了 onAfterAction 挂钩,它会覆盖它。此外,它向模板添加了 onRendered 函数,创建了一个混乱的测试环境

路由器-helpers.test.js

import { Template } from 'meteor/templating';
import { Tracker } from 'meteor/tracker';
import { Router } from 'meteor/iron:router';

export const withRenderedRoute = function(templates, callback) {
    let routeRendered = new ReactiveVar(false);
    Router.onAfterAction(function() {
        routeRendered.set(true);
    });
    let templatesRendered = [];
    if (Array.isArray(templates)) {
        templates.forEach(function(templateName) {
            let rendered = new ReactiveVar(false);
            Template[templateName].onRendered(function() {
                rendered.set(true);
            });
            templatesRendered.push(rendered);
        });
    }
    Tracker.autorun(function() {
        const areTemplatesRendered = templatesRendered.every(function(rendered) {
            return rendered.get();
        });
        if (routeRendered.get() && areTemplatesRendered) {
            Router.onAfterAction(function() {});
            if (callback) {
                callback();
            }
        }
    });
};

router.test.html

<template name="dummyLayout">{{> yield}}</template>
<template name="dummyTemplate"></template>

router.test.js

import { chai } from 'meteor/practicalmeteor:chai';
import { withRenderedRoute } from './router-helpers.test.js';
import './router.test.html';
import './router.js';

const RoutesToTest = [
    { name: 'home', path: '/', template: 'home', layout: 'layoutDefault' }
    // more routes
];

describe('router', function() {
    before(function() {
        Router.route('/dummyRoute', { name: 'dummyRoute', template: 'dummyTemplate', layoutTemplate: 'dummyLayout' });
    });
    beforeEach(function(done) {
        Router.go('dummyRoute');
        withRenderedRoute(['dummyTemplate'], done);
    });
    after(function() {
        Router.go('/');
    });
    RoutesToTest.forEach(function(testRoute) {
        let message = 'route ' + testRoute.name + ' with path ' + testRoute.path;
        message += ' should render template ' + testRoute.template + ' with layout ' + testRoute.layout;
        it(message, function(done) {
            Router.go(testRoute.name);
            withRenderedRoute([testRoute.template, testRoute.layout], function() {
                // the route and templates have been rendered correctly at this point, otherwise the test will timeout
                chai.assert.equal(Router.routes[testRoute.name].path(), testRoute.path);
                done();
            });
        });
    });
});