Reputation: 1
I'm encountering a 500 Internal Server Error when running a Jest test for my Express app using Supertest, but the app works fine when run normally (e.g., in a browser or Postman). I suspect the issue lies in the test setup, but I'm unable to pinpoint the exact cause.
This is the error message when running npm test
$ npm test
> [email protected] test
> cross-env NODE_OPTIONS=--experimental-vm-modules jest
(node:16440) ExperimentalWarning: VM Modules is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
FAIL tests/movies.test.js
× Home page shows list of movies and navigation links (31 ms)
● Home page shows list of movies and navigation links
expected 200 "OK", got 500 "Internal Server Error"
33 | );
34 |
> 35 | const response = await request(app).get('/').expect('Content-Type', /html/).expect(200);
| ^
36 |
37 | expect(response.text).toMatch('Pulp Fiction');
38 | expect(response.text).toMatch('Fire Walk With Me');
at Object.expect (tests/movies.test.js:35:79)
----
at Test._assertStatus (node_modules/supertest/lib/test.js:252:14)
at node_modules/supertest/lib/test.js:308:13
at Test._assertFunction (node_modules/supertest/lib/test.js:285:13)
at Test.assert (node_modules/supertest/lib/test.js:164:23)
at Server.localAssert (node_modules/supertest/lib/test.js:120:14)
Test Suites: 1 failed, 1 total Tests: 1 failed, 1 total Snapshots: 0 total Time: 0.617 s, estimated 1 s Ran all test suites.
I'll provide some of my code movies.test.js
import { expect, test } from '@jest/globals';
import request from 'supertest';
import { fetchAllMovies, fetchMovie } from '../src/js/server/fetchMovies.js';
import startApp from '../src/js/server/app.js';
test('Home page shows list of movies and navigation links', async () => {
const app = startApp(
{
fetchMovie: async () => ({
id: 1,
title: 'Pulp Fiction',
}),
fetchAllMovies: async () => [
{ id: 1, title: 'Pulp Fiction' },
{ id: 2, title: 'Fire Walk With Me' },
{ id: 3, title: 'Isle of Dogs' },
],
},
{
navLinks: async () => ({
headerData: [
{ label: 'BILJETTER', id: 'biljetter', link: '#' },
{ label: 'EVENEMANG', id: 'evenemang', link: '#' },
{ label: 'FILMER', id: 'filmer', link: 'movies' },
],
footerSection1: [
{ label: 'OM KINO', link: 'about' },
{ label: 'FRÅGOR SVAR', link: '#' },
{ label: 'KONTAKTA OSS', link: '#' },
],
}),
}
);
const response = await request(app).get('/').expect('Content-Type', /html/).expect(200);
expect(response.text).toMatch('Pulp Fiction');
expect(response.text).toMatch('Fire Walk With Me');
expect(response.text).toMatch('Isle of Dogs');
expect(response.text).toMatch('BILJETTER');
expect(response.text).toMatch('EVENEMANG');
expect(response.text).toMatch('FILMER');
});
server.js
import startApp from './src/js/server/app.js';
import { fetchAllMovies, fetchMovie } from './src/js/server/fetchMovies.js';
import navLinks from './src/js/server/navLinks.js';
const api = {
fetchMovie,
fetchAllMovies,
};
const nav = {
navLinks,
};
const app = startApp(api, nav);
const PORT = process.env.PORT || 5080;
app.listen(5080, () => {
console.log(`Server running on http://localhost:${PORT}`);
});
app.js
import express from 'express';
import ejs from 'ejs';
import { marked } from 'marked';
function startApp(api, nav) {
const app = express();
app.locals.formatMarkdown = (text) => marked(text);
app.set('view engine', 'ejs');
app.get('/', async (req, res) => {
const linkData = await nav.navLinks();
const moviesData = await api.fetchAllMovies();
res.render('pages/index', { moviesData, ...linkData });
});
app.get('/movies', async (req, res) => {
const linkData = await nav.navLinks();
const moviesData = await api.fetchAllMovies();
res.render('pages/allMovies', { moviesData, ...linkData });
});
app.get('/movie/:movieId', async (req, res) => {
const linkData = await nav.navLinks();
const movieData = await api.fetchMovie(req.params.movieId);
res.render('pages/movie', { movieData, ...linkData });
});
app.use('/static', express.static('./static'));
app.use((req, res) => {
const linkData = nav.navLinks();
res.status(404).render('pages/error', { message: 'Page not found', ...linkData });
});
return app;
}
export default startApp;
navLinks.js
const headerData = [
{
label: 'BILJETTER',
id: 'biljetter',
link: '#',
},
{
label: 'EVENEMANG',
id: 'evenemang',
link: '#',
},
{
label: 'FILMER',
id: 'filmer',
link: 'movies',
},
{
label: 'MEDLEMSKAP',
id: 'medlemskap',
link: '#',
},
{
label: 'OM OSS',
id: 'omoss',
link: 'about',
},
];
const footerSection1 = [
{ label: 'OM KINO', link: 'about' },
{ label: 'FRÅGOR SVAR', link: '#' },
{ label: 'KONTAKTA OSS', link: '#' },
];
const footerSection2 = [
{ label: 'PRESENTKORT', link: '#' },
{ label: 'TILLGÄNGLIGHET', link: '#' },
{ label: 'MEDLEMSKAP', link: '#' },
{ label: 'BISTRO-BIO', link: '#' },
{ label: 'EVENEMANG', link: '#' },
];
const footerSection3 = [
{ label: 'FACEBOOK', link: '#' },
{ label: 'INSTAGRAM', link: '#' },
];
export default function navLinks() {
return {
headerData,
footerSection1,
footerSection2,
footerSection3,
};
}
Upvotes: 0
Views: 71
Reputation: 1
There are many possible reasons you might be getting an Internal Server Error:
....other errors due to the specificity of the modules you imported
I am not exactly sure of the answer, I hope the above tips head you in the right direction. Please provide as many details as possible.
A good practice in your case when facing such a bug is to decouple all the things you are trying to use all at once and test them individually. This will help you find where your code went wrong.
Some tips to gain visibility:
const linkData = await nav.navLinks();
const moviesData = await api.fetchAllMovies();
outside of the individual routes. You can get the linkData and moviesData in the app. That way your /* routes only have to return html. Only one purpose that you can test and validate that it's not the source of the problem.
Use the same fetchMovies and fetchAllMovies and navlinks in your app and in your tests. If they are different, that might be the reason one way it's running ok and the other it's failing.
Separate your logic functions from your routes and test them one by one by logging in the app what they get.
Test your render function without the logic with test html
Make sure 'Content-Type', /html/ is correct
Change to different modules that do the same thing for you, see what error you get.
Please get back to me at any stage with more information. I would be happy to help further.
Best
Upvotes: 0
Reputation: 1
The issue stemmed from missing data in the test that was required for rendering the footer section in the EJS template. Specifically, the footerSection2 and footerSection3 data were not provided in the mock data for the test. This resulted in forEach loops inside my partials (footer) not rendering correctly during the GET request.
Upvotes: 0