Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Array.includes() does not support more than 1 type #133

Closed
runrightfast opened this issue Oct 19, 2013 · 3 comments
Closed

Array.includes() does not support more than 1 type #133

runrightfast opened this issue Oct 19, 2013 · 3 comments
Assignees
Milestone

Comments

@runrightfast
Copy link

Below is a test case that produces the issue. In other words, it only supports homogeneous arrays - not heterogeneous arrays. However, according to the docs, it should be able to support heterogeneous arrays.

describe.only('Joi Array Type', function() {
        it('can validate that its elements only include certain types', function() {
            var schema = {
                array : joi.types.Array().includes(joi.types.String().min(5), joi.types.Number().min(0))
            };

            var obj = {
                array : [ '12345' ]
            };
            var err = joi.validate(obj, schema);
            if (err) {
                throw new Error(JSON.stringify(obj) + '\n' + err);
            }

            obj = {
                array : [ '1234' ]
            };
            err = joi.validate(obj, schema);
            if (!err) {
                throw new Error(JSON.stringify(obj) + '\n Should be invalid because it contains a String with length < 5');
            }

            obj = {
                array : [ 3 ]
            };
            err = joi.validate(obj, schema);
            if (err) {
                throw new Error(JSON.stringify(obj) + '\n' + err);
            }

            obj = {
                array : [ '12345', 3 ]
            };
            err = joi.validate(obj, schema);
            if (err) {
                throw new Error(JSON.stringify(obj) + '\n' + err);
            }

        });

    });
@papajuans
Copy link

Joi will automatically try to do type conversions for you: https://github.com/spumko/joi#skip-conversions

@runrightfast
Copy link
Author

Right, but that is not the issue. The issue is that Array.includes() isn't working as expected. For example, the following schema doesn't validate properly (but it should) against the objects listed below :

var schema = { array : joi.types.Array().includes(joi.types.String().min(5), joi.types.Number().min(0)) };

The above schema reads that the object can contain an 'array' key whose type is an Array which can include array values of type String (with min length of 5 chars) or numbers >= 0.

With the above schema, I expect the the following objects to be valid, but Joi says that are invalid against the above schema:

{"array":[3]} : Error: the value of array must be a string, the value of array must be at least 5 characters long

{"array":["12345",3]} : Error: the value of array must be a string, the value of array must be at least 5 characters long

I wrote another test, which implies that when (at least) when Number and String are included together, Number is being ignored:

it.only('can validate that its elements only include certain types', function(done) {
var schema1 = {
array : joi.types.Array().includes(joi.types.String().min(5), joi.types.Number().min(0))
};

var schema2 = {
    array : joi.types.Array().includes(joi.types.Number().min(0), joi.types.String().min(5))
};

var errors = [];

var obj = {
    array : [ '12345' ]
};
var err = joi.validate(obj, schema1);
if (err) {
    errors.push(new Error(JSON.stringify(obj) + ' : schema1 : ' + err));
}
err = joi.validate(obj, schema2);
if (err) {
    errors.push(new Error(JSON.stringify(obj) + ' : schema2 : ' + err));
}

obj = {
    array : [ '1234' ]
};
err = joi.validate(obj, schema1);
if (!err) {
    errors.push(new Error(JSON.stringify(obj) + ' : schema1 : Should be invalid because it contains a String with length < 5'));
}
err = joi.validate(obj, schema2);
if (!err) {
    errors.push(new Error(JSON.stringify(obj) + ' : schema2 : Should be invalid because it contains a String with length < 5'));
}

obj = {
    array : [ 3 ]
};
err = joi.validate(obj, schema1);
if (err) {
    errors.push(new Error(JSON.stringify(obj) + ' : schema1 : ' + err));
}
err = joi.validate(obj, schema2);
if (err) {
    errors.push(new Error(JSON.stringify(obj) + ' : schema2 : ' + err));
}

obj = {
    array : [ '12345', 3 ]
};
err = joi.validate(obj, schema1);
if (err) {
    errors.push(new Error(JSON.stringify(obj) + ' : schema1 : ' + err));
}
err = joi.validate(obj, schema2);
if (err) {
    errors.push(new Error(JSON.stringify(obj) + ' : schema2 : ' + err));
}

if (errors.length > 0) {
    done(new Error(errors.join('\n')));
} else {
    done();
}

});

The test output is:

  1. Validator Domain Joi Array Type can validate that its elements only include certain types:
    Error: Error: {"array":[3]} : schema1 : Error: the value of array must be a string, the value of array must be at least 5 characters long
    Error: {"array":[3]} : schema2 : Error: the value of array must be a string, the value of array must be at least 5 characters long
    Error: {"array":["12345",3]} : schema1 : Error: the value of array must be a string, the value of array must be at least 5 characters long
    Error: {"array":["12345",3]} : schema2 : Error: the value of array must be a string, the value of array must be at least 5 characters long

@runrightfast
Copy link
Author

The issue is that validation works at the type level, but not via Joi.validate

here's one of Joi's tests from array.js:

it('should validate array of mixed Numbers & Strings', function (done) {

            verifyBehavior(A().includes(N(), S()), [
                [
                    [1, 2, 3],
                    true
                ],
                [
                    [50, 100, 1000],
                    true
                ],
                [
                    [1, 'a', 5, 10],
                    true
                ],
                [
                    ['walmart', 'everydaylowprices', 5000],
                    true
                ]
            ], done);
        });

It passes just fine.

here's another version of the test, except that now the array types are part of an object schema:

it.skip('should validate array of mixed Numbers & Strings', function() {
var A = joi.types.Array, N = joi.types.Number, S = joi.types.String;

        var schema = {
            a : A().includes(N(), S())
        };
        var error;
        error = joi.validate({
            a : [ 1, 2, 3 ]
        }, schema);
        if (error) {
            throw new Error('[ 1, 2, 3 ]: ' + error);
        }

        error = joi.validate({
            a : [ 50, 100, 1000 ]
        }, schema);
        if (error) {
            throw new Error('[ 50, 100, 1000 ]:' + error);
        }

        error = joi.validate({
            a : [ 1, 'a', 5, 10 ]
        }, schema);
        if (error) {
            throw new Error("[ 1, 'a', 5, 10 ]: " + error);
        }

        error = joi.validate({
            a : [ 'walmart', 'everydaylowprices', 5000 ]
        }, schema);
        if (error) {
            throw new Error("[ 'walmart', 'everydaylowprices', 5000 ]: " + error);
        }

    });

The test fails with the following error:

  1. Validator Domain Joi Array Type should validate array of mixed Numbers & Strings:
    Error: [ 1, 2, 3 ]: Error: the value of a must be a string, the value of a must be a string, the value of a must be a string

@ghost ghost assigned hueniverse Nov 4, 2013
@lock lock bot locked as resolved and limited conversation to collaborators Jan 11, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants