d2-ui
Version:
239 lines (183 loc) • 8.03 kB
JavaScript
import createFormValidator from '../../src/forms/FormValidator';
import {FormFieldStatuses} from '../../src/forms/FormValidator';
import log from 'loglevel';
import Rx from 'rx';
describe('FormValidator', () => {
let formValidator;
beforeEach(() => formValidator = createFormValidator());
it('should be be a function', () => {
expect(createFormValidator).to.be.a('function');
});
describe('status', () => {
it('should be able to subscribe to the status', () => {
formValidator.status.subscribe(spy());
});
it('should not emit a value on subscription without a status', () => {
const statusCallBack = spy();
formValidator.status.subscribe(statusCallBack);
expect(statusCallBack).not.to.be.called;
});
it('should emit a value when setStatus was called', (done) => {
function statusCallback(statusValue) {
expect(statusValue).to.deep.equal({
name: 'name',
status: FormFieldStatuses.VALID,
});
done();
}
formValidator.status.subscribe(statusCallback);
formValidator.setStatus({
name: 'name',
status: FormFieldStatuses.VALID,
});
});
});
describe('runFor', () => {
let validators;
let testScheduler;
beforeEach(() => {
testScheduler = new Rx.TestScheduler()
validators = [
sinon.stub().returns(true),
sinon.stub().returns(true),
];
formValidator = createFormValidator([
{name: 'name', validators},
{name: 'code', validators},
], testScheduler);
});
it('should return false when there are no validators for this fieldName', () => {
formValidator = createFormValidator();
expect(formValidator.runFor('name')).to.be.false;
});
xit('should run the validators for the field it is called with', (done) => {
formValidator.runFor('name', 'Mark');
setTimeout(() => {
expect(validators[0]).to.be.calledWith('Mark', 'name');
expect(validators[1]).to.be.calledWith('Mark', 'name');
done();
}, 301);
});
xit('should set the status when the runFor() is called', (done) => {
function statusCallback(statusValue) {
expect(Array.from(statusValue)).to.deep.equal([
['name', {status: FormFieldStatuses.VALID, messages: []}],
['code', {status: FormFieldStatuses.VALID, messages: []}],
]);
done();
}
formValidator.runFor('name');
formValidator.status.subscribe(statusCallback);
});
xit('should emit a status that represents the validator results', (done) => {
const requiredValidator = stub().returns(false);
requiredValidator.message = 'field_is_required';
validators.push(requiredValidator);
formValidator = createFormValidator([
{name: 'name', validators},
{name: 'code', validators},
]);
function statusCallback(statusValue) {
expect(Array.from(statusValue)).to.deep.equal([
['name', {status: FormFieldStatuses.INVALID, messages: ['field_is_required']}],
['code', {status: FormFieldStatuses.VALID, messages: []}],
]);
done();
}
formValidator.runFor('name');
formValidator.status.subscribe(statusCallback);
});
xit('should emit a pending status for an async validator', (done) => {
const asyncValidator = stub().returns(new Promise(() => {}));
validators.push(asyncValidator);
formValidator = createFormValidator([
{name: 'name', validators},
{name: 'code', validators},
]);
function statusCallback(statusValue) {
expect(Array.from(statusValue)).to.deep.equal([
['name', {status: FormFieldStatuses.VALIDATING, messages: []}],
['code', {status: FormFieldStatuses.VALID, messages: []}],
]);
done();
}
formValidator.runFor('name');
formValidator.status.subscribe(statusCallback);
});
it('should pass the field validation when the async validator resolves', (done) => {
const asyncValidator = stub().returns(Promise.resolve(true));
validators.push(asyncValidator);
formValidator = createFormValidator([
{name: 'name', validators},
{name: 'code', validators},
]);
function statusCallback(statusValue) {
expect(Array.from(statusValue)).to.deep.equal([
['name', {status: FormFieldStatuses.VALID, messages: []}],
['code', {status: FormFieldStatuses.VALID, messages: []}],
]);
done();
}
formValidator.runFor('name');
formValidator.status.subscribe(statusCallback);
});
it('should fail the field validation when the async validator rejects', (done) => {
const asyncValidator = stub().returns(Promise.reject('field_should_pass_async'));
validators.push(asyncValidator);
formValidator = createFormValidator([
{name: 'name', validators},
{name: 'code', validators},
]);
function statusCallback(statusValue) {
expect(Array.from(statusValue)).to.deep.equal([
['name', {status: FormFieldStatuses.INVALID, messages: ['field_should_pass_async']}],
['code', {status: FormFieldStatuses.VALID, messages: []}],
]);
done();
}
formValidator.runFor('name');
formValidator.status.subscribe(statusCallback);
});
xit('should log a warning when a validator is not a function', (done) => {
stub(log, 'warn');
validators.push('Not a validator');
formValidator.runFor('name', 'Mark');
setTimeout(() => {
expect(log.warn).to.be.calledWith(`Warning: One of the validators for 'name' is not a function.`);
done();
}, 301);
});
xit('should log an error when something fails', (done) => {
stub(log, 'debug');
function throwingValidator() {
throw new Error('Something failed!');
}
validators.push(throwingValidator);
formValidator.runFor('name', 'Mark');
setTimeout(() => {
expect(log.debug).to.be.calledWith(`Validator for 'name' ignored because the validator threw an error.`);
expect(log.debug).to.be.calledWith(`${throwingValidator}`);
expect(log.debug).to.be.calledWith('Something failed!');
done();
}, 400);
});
});
describe('getStatusFor', () => {
beforeEach(() => {
const validators = [
sinon.stub().returns(true),
sinon.stub().returns(true),
];
formValidator = createFormValidator([
{name: 'name', validators},
{name: 'code', validators},
]);
});
it('should return the current status for the field', () => {
expect(formValidator.getStatusFor('name')).to.deep.equal({
status: FormFieldStatuses.VALID,
messages: [],
});
});
});
});