feat(engine): showValidation on block level and params.regex for Validate.

This commit is contained in:
Gervwyk 2021-08-16 22:10:35 +02:00
parent df6a5904a8
commit 6824b07127
4 changed files with 502 additions and 130 deletions

View File

@ -217,6 +217,7 @@ class Blocks {
const initState = serializer.copy(initWithState || this.context.state);
this.loopBlocks((block) => {
block.update = true;
block.showValidation = false;
if (get(block, 'meta.category') === 'input' || get(block, 'meta.category') === 'list') {
let blockValue = get(initState, block.field);
if (type.isUndefined(blockValue)) {
@ -368,13 +369,13 @@ class Blocks {
}
}
});
if (this.context.showValidationErrors && validation.length > 0) {
if (validation.length > 0) {
block.validationEval.output.status = 'success';
}
if (validationWarning) {
block.validationEval.output.status = 'warning';
}
if (this.context.showValidationErrors && validationError) {
if (validationError) {
block.validationEval.output.status = 'error';
}
@ -497,18 +498,26 @@ class Blocks {
});
}
getValidateRec(result) {
getValidateRec(params, match, result) {
this.loopBlocks((block) => {
if (block.visibleEval.output && block.validationEval.output.status === 'error') {
result.push({
blockId: block.blockId,
validation: block.validationEval.output,
});
if (match(block.blockId, params)) {
block.showValidation = true;
block.update = true;
if (
block.visibleEval.output !== false &&
block.validationEval.output &&
block.validationEval.output.status === 'error'
) {
result.push({
blockId: block.blockId,
validation: block.validationEval.output,
});
}
}
});
Object.keys(this.subBlocks).forEach((subKey) => {
this.subBlocks[subKey].forEach((subBlock) => {
subBlock.getValidateRec(result);
subBlock.getValidateRec(params, match, result);
});
});
return result;
@ -536,9 +545,11 @@ class Blocks {
});
}
validate() {
this.update(); // update to recalculate validationEval with showValidationErrors set to raise block errors
return this.getValidateRec([]);
validate(params, match) {
this.updateStateFromRoot(); // update to recalculate validationEval to raise block errors
const validationErrors = this.getValidateRec(params, match, []); // get all relevant raised block errors and set showValidation
this.setBlocksCache(); // update cache to render
return validationErrors;
}
update() {
@ -562,7 +573,10 @@ class Blocks {
required: block.requiredEval.output,
layout: block.layoutEval.output,
style: block.styleEval.output,
validation: block.validationEval.output,
validation: {
...(block.validationEval.output || {}),
status: block.showValidation ? (block.validationEval.output || {}).status : null,
},
value: type.isNone(block.value) ? null : block.value,
visible: block.visibleEval.output,
};

View File

@ -16,23 +16,47 @@
import { type } from '@lowdefy/helpers';
const getMatch = (params) => (id) => {
if (params.blockIds === true || (type.isArray(params.blockIds) && params.blockIds.includes(id))) {
return true;
}
if (type.isArray(params.regex)) {
for (const regex of params.regex) {
if (regex.test(id)) {
return true;
}
}
}
return false;
};
async function Validate({ context, params }) {
if (!type.isNone(params) && !type.isString(params) && !type.isArray(params)) {
let testParams = params;
if (type.isNone(testParams)) {
testParams = { blockIds: true };
}
if (type.isString(testParams)) {
testParams = { blockIds: [testParams] };
}
if (type.isArray(testParams)) {
testParams = { blockIds: testParams };
}
if (!type.isObject(testParams)) {
throw new Error('Invalid validate params.');
}
context.showValidationErrors = true;
let validationErrors = context.RootBlocks.validate();
if (params) {
const blockIds = type.isString(params) ? [params] : params;
validationErrors = validationErrors.filter((block) => {
return blockIds.includes(block.blockId);
});
if (type.isString(testParams.regex)) {
testParams.regex = [testParams.regex];
}
if (type.isArray(testParams.regex)) {
testParams.regex = testParams.regex.map((regex) => new RegExp(regex));
}
const validationErrors = context.RootBlocks.validate(testParams, getMatch(testParams));
if (validationErrors.length > 0) {
const message = `Your input has ${validationErrors.length} validation error${
validationErrors.length !== 1 ? 's' : ''
}.`;
const error = new Error(message);
const error = new Error(
`Your input has ${validationErrors.length} validation error${
validationErrors.length !== 1 ? 's' : ''
}.`
);
throw error;
}
}

View File

@ -29,8 +29,9 @@ const RealDate = Date;
const mockDate = jest.fn(() => ({ date: 0 }));
mockDate.now = jest.fn(() => 0);
// Comment out to use console.log
// Comment out to use console
console.log = () => {};
console.error = () => {};
beforeEach(() => {
displayMessage.mockReset();
@ -88,7 +89,7 @@ test('Validate required field', async () => {
rootBlock,
});
const { button, text1 } = context.RootBlocks.map;
expect(text1.validationEval.output).toEqual({
expect(text1.eval.validation).toEqual({
errors: ['This field is required'],
status: null,
warnings: [],
@ -120,7 +121,7 @@ test('Validate required field', async () => {
startTimestamp: { date: 0 },
endTimestamp: { date: 0 },
});
expect(text1.validationEval.output).toEqual({
expect(text1.eval.validation).toEqual({
errors: ['This field is required'],
status: 'error',
warnings: [],
@ -155,7 +156,7 @@ test('Validate required field', async () => {
startTimestamp: { date: 0 },
endTimestamp: { date: 0 },
});
expect(text1.validationEval.output).toEqual({
expect(text1.eval.validation).toEqual({
errors: [],
status: 'success',
warnings: [],
@ -226,7 +227,7 @@ test('Validate all fields', async () => {
rootBlock,
});
const { button, text1, text2 } = context.RootBlocks.map;
expect(text1.validationEval.output).toEqual({
expect(text1.eval.validation).toEqual({
errors: ['text1 does not match pattern "text1"'],
status: null,
warnings: [],
@ -258,12 +259,12 @@ test('Validate all fields', async () => {
startTimestamp: { date: 0 },
endTimestamp: { date: 0 },
});
expect(text1.validationEval.output).toEqual({
expect(text1.eval.validation).toEqual({
errors: ['text1 does not match pattern "text1"'],
status: 'error',
warnings: [],
});
expect(text2.validationEval.output).toEqual({
expect(text2.eval.validation).toEqual({
errors: ['text2 does not match pattern "text2"'],
status: 'error',
warnings: [],
@ -309,12 +310,12 @@ test('Validate all fields', async () => {
startTimestamp: { date: 0 },
endTimestamp: { date: 0 },
});
expect(text1.validationEval.output).toEqual({
expect(text1.eval.validation).toEqual({
errors: [],
status: 'success',
warnings: [],
});
expect(text2.validationEval.output).toEqual({
expect(text2.eval.validation).toEqual({
errors: ['text2 does not match pattern "text2"'],
status: 'error',
warnings: [],
@ -349,12 +350,12 @@ test('Validate all fields', async () => {
startTimestamp: { date: 0 },
endTimestamp: { date: 0 },
});
expect(text1.validationEval.output).toEqual({
expect(text1.eval.validation).toEqual({
errors: [],
status: 'success',
warnings: [],
});
expect(text2.validationEval.output).toEqual({
expect(text2.eval.validation).toEqual({
errors: [],
status: 'success',
warnings: [],
@ -424,7 +425,7 @@ test('Validate only one field', async () => {
rootBlock,
});
const { button, text1, text2 } = context.RootBlocks.map;
expect(text1.validationEval.output).toEqual({
expect(text1.eval.validation).toEqual({
errors: ['text1 does not match pattern "text1"'],
status: null,
warnings: [],
@ -457,14 +458,14 @@ test('Validate only one field', async () => {
startTimestamp: { date: 0 },
endTimestamp: { date: 0 },
});
expect(text1.validationEval.output).toEqual({
expect(text1.eval.validation).toEqual({
errors: ['text1 does not match pattern "text1"'],
status: 'error',
warnings: [],
});
expect(text2.validationEval.output).toEqual({
expect(text2.eval.validation).toEqual({
errors: ['text2 does not match pattern "text2"'],
status: 'error',
status: null,
warnings: [],
});
expect(displayMessage.mock.calls).toMatchInlineSnapshot(`
@ -497,14 +498,14 @@ test('Validate only one field', async () => {
startTimestamp: { date: 0 },
endTimestamp: { date: 0 },
});
expect(text1.validationEval.output).toEqual({
expect(text1.eval.validation).toEqual({
errors: [],
status: 'success',
warnings: [],
});
expect(text2.validationEval.output).toEqual({
expect(text2.eval.validation).toEqual({
errors: ['text2 does not match pattern "text2"'],
status: 'error',
status: null,
warnings: [],
});
expect(displayMessage.mock.calls).toMatchInlineSnapshot(`Array []`);
@ -587,17 +588,17 @@ test('Validate list of fields', async () => {
});
const { button, text1, text2, text3 } = context.RootBlocks.map;
text1.setValue('text1');
expect(text1.validationEval.output).toEqual({
expect(text1.eval.validation).toEqual({
errors: [],
status: null,
warnings: [],
});
expect(text2.validationEval.output).toEqual({
expect(text2.eval.validation).toEqual({
errors: ['text2 does not match pattern "text2"'],
status: null,
warnings: [],
});
expect(text3.validationEval.output).toEqual({
expect(text3.eval.validation).toEqual({
errors: ['text3 does not match pattern "text3"'],
status: null,
warnings: [],
@ -644,19 +645,19 @@ test('Validate list of fields', async () => {
displayMessage.mockReset();
displayMessage.mockImplementation(() => closeLoader);
text2.setValue('text2');
expect(text1.validationEval.output).toEqual({
expect(text1.eval.validation).toEqual({
errors: [],
status: 'success',
warnings: [],
});
expect(text2.validationEval.output).toEqual({
expect(text2.eval.validation).toEqual({
errors: [],
status: 'success',
warnings: [],
});
expect(text3.validationEval.output).toEqual({
expect(text3.eval.validation).toEqual({
errors: ['text3 does not match pattern "text3"'],
status: 'error',
status: null,
warnings: [],
});
await button.triggerEvent({ name: 'onClick' });
@ -675,9 +676,9 @@ test('Validate list of fields', async () => {
startTimestamp: { date: 0 },
endTimestamp: { date: 0 },
});
expect(text3.validationEval.output).toEqual({
expect(text3.eval.validation).toEqual({
errors: ['text3 does not match pattern "text3"'],
status: 'error',
status: null,
warnings: [],
});
expect(displayMessage.mock.calls).toMatchInlineSnapshot(`Array []`);
@ -703,7 +704,7 @@ test('Invalid Validate params', async () => {
{
id: 'validate',
type: 'Validate',
params: { invalid: true },
params: 1,
},
],
},
@ -725,9 +726,7 @@ test('Invalid Validate params', async () => {
error: {
action: {
id: 'validate',
params: {
invalid: true,
},
params: 1,
type: 'Validate',
},
error: {
@ -808,9 +807,9 @@ test('Validate does not fail on warnings', async () => {
rootBlock,
});
const { button, text1 } = context.RootBlocks.map;
expect(text1.validationEval.output).toEqual({
expect(text1.eval.validation).toEqual({
errors: [],
status: 'warning',
status: null,
warnings: ['text1 does not match pattern "text1"'],
});
await button.triggerEvent({ name: 'onClick' });
@ -828,4 +827,356 @@ test('Validate does not fail on warnings', async () => {
startTimestamp: { date: 0 },
endTimestamp: { date: 0 },
});
expect(text1.eval.validation).toEqual({
errors: [],
status: 'warning',
warnings: ['text1 does not match pattern "text1"'],
});
});
test('Validate on nested objects using params.regex string', async () => {
const rootBlock = {
blockId: 'root',
meta: {
category: 'context',
},
areas: {
content: {
blocks: [
{
blockId: 'obj.text1',
type: 'TextInput',
meta: {
category: 'input',
valueType: 'string',
},
validate: [
{
pass: { _regex: { pattern: 'text1', key: 'text1' } },
message: 'text1 does not match pattern "text1"',
},
],
},
{
blockId: 'text2',
type: 'TextInput',
meta: {
category: 'input',
valueType: 'string',
},
validate: [
{
pass: { _regex: { pattern: 'text2', key: 'text2' } },
message: 'text2 does not match pattern "text2"',
},
],
},
{
blockId: 'button',
type: 'Button',
meta: {
category: 'display',
},
events: {
onClick: [
{
id: 'validate',
type: 'Validate',
params: {
regex: '^obj.*1$',
},
},
],
},
},
],
},
},
};
const context = await testContext({
lowdefy,
rootBlock,
});
const { button, 'obj.text1': text1 } = context.RootBlocks.map;
expect(text1.eval.validation).toEqual({
errors: ['text1 does not match pattern "text1"'],
status: null,
warnings: [],
});
await button.triggerEvent({ name: 'onClick' });
expect(button.Events.events.onClick.history[0]).toEqual({
blockId: 'button',
error: {
error: { type: 'Validate', error: new Error('Your input has 1 validation error.'), index: 0 },
action: { id: 'validate', type: 'Validate', params: { regex: '^obj.*1$' } },
},
eventName: 'onClick',
responses: {
validate: {
type: 'Validate',
error: new Error('Your input has 1 validation error.'),
index: 0,
},
},
endTimestamp: { date: 0 },
startTimestamp: { date: 0 },
success: false,
});
expect(text1.eval.validation).toEqual({
errors: ['text1 does not match pattern "text1"'],
status: 'error',
warnings: [],
});
});
test('Validate on nested objects using params.regex array', async () => {
const rootBlock = {
blockId: 'root',
meta: {
category: 'context',
},
areas: {
content: {
blocks: [
{
blockId: 'obj.text1',
type: 'TextInput',
meta: {
category: 'input',
valueType: 'string',
},
validate: [
{
pass: { _regex: { pattern: 'text1', key: 'text1' } },
message: 'text1 does not match pattern "text1"',
},
],
},
{
blockId: 'obj.abc1',
type: 'TextInput',
meta: {
category: 'input',
valueType: 'string',
},
validate: [
{
pass: { _regex: { pattern: 'abc1', key: 'abc1' } },
message: 'abc1 does not match pattern "abc1"',
},
],
},
{
blockId: 'text2',
type: 'TextInput',
meta: {
category: 'input',
valueType: 'string',
},
validate: [
{
pass: { _regex: { pattern: 'text2', key: 'text2' } },
message: 'text2 does not match pattern "text2"',
},
],
},
{
blockId: 'button',
type: 'Button',
meta: {
category: 'display',
},
events: {
onClick: [
{
id: 'validate',
type: 'Validate',
params: {
regex: ['^obj.*1$'],
},
},
],
},
},
],
},
},
};
const context = await testContext({
lowdefy,
rootBlock,
});
const { button, text2, 'obj.text1': text1, 'obj.abc1': abc1 } = context.RootBlocks.map;
expect(text1.eval.validation).toEqual({
errors: ['text1 does not match pattern "text1"'],
status: null,
warnings: [],
});
await button.triggerEvent({ name: 'onClick' });
expect(button.Events.events.onClick.history[0]).toEqual({
blockId: 'button',
error: {
error: {
type: 'Validate',
error: new Error('Your input has 2 validation errors.'),
index: 0,
},
action: { id: 'validate', type: 'Validate', params: { regex: ['^obj.*1$'] } },
},
eventName: 'onClick',
responses: {
validate: {
type: 'Validate',
error: new Error('Your input has 2 validation errors.'),
index: 0,
},
},
endTimestamp: { date: 0 },
startTimestamp: { date: 0 },
success: false,
});
expect(text1.eval.validation).toEqual({
errors: ['text1 does not match pattern "text1"'],
status: 'error',
warnings: [],
});
expect(abc1.eval.validation).toEqual({
errors: ['abc1 does not match pattern "abc1"'],
status: 'error',
warnings: [],
});
expect(text2.eval.validation).toEqual({
errors: ['text2 does not match pattern "text2"'],
status: null,
warnings: [],
});
});
test('Validate on nested objects using params.regex array and blockIds', async () => {
const rootBlock = {
blockId: 'root',
meta: {
category: 'context',
},
areas: {
content: {
blocks: [
{
blockId: 'obj.text1',
type: 'TextInput',
meta: {
category: 'input',
valueType: 'string',
},
validate: [
{
pass: { _regex: { pattern: 'text1', key: 'text1' } },
message: 'text1 does not match pattern "text1"',
},
],
},
{
blockId: 'obj.abc1',
type: 'TextInput',
meta: {
category: 'input',
valueType: 'string',
},
validate: [
{
pass: { _regex: { pattern: 'abc1', key: 'abc1' } },
message: 'abc1 does not match pattern "abc1"',
},
],
},
{
blockId: 'text2',
type: 'TextInput',
meta: {
category: 'input',
valueType: 'string',
},
validate: [
{
pass: { _regex: { pattern: 'text2', key: 'text2' } },
message: 'text2 does not match pattern "text2"',
},
],
},
{
blockId: 'button',
type: 'Button',
meta: {
category: 'display',
},
events: {
onClick: [
{
id: 'validate',
type: 'Validate',
params: {
regex: ['^obj.*t1$'],
blockIds: ['text2'],
},
},
],
},
},
],
},
},
};
const context = await testContext({
lowdefy,
rootBlock,
});
const { button, text2, 'obj.text1': text1, 'obj.abc1': abc1 } = context.RootBlocks.map;
expect(text1.eval.validation).toEqual({
errors: ['text1 does not match pattern "text1"'],
status: null,
warnings: [],
});
await button.triggerEvent({ name: 'onClick' });
expect(button.Events.events.onClick.history[0]).toEqual({
blockId: 'button',
error: {
error: {
type: 'Validate',
error: new Error('Your input has 2 validation errors.'),
index: 0,
},
action: {
id: 'validate',
type: 'Validate',
params: { regex: ['^obj.*t1$'], blockIds: ['text2'] },
},
},
event: undefined,
eventName: 'onClick',
responses: {
validate: {
type: 'Validate',
error: new Error('Your input has 2 validation errors.'),
index: 0,
},
},
endTimestamp: { date: 0 },
startTimestamp: { date: 0 },
success: false,
});
expect(text1.eval.validation).toEqual({
errors: ['text1 does not match pattern "text1"'],
status: 'error',
warnings: [],
});
expect(text2.eval.validation).toEqual({
errors: ['text2 does not match pattern "text2"'],
status: 'error',
warnings: [],
});
expect(abc1.eval.validation).toEqual({
errors: ['abc1 does not match pattern "abc1"'],
status: null,
warnings: [],
});
});

View File

@ -1,27 +1,27 @@
/*
Copyright 2020-2021 Lowdefy, Inc
Copyright 2020-2021 Lowdefy, Inc
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import testContext from '../testContext';
const pageId = 'one';
const match = () => true;
const lowdefy = { pageId };
// Comment out to use console.log
// Comment out to use console
console.log = () => {};
// Comment out to use console.log
console.error = () => {};
test('parse validate on fields', async () => {
@ -63,25 +63,24 @@ test('parse validate on fields', async () => {
const { text } = context.RootBlocks.map;
expect(context.state).toEqual({ text: 'a' });
expect(text.validationEval.output).toEqual({ errors: ["Not 'c'"], status: null, warnings: [] });
expect(text.eval.validation).toEqual({ errors: ["Not 'c'"], status: null, warnings: [] });
context.showValidationErrors = true;
context.update();
expect(text.validationEval.output).toEqual({
context.RootBlocks.validate(true, match);
expect(text.eval.validation).toEqual({
errors: ["Not 'c'"],
status: 'error',
warnings: [],
});
text.setValue('c');
expect(text.validationEval.output).toEqual({
expect(text.eval.validation).toEqual({
errors: ["Not 'a'"],
status: 'error',
warnings: [],
});
text.setValue('b');
expect(text.validationEval.output).toEqual({
expect(text.eval.validation).toEqual({
errors: ["Not 'a'", "Not 'c'"],
status: 'error',
warnings: [],
@ -121,9 +120,8 @@ test('validate should fail if parser has errors', async () => {
});
const { text } = context.RootBlocks.map;
context.showValidationErrors = true;
context.update();
expect(text.validationEval.output).toEqual({
context.RootBlocks.validate(true, match);
expect(text.eval.validation).toEqual({
errors: ['Parser failed'],
status: 'error',
warnings: [],
@ -168,9 +166,8 @@ test('validate, only test where parser failed should fail', async () => {
});
const { text } = context.RootBlocks.map;
context.showValidationErrors = true;
context.update();
expect(text.validationEval.output).toEqual({
context.RootBlocks.validate(true, match);
expect(text.eval.validation).toEqual({
errors: ['Parser failed'],
status: 'error',
warnings: [],
@ -211,20 +208,19 @@ test('parse validate, validate an object not an array', async () => {
});
const { text } = context.RootBlocks.map;
expect(context.state).toEqual({ text: 'a' });
expect(text.validationEval.output).toEqual({ errors: ["Not 'c'"], status: null, warnings: [] });
expect(text.eval.validation).toEqual({ errors: ["Not 'c'"], status: null, warnings: [] });
context.showValidationErrors = true;
context.update();
expect(text.validationEval.output).toEqual({
context.RootBlocks.validate(true, match);
expect(text.eval.validation).toEqual({
errors: ["Not 'c'"],
status: 'error',
warnings: [],
});
text.setValue('c');
expect(text.validationEval.output).toEqual({ errors: [], status: 'success', warnings: [] });
expect(text.eval.validation).toEqual({ errors: [], status: 'success', warnings: [] });
});
test('RootBlock.validate() to ignore errors where field not visible', async () => {
test('RootBlock.validate(true, match) to ignore errors where field not visible', async () => {
const rootBlock = {
blockId: 'root',
meta: {
@ -288,14 +284,10 @@ test('RootBlock.validate() to ignore errors where field not visible', async () =
rootBlock,
});
const { text, list } = context.RootBlocks.map;
expect(context.RootBlocks.validate()).toEqual([]);
expect(context.RootBlocks.validate(true, match)).toEqual([]);
text.setValue('1');
expect(context.RootBlocks.validate()).toEqual([]);
context.showValidationErrors = true;
context.RootBlocks.update();
expect(context.RootBlocks.validate()).toEqual([
expect(context.RootBlocks.validate(true, match)).toEqual([
{
blockId: 'list',
validation: { errors: ['Error 123'], status: 'error', warnings: [] },
@ -303,7 +295,7 @@ test('RootBlock.validate() to ignore errors where field not visible', async () =
]);
text.setValue('12');
expect(context.RootBlocks.validate()).toEqual([
expect(context.RootBlocks.validate(true, match)).toEqual([
{
blockId: 'list',
validation: { errors: ['Error 123'], status: 'error', warnings: [] },
@ -311,11 +303,11 @@ test('RootBlock.validate() to ignore errors where field not visible', async () =
]);
text.setValue('123');
expect(context.RootBlocks.validate()).toEqual([]);
expect(context.RootBlocks.validate(true, match)).toEqual([]);
text.setValue('12');
list.pushItem();
expect(context.RootBlocks.validate()).toEqual([
expect(context.RootBlocks.validate(true, match)).toEqual([
{ blockId: 'list', validation: { errors: ['Error 123'], status: 'error', warnings: [] } },
{
blockId: 'list.0.innerText',
@ -325,7 +317,7 @@ test('RootBlock.validate() to ignore errors where field not visible', async () =
text.setValue('123');
list.pushItem();
expect(context.RootBlocks.validate()).toEqual([
expect(context.RootBlocks.validate(true, match)).toEqual([
{
blockId: 'list.0.innerText',
validation: { errors: ['Error 1234'], status: 'error', warnings: [] },
@ -337,13 +329,13 @@ test('RootBlock.validate() to ignore errors where field not visible', async () =
]);
text.setValue('1234');
expect(context.RootBlocks.validate()).toEqual([]);
expect(context.RootBlocks.validate(true, match)).toEqual([]);
text.setValue('0');
expect(context.RootBlocks.validate()).toEqual([]);
expect(context.RootBlocks.validate(true, match)).toEqual([]);
text.setValue('12');
expect(context.RootBlocks.validate()).toEqual([
expect(context.RootBlocks.validate(true, match)).toEqual([
{ blockId: 'list', validation: { errors: ['Error 123'], status: 'error', warnings: [] } },
{
blockId: 'list.0.innerText',
@ -356,7 +348,7 @@ test('RootBlock.validate() to ignore errors where field not visible', async () =
]);
});
test('required on input to return validation error on RootBlock.validate()', async () => {
test('required on input to return validation error on RootBlock.validate(true, match)', async () => {
const rootBlock = {
blockId: 'root',
meta: {
@ -386,18 +378,16 @@ test('required on input to return validation error on RootBlock.validate()', asy
expect(context.state).toEqual({
text: null,
});
expect(context.RootBlocks.validate()).toEqual([]);
context.showValidationErrors = true;
expect(context.RootBlocks.validate()).toEqual([
expect(context.RootBlocks.validate(true, match)).toEqual([
{
blockId: 'text',
validation: { errors: ['This field is required'], status: 'error', warnings: [] },
},
]);
text.setValue('a');
expect(context.RootBlocks.validate()).toEqual([]);
expect(context.RootBlocks.validate(true, match)).toEqual([]);
text.setValue('');
expect(context.RootBlocks.validate()).toEqual([
expect(context.RootBlocks.validate(true, match)).toEqual([
{
blockId: 'text',
validation: { errors: ['This field is required'], status: 'error', warnings: [] },
@ -405,7 +395,7 @@ test('required on input to return validation error on RootBlock.validate()', asy
]);
});
test('required on input to return validation error with priority over validation errors on RootBlock.validate()', async () => {
test('required on input to return validation error with priority over validation errors on RootBlock.validate(true, match)', async () => {
const rootBlock = {
blockId: 'root',
meta: {
@ -442,9 +432,7 @@ test('required on input to return validation error with priority over validation
expect(context.state).toEqual({
text: null,
});
expect(context.RootBlocks.validate()).toEqual([]);
context.showValidationErrors = true;
expect(context.RootBlocks.validate()).toEqual([
expect(context.RootBlocks.validate(true, match)).toEqual([
{
blockId: 'text',
validation: {
@ -455,7 +443,7 @@ test('required on input to return validation error with priority over validation
},
]);
text.setValue('a');
expect(context.RootBlocks.validate()).toEqual([
expect(context.RootBlocks.validate(true, match)).toEqual([
{
blockId: 'text',
validation: {
@ -466,9 +454,9 @@ test('required on input to return validation error with priority over validation
},
]);
text.setValue('1234');
expect(context.RootBlocks.validate()).toEqual([]);
expect(context.RootBlocks.validate(true, match)).toEqual([]);
text.setValue('');
expect(context.RootBlocks.validate()).toEqual([
expect(context.RootBlocks.validate(true, match)).toEqual([
{
blockId: 'text',
validation: {
@ -480,7 +468,7 @@ test('required on input to return validation error with priority over validation
]);
});
test('nested arrays with validate, and RootBlock.validate() returns all validation errors', async () => {
test('nested arrays with validate, and RootBlock.validate(true, match) returns all validation errors', async () => {
const rootBlock = {
blockId: 'root',
meta: {
@ -609,11 +597,7 @@ test('nested arrays with validate, and RootBlock.validate() returns all validati
{ innerList: [], swtch: true },
],
});
expect(context.RootBlocks.validate()).toEqual([]);
context.showValidationErrors = true;
context.RootBlocks.update();
expect(context.RootBlocks.validate()).toEqual([
expect(context.RootBlocks.validate(true, match)).toEqual([
{
blockId: 'list.0.swtch',
validation: {
@ -672,7 +656,7 @@ test('nested arrays with validate, and RootBlock.validate() returns all validati
},
]);
text.setValue('1');
expect(context.RootBlocks.validate()).toEqual([
expect(context.RootBlocks.validate(true, match)).toEqual([
{
blockId: 'list.0.swtch',
validation: {
@ -715,9 +699,9 @@ test('nested arrays with validate, and RootBlock.validate() returns all validati
},
]);
text.setValue('12');
expect(context.RootBlocks.validate()).toEqual([]);
expect(context.RootBlocks.validate(true, match)).toEqual([]);
text.setValue('0');
expect(context.RootBlocks.validate()).toEqual([
expect(context.RootBlocks.validate(true, match)).toEqual([
{
blockId: 'list.0.swtch',
validation: {
@ -818,29 +802,28 @@ test('validation warnings', async () => {
const { text } = context.RootBlocks.map;
expect(context.state).toEqual({ text: 'a' });
expect(text.validationEval.output).toEqual({
expect(text.eval.validation).toEqual({
errors: [],
status: 'warning',
status: null,
warnings: ["Not 'c'"],
});
context.showValidationErrors = true;
context.update();
expect(text.validationEval.output).toEqual({
context.RootBlocks.validate(true, match);
expect(text.eval.validation).toEqual({
errors: [],
status: 'warning',
warnings: ["Not 'c'"],
});
text.setValue('c');
expect(text.validationEval.output).toEqual({
expect(text.eval.validation).toEqual({
errors: [],
status: 'warning',
warnings: ["Not 'a'"],
});
text.setValue('b');
expect(text.validationEval.output).toEqual({
expect(text.eval.validation).toEqual({
errors: [],
status: 'warning',
warnings: ["Not 'a'", "Not 'c'"],