Testing fails because Validator extension 'exists'

Hello everyone,

First of all, thanks for taking the time to read me.

I’m doing some functional testing of an API that I’m working on. This API needed to implement, or well said, to extend the Validator in order to be able to use ‘exists’ as a validation rule when storing new records to a model through the POST route (store method in the controller).

This is one of my very first times with testing. Before using adonis test to test I used Postman to test my API. The problem I’m facing comes when I try to store a new record to my database that is related to another model. The error message I get is the following:

"message":"exists is not defined as a validation rule","field":"approach_id","validation":"ENGINE_EXCEPTION"

And this is the code of the test, which I changed slightly in order to explain my issue:

test('store a new approach feature', async ({ client }) => {
  const approach = await Approach.firstOrFail()
  
  const response = await client
                              .post('/approach-features')
                              .send({
                                name: 'A brand new approach feature',
                                approach_id: approach.id
                              })
                              .header('accept', 'application/json')
                              .end()

  response.assertStatus(200)
})

Just in case it to be necessary, the following one is the code of my the store validator:

class StoreApproachFeature {
  get rules () {
    return {
      name: 'required|accepted|min:3|max:255',
      approach_id: 'required|exists:approaches,id'
    }
  }

  get validateAll () {
    return true
  }
}

When I test this API route with Postman it doesn’t throw any error, but a response with a 200 OK status. However, in adonis testing, the test doesn’t pass because of the error I mentioned previously.

As I mentioned before, I already extended the Validator in order to use the exists validation.

Has somebody gone through the same issue? Have you found a solution to this?

Thanks again!

1 Like

Can you share how you have extended the validator and where exactly you have written that code?

Sure, I first created a file called hooks.js in the start directory: start/hooks.js, this file contains the following code:

const { hooks } = require("@adonisjs/ignitor")

hooks.before.httpServer(() => {
    const Validator = use('Validator')
    const Database = use('Database')
    
    const existsFn = async (data, field, message, args, get) => {
      const value = get(data, field)
      if (!value) {
        /**
         * skip validation if value is not defined. `required` rule
         * should take care of it.
        */
        return
      }
    
      const [table, column] = args
      const row = await Database.table(table).where(column, value).first()
    
      if (!row) {
        throw message
      }
    }
    Validator.extend('exists', existsFn)
})

I already found the solution to my issue. The problem was that I extended the validator at the before.httpServer hook event and I should have set it at before.providersBooted.

Thank you so much anyway for trying to help me.

1 Like