Testing Login Route

I’m used to work with jest, but I’m working on a personal project and I’m giving adonis a fair shot to build an API. I’m trying to test the login route and here is my code.

test('that user can login', async ({ client }) => {
  const user = await User.create({
      email: 'test@test.com',
      password: await Hash.make('test,.123')
  })
  const response = await client
    .post('login')
    .send({
      email: 'test@test.com',
      password: 'test,.123'
    })
    .end()
  console.log(response)
})

and I’m getting back

status: 401,
text: 'E_USER_NOT_FOUND: Cannot find user with email as undefined',

How do I test the login route?

FYI

I have another test where I’m testing the profile route and that one does work. Here is the code.

test('that user/profile route can be access', async ({ client }) => {
  const user  = await User.create({
      email: 'test@test.com',
      password: await Hash.make('test,.123')
  })

  const response = await client
    .get('user/profile')
    .loginVia(user, 'jwt')
    .end()

  response.assertStatus(200)
})

Hi @diazgilberto !

Can you share your route / controller code. Test seems to be fine at first glance.

class UserController {
  async login({ auth, request, response }) {
    const { uid, password } = request.all()
    const authUser = await auth.attempt(uid, password)
    response.send(authUser)
  }

  async profile({ auth, response }) {
    response.send(auth.user)
  }
}

The route…

Route.post('login', 'UserController.login')
  .middleware('guest')

Hi!

const { uid, password } = request.all()
Here you take uid

But in test you send email and password :wink:

1 Like

I changed everything, in the UserController and in the test to be email instead of uid and I’m getting the same error. To confirm that the user got create I `console.log(user) after its creation and indeed I get the user back…

    email: 'test@test.com',
    password: '$2a$10$RLB7icFIp3L197Npe6sEw.3O5SpT2dRvqhFsxySF9pzZx5FF9T1Zi',
    created_at: '2019-07-22 18:40:19',
    updated_at: '2019-07-22 18:40:19',
    id: 1

What could be wrong with this test?

What fields you have in config/auth.js for your chosen provider?

I mean uid and password.

uid: 'email',
password: 'password'

Is error message still same: Cannot find user with email as undefined ?

Ok, changing all keys to uid as in the config/auth.sj I get a different error…

      status: 401,
      text: 'E_PASSWORD_MISMATCH: Cannot verify user password',
      method: 'POST',
      path: '/login'

So it seems that the test does hit the route but can’t unhash the password?

Can you share how do you hash the user password?

test('that user can login', async ({ client }) => {
  const user = await User.create({
      email: 'test@test.com',
      password: await Hash.make('test,.123')
  })
  const response = await client
    .post('login')
    .send({
      uid: 'test@test.com',
      password: 'test,.123'
    })
    .end()
  console.log(response)
})

Hi,

your User Model not use hook hash?

//App/Models/User.js

  /**
     * A hook to hash the user password before saving
     * it to the database.
     */
    this.addHook('beforeSave', async userInstance => {
      if (userInstance.dirty.password) {
        userInstance.password = await Hash.make(userInstance.password);
      }
    });

If yes, you dont need password: await Hash.make('test,.123')

hope this will help :slightly_smiling_face:

If I use…

const user = beforeEach(async () => {
  await User.create({
    email: 'test@test.com',
    password: 'test,.123'
  })
})

afterEach(async () => {
  await User.truncate()
})

I get Error: SQLITE_CONSTRAINT: UNIQUE constraint failed: users.email

I have two tests, the firs test passes and the second one fails with that error. Looks like User.truncate() is not reseting the database.

If I create the user inside each test and truncate inside each test, both test passes.

'use strict'

const { afterEach, beforeEach, test, trait } = use('Test/Suite')('User Controller')
const User = use('App/Models/User')
const Database = use('Database')

trait('Test/ApiClient')
trait('Auth/Client')
trait('DatabaseTransactions')

const user = beforeEach(async () => {
  await User.create({
    email: 'test@test.com',
    password: 'test,.123'
  })
})

afterEach(async () => {
  await User.truncate()
})

test('that user can login', async ({ client }) => {
  // await User.create({
  //   email: 'test@test.com',
  //   password: 'test,.123'
  // })
  const response = await client
    .post('login')
    .send({
      email: 'test@test.com',
      password: 'test,.123'
    })
    .end()
    response.assertStatus(200)
    // await User.truncate()
})

test('that user/profile route can be access', async ({ client }) => {
  // const user = await User.create({
  //   email: 'test@test.com',
  //   password: 'test,.123'
  // })
  const response = await client
    .get('user/profile')
    .loginVia(user, 'jwt')
    .end()

  response.assertStatus(200)
})

I believe you are mixing too many concerns in a single thread. I am not even sure, if the password hashing thing worked for you or not.

Please create a dedicated focused thread for a single use case, so that people searching for the title in the future can get some help

1 Like