From 0cabb374df9e503083bec655efffa5e8da99be17 Mon Sep 17 00:00:00 2001 From: Michal Remis Date: Wed, 15 Apr 2020 00:29:35 +0200 Subject: [PATCH] Added tests for :horizontal_form wrapper and made it pass --- dist/simple-form.bootstrap4.esm.js | 7 +- dist/simple-form.bootstrap4.js | 7 +- src/main.bootstrap4.js | 8 +- .../validateHorizontalSimpleFormBootstrap4.js | 125 ++++++++++++++++++ ...ails.validations.simple_form.bootstrap4.js | 7 +- 5 files changed, 142 insertions(+), 12 deletions(-) create mode 100644 test/javascript/public/test/form_builders/validateHorizontalSimpleFormBootstrap4.js diff --git a/dist/simple-form.bootstrap4.esm.js b/dist/simple-form.bootstrap4.esm.js index 5cf2108..d0462c2 100644 --- a/dist/simple-form.bootstrap4.esm.js +++ b/dist/simple-form.bootstrap4.esm.js @@ -20,7 +20,8 @@ ClientSideValidations.formBuilders['SimpleForm::FormBuilder'] = { wrappers: { "default": { add: function add(element, settings, message) { - var wrapperElement = element.parent(); + var parentElement = element.parent(); + var wrapperElement = element.closest(settings.wrapper_tag + '.' + settings.wrapper_class.replace(/ /g, '.')); var errorElement = wrapperElement.find(settings.error_tag + '.invalid-feedback'); if (!errorElement.length) { @@ -28,7 +29,7 @@ ClientSideValidations.formBuilders['SimpleForm::FormBuilder'] = { "class": 'invalid-feedback', text: message }); - wrapperElement.append(errorElement); + parentElement.append(errorElement); } wrapperElement.addClass(settings.wrapper_error_class); @@ -36,7 +37,7 @@ ClientSideValidations.formBuilders['SimpleForm::FormBuilder'] = { errorElement.text(message); }, remove: function remove(element, settings) { - var wrapperElement = element.parent(); + var wrapperElement = element.closest(settings.wrapper_tag + '.' + settings.wrapper_class.replace(/ /g, '.')); var errorElement = wrapperElement.find(settings.error_tag + '.invalid-feedback'); wrapperElement.removeClass(settings.wrapper_error_class); element.removeClass('is-invalid'); diff --git a/dist/simple-form.bootstrap4.js b/dist/simple-form.bootstrap4.js index e5bd428..15c3089 100644 --- a/dist/simple-form.bootstrap4.js +++ b/dist/simple-form.bootstrap4.js @@ -26,7 +26,8 @@ wrappers: { "default": { add: function add(element, settings, message) { - var wrapperElement = element.parent(); + var parentElement = element.parent(); + var wrapperElement = element.closest(settings.wrapper_tag + '.' + settings.wrapper_class.replace(/ /g, '.')); var errorElement = wrapperElement.find(settings.error_tag + '.invalid-feedback'); if (!errorElement.length) { @@ -34,7 +35,7 @@ "class": 'invalid-feedback', text: message }); - wrapperElement.append(errorElement); + parentElement.append(errorElement); } wrapperElement.addClass(settings.wrapper_error_class); @@ -42,7 +43,7 @@ errorElement.text(message); }, remove: function remove(element, settings) { - var wrapperElement = element.parent(); + var wrapperElement = element.closest(settings.wrapper_tag + '.' + settings.wrapper_class.replace(/ /g, '.')); var errorElement = wrapperElement.find(settings.error_tag + '.invalid-feedback'); wrapperElement.removeClass(settings.wrapper_error_class); element.removeClass('is-invalid'); diff --git a/src/main.bootstrap4.js b/src/main.bootstrap4.js index 7c4175a..01e2e4e 100644 --- a/src/main.bootstrap4.js +++ b/src/main.bootstrap4.js @@ -15,12 +15,14 @@ ClientSideValidations.formBuilders['SimpleForm::FormBuilder'] = { wrappers: { default: { add (element, settings, message) { - const wrapperElement = element.closest(settings.wrapper_tag + '.' + settings.wrapper_class.replace(/\ /g, '.')); + const parentElement = element.parent() + const wrapperElement = element.closest(settings.wrapper_tag + '.' + settings.wrapper_class.replace(/ /g, '.')) + let errorElement = wrapperElement.find(settings.error_tag + '.invalid-feedback') if (!errorElement.length) { errorElement = $('<' + settings.error_tag + '>', { class: 'invalid-feedback', text: message }) - wrapperElement.append(errorElement) + parentElement.append(errorElement) } wrapperElement.addClass(settings.wrapper_error_class) @@ -29,7 +31,7 @@ ClientSideValidations.formBuilders['SimpleForm::FormBuilder'] = { }, remove (element, settings) { - const wrapperElement = settings.wrapper_tag + "." + settings.wrapper_class.replace(/\ /g, ".") + const wrapperElement = element.closest(settings.wrapper_tag + '.' + settings.wrapper_class.replace(/ /g, '.')) const errorElement = wrapperElement.find(settings.error_tag + '.invalid-feedback') wrapperElement.removeClass(settings.wrapper_error_class) diff --git a/test/javascript/public/test/form_builders/validateHorizontalSimpleFormBootstrap4.js b/test/javascript/public/test/form_builders/validateHorizontalSimpleFormBootstrap4.js new file mode 100644 index 0000000..b439e17 --- /dev/null +++ b/test/javascript/public/test/form_builders/validateHorizontalSimpleFormBootstrap4.js @@ -0,0 +1,125 @@ +QUnit.module('Validate Horizontal wrapper SimpleForm Bootstrap 4', { + before: function () { + currentFormBuilder = window.ClientSideValidations.formBuilders['SimpleForm::FormBuilder'] + window.ClientSideValidations.formBuilders['SimpleForm::FormBuilder'] = BS4_FORM_BUILDER + }, + + after: function () { + window.ClientSideValidations.formBuilders['SimpleForm::FormBuilder'] = currentFormBuilder + }, + + beforeEach: function () { + dataCsv = { + html_settings: { + type: 'SimpleForm::FormBuilder', + error_class: 'is-invalid', + error_tag: 'div', + wrapper_error_class: 'form-group-invalid', + wrapper_tag: 'div', + wrapper_class: 'form-group' + }, + validators: { + 'user[name]': { presence: [{ message: 'must be present' }], format: [{ message: 'is invalid', 'with': { options: 'g', source: '\\d+' } }] }, + 'user[username]': { presence: [{ message: 'must be present' }] } + } + } + + $('#qunit-fixture') + .append( + $('
', { + action: '/users', + 'data-client-side-validations': JSON.stringify(dataCsv), + method: 'post', + id: 'new_user' + }) + .append( + $('
', { 'class': 'form-group row' }) + .append( + $('')) + .append( + $('
', { 'class': 'col-sm-9' }) + .append( + $('', { 'class': 'form-control', name: 'user[name]', id: 'user_name', type: 'text' })))) + // there isn't horizontal :input_group wrapper in simple_form's bootstrap 4 configuration by default + // but if somebody would do it it would look like this + .append( + $('
', { 'class': 'form-group row' }) + .append( + $('')) + .append( + $('
', { 'class': 'col-sm-9' }) + .append( + $('
', { 'class': 'input-group' }) + .append( + $('
', { 'class': 'input-group-prepend' }) + .append( + $('', { 'class': 'input-group-text', text: '@' }))) + .append( + $('', { 'class': 'form-control', name: 'user[username]', id: 'user_username', type: 'text' })))))) + + $('form#new_user').validate() + } +}) + +var wrappers = ['horizontal_form' ] + +for (var i = 0; i < wrappers.length; i++) { + var wrapper = wrappers[i] + + QUnit.test(wrapper + ' - Validate error attaching and detaching', function (assert) { + var form = $('form#new_user') + var input = form.find('input#user_name') + var label = $('label[for="user_name"]') + form[0].ClientSideValidations.settings.html_settings.wrapper = wrapper + + input.trigger('focusout') + assert.ok(input.closest('.form-group').hasClass('form-group-invalid')) + assert.ok(label.parent().hasClass('form-group-invalid')) + assert.ok(input.parent().find('div.invalid-feedback:contains("must be present")')[0]) + + input.val('abc') + input.trigger('change') + input.trigger('focusout') + assert.ok(input.closest('.form-group').hasClass('form-group-invalid')) + assert.ok(input.parent().find('div.invalid-feedback:contains("is invalid")')[0]) + assert.ok(input.hasClass('is-invalid')) + + input.val('123') + input.trigger('change') + input.trigger('focusout') + assert.notOk(input.closest('.form-group').parent().hasClass('form-group-invalid')) + assert.notOk(input.parent().parent().find('div.invalid-feedback:contains("is invalid")')[0]) + assert.notOk(input.hasClass('is-invalid')) + }) + + QUnit.test(wrapper + ' - Validate pre-existing error blocks are re-used', function (assert) { + var form = $('form#new_user'); var input = form.find('input#user_name') + var label = $('label[for="user_name"]') + form[0].ClientSideValidations.settings.html_settings.wrapper = wrapper + + input.parent().append($('
Error from Server')) + assert.ok(input.parent().find('div.invalid-feedback:contains("Error from Server")')[0]) + input.val('abc') + input.trigger('change') + input.trigger('focusout') + assert.ok(input.closest('.form-group').hasClass('form-group-invalid')) + assert.ok(label.parent().hasClass('form-group-invalid')) + assert.ok(input.parent().find('div.invalid-feedback:contains("is invalid")').length === 1) + assert.ok(form.find('div.invalid-feedback').length === 1) + }) + + QUnit.test(wrapper + ' - Validate input-group', function (assert) { + var form = $('form#new_user'); var input = form.find('input#user_username') + form[0].ClientSideValidations.settings.html_settings.wrapper = wrapper + + input.trigger('change') + input.trigger('focusout') + assert.ok(input.closest('.input-group-prepend').find('div.invalid-feedback').length === 0) + assert.ok(input.closest('.input-group').find('div.invalid-feedback').length === 1) + + input.val('abc') + input.trigger('change') + input.trigger('focusout') + assert.ok(input.closest('.input-group').find('div.invalid-feedback').length === 0) + }) +} diff --git a/vendor/assets/javascripts/rails.validations.simple_form.bootstrap4.js b/vendor/assets/javascripts/rails.validations.simple_form.bootstrap4.js index e5bd428..15c3089 100644 --- a/vendor/assets/javascripts/rails.validations.simple_form.bootstrap4.js +++ b/vendor/assets/javascripts/rails.validations.simple_form.bootstrap4.js @@ -26,7 +26,8 @@ wrappers: { "default": { add: function add(element, settings, message) { - var wrapperElement = element.parent(); + var parentElement = element.parent(); + var wrapperElement = element.closest(settings.wrapper_tag + '.' + settings.wrapper_class.replace(/ /g, '.')); var errorElement = wrapperElement.find(settings.error_tag + '.invalid-feedback'); if (!errorElement.length) { @@ -34,7 +35,7 @@ "class": 'invalid-feedback', text: message }); - wrapperElement.append(errorElement); + parentElement.append(errorElement); } wrapperElement.addClass(settings.wrapper_error_class); @@ -42,7 +43,7 @@ errorElement.text(message); }, remove: function remove(element, settings) { - var wrapperElement = element.parent(); + var wrapperElement = element.closest(settings.wrapper_tag + '.' + settings.wrapper_class.replace(/ /g, '.')); var errorElement = wrapperElement.find(settings.error_tag + '.invalid-feedback'); wrapperElement.removeClass(settings.wrapper_error_class); element.removeClass('is-invalid');