src/components/selectboxes/SelectBoxes.unit.js
import assert from 'power-assert';
import Harness from '../../../test/harness';
import _ from 'lodash';
import SelectBoxesComponent from './SelectBoxes';
import { Formio } from './../../Formio';
import {
comp1,
comp3,
comp4,
comp5,
comp6,
comp7,
} from './fixtures';
import wizardWithSelectBoxes from '../../../test/forms/wizardWithSelectBoxes';
describe('SelectBoxes Component', () => {
it('Should build a SelectBoxes component', () => {
return Harness.testCreate(SelectBoxesComponent, comp1).then((component) => {
Harness.testElements(component, 'input[type="checkbox"]', 8);
});
});
it('Should build a SelectBoxes component with URL DataSrc', (done) => {
const form = _.cloneDeep(comp5);
const element = document.createElement('div');
const originalMakeRequest = Formio.makeRequest;
Formio.makeRequest = function() {
return new Promise(resolve => {
const values = [
{ name : 'Alabama', abbreviation : 'AL' },
{ name : 'Alaska', abbreviation: 'AK' },
{ name: 'American Samoa', abbreviation: 'AS' }
];
resolve(values);
});
};
Formio.createForm(element, form).then(form => {
const selectBoxes = form.getComponent('selectBoxes');
setTimeout(()=>{
assert.equal(selectBoxes.loadedOptions.length, 3);
Formio.makeRequest = originalMakeRequest;
done();
}, 200);
}).catch(done);
});
it('Should display values in DataTab', function(done) {
Harness.testCreate(SelectBoxesComponent, comp6).then((component) => {
const value1 = component.getView({ Alabama: false, Alaska: true });
const value2 = component.getView({ Alabama: true, Alaska: true });
assert.equal(value1, 'Alaska');
assert.equal(value2, 'Alabama, Alaska');
done();
});
});
it('Should provide metadata.selectData for SelectBoxes component with URL DataSrc', (done) => {
const form = _.cloneDeep(comp5);
const element = document.createElement('div');
const originalMakeRequest = Formio.makeRequest;
Formio.makeRequest = function() {
return new Promise(resolve => {
const values = [
{ name : 'Alabama', abbreviation : 'AL' },
{ name : 'Alaska', abbreviation: 'AK' },
{ name: 'American Samoa', abbreviation: 'AS' }
];
resolve(values);
});
};
Formio.createForm(element, form).then(form => {
const selectBoxes = form.getComponent('selectBoxes');
setTimeout(()=>{
const value = { AL: false, AK: true, AS: true };
selectBoxes.setValue(value);
setTimeout(() => {
assert.equal(selectBoxes.dataValue, value);
const submit = form.getComponent('submit');
const clickEvent = new Event('click');
const submitBtn = submit.refs.button;
submitBtn.dispatchEvent(clickEvent);
setTimeout(() => {
assert.equal(_.isEqual(form.submission.metadata.selectData.selectBoxes, [{ name : 'Alaska' }, { name : 'American Samoa' }]), true);
assert.equal(form.submission.metadata.listData.selectBoxes.length, 3);
Formio.makeRequest = originalMakeRequest;
done();
},200);
},200);
}, 200);
}).catch(done);
});
describe('error messages', () => {
it('Should have a minSelectedCount validation message', () => {
const formJson = {
components: [
{
type: 'selectboxes',
key: 'options',
values: [
{ label: 'Option 1', value: '1' },
{ label: 'Option 2', value: '2' },
{ label: 'Option 3', value: '3' },
{ label: 'Option 4', value: '4' }
],
validate: {
minSelectedCount: 2
}
}
]
};
const element = document.createElement('div');
return Formio.createForm(element, formJson)
.then(async form => {
form.submission = {
data: {
options: { 1: true }
}
};
const comp = form.getComponent('options');
setTimeout(() => {
const { messageContainer } = comp.refs;
assert.equal(
messageContainer.textContent.trim(),
'You must select at least 2 items.'
);
}, 300);
});
});
it('Should use the minSelectedCountMessage if provided', () => {
const formJson = {
components: [
{
type: 'selectboxes',
key: 'options',
values: [
{ label: 'Option 1', value: '1' },
{ label: 'Option 2', value: '2' },
{ label: 'Option 3', value: '3' },
{ label: 'Option 4', value: '4' }
],
validate: {
minSelectedCount: 2,
},
minSelectedCountMessage: 'Please select at least {{minCount}} items.'
}
]
};
const element = document.createElement('div');
return Formio.createForm(element, formJson)
.then(async form => {
form.submission = {
data: {
options: { 1: true }
}
};
const comp = form.getComponent('options');
setTimeout(() => {
const { messageContainer } = comp.refs;
assert.equal(
messageContainer.textContent.trim(),
'Please select at least 2 items.'
);
}, 300);
});
});
it('Hidden SelectBoxes validation should not prevent submission', (done) => {
const element = document.createElement('div');
Formio.createForm(element, comp4)
.then(async form => {
const submit = form.getComponent('submit');
const clickEvent = new Event('click');
const submitBtn = submit.refs.button;
submitBtn.dispatchEvent(clickEvent);
setTimeout(() => {
assert.equal(form.submission.state, 'submitted');
assert.equal(form.errors.length, 0);
done();
}, 500);
})
.catch(done);
});
it('Should have a maxSelectedCount validation message', () => {
const formJson = {
components: [
{
type: 'selectboxes',
key: 'options',
values: [
{ label: 'Option 1', value: '1' },
{ label: 'Option 2', value: '2' },
{ label: 'Option 3', value: '3' },
{ label: 'Option 4', value: '4' }
],
validate: {
maxSelectedCount: 2
}
}
]
};
const element = document.createElement('div');
return Formio.createForm(element, formJson)
.then(async form => {
form.submission = {
data: {
options: { 1: true, 2: true, 3: true }
}
};
const comp = form.getComponent('options');
setTimeout(() => {
const { messageContainer } = comp.refs;
assert.equal(
messageContainer.textContent.trim(),
'You can only select up to 2 items.'
);
}, 300);
});
});
it('Should use the maxSelectedCountMessage if provided', () => {
const formJson = {
components: [
{
type: 'selectboxes',
key: 'options',
values: [
{ label: 'Option 1', value: '1' },
{ label: 'Option 2', value: '2' },
{ label: 'Option 3', value: '3' },
{ label: 'Option 4', value: '4' }
],
validate: {
maxSelectedCount: 2,
},
maxSelectedCountMessage: 'Please select {{maxCount}} items at most.'
}
]
};
const element = document.createElement('div');
return Formio.createForm(element, formJson)
.then(async form => {
form.submission = {
data: {
options: { 1: true, 2: true, 3: true }
}
};
const comp = form.getComponent('options');
setTimeout(() => {
const { messageContainer } = comp.refs;
assert.equal(
messageContainer.textContent.trim(),
'Please select 2 items at most.'
);
}, 300);
});
});
it('Should provide validation for ValueProperty', (done) => {
const form = _.cloneDeep(comp5);
const element = document.createElement('div');
const originalMakeRequest = Formio.makeRequest;
Formio.makeRequest = function() {
return new Promise(resolve => {
const values = [
{ name : 'Alabama', abbreviation : 'AL' },
{ name : 'Alaska', abbreviation: { a:2, b: 'c' } },
{ name : 'American Samoa', abbreviation: true }
];
resolve(values);
});
};
Formio.createForm(element, form).then(async form => {
const selectBoxes = form.getComponent('selectBoxes');
setTimeout(()=>{
const inputs = selectBoxes.element.querySelectorAll('input');
inputs[1].checked = true;
inputs[2].checked = true;
setTimeout(()=>{
const submit = form.getComponent('submit');
const clickEvent = new Event('click');
const submitBtn = submit.refs.button;
submitBtn.dispatchEvent(clickEvent);
setTimeout(()=>{
assert.equal(form.errors.length, 1);
assert.equal(selectBoxes.error.message, 'Invalid Value Property');
selectBoxes.setValue({ 'AL': true });
setTimeout(()=>{
assert.equal(form.errors.length, 0);
assert.equal(!!selectBoxes.error, false);
document.innerHTML = '';
Formio.makeRequest = originalMakeRequest;
done();
}, 300);
}, 300);
}, 300);
}, 200);
}).catch(done);
});
});
it('Should set "checked" attribute correctly when value is changed', (done) => {
Formio.createForm(document.createElement('div'), wizardWithSelectBoxes).then((form) => {
const selectBoxes = form.getComponent(['selectBoxes']);
const value = {
five: false,
four: false,
one: true,
three: false,
two: true,
};
selectBoxes.setValue(value);
const checkInputs = (values) => {
Object.entries(values).forEach(([key, value]) => {
const input = selectBoxes.element.querySelector(`input[value="${key}"]`);
assert.equal(input.checked, value, 'Should be checked');
});
};
setTimeout(() => {
checkInputs(value);
form.setPage(1);
setTimeout(() => {
form.setPage(0);
setTimeout(() => {
checkInputs(value);
done();
});
}, 200);
}, 200);
}).catch(done);
});
});
describe('SelectBoxes Component', () => {
it('should have red asterisk left hand side to the options labels if component is required and label is hidden', () => {
return Harness.testCreate(SelectBoxesComponent, comp3).then(component => {
const options = component.element.querySelectorAll('.form-check-label');
options.forEach(i => {
assert.deepEqual(!!getComputedStyle(i, ':before'), true);
});
});
});
it('Should perform OnlyAvailableItems check properly', (done) => {
Harness.testCreate(SelectBoxesComponent, comp7).then(component => {
assert.equal(component.validateValueAvailability(true, { a: true }), true, 'Should be valid');
assert.equal(component.validateValueAvailability(true, { a: false, b: false, c: false }), true, 'Should be valid');
assert.equal(component.validateValueAvailability(true, { a: false, newKey: false }), false, 'Should not be valid');
assert.equal(component.validateValueAvailability(true, { newKey: false }), false, 'Should not be valid');
assert.equal(component.validateValueAvailability(true, {}), true, 'Should be valid');
assert.equal(component.validateValueAvailability(false, {}), true, 'Should be valid');
done();
}).catch(done);
});
});