Reputation: 4701
I'm working on a HapiJS api and I've defined a plugin that registers the Vision plugin and configures a rendering engine (ejs). But when I try and respond to the request by rendering a view I get the error
AssertionError [ERR_ASSERTION]: Missing views manager
If I register the Vision plugin and its config somewhere outside the plugin the tests pass but my expectation is that I should be able to encapsulate this logic in a plugin.
// plugin
const ejs = require('ejs');
const Vision = require('vision');
module.exports = {
name: 'views',
version: '0.0.1',
register: async (server, { path }) => {
await server.register(Vision);
server.views({
engines: { ejs },
path,
});
},
};
The handler code is
// api
server.route({
path: '/korin/songs',
method: 'GET',
handler: async (request, h) => {
try {
const acceptType = getMediaType(request.headers.accept);
const data = await server.methods.getTopTracks({
getTopTracks,
lastfmApi,
});
if (acceptType === 'text/html') {
return h.view('index'); // <-- this errors
}
return data;
} catch (error) {
console.warn(error);
}
},
});
The error is generated by a failing test which is
suite('render content', () => {
test.only(`given text/html page should respond with header and footer`, async () => {
const { server } = await setup();
const { payload } = await server.inject({
method: 'GET',
url: '/korin/songs',
headers: {
accept: 'text/html',
},
});
expect(payload).to.contain(`<header>`);
expect(payload).to.contain(`<footer>`);
});
});
// test setup
const setup = async options => {
const server = new Hapi.Server();
// truncated for brevity
await server.register({
plugin: require('../../server/api'),
options: {
...defaults,
...options,
},
});
await server.register({
plugin: require('../../server/views'),
options: { path: path.join(__dirname, '../views/templates') },
});
return {
server
};
};
Is there something I'm missing? I've tried running a console.log and the code seems to be running in the right order but failing anyway.
Upvotes: 0
Views: 492
Reputation: 3321
There is an old thread on GitHub about this. TL;DR: the reference to server
passed to the plugin when registering is slightly not the same as the "root" server
. Some difference about realms, apparently still an issue.
Indeed: in the plugin, server.getViewsManager()
(decorated by vision
) after registration of vision
and server.views
will show something, whereas the same call in your route (so, after plugin registration) will show null
. So much for "references".
I just tried a similar structure to you, got the same error, and this thread pointed me to a workaround: when registering your views
plugin, just pass along a reference to the "real" server
in the options.
// plugin
const ejs = require('ejs');
const Vision = require('vision');
module.exports = {
name: 'views',
version: '0.0.1',
register: async (server, { path, realServer }) => { // <= added option
await realServer.register(Vision); // <= replaced server w/ realServer
realServer.views({ // <= replaced server w/ realServer
engines: { ejs },
path,
});
},
};
// test setup
// ...
const server = new Hapi.Server();
// ...
await server.register({
plugin: require('../../server/views'),
options: {
path: path.join(__dirname, '../views/templates'),
realServer: server // <= added option
}
});
And, obviously, have the same options everywhere you register this plugin.
Upvotes: 1