vendredi 21 février 2020

How to test server api endpoints using scaffolded Nuxt app with Express?

When scaffolding a Nuxt app using create-nuxt-app, there's an option to add both a backend server and a testing framework.

I've chosen Express as by backend framework, and Jest as my testing framework, which allows me to runs tests with Jest perfectly. However, there's no server-side test example available in which you can test API end points.

I've create an api endpoint /api/threads and tried testing it with something like this:

const request = require('supertest')
const app = require('../app')

describe('GET /api/threads', () => {
  it('should return 200', async () => {
    await request(app)
      .get(`/api/threads`)
      .expect(200)
  })
})

But am returned with the error: VueRenderer is not a constructor

I also made sure to export app.js, which currently looks like:

require('dotenv-safe').load()
const path = require('path')
const express = require('express')
const consola = require('consola')
const bodyParser = require('body-parser')
const bcrypt = require('bcryptjs')
const session = require('express-session')
const passport = require('passport')
const LocalStrategy = require('passport-local').Strategy
const SequelizeStore = require('connect-session-sequelize')(session.Store)
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY)
const { Nuxt, Builder } = require('nuxt')

// Import and Set Nuxt.js options
const config = require('../nuxt.config.js')
const sequelize = require('./sequelize')
const models = require('./models')
const router = require('./router')
const controllers = require('./controllers')

const app = express()

config.dev = !(
  process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'test'
)

function addSessions() {
  const sessionStorage = new SequelizeStore({
    db: sequelize
  })

  app.use(
    session({
      secret: process.env.SESSION_SECRET,
      resave: false,
      saveUninitialized: false,
      store: sessionStorage
    })
  )
  app.use(passport.initialize())
  app.use(passport.session())
  sessionStorage.sync()
}

function addLocalStrategy() {
  passport.use(
    new LocalStrategy(
      {
        usernameField: 'email',
        passwordField: 'password'
      },
      async (email, password, done) => {
        try {
          let user = await models.User.findOne({ where: { email } })

          if (!user)
            return done(null, false, {
              message: 'Incorrect email.'
            })

          user = user.toJSON()

          const passValid = await bcrypt.compare(
            password,
            user.password.toString('utf8')
          )
          if (passValid === false)
            return done(null, false, {
              message: 'Incorrect password.'
            })

          if (user && user.subscriptionId) {
            const subscription = await stripe.subscriptions.retrieve(
              user.subscriptionId
            )
            user.subscriptionStatus = subscription.status
          }

          return done(null, user)
        } catch (err) {
          console.log(err)
          return done(err)
        }
      }
    )
  )

  passport.serializeUser((user, done) => {
    done(null, user.id)
  })

  passport.deserializeUser(async (id, done) => {
    try {
      const user = await models.User.findById(id)

      done(null, user)
    } catch (err) {
      throw new Error(err)
    }
  })
}

async function start() {
  try {
    const nuxt = new Nuxt(config)
    const { host, port } = nuxt.options.server

    // Build only in dev mode
    if (config.dev) {
      const builder = new Builder(nuxt)
      await builder.build()
    } else {
      await nuxt.ready()
    }

    app.use(bodyParser.json())
    app.use(bodyParser.urlencoded({ extended: false }))

    addSessions()
    addLocalStrategy()
    app.use('/', router)
    app.use('/private', controllers.User.authenticate)
    app.use('/private', express.static(path.join(__dirname, 'private')))

    // Give nuxt middleware to express
    app.use(nuxt.render)

    app.listen(port, host)
    consola.ready({
      message: `Server listening on http://${host}:${port}`,
      badge: true
    })
  } catch (err) {
    throw new Error(err)
  }
}
start()

module.export = app

Essentially it's the scaffolded server/app.js, but with code for sessions and authentication.

Any ideas on how to successfully receive a 200 response when hitting a backend API endpoint with a Nuxt / Express combo?

Aucun commentaire:

Enregistrer un commentaire