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

An error occurred with redirecting using jQuery Mobile's new method in version 1.5

Utilizing jQuery Mobile for its history state feature, I am looking to redirect users to another "page" using the jQuery method recommended in their latest documentation. p/s: I prefer the jQuery navigation method due to the hashchange/history support and ...

Encountering issues with Visual Studio Code following the integration of the MongoDB API Mongoose into my code

As I delve into the world of web development, I have been exploring databases with MongoDB Atlas and mongoose. Interestingly, my debugging process has hit a bump when using the node.js(legacy) debugger in VS code after importing mongoose with const mongoos ...

After submitting my form, the Bootstrap Modal does not hide as intended by my Ajax

I am facing an issue with my webpage that displays 6 Bootstrap Cards in 3 columns. Each card contains an image, name, description, and a footer button. When a user clicks on the button, a Bootstrap Modal opens with specific data fetched from a SQL row by I ...

Leverage the power of openCv.js within your next.js projects

I am attempting to incorporate openCv.js into my next.js application a. I started the project with: npx create-next-app b. Next, I installed: $ yarn add @techstark/opencv-js c. Imported OpenCV with: import cv from "@techstark/opencv-js" d. Ho ...

Is there a way to streamline and optimize this React/Material UI code for faster performance?

There seems to be a lot of repetition in the code that needs to be cleaned up. I'm wondering if the switch statement is necessary. It looks like it requires the muiTheme palette to be passed this way. Also, can these theme constants be placed in a sep ...

Is it possible to have the ShowHide plugin fade in instead of toggling?

I'm currently utilizing the ShowHide Plugin and attempting to make it fade in instead of toggle/slide into view. Here's my code snippet: showHide.js (function ($) { $.fn.showHide = function (options) { //default variables for the p ...

JavaScript regular expressions: filtering out results from the output

I'm trying to extract a specific number from a dynamically added string. The text looks like this: nisi non text600 elit, where 600 is the number I need to retrieve. Is there a way to achieve this without replacing the word text? var str = ('nis ...

I'm encountering an issue with my API Key being undefined, despite having it saved in both an .env file and as a global variable

While attempting to retrieve information from an API, I encountered an issue where the key I was using was labeled as "undefined". However, after manually replacing {key=undefined} with the correct string in the network console, I was able to successfull ...

Locate all posts associated with the specified User ID

Using mongoose, I am able to populate the "Post Schema" with relevant information about users who create the posts. postModule.js const mongoose = require('mongoose'); const postSchema = mongoose.Schema({ title:String, description:String, date ...

Using AngularJS to integrate a function within a component

Hey there, I am facing an issue trying to call a function that is in a component. Let me share the code snippet from my component buttonsController: (function(){ "use strict"; angular .module('my') .component('myButton&ap ...

Are you encountering issues with retrieving $http results from the cache?

During my initial $http requests, I am saving the results in cache using two functions in my controller. Both functions call the same function in a service which handles the $http request. The first function successfully saves the results in cache, but whe ...

Modifying modal content disrupts AJAX events

When using jquery-ujs for ajax requests with data-remote="true", I encounter an issue where the first request goes smoothly but subsequent ones break. It seems that when certain events like $('#modal').empty(), $('#modal').tex ...

The node module.exports in promise function may result in an undefined return value

When attempting to log the Promise in routes.js, it returns as undefined. However, if logged in queries.js, it works fine. What changes should be made to the promise in order to properly return a response to routes.js? In queries.js: const rsClient = req ...

Dynamic content loading in Angular through HTML upon clicking

In the process of developing an Angular store, I aim to create anchor tags for each product so that clicking on a tag will display the selected product information in an HTML template below. Below is the current code snippet: (function() { var app = an ...

Automatically selecting and fetching checkbox values using JavaScript

I was struggling with coding a function that involved generating checkboxes using JavaScript. My goal is to automatically select the elements "March" and "September" from the array target[] and display them as checked in the text area. So, "March" and "Se ...

What is the alternative to using document.getElementById?

1) Question 1 Why does the following example work without using "document.getElementById('myId')" and is it acceptable to skip this step? <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Javascript quest ...

"What is the best way to change the props of a React component that has already been rendered from App.js

My React component, MoviesGallery.js, is set up with the following structure: class MoviesGallery extends Component { constructor(props) { super(props) this.state = { currentImage: 0 }; this.closeLightbox = this.closeLightbox. ...

The function to focus on this.$refs[("p" + index)] element is not available

I need help transforming a div into an input box when clicked, allowing me to edit the post inside a loop. Here is the button found on the post: <a @click="setFocusEdit(index)" v-if="isAuthor(post)" href="#" >Edit Me</a> And here is the spec ...

Is JavaScript Gallery Acting Up? Possible Layer Glitch!

Seeking assistance with a website issue. I have an index.php file set up with a sideshow script in the head that appears on all pages. Additionally, within the index.php file, there is a portfolio.html page that displays a gallery script when loaded. The p ...

What are the best ways to create image animations on top of other images using CSS or JavaScript?

Imagine if the first image is in black and white, while the second one is colored. How can we make the black and white image change to color after a timeout period, with an animation similar to loading progress bars? Is this achievable using CSS or JavaScr ...