/// <reference path="../typings/tsd.d.ts" />
'use strict'

import {Observable} from '../node_modules/rxjs/Rx';
import * as chai from 'chai';
import {Validator, ValidationSchema} from '../src/Validator';
import {ValidationResult} from '../src/ValidationResult'

const expect = chai.expect;

describe('Validator', () => {
  it('should be exported', () => {
    expect(Validator).to.be.an('function');
  });

  it('instantation', () => {
    const validator = new Validator();
    expect(validator).to.be.instanceof(Validator);
  });

  it('validation without schema', done => {
    const validator = new Validator();

    validator.validate({ test: true })
      .subscribe(result => {
        expect(result).to.be.instanceof(ValidationResult);
        done();
      });
  });

  it('validation joi', done => {
    const schema: ValidationSchema = {
      name: {
        string: true,
        required: true
      },
      price: {
        string: true,
        required: true
      }
    };
    const validator = new Validator(schema);

    validator.validate({ name: true, price: 1056 })
      .subscribe(result => {
        expect(result).to.be.instanceof(ValidationResult);
        expect(result.isValid).to.be.equal(false);
      }, err => done(err), () => {
        done();
      });
  });

  it('validation email', done => {
    const schema: ValidationSchema = {
      email: {
        string: true,
        email: true
      }
    };
    const validator = new Validator(schema);

    validator.validate({ email: 'mm' })
      .subscribe(result => {
        expect(result).to.be.instanceof(ValidationResult);
        expect(result.isValid).to.be.equal(false);
      }, err => done(err), () => {
        done();
      });
  });

  it('validation custom', done => {
    const schema: ValidationSchema = {
      name: {
        notEqualJurek: function(property) {
          return Observable.create(subscriber => {
            if (this[property] === 'Jurek') {
              subscriber.next({
                path: property,
                type: 'notEqualJurek',
                message: `Invalid "${property}", it cant equal "Jurek"`
              });
            }
            subscriber.complete();
          });
        }
      }
    };
    const validator = new Validator(schema);

    validator.validate({ name: 'Jurek', price: 1056 })
      .subscribe(result => {
        expect(result).to.be.instanceof(ValidationResult);
        expect(result.isValid).to.be.equal(false);
        expect(result.getInvalidProperties()).to.be.deep.equal(['name']);
        expect(result.getPropertyErrors('name')[0].message).to.be.equal('Invalid \'name\', it cant equal \'Jurek\'');
        expect(result.getPropertyErrors('name')[0].type).to.be.equal('notEqualJurek');
        expect(Object.keys(result.toJSON())).to.be.deep.equal(['isValid', 'errors']);
      }, err => done(err), () => {
        done()
      });
  });

});