Home Reference Source

src/components/button/Button.unit.js

import assert from 'power-assert';
import _ from 'lodash';
import Harness from '../../../test/harness';
import ButtonComponent from './Button';
import { Formio } from './../../Formio';
import sinon from 'sinon';

import {
  comp1,
  comp2,
  comp3
} from './fixtures';
import Webform from '../../Webform';
import formWithResetValue from '../../../test/formtest/formWithResetValue';

describe('Button Component', () => {
  it('Should build a button component', () => {
    return Harness.testCreate(ButtonComponent, comp1).then((component) => {
      const buttons = Harness.testElements(component, 'button[type="submit"]', 1);
      for (const button of buttons) {
        assert.equal(button.name, `data[${comp1.key}]`);
        assert.equal(button.innerHTML.trim(), comp1.label);
      }
    });
  });

  it('POST to URL button should pass URL and headers', (done) => {
    const formJson = {
      'type': 'form',
      'components': [{
          'label': 'Some Field',
          'type': 'textfield',
          'input': true,
          'key': 'someField'
        },
        {
          'label': 'POST to URL',
          'action': 'url',
          'url': 'someUrl',
          'headers': [{
            'header': 'testHeader',
            'value': 'testValue'
          }],
          'type': 'button',
          'input': true,
          'key': 'postToUrl'
        }
      ]
    };
    const element = document.createElement('div');
    Formio.createForm(element, formJson)
      .then(form => {
        const spy = sinon.spy(Formio, 'makeStaticRequest');
        form.getComponent('postToUrl').refs.button.click();
        const passedUrl = spy.firstCall.args[0];
        const passedHeaders = spy.firstCall.lastArg.headers;
        spy.restore();
        assert.deepEqual(passedHeaders, {
          'testHeader': 'testValue'
        });
        assert.equal(passedUrl, 'someUrl');
        done();
      })
      .catch(done);
  });

  it('Test on error', (done) => {
    const element = document.createElement('div');
    Formio.createForm(element, {
      components: [{
          type: 'textfield',
          key: 'a',
          label: 'A',
          validate: {
            required: true
          }
        },
        {
          type: 'button',
          action: 'submit',
          key: 'submit',
          disableOnInvalid: true,
          input: true
        }
      ]
    }).then(form => {
      form.on('change', () => {
        const button = form.getComponent('submit');
        assert(button.disabled, 'Button should be disabled');
        button.emit('submitError');
        setTimeout(() => {
          console.log('Text Content: ', button.refs.buttonMessage.innerHTML);
          assert.equal(button.refs.buttonMessage.textContent, 'Please check the form and correct all errors before submitting.');
          done();
        }, 100);
      });
      form.submission = {
        data: {}
      };
    }).catch(done);
  });

  it('POST to URL button should perform URL interpolation', (done) => {
    const formJson = {
      'type': 'form',
      'components': [{
          'label': 'Some Field',
          'type': 'textfield',
          'input': true,
          'key': 'someField'
        },
        {
          'label': 'URL',
          'type': 'textfield',
          'input': true,
          'key': 'url'
        },
        {
          'label': 'POST to URL',
          'action': 'url',
          'url': '{{data.url}}/submission',
          'type': 'button',
          'input': true,
          'key': 'postToUrl'
        }
      ]
    };
    const element = document.createElement('div');
    Formio.createForm(element, formJson)
      .then(form => {
        form.submission = {
          data: {
            url: 'someUrl'
          }
        };
        return form.submissionReady
          .then(() => {
            const spy = sinon.spy(Formio, 'makeStaticRequest');
            form.getComponent('postToUrl').refs.button.click();
            const passedUrl = spy.firstCall.args[0];
            spy.restore();
            assert.equal(passedUrl, 'someUrl/submission');
            done();
          });
      })
      .catch(done);
  });

  it('POST to URL button should perform headers interpolation', (done) => {
    const formJson = {
      'type': 'form',
      'components': [{
          'label': 'Some Field',
          'type': 'textfield',
          'input': true,
          'key': 'someField'
        },
        {
          'label': 'Header',
          'type': 'textfield',
          'input': true,
          'key': 'header'
        },
        {
          'label': 'POST to URL',
          'action': 'url',
          'url': 'someUrl',
          'headers': [{
            'header': 'testHeader',
            'value': 'Value {{data.header}}'
          }],
          'type': 'button',
          'input': true,
          'key': 'postToUrl'
        }
      ]
    };
    const element = document.createElement('div');
    Formio.createForm(element, formJson)
      .then(form => {
        form.submission = {
          data: {
            someField: 'some value',
            header: 'some header'
          }
        };
        return form.submissionReady
          .then(() => {
            const spy = sinon.spy(Formio, 'makeStaticRequest');
            form.getComponent('postToUrl').refs.button.click();
            const passedHeaders = spy.firstCall.lastArg.headers;
            spy.restore();
            assert.deepEqual(passedHeaders, {
              'testHeader': 'Value some header'
            });
            done();
          });
      })
      .catch(done);
  });

  it('Should not change color and show message if the error is silent', (done) => {
    const formJson = {
      'type': 'form',
      'components': [{
          'label': 'Some Field',
          'type': 'textfield',
          'input': true,
          'key': 'someField'
        },
        {
          'label': 'Submit',
          'action': 'submit',
          'type': 'button',
          'input': true,
          'key': 'submit'
        }
      ]
    };
    const element = document.createElement('div');
    Formio.createForm(element, formJson, {
        hooks: {
          beforeSubmit: function(submission, callback) {
            callback({
              message: 'Err',
              component: submission.component,
              silent: true,
            }, submission);
          }
        }
      })
      .then(form => {
        const button = form.getComponent('submit');
        button.emit('submitButton', {
          state: button.component.state || 'submitted',
          component: button.component,
          instance: button
        });
        setTimeout(() => {
          assert(!button.refs.button.className.includes('btn-danger submit-fail'));
          assert(!button.refs.button.className.includes('btn-success submit-success'));
          assert(!button.refs.buttonMessageContainer.className.includes('has-success'));
          assert(!button.refs.buttonMessageContainer.className.includes('has-error'));
          assert(button.refs.buttonMessage.innerHTML === '');
          done();
        }, 100);
      })
      .catch(done);
  });

  it('Should reset values of all the form\'s components and update properties dependent on values', (done) => {
    const formElement = document.createElement('div');
    const form = new Webform(formElement);

    form.setForm(formWithResetValue).then(() => {
      const select = form.getComponent(['showPanel']);

      select.setValue('yes');

      setTimeout(() => {
        const panel = form.getComponent(['panel']);
        const textField = form.getComponent(['textField']);
        const textArea = form.getComponent(['textArea']);

        assert.equal(panel.visible, true, 'Panel should be visible');
        assert.equal(textField.visible, true, 'TextFiled should be visible');
        assert.equal(textArea.visible, true, 'TextArea should be visible');

        const resetButton = form.getComponent(['reset']);
        resetButton.emit('resetForm');

        setTimeout(() => {
          const panel = form.getComponent(['panel']);
          const textField = form.getComponent(['textField']);
          const textArea = form.getComponent(['textArea']);

          assert.equal(panel.visible, false, 'Panel should NOT be visible');
          assert.equal(textField.visible, false, 'TextFiled should NOT be visible');
          assert.equal(textArea.visible, false, 'TextArea should NOT be visible');
          done();
        }, 300);
      }, 300);
    }).catch((err) => done(err));
  });

  it('Should perform custom logic', (done) => {
    const element = document.createElement('div');
    const form = new Webform(element);
    const testForm = {
      components: [{
          type: 'number',
          key: 'number',
          label: 'Number'
        },
        {
          type: 'button',
          key: 'custom',
          label: 'Custom',
          action: 'custom',
          custom: 'data[\'number\'] = 5555'
        }
      ]
    };

    form.setForm(testForm)
      .then(() => {
        const button = form.getComponent('custom');
        const changeEventTriggered = sinon.spy(button, 'triggerChange');
        button.refs.button.click();
        assert(changeEventTriggered.calledOnce, 'Click on custom button should trigger change event');
        form.on('change', () => {
          const {
            data
          } = form.submission;
          assert.deepEqual(data, {
            number: 5555,
            custom: true
          });
          done();
        });
      })
      .catch((err) => done(err));
  });

  it('Should correctly set theme', (done) => {
    const form = _.cloneDeep(comp2);
    const element = document.createElement('div');

    Formio.createForm(element, form).then(formObj => {
      const btns = formObj.components;
      const theme = ['warning', 'danger', 'success', 'info', 'secondary', 'primary'];

      _.each(btns, (btn, index) => {
        const btnClass = `btn-${theme[index]}`;
        const includeClass = btn.refs.button.classList.contains(btnClass);
        assert.equal(includeClass, true, `Should set ${theme[index]} theme for button`);
      });

      done();
    }).catch(done);
  });

  it('Should render block btn', (done) => {
    const form = _.cloneDeep(comp2);
    form.components = [{
      label: 'Submit',
      showValidations: false,
      block: true,
      tableView: false,
      key: 'submit',
      type: 'button',
      input: true
    }];

    const element = document.createElement('div');

    Formio.createForm(element, form).then(formObj => {
      const btn = formObj.components[0];
      const btnClass = 'btn-block';
      const includeClass = btn.refs.button.classList.contains(btnClass);

      assert.equal(includeClass, true, 'Should set btn-block class for button');

      done();
    }).catch(done);
  });

  it('Test event, reset, post, save in state actions', (done) => {
    const form = _.cloneDeep(comp3);
    const element = document.createElement('div');

    const originalMakeRequest = Formio.makeStaticRequest;
    Formio.makeStaticRequest = function(url, method, data) {
      assert.equal(url, 'https://test.com');
      assert.equal(method, 'POST');
      assert.deepEqual(data.data, {
        event: false,
        post: true,
        reset: false,
        saveInState: false
      });

      return new Promise(resolve => {
        resolve({
          ...data
        });
      });
    };

    Formio.createForm(element, form).then(form => {
      const formio = new Formio('http://test.localhost/test', {});

      formio.makeRequest = (type, url, method, data) => {
        assert.equal(data.state, 'testState');
        assert.equal(method.toUpperCase(), 'POST');

        return new Promise(resolve => resolve({
          ...data
        }));
      };

      form.formio = formio;

      const click = (btnComp) => {
        const elem = btnComp.refs.button;
        const clickEvent = new Event('click');
        elem.dispatchEvent(clickEvent);
      };

      const saveInStateBtn = form.getComponent('saveInState');
      click(saveInStateBtn);

      setTimeout(() => {
        const eventBtn = form.getComponent('event');
        click(eventBtn);

        setTimeout(() => {
          const numberComp = form.getComponent('number');
          assert.equal(numberComp.dataValue, 2);
          assert.equal(numberComp.getValue(), 2);

          const resetBtn = form.getComponent('reset');
          click(resetBtn);

          setTimeout(() => {
            const numberComp = form.getComponent('number');
            assert.equal(numberComp.dataValue, null);
            assert.equal(numberComp.getValue(), null);

            const postBtn = form.getComponent('post');
            click(postBtn);

            setTimeout(() => {
              Formio.makeStaticRequest = originalMakeRequest;
              done();
            }, 300);
          }, 300);
        }, 300);
      }, 300);
    }).catch(done);
  });
});