capejs/capejs

View on GitHub
test/spec/virtual_forms_test.js

Summary

Maintainability
C
1 day
Test Coverage
'use strict'

var isNode = typeof module !== 'undefined' && module.exports !== undefined

describe('VirtualForms', () => {
  beforeEach(() => {
    var div = document.createElement('div')
    div.id = "target"
    document.body.appendChild(div)
  })

  afterEach(() => {
    var element = document.getElementById('target')
    document.body.removeChild(element)
  })

  describe('val', () => {
    it('should get the value of a form field', () => {
      var component

      class Klass extends Cape.Component {
        init() {
          this.setValues('', { title: 'A', confirmed: true, genre: 'H' })
          this.refresh()
        }

        render(m) {
          m.form(function(m) {
            m.a({ name: 'name' })
            m.textField('title')
            m.textField('name', { value: 'B' })
            m.textField('ghost', { disabled: true, value: 'X' })
            m.textareaField('comment', { value: 'X' })
            m.checkBox('confirmed')
            m.checkBox('published')
            m.radioButton('color', 'red')
            m.radioButton('color', 'blue')
            m.radioButton('genre', 'G')
            m.radioButton('genre', 'H')
            m.hiddenField('uid', { value: '' })
          })
        }
      }

      component = new Klass()
      component.mount('target')
      expect(component.val('confirmed')).to.equal('1')
      component.val('name', 'C')
      component.val('published', true)
      component.val('color', 'blue')
      component.val('uid', '1000')
      component.refresh()

      expect(component.val('title')).to.equal('A')
      expect(component.val('name')).to.equal('C')
      expect(component.val('ghost')).to.equal('')
      expect(component.val('comment')).to.equal('X')
      expect(component.val('confirmed')).to.equal('1')
      expect(component.val('published')).to.equal('1')
      expect(component.val('color')).to.equal('blue')
      expect(component.val('genre')).to.equal('H')
      expect(component.val('uid')).to.equal('1000')
      expect(component.val('xxx')).to.equal('')
    })

    it('should toggle check boxes whose name end with []', () => {
      var component, elem

      class Klass extends Cape.Component {
        init() {
          this.setValues('', { 'types[]': [ 'a', 'b' ] })
          this.refresh()
        }

        render(m) {
          m.form(function(m) {
            m.checkBox('types[]', { value: 'a', id: 'type_a' } )
            m.checkBox('types[]', { value: 'b' } )
            m.checkBox('types[]', { value: 'c' } )
            m.checkBox('tags[]', { value: 'x', id: 'tag_x' } )
            m.checkBox('tags[]', { value: 'y' } )
            m.checkBox('tags[]', { value: 'z' } )
          })
        }
      }

      component = new Klass()
      component.mount('target')

      elem = document.getElementById('type_a')
      expect(elem.checked).to.be.true

      expect(component.val('types[]').length).to.equal(2)
      expect(component.val('tags[]').length).to.equal(0)

      component.val('types[]', [ 'a', 'c' ])
      elem = document.getElementById('tag_x')
      elem.checked = true

      component.refresh()
      elem = document.getElementById('tag_x')
      expect(elem.checked).to.be.true
      expect(component.val('types[]').length).to.equal(2)
      expect(component.val('types[]')[1]).to.equal('c')
      expect(component.val('tags[]').length).to.equal(1)
      expect(component.val('tags[]')[0]).to.equal('x')
    })

    it('should get the value of a select field', () => {
      var component

      class Klass extends Cape.Component {
        render(m) {
          m.form(function(m) {
            m.selectBox('genre', function(m) {
              m.option('X', { value: 'x' })
              m.option('Y', { value: 'y' })
            })
            m.selectBox('type', { value: 'b' }, function(m) {
              m.option('A', { value: 'a' })
              m.option('B', { value: 'b' })
              m.option('C', { value: 'c' })
            })
          })
        }
      }

      component = new Klass()
      component.mount('target')

      // The next assertion fails on jsdom, which returns the value of first option
      // when a select element has no selected option.
      if (!isNode) expect(component.val('genre')).to.equal('')
      expect(component.val('type')).to.equal('b')

      component.val('genre', 'y')
      component.val('type', 'c')
      component.refresh()
      expect(component.val('genre')).to.equal('y')
      expect(component.val('type')).to.equal('c')
    })

    it('should get the value of a field of named form', () => {
      var component

      class Klass extends Cape.Component {
        render(m) {
          m.formFor('foo', function(m) {
            m.textField('title', { value: 'A' })
            m.textField('name', { value: 'B' })
          })
        }
      }

      component = new Klass()
      component.mount('target')
      component.val('foo.name', 'C')
      expect(component.val('foo.title')).to.equal('A')
      expect(component.val('foo.name')).to.equal('C')
      expect(component.val('foo.xxx')).to.equal('')
      expect(component.val('bar.name')).to.equal('')
    })

    it('should set the value of a form field', () => {
      var component

      class Klass extends Cape.Component {
        render(m) {
          m.form(function(m) {
            m.textField('title')
            m.textField('name')
          })
        }
      }

      component = new Klass()
      component.mount('target')
      component.val('title', 'A')
      component.val('name', 'B')
      component.refresh()
      expect(component.val('title')).to.equal('A')
      expect(component.val('name')).to.equal('B')
    })

    it('should set the value of a field of named form', () => {
      var component

      class Klass extends Cape.Component {
        render(m) {
          m.form({ name: 'foo' }, function(m) {
            m.textField('title')
            m.textField('name')
          })
        }
      }

      component = new Klass()
      component.mount('target')
      component.val('foo.title', 'A')
      component.val('foo.name', 'B')
      component.refresh()
      expect(component.val('foo.title')).to.equal('A')
      expect(component.val('foo.name')).to.equal('B')
    })

    it('should set the value of a form field by a hash', () => {
      var component

      class Klass extends Cape.Component {
        render(m) {
          m.form(function(m) {
            m.textField('title')
            m.textField('name')
          })
        }
      }

      component = new Klass()
      component.mount('target')
      component.val({ title: 'A', name: 'B' })
      component.refresh()
      expect(component.val('title')).to.equal('A')
      expect(component.val('name')).to.equal('B')
    })

    it('should set the value of a field of named form by a hash', () => {
      var component

      class Klass extends Cape.Component {
        render(m) {
          m.form({ name: 'foo' }, function(m) {
            m.textField('title')
            m.textField('name')
          })
        }
      }

      component = new Klass()
      component.mount('target')
      component.val({ foo: { title: 'A', name: 'B'} })
      component.refresh()
      expect(component.val('foo.title')).to.equal('A')
      expect(component.val('foo.name')).to.equal('B')
    })

    it('should set a field value of a nested form', () => {
      var component

      class Klass extends Cape.Component {
        render(m) {
          m.formFor('book', function(m) {
            m.textField('title')
            m.fieldsFor('author', function(m) {
              m.textField('family_name')
              m.textField('given_name')
              m.fieldsFor('tags', { index: 0 }, function(m) {
                m.textField('value')
              })
              m.fieldsFor('tags', { index: 1 }, function(m) {
                m.textField('value')
              })
            })
            m.fieldsFor('comments', { index: 0 }, function(m) {
              m.textareaField('body')
            })
            m.fieldsFor('comments', { index: 1 }, function(m) {
              m.textareaField('body')
            })
          })
        }
      }

      component = new Klass()
      component.mount('target')
      component.val('book.author/family_name', 'Doe')
      component.val('book.author/tags/0/value', 'S')
      component.val('book.comments/1/body', 'Y')
      component.refresh()
      expect(component.val('book.author/family_name')).to.equal('Doe')
      expect(component.val('book.author/tags/0/value')).to.equal('S')
      expect(component.val('book.comments/1/body')).to.equal('Y')
    })

    it('should not change other forms', () => {
      var component, div, form

      class Klass extends Cape.Component {
        init() { this.mode = 'foo'; }
        render(m) {
          if (this.mode === 'foo')
            m.formFor('foo', function(m) {
              m.textField('title')
              m.checkBox('published')
            })
          else
            m.formFor('bar', function(m) {
              m.textField('title')
              m.checkBox('published')
            })
        }
      }

      component = new Klass()
      component.mount('target')
      component.val('foo.title', 'X')
      component.val('foo.published', true)
      component.refresh()

      div = document.getElementById('target')
      form = div.getElementsByTagName('form')[0]
      expect(form.name).to.equal('foo')
      expect(form.getElementsByTagName('input')[0].value).to.equal('X')
      expect(form.getElementsByTagName('input')[2].checked).to.be.true

      component.mode = 'bar'
      component.refresh()
      form = div.getElementsByTagName('form')[0]
      expect(form.name).to.equal('bar')
      expect(div.getElementsByTagName('input')[0].value).to.equal('')
      expect(form.getElementsByTagName('input')[2].checked).to.be.false
    })
  })

  describe('setValues', () => {
    it('should set the values of form fields', () => {
      var component

      class Klass extends Cape.Component {
        render(m) {
          m.formFor('book', function(m) {
            m.textField('title')
            m.textField('author')
          })
        }
      }

      component = new Klass()
      component.mount('target')
      component.setValues('book', { title: 'A', author: 'B' })
      component.refresh()
      expect(component.val('book.title')).to.equal('A')
      expect(component.val('book.author')).to.equal('B')
    })

    it('should set the field values of a nested form', () => {
      var component

      class Klass extends Cape.Component {
        render(m) {
          m.formFor('book', function(m) {
            m.textField('title')
            m.fieldsFor('author', function(m) {
              m.textField('family_name')
              m.textField('given_name')
              m.fieldsFor('tags', { index: 0 }, function(m) {
                m.textField('value')
              })
              m.fieldsFor('tags', { index: 1 }, function(m) {
                m.textField('value')
              })
            })
            m.fieldsFor('comments', { index: 0 }, function(m) {
              m.textareaField('body')
            })
            m.fieldsFor('comments', { index: 1 }, function(m) {
              m.textareaField('body')
            })
          })
        }
      }

      component = new Klass()
      component.mount('target')
      component.setValues('book', {
        title: 'A',
        author: {
          family_name: 'Doe', given_name: 'John',
          tags: [ { value: 'S' }, { value: 'T' } ]
        },
        comments: [
          { body: 'X' }, { body: 'Y' }
        ]
      })
      component.refresh()
      expect(component.val('book.title')).to.equal('A')
      expect(component.val('book.author/family_name')).to.equal('Doe')
      expect(component.val('book.author/tags/0/value')).to.equal('S')
      expect(component.val('book.comments/1/body')).to.equal('Y')
    })
  })

  describe('formData', () => {
    it('should return an object that contains parameters', () => {
      var component, params

      class Klass extends Cape.Component {
        render(m) {
          m.form(function(m) {
            m.textField('title', { value: 'A' })
            m.textField('name', { value: 'B' })
            m.checkBox('published', { checked: true })
            m.checkBox('deleted')
            m.fieldsFor('email', { index: 1 }, function(m) {
              m.textField('address', { value: 'foo@example.com' })
              m.checkBox('main')
            })
          })
        }
      }

      component = new Klass()
      component.mount('target')
      params = component.formData()

      expect(params.title).to.equal('A')
      expect(params.name).to.equal('B')
      expect(params.published).to.equal('1')
      expect(params.deleted).to.equal('0')
      expect(params.email['1'].address).to.equal('foo@example.com')
      expect(params.email['1'].main).to.equal('0')
    })

    it('should return an object that contains parameters for a named form', () => {
      var component, params

      class Klass extends Cape.Component {
        render(m) {
          m.formFor('article', function(m) {
            m.textField('title', { value: 'A' })
            m.textField('name', { value: 'B' })
          })
        }
      }

      component = new Klass()
      component.mount('target')
      params = component.formData('article')

      expect(params.title).to.equal('A')
      expect(params.name).to.equal('B')
    })

    it('should return array of values when the name of checkbox has "[]" in the end', () => {
      var component, params

      class Klass extends Cape.Component {
        render(m) {
          m.form(function(m) {
            m.checkBox('types[]', { value: 'a', checked: true })
            m.checkBox('types[]', { value: 'b', checked: true })
          })
        }
      }

      component = new Klass()
      component.mount('target')
      params = component.formData()
      expect(Array.isArray(params.types)).to.equal(true)
      expect(params.types.length).to.equal(2)
      expect(params.types[0]).to.equal('a')
      expect(params.types[1]).to.equal('b')
    })

    it('should return string when the name of checkbox does not have "[]" in the end', () => {
      var component, params

      class Klass extends Cape.Component {
        render(m) {
          m.form(function(m) {
            m.checkBox('types', { value: 'a', checked: true })
            m.checkBox('types', { value: 'b', checked: true })
          })
        }
      }

      component = new Klass()
      component.mount('target')
      params = component.formData()
      expect(Array.isArray(params.types)).to.equal(false)
      expect(params.types).to.equal('b')
    })
  })

  describe('paramsFor', () => {
    it('should return an object that is suitable for API requests', () => {
      var component, params

      class Klass extends Cape.Component {
        render(m) {
          m.formFor('article', function(m) {
            m.textField('title', { value: 'A' })
            m.textField('name', { value: 'B' })
            m.fieldsFor('comments', { index: 1 }, function(m) {
              m.textField('body', { value: 'C' })
            })
            m.fieldsFor('info', function(m) {
              m.textField('page_rank', { value: 'D' })
            })
          })
        }
      }

      component = new Klass()
      component.mount('target')
      params = component.paramsFor('article')

      expect(params.article.title).to.equal('A')
      expect(params.article.name).to.equal('B')
      expect(params.article.comments['1'].body).to.equal('C')
      expect(params.article.info.page_rank).to.equal('D')
    })

    it('should take "as" option to change parameter name', () => {
      var component, params

      class Klass extends Cape.Component {
        render(m) {
          m.formFor('blog', function(m) {
            m.textField('title', { value: 'A' })
            m.textField('name', { value: 'B' })
          })
        }
      }

      component = new Klass()
      component.mount('target')
      params = component.paramsFor('blog', { as: 'article' })

      expect(params.article.title).to.equal('A')
      expect(params.article.name).to.equal('B')
    })
  })

  describe('jsonFor', () => {
    it('should return a JSON string that contains form data', () => {
      var component, json, params

      class Klass extends Cape.Component {
        render(m) {
          m.formFor('article', function(m) {
            m.textField('title', { value: 'A' })
            m.textField('name', { value: 'B' })
            m.fieldsFor('comments', { index: 0 }, function(m) {
              m.textareaField('body', { value: 'X' })
            })
            m.fieldsFor('comments', { index: 1 }, function(m) {
              m.textareaField('body', { value: 'Y' })
            })
          })
        }
      }

      component = new Klass()
      component.mount('target')
      json = component.jsonFor('article')
      params = JSON.parse(json)

      expect(params.article.title).to.equal('A')
      expect(params.article.name).to.equal('B')
      expect(Array.isArray(params.article.comments)).to.be.true
      expect(params.article.comments[0].body).to.equal('X')
    })
  })

  describe('checkedOn', () => {
    it('should get the value of a check field', () => {
      var component

      class Klass extends Cape.Component {
        render(m) {
          m.form(function(m) {
            m.textField('name')
            m.textareaField('comment', { value: 'X' })
            m.checkBox('confirmed')
            m.checkBox('published')
            m.radioButton('color', 'red')
            m.radioButton('color', 'blue')
          })
          m.formFor('f2', function(m) {
            m.checkBox('confirmed')
          })
        }
      }

      component = new Klass()
      component.mount('target')
      expect(component.checkedOn('confirmed')).to.be.false

      component.val('published', true)
      component.val('color', 'blue')
      component.val('f2.confirmed', true)
      component.refresh()

      expect(component.checkedOn('name')).to.be.undefined
      expect(component.checkedOn('comment')).to.be.undefined
      expect(component.checkedOn('confirmed')).to.be.false
      expect(component.checkedOn('f2.confirmed')).to.be.true
      expect(component.checkedOn('published')).to.be.true
      expect(component.checkedOn('color')).to.be.undefined
      expect(component.checkedOn('xxx')).to.be.undefined
    })
  })
})