2

ValidationError: child "password" fails because ["password" is required] error is showing when run the test

I am using hapijs v17.2.3 and mongodb as back-end. I am trying to perform unit testing using the lab and code . This is my tests.js

'use strict';

const Hapi = require('hapi');
const application = require('../app');
const Code = require('code');
const Lab = require('lab');
const lab = exports.lab = Lab.script();
const getServer = function () {
    const server = new Hapi.Server();
    server.connection();
    return server.register(application)
        .then(() => server);
};

 ......
 ......
 ......


lab.test('Simply test the unique route', (done) => {

    const signUpData = {
        method: 'POST',
        url: '/signup',
        payload: {
            name: 'vulcan',
            password: 'vulcan@123',
            verify: 'vulcan@123',
            email: 'vulcan@gmail.com',
            username: 'vulcan',
            referredBy: 'admin@gg',
            dob: '12/08/1994'
        }
    };

    getServer()
        .then((server) => server.inject(signUpData))
        .then((response) => {

            Code.expect(response.statusCode).to.equal(200);
            const payload = JSON.parse(response.payload);
            Code.expect(payload).to.exist();

            done();
        })
        .catch(done);
});

when I am run the above code I got the following error

{ ValidationError: child "password" fails because ["password" is required]
    at Object.exports.process (/home/jeslin/projects/hapi/gamergully/node_modules/joi/lib/errors.js:196:19)
    at internals.Object._validateWithOptions (/home/jeslin/projects/hapi/gamergully/node_modules/joi/lib/types/any/index.js:675:31)
    at module.exports.internals.Any.root.validate (/home/jeslin/projects/hapi/gamergully/node_modules/joi/lib/index.js:146:23)
    at Object.internals.implementation [as cookie] (/home/jeslin/projects/hapi/gamergully/node_modules/hapi-auth-cookie/lib/index.js:95:25)
    at module.exports.internals.Auth._strategy (/home/jeslin/projects/hapi/gamergully/node_modules/hapi/lib/auth.js:52:47)
    at Object.register (/home/jeslin/projects/hapi/gamergully/lib/auth.js:6:116)
    at internals.Server.register (/home/jeslin/projects/hapi/gamergully/node_modules/hapi/lib/server.js:451:35)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:189:7)
    at Function.Module.runMain (module.js:696:11)
    at startup (bootstrap_node.js:204:16)
    at bootstrap_node.js:625:3
  isJoi: true,
  name: 'ValidationError',
  details:
   [ { message: '"password" is required',
       path: [Array],
       type: 'any.required',
       context: [Object] } ],
  _object:
   { password: undefined,
     cookie: 'GG-auth',
     isSecure: false,
     clearInvalid: true,
     ttl: 86400000,
     redirectTo: '/login',
     appendNext: true,
     redirectOnTry: false,
     isSameSite: 'Lax' },
  annotate: [Function] }

I can't figure out what the error is and I have wasted much time for solve it

this is my controller for signup which have all the validation with joi

exports.postForm = {
    description: 'Submit the signup page',
    tags: ['api'],
    notes: 'accepts name password verify and email',

    auth: {
        mode: 'try',
        strategy: 'session'
    },
    validate: {
        payload: {
            name: Joi.string().required(),
            password: Joi.string().min(4).max(20).required(),
            verify: Joi.string().required(),
            email: Joi.string().email().required(),
            username: Joi.string().min(3).max(20).required(),
            referredBy: Joi.any(),
            dob: Joi.date().required().label('Date of Birth')
        },
        failAction: (request, h, error) => {
            // Boom bad request
            console.log('Validation Failed');
            request.yar.flash('error', error.details[0].message.replace(/['"]+/g, ''));
            return h.redirect('/signup').takeover();
        }
    },
    handler: async (request, h) => {
        try {

            ................

            ................

            var user = {
                name: request.payload.name,
                password: reques67t.payload.password,
                email: request.payload.email,
                username: request.payload.username,
                referralName: request.payload.username + '@gg',
                emailConfirmationToken: uuidv1(),
                dob: request.payload.dob
            };
            // Then save the user
            let data = await signupHelper.signUpUser(user, request);
            if (data.statusCode === 200) {

                if (request.payload.referredBy) {

                    request.yar.flash('success', 'Account created, Please Login');

                }
            } else {
                request.yar.flash('error', data.message);
                return h.redirect('/signup');
            }
        } catch (error) {
            console.log('error occired = ', error);

            return h.redirect('/signup');
        }
    }
};
jeslin
  • 21
  • 5
  • Could you please share your route and validation detail?. This information is not enough to inspect your problem. Obviously it is related your payload validation but we need to see it. – metoikos Jan 16 '19 at 12:28
  • I have added my controller that performs validations over the submitted data @metoikos – jeslin Jan 16 '19 at 13:18

1 Answers1

2

I've created a simple test suit and it passed. I couldn't spot the problem on your joi validation.

const Lab = require('lab');
const lab = exports.lab = Lab.script();
const describe = lab.describe;
const it = lab.it;
const expect = require('code').expect;
const Joi = require('joi');
describe('Validator accountSetupToken checks', () => {

    let validation = Joi.object().keys({
        name: Joi.string().required(),
        password: Joi.string().min(4).max(20).required(),
        verify: Joi.string().required(),
        email: Joi.string().email().required(),
        username: Joi.string().min(3).max(20).required(),
        referredBy: Joi.any(),
        dob: Joi.date().required().label('Date of Birth')
    });

    it('Reject invalid payload', async () => {
        const result = Joi.validate({
            name: 'vulcan',
            password: 'vulcan@123',
            verify: 'vulcan@123',
            email: 'vulcan@gmail.com',
            username: 'vulcan',
            referredBy: 'admin@gg',
            dob: '12/08/1994'
        }, validation, {abortEarly: false});
        expect(result.error).to.null();
        expect(result.error).to.not.exist();
    });

});

Here is the result.

> lab --coverage-exclude test/data -m 5000n -a code -P "simple" "test/validators"


  .

1 tests complete
Test duration: 13 ms
Assertions count: 2 (verbosity: 2.00)
No global variable leaks detected

But then i saw in your exception message this

details:
   [ { message: '"password" is required',
       path: [Array],
       type: 'any.required',
       context: [Object] } ],
  _object:
   { password: undefined,
     cookie: 'GG-auth',
     isSecure: false,
     clearInvalid: true,
     ttl: 86400000,
     redirectTo: '/login',
     appendNext: true,
     redirectOnTry: false,
     isSameSite: 'Lax' },
  annotate: [Function] }

The password field seems undefined, are you sure that you are making a valid request to your route?

metoikos
  • 1,315
  • 11
  • 18