What is the best method for checking if a template has successfully rendered in an Iron:Router route during a mocha test?

I am working on testing if a specific template has rendered in my meteor app for a particular route. My current setup involves iron:router, practicalmeteor:mocha, and I'm using Blaze for rendering.

There are a couple of challenges that I am facing:

  • waiting for the route to finish without relying on setTimeout (preferably using a callback)
  • determining whether or not a Blaze template has been rendered on the page

Is there a way to test if a template has rendered after calling 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('should render template exampleTemp', function() {
        Router.go('/example');
        // unsure how to wait for the route to finish here

        // uncertain about achieving the following assertion
        chai.assert.isTrue(Template.exampleTemp.isRendered());
    });
});

Answer №1

This solution may not be ideal as it can override the onAfterAction hook if already defined, and it introduces onRendered functions to templates which can complicate testing.

testing-router-helper.js

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

export const testRouteRendering = 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();
            }
        }
    });
};

test-router.html

<template name="placeholderLayout">{{> yield}}</template>
<template name="placeholderTemplate"></template>

test-router.js

import { chai } from 'meteor/practicalmeteor:chai';
import { testRouteRendering } from './testing-router-helper.js';
import './test-router.html';
import './router.js';

const RoutesToTest = [
    { name: 'about', path: '/about', template: 'aboutPage', layout: 'defaultLayout' }
    // additional routes
];

describe('router testing', function() {
    before(function() {
        Router.route('/exampleRoute', { name: 'exampleRoute', template: 'exampleTemplate', layoutTemplate: 'exampleLayout' });
    });
    beforeEach(function(done) {
        Router.go('exampleRoute');
        testRouteRendering(['exampleTemplate'], done);
    });
    after(function() {
        Router.go('/');
    });
    RoutesToTest.forEach(function(testRoute) {
        let message = 'testing 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);
            testRouteRendering([testRoute.template, testRoute.layout], function() {
                // verifies that the route and templates have been rendered correctly, otherwise the test will timeout
                chai.assert.equal(Router.routes[testRoute.name].path(), testRoute.path);
                done();
            });
        });
    });
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Managing and keeping track of a universal value within the success callback function among numerous Ajax POST requests

I am faced with a challenge involving two HTML elements: 1). a div element that functions as a multiple select, created automatically by a predefined widget, and 2). a button that triggers an onclick event. On the JavaScript side, I have a global variable ...

Modifying a single route among several nested routes with specific names

My template includes various named, nested views: Template 1: <body> <div ui-view></div> </body> Template 2: <header></header> <div ui-view="left"></div> <div ui-view="canva ...

Phonegap - Retaining text data in a checklist app beyond app shutdown

This is my first time developing an app with Phonegap. I am looking to create a checklist feature where users can input items into an input field. However, I am struggling with figuring out how to save these items so that they remain in the checklist even ...

"An error has occurred stating that the function Factory.function() in AngularJS

I'm a beginner with AngularJS and could use some assistance! My issue involves retrieving JSON data from a URL in a factory function and returning it to the controller. However, I keep getting an error stating that the function doesn't exist. Wh ...

Halt the execution of a function upon clicking a div element

I'm currently working on a function that needs to be stopped when a div with the class "ego" is clicked. This function toggles the visibility of the header based on the scroll position and should only run by default. Below is the code snippet: $("#e ...

Raphael and jQuery/JavaScript for user-selected array intersections

Hello everyone! This is my first time posting here, and I must say that I'm still quite new to JavaScript/jQuery/Raphael. Please forgive me if I make any mistakes or ask basic questions. :) I've been searching high and low for answers to my quer ...

JavaScript element styling in a Partial view, experiencing issues with functionality

In the main view, the javascript element is working fine. However, in the partial view it seems to not be functioning even though it is correctly formatted. Any ideas on how to fix this issue? Check out this fiddle for reference: http://jsfiddle.net/bgrin ...

Unable to remove the necessary row with Angular.js/JavaScript

I am facing an issue in deleting the correct row from an array using Angular.js. Below is the code snippet that I am working with: <tr ng-repeat="d in days"> <td>{{d.day_name}}</td> <td> <table ...

Harnessing the power of the bluebird promise library

Within myPeople function, there is a promise function being called as shown below: var myPeople = function(){ var go; return new Promise (function(resolve){ User .getPeople() .then(function(allPeople){ ...

Achieving the extraction of a particular string from an HTML element using JavaScript

<input id="WD01B3" ct="CB" lsdata="{2:'WD01B4',4:'Any',20:'\x7b\x22WDA_TYPE\x22\x3a\x22DROPDOWN_BY_KEY\x22,\x22WDA_ID\x22\x3a\x22ABCA950297D2C0C432BAB9BB ...

What is the best way for library creators to indicate to VSCode which suggested "import" is the correct one?

As a library creator, I have noticed that VSCode often suggests incorrect imports to users. For instance, VSCode typically suggests the following import: import useTranslation from 'next-translate/lib/esm/useTranslation' However, the correct im ...

Clicking on Google Code Prettify does not trigger syntax highlighting

I utilize Google Code Prettify for syntax highlighting my code. Below is the HTML snippet I use: <head> <script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script> </head> <body> ...

Angular - Navigate to Login Page post registration and display a confirmation message

As a newcomer to Angular, I am currently working on an Angular and Spring Boot application. So far, I have created components for user login and registration along with validation features. Now, my goal is to redirect the user to the login page upon succes ...

Prevent CSS3 columns from reverting back to their original state after being rendered

Utilizing css3 columns, I have created a layout with an unordered list displayed in 3 columns. Each list item contains another list that can be toggled to show or hide by clicking on the title using jQuery. The structure of the html is as follows (with ex ...

Put the code inside a function. I'm new to this

My goal is to encapsulate this code: if($(window).width() > 980) { $(window).on("scroll", function() { if($(window).scrollTop() > 20) { //add black background $(".x-navbar").addClass("active"); $(".x-navbar .desktop ...

How to iterate through a JavaScript array in reverse order using a for loop and the array's length property

When looking to iterate through an array with the values [8,7,6,5,4], some may wonder why a for loop using the length of 5 continues to function even though there is no element at index 5 in the array. for(let i=array.length;i>=0;i++){ //do somethin ...

How to Make a Div Tag Fade Effect with JavaScript in an External File

*** New Team Member Notice *** I'm currently working on an assignment and trying to implement a simple fade effect on a box. While it seems like this should be straightforward, I'm encountering some obstacles. Currently, the button causes the bo ...

Tips for refreshing the tawk.to widget when the language changes with the help of i18next

Utilizing i18n-jquery for language switching and integrating the tawk.to chat widget, I've successfully loaded different languages on page reload. However, due to i18n not refreshing the page (which I don't want to do), I need to figure out how t ...

Having trouble with moving the svg:svg element?

I'm struggling to move an svg element that is nested within another svg. I am trying to directly manipulate the x and y values, but I keep encountering a "read-only" error. I attempted to use transform instead, but it doesn't seem to have any eff ...

Strange issue encountered when utilizing Worklight along with XSL transformation on a JSON response

I'm facing an unusual issue that I can't seem to resolve. Here is an example of a JSON response that I am dealing with. "values": [ { "time": "2014-02-26T09:01:00+01:00", "data": [ "A", "B" ] }, // additional objec ...