<commit_before>var DbContext = require('./setup'),
    expect = require('chai').expect,
    ValidationError = require('../').ValidationError;

describe('validator', function () {
    before(function () {
        return DbContext.knex.schema.dropTableIfExists('obj')
            .then(function () {
                return DbContext.knex.schema.createTable('obj', function (table) {
                    table.increments('id').primary();
                    table.string('name').notNullable().unique();
                    table.integer('quantity');
                    table.string('str');
                });
            });
    });

    var Obj = DbContext.Model.extend({
        tableName: 'obj',
        validation: {
            'name': [
                function (value, context) {
                    if (!this.isNew()) {
                        this.unset('name');
                        return context.yield();
                    }
                },
                { validator: 'notEmpty', message: 'name is required' },
                { validator: 'matches', args: [/^[a-z0-9 ]+$/i], message: 'name format incorrect'},
                function (value, context) {
                    return DbContext.knex('obj').where('name', value).count('* AS count')
                        .then(function (results) {
                            if (results[0].count > 0)
                                context.addError('name already exists');
                        });
                }
            ],
            'quantity': [
                { validator: 'isInt', message: 'quantity must be integer' }
            ]
        }
    });

    var saved;

    it('should fail: empty object', function () {
        return Obj.forge({}).save()
            .then(function () {
                throw new Error('obj should not be saved');
            })
            .catch(ValidationError, function (e) {
                expect(e.errors).to.have.keys(['name', 'quantity']);
                expect(e.errors.name).to.have.length(2);
                expect(e.errors.name).to.deep.equal(['name is required', 'name format incorrect']);
                expect(e.errors.quantity).to.have.length(1);
                expect(e.errors.quantity[0]).to.equal('quantity must be integer');
            });
    });

    it('should fail: name exists', function () {
        return Obj.forge({ name: 'Name', quantity: 1, str: 'secret' }).save()
            .then(function (model) {
                saved = model;
                return Obj.forge({ name: 'Name', quantity: 1}).save()
                    .then(function () {
                        throw new Error('obj should not be saved');
                    })
                    .catch(ValidationError, function (e) {
                        expect(e.errors).to.have.keys(['name']);
                        expect(e.errors.name).to.have.length(1);
                        expect(e.errors.name[0]).to.equal('name already exists');
                    });
            });
    });

    it('should have "this" set to model', function () {
        return saved.save({ name: '<NAME>', quantity: 8 })
            .then(function () {
                return Obj.forge({id: saved.id}).fetch();
            })
            .then(function (model) {
                saved = model;
                expect(model.get('name')).equals('Name');
                expect(model.get('str')).equals('secret');
                expect(model.get('quantity')).equals(8);
            });
    });

});<commit_msg>add test for result caching<commit_after>var DbContext = require('./setup'),
    expect = require('chai').expect,
    ValidationError = require('../').ValidationError;

describe('validator', function () {
    before(function () {
        return DbContext.knex.schema.dropTableIfExists('obj')
            .then(function () {
                return DbContext.knex.schema.createTable('obj', function (table) {
                    table.increments('id').primary();
                    table.string('name').notNullable().unique();
                    table.integer('quantity');
                    table.string('str');
                });
            });
    });

    var runCount = 0,
        Obj = DbContext.Model.extend({
            tableName: 'obj',
            validation: {
                'name': [
                    function (value, context) {
                        ++ runCount;
                        if (!this.isNew()) {
                            this.unset('name');
                            return context.yield();
                        }
                    },
                    { validator: 'notEmpty', message: 'name is required' },
                    { validator: 'matches', args: [/^[a-z0-9 ]+$/i], message: 'name format incorrect'},
                    function (value, context) {
                        return DbContext.knex('obj').where('name', value).count('* AS count')
                            .then(function (results) {
                                if (results[0].count > 0)
                                    context.addError('name already exists');
                            });
                    }
                ],
                'quantity': [
                    { validator: 'isInt', message: 'quantity must be integer' }
                ]
            }
        });

    var saved;

    it('should fail: empty object', function () {
        return Obj.forge({}).save()
            .then(function () {
                throw new Error('obj should not be saved');
            })
            .catch(ValidationError, function (e) {
                expect(e.errors).to.have.keys(['name', 'quantity']);
                expect(e.errors.name).to.have.length(2);
                expect(e.errors.name).to.deep.equal(['name is required', 'name format incorrect']);
                expect(e.errors.quantity).to.have.length(1);
                expect(e.errors.quantity[0]).to.equal('quantity must be integer');
            });
    });

    it('should fail: name exists', function () {
        return Obj.forge({ name: 'Name', quantity: 1, str: 'secret' }).save()
            .then(function (model) {
                saved = model;
                return Obj.forge({ name: 'Name', quantity: 1 }).save()
                    .then(function () {
                        throw new Error('obj should not be saved');
                    })
                    .catch(ValidationError, function (e) {
                        expect(e.errors).to.have.keys(['name']);
                        expect(e.errors.name).to.have.length(1);
                        expect(e.errors.name[0]).to.equal('name already exists');
                    });
            });
    });

    it('should have "this" set to model', function () {
        return saved.save({ name: '<NAME>', quantity: 8 })
            .then(function () {
                return Obj.forge({id: saved.id}).fetch();
            })
            .then(function (model) {
                saved = model;
                expect(model.get('name')).equals('Name');
                expect(model.get('str')).equals('secret');
                expect(model.get('quantity')).equals(8);
            });
    });

    it('result cache', function () {
        return Obj.forge({ name: 'Name 3', quantity: 1, str: 'secret' }).save()
            .then(function (model) {
                saved = model;
                var count = runCount;
                return saved.validate()
                    .then(function (result) {
                        expect(runCount).equals(count);
                        return saved.save({ quantity: 222 })
                            .then(function () {
                                expect(runCount).equals(count + 1);
                            });
                    })
            });
    });

});
{'fraction_non_alphanumeric': 0.1495267331798414, 'fraction_numerical': 0.00422102839600921, 'mean_word_length': 1.3098966026587888, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4758559', 'n_tokens_mistral': 2033, 'n_tokens_neox': 1873, 'n_words': 386}