Search code examples
jsonvalidationsimple-schemameteor-collection2

Validation fails but insertion succeeds in Simple-Schema


So I'm using Simple-Schema/Collection2, and I thought my schema definitions were fine, as they caught malformed fields, and records inserted succesfully when properly formed.

However, I'm trying to run MySchemas.Schema.validate(document) and running into a validation error inside of a chai expect() block

Error: expected [Function] to not throw 'Error' but 'ClientError: fieldOne.fieldTwo.0 is not allowed by the schema' was thrown

The fields are failing on a subschema. The actual document is complicated, but here is the relevant skeleton.

const testSchema = new SimpleSchema({ 
        fieldOne: {
        ...,
        ...,
        fieldOne.fieldTwo: {
             type: subSchema,
        },
        ...,
    });

const subSchema = new SimpleSchema({
    fieldTwo: {
        type: Array,
    },
    "fieldTwo.$": {
        type: Object,
     }
     "fieldTwo.$.foo": {
          type: String,
     },
     ....,
};

Example Object:

{ fieldOne: {
    fieldTwo: [
        { foo: "bar"},
        { foo: "bar"},]
    }
}

Essentially, I have a subschema for an array of objects with some fields. The record inserts perfectly well, without returning an error, and is properly formatted, but it fails validation. Any idea why?


Solution

  • Ok, so it turns out that the key was how it succeeded on insert. Collection to automatically calls Schema.clean() on a document before insertion, and so it was doing some automatic formatting work. If I call Schema.clean(myObject) manually, the validation succeeds. Looking on the github page for simple-schema, this is something the creator is aware of, and looking to fix in a later verison.

    It also turns out the schema does not play nice with array subschemas, so I had to reformat my objects like so:

    const testSchema = new SimpleSchema({ 
        fieldOne: {
        ...,
        ...,
        fieldOne.fieldTwo: {
             type: Array,
        },
        "fieldOne.fieldTwo.$": {
             type: subSchema,
         }
        ...,
    });
    
    const subSchema = new SimpleSchema({
        foo: {
          type: String,
        },
        ....,
    };
    

    So instead of defining a field as of type "subSchema", and then in the subschema specifying an array, specify the field as an array, then indicate with $ the array element is of type subSchema