hapijs / joi

The most powerful data validation library for JS
Other
20.95k stars 1.51k forks source link

Unable to validate nested arrays of objects #2958

Closed logonv closed 1 year ago

logonv commented 1 year ago

Support plan

Context

We are trying to use JOI with a nextJs 13.4.4 app with node 18.6.0. ​ The same issue can be reproduced on https://npm.runkit.com/joi and that's what's described below.

What are you trying to achieve or the steps to reproduce?

Reproduction can be found here https://runkit.com/logan-runkit/joi-bug

var Joi = require('joi')
​
// episodes
const episodeSchema = Joi.object({
  id: Joi.string().required(),
  name: Joi.string(),
})
​
// seasons
const seasonSchema = Joi.object({
  id: Joi.string().required(),
  seasonNumber: Joi.number(),
  episodes: Joi.array().items(episodeSchema).required(),
})
​
const schema = Joi.object({
  id: Joi.string().required(),
  format: Joi.string().equal(...['movie', 'series']).required(),
  status: Joi.string().equal(...['fail', 'pass']).required(),
  seasons: Joi.when('format', {
    is: 'series',
    then: Joi.array().items(seasonSchema),
    otherwise: Joi.forbidden(),
  }),
})
  .when(Joi.object({
    format: 'series',
    status: 'pass',
  }),
  {
    then: Joi.object({
      seasons: Joi.array().items(
        seasonSchema.keys(
          { episodes: Joi.array().items(episodeSchema).required().min(5) },
        ),
      ).min(2).required(),
    }),
  })
​
const { value, error } = schema.validate({
  id: 'a', format: 'series', status: 'pass', seasons: [{ id: 'b', episodes: [] }],
})
​
// Above should result in an error as the format is 'series', the status is 'pass' but episodes is an array with length 0 and there is only 1 season
​
console.log('value', value)
console.log('error', error)

What was the result you got?

Validation passes

What result did you expect?

Validation should fail

Marsup commented 1 year ago

Hi,

Thanks for the detailed example. I can see 2 "mistakes" in this schema:

Knowing all of this, I would write your schema like that: https://runkit.com/embed/m8hwqfjgjg5c I think it passes all your scenarios, or at least it's a good starting point.

logonv commented 1 year ago

Apologies for the late reply, thanks for your help!