Fastify CLI decorators undefined

579 views Asked by At

I'm using fastify-cli for building my server application.

For testing I want to generate some test JWTs. Therefore I want to use the sign method of the fastify-jwt plugin.

If I run the application with fastify start -l info ./src/app.js everything works as expected and I can access the decorators.

But in the testing setup I get an error that the jwt decorator is undefined. It seems that the decorators are not exposed and I just can't find any error. For the tests I use node-tap with this command: tap \"test/**/*.test.js\" --reporter=list

app.js

import { dirname, join } from 'path'
import autoload from '@fastify/autoload'
import { fileURLToPath } from 'url'
import jwt from '@fastify/jwt'

export const options = {
  ignoreTrailingSlash: true,
  logger: true
}

export default async (fastify, opts) => {
  await fastify.register(jwt, {
    secret: process.env.JWT_SECRET
  })

  // autoload plugins and routes
  await fastify.register(autoload, {
    dir: join(dirname(fileURLToPath(import.meta.url)), 'plugins'),
    options: Object.assign({}, opts),
    forceESM: true,
  })

  await fastify.register(autoload, {
    dir: join(dirname(fileURLToPath(import.meta.url)), 'routes'),
    options: Object.assign({}, opts),
    forceESM: true
  })
}

helper.js

import { fileURLToPath } from 'url'
import helper from 'fastify-cli/helper.js'
import path from 'path'

// config for testing
export const config = () => {
  return {}
}

export const build = async (t) => {
  const argv = [
    path.join(path.dirname(fileURLToPath(import.meta.url)), '..', 'src', 'app.js')
  ]

  const app = await helper.build(argv, config())

  t.teardown(app.close.bind(app))

  return app
}

root.test.js

import { auth, build } from '../helper.js'
import { test } from 'tap'

test('requests the "/" route', async t => {
  t.plan(1)

  const app = await build(t)

  const token = app.jwt.sign({ ... }) //-> jwt is undefined

  const res = await app.inject({
    method: 'GET',
    url: '/'
  })

  t.equal(res.statusCode, 200, 'returns a status code of 200')
})
1

There are 1 answers

0
Manuel Spigolon On BEST ANSWER

The issue is that your application diagram looks like this:

and when you write const app = await build(t) the app variable points to Root Context, but Your app.js contains the jwt decorator.

To solve it, you need just to wrap you app.js file with the fastify-plugin because it breaks the encapsulation:

import fp from 'fastify-plugin'

export default fp(async (fastify, opts) => { ... })

Note: you can visualize this structure by using fastify-overview (and the fastify-overview-ui plugin together:

structure