rf guy
rf guy

Reputation: 439

Unable to return a thrown error to calling API

I have an API that simply logs in a user. I am testing out certain test cases for when the username or password are invalid. For some reason, I can't detect the thrown error is not being returned to the API.

The API looks like this:

// routes/users.js
router.post('/users/login', async (req, res) => {
  //Login a registered user
  try {
    const { email, password } = req.body
    const user = await User.findByCredentials(email, password)
    if (!user) {
      return res.status(401).send({ error: 'Login failed! Check authentication credentials' })
    }
    const token = await user.generateAuthToken()
    res.send({ user, token })
  } catch (error) {
    res.status(400).send(error)
  }
})

And here is the method in the model that should return the error. Using, the debugger I can step through the code and it looks like all the statements are being executed but the error is returned as an empty object as such, Error: [object Object]

// models/user.models.js
userSchema.statics.findByCredentials = async (email, password) => {
    // Search for a user by email and password.
    const user = await User.findOne({ email} )
    if (!user) {
        throw new Error({ error: 'Invalid user name' })
    }
    const isPasswordMatch = await bcrypt.compare(password, user.password)
    if (!isPasswordMatch) {
        throw new Error({ error: 'Invalid password' })
    }
    return user
}

Upvotes: 0

Views: 42

Answers (2)

rf guy
rf guy

Reputation: 439

So this seems to do the trick. Not sure why this works and the original approach did not. The difference is basically a user defined function handling the error message.

    userSchema.statics.findByCredentials = async (email, password) => {
        // Search for a user by email and password.
        const user = await User.findOne({ email })

        function myError(message) {
            this.message = message
        }

        myError.prototype = new Error()

        if (!user) {
            throw new myError('Username provided is incorrect, please try again')
        }
        const isPasswordMatch = await bcrypt.compare(password, user.password)
        if (!isPasswordMatch) {
            throw new myError('Password provided is incorrect, please try again')
        }
        return user
    }

Upvotes: 0

DevKyle
DevKyle

Reputation: 1091

Looking at the code, I don't think (!user) should be considered an error, as the query just simply found no user record that matches the query condition. As far as handling the real error, try below:

If you want to test this, try:

User.findOne({email}, function(err, user) {
    if (err) { 

      //true error

    } else {

      if (!user) {
         //this is when no user matching the email was found
      } else {
         //user matching email was found
      }

    }

}

Because there was no runtime error, there would be no error object in the case the no user was found:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error

Upvotes: 1

Related Questions