Skip to content

Chain validator in conditional statement behavior different from regular judgement  #762

@gwh-cpnet

Description

@gwh-cpnet

In this case, body('b') is only required when body('root') === 'b'.

/* eslint-env mocha */
import chai from 'chai';
import 'chai/register-should';
import chaiHttp from 'chai-http';
import express from 'express';
import { body, validationResult, matchedData } from 'express-validator';

chai.use(chaiHttp);

describe('validate with regular methods', () => {
  let $http;

  before(() => {
    const app = express();
    app.use(express.json());
    app.post('/api',  [
      body('root').exists().isIn(['a', 'b']),
      body('b').if((val, { req }) => ['b'].includes(req.body.root)).exists(),
    ], (req, res) => {
      try {
        validationResult(req).throw();
        res.json(matchedData(req));
      } catch (e) {
        res.status(400).json(e.mapped());
      }
    });
    $http = chai.request(app).keepOpen();
  });

  it('should 200 with only root === a', async () => {
    const res = await $http.post('/api')
      .send({ root: 'a' });
    res.should.have.status(200);
    res.body.should.have.include({ root: 'a' });
  });

  it('should 400 with only root === b', async () => {
    const res = await $http.post('/api')
      .send({ root: 'b' });
    res.should.have.status(400);
    res.body.should.have.nested.include({
      'b.location': 'body',
    });
  });

  it('should 200 with root === b and b exists', async () => {
    const res = await $http.post('/api')
      .send({ root: 'b', b: 'b' });
    res.should.have.status(200);
    res.body.should.have.include({ root: 'b', b: 'b' });
  });

  after(() => $http.close());
});

describe('validate with chain methods', () => {
  let $http;

  before(() => {
    const app = express();
    app.use(express.json());
    app.post('/api',  [
      body('root').exists().isIn(['a', 'b']),
      body('b').if(body('root').isIn(['b'])).exists(),
    ], (req, res) => {
      try {
        validationResult(req).throw();
        res.json(matchedData(req));
      } catch (e) {
        res.status(400).json(e.mapped());
      }
    });
    $http = chai.request(app).keepOpen();
  });

  it('should 200 with only root === a', async () => {
    const res = await $http.post('/api')
      .send({ root: 'a' });
    res.should.have.status(200);
    res.body.should.have.include({ root: 'a' });
  });

  it('should 400 with only root === b', async () => {
    const res = await $http.post('/api')
      .send({ root: 'b' });
    res.should.have.status(400);
    res.body.should.have.nested.include({
      'b.location': 'body',
    });
  });

  it('should 200 with root === b and b exists', async () => {
    const res = await $http.post('/api')
      .send({ root: 'b', b: 'b' });
    res.should.have.status(200);
    res.body.should.have.include({ root: 'b', b: 'b' });
  });

  after(() => $http.close());
});

it would result:

  validate with regular methods
    ✓ should 200 with only root === a (57ms)
    ✓ should 400 with only root === b
    ✓ should 200 with root === b and b exists

  validate with chain methods
    1) should 200 with only root === a
    ✓ should 400 with only root === b
    ✓ should 200 with root === b and b exists


  5 passing (141ms)
  1 failing

as discussed in #658

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions