<NME> select.jsx
<BEF> ADDFILE
<MSG> fix disabled, and readOnly props for each widget

disabled and readonly should work as expected now, with readonly
allowing focus. Tests for select, combobox, and dropdown were added.

also fixes #15 and makes value prop usage consistent

<DFF> @@ -0,0 +1,212 @@
+require('../vendor/phantomjs-shim')
+
+var React = require('react/addons');
+var Select = require('../src/select/select.jsx')
+  , TagList = require('../src/select/tag-list.jsx')
+  , _ = require('lodash');
+
+
+var TestUtils = React.addons.TestUtils
+  , render = TestUtils.renderIntoDocument
+  , findTag = TestUtils.findRenderedDOMComponentWithTag
+  , findClass = TestUtils.findRenderedDOMComponentWithClass
+  , findAllTag = TestUtils.scryRenderedDOMComponentsWithTag
+  , findAllClass = TestUtils.scryRenderedDOMComponentsWithClass
+  , findType = TestUtils.findRenderedComponentWithType
+  , findAllType = TestUtils.scryRenderedComponentWithType
+  , trigger = TestUtils.Simulate;
+
+describe('Select', function(){
+  var dataList = [
+        { label: 'jimmy', id: 0 },
+        { label: 'sally', id: 1 },
+        { label: 'pat', id: 2 }
+      ];
+
+  it('should set initial values', function(){
+    var select = render(<Select value={['hello']} onChange={_.noop} />)
+      , tags   = findType(select, TagList).getDOMNode();
+
+    expect( tags.children[0].children[0].textContent).to.be('hello');
+  })
+
+  it('should respect textField and valueFields', function(){
+    var select = render(<Select value={[0]} data={dataList} textField='label' valueField='id' />)
+      , tags   = findType(select, TagList).getDOMNode();
+
+    expect( tags.children[0].children[0].textContent).to.be('jimmy');
+  }) 
+
+  it('should start closed', function(done){
+    var select = render(<Select value={[0]} data={dataList} textField='label' valueField='id' />);
+    var popup = findType(select, require('../src/popup/popup.jsx'));
+
+    expect(select.state.open).to.be(false)
+    expect(select.getDOMNode().className).to.not.match(/\brw-open\b/)
+    expect(findClass(select, 'rw-input').getDOMNode().getAttribute('aria-expanded')).to.be('false')
+  
+    setTimeout(function(){
+      expect(popup.getDOMNode().style.display).to.be('none')
+      done()
+    }, 0)
+  })
+
+  it('should open when clicked', function(done){
+    var select = render(<Select value={['jimmy']} data={dataList} duration={0}/>);
+    var popup = findType(select, require('../src/popup/popup.jsx'))
+
+    trigger.click(findClass(select, 'rw-select-wrapper').getDOMNode())
+
+    setTimeout(function() {
+      expect(select.state.open).to.be(true)
+      expect(select.getDOMNode().className).to.match(/\brw-open\b/)
+      expect(findClass(select, 'rw-input').getDOMNode().getAttribute('aria-expanded')).to.be('true')
+      expect(popup.props.open).to.be(true)
+      done()
+    }, 0) 
+  })
+
+  it('should remove tag when clicked', function(){
+    var del = sinon.spy()
+      , tags = render(
+          <TagList value={[dataList[0], dataList[1]]} data={dataList} textField='label' valueField='id' onDelete={del}/>)
+          .getDOMNode();
+
+    expect(tags.children.length).to.be(2)
+    trigger.click(tags.children[1].children[1]) // click button
+
+    expect(del.calledOnce).to.be(true)
+    expect(del.calledWith(dataList[1])).to.be(true)
+  })
+
+  it('should change value when tag is clicked', function(){
+    var change = sinon.spy()
+      , select = render(<Select onChange={change} value={[dataList[0], dataList[1]]} data={dataList} textField='label' valueField='id' />)
+      , tags   = findType(select, TagList).getDOMNode()
+
+    expect(tags.children.length).to.be(2)
+    trigger.click(tags.children[1].children[1]) // click button
+
+    expect(change.calledOnce).to.be(true)
+    expect(change.args[0][0]).to.eql([ dataList[0] ])
+  })
+
+  it('should do nothing when disabled', function(done){
+    var select = render(<Select value={['jimmy']} data={dataList} duration={0} disabled={true}/>)
+      , input  = findType(select, require('../src/select/search-input.jsx')).getDOMNode()
+      , tags   = findType(select, TagList).getDOMNode();
+
+    expect( input.hasAttribute('disabled')).to.be(true);
+    expect( input.getAttribute('aria-disabled')).to.be('true');
+    expect( input.getAttribute('disabled')).to.be('');
+
+    trigger.click(findTag(select, 'button').getDOMNode())
+
+    setTimeout(function() {
+      expect(select.state.open).to.be(false)
+      expect(tags.children.length).to.be(1)
+      expect(select.getDOMNode().className).to.not.match(/\brw-state-focus\b/)
+      done()
+    }, 0) 
+  })
+
+  it('should disable only certain tags', function(done){
+    var select = render(<Select value={[0,1]} data={dataList} disabled={[1]}  textField='label' valueField='id'/>)
+      , input  = findType(select, require('../src/select/search-input.jsx')).getDOMNode()
+      , tags   = findType(select, TagList).getDOMNode();
+
+    expect(tags.children.length).to.be(2)
+    expect(tags.children[1].className).to.match(/\brw-state-disabled\b/);
+
+    trigger.click(tags.children[1].children[1]) // click button
+
+    setTimeout(function() {
+      expect(select.state.open).to.be(true)
+      expect(tags.children.length).to.be(2)
+      done()
+    }, 0) 
+  })
+
+  it('should do nothing when readonly', function(done){
+    var select = render(<Select value={['jimmy']} data={dataList} duration={0} readOnly={true}/>)
+      , input  = findType(select, require('../src/select/search-input.jsx')).getDOMNode()
+      , tags   = findType(select, TagList).getDOMNode();
+
+    expect( input.hasAttribute('readonly')).to.be(true);
+    expect( input.getAttribute('aria-readonly')).to.be('true');
+    expect( input.getAttribute('readonly')).to.be('');
+
+    trigger.click(findTag(select, 'button').getDOMNode())
+
+    setTimeout(function() {
+      expect(select.state.open).to.be(false)
+      expect(tags.children.length).to.be(1)
+      done()
+    }, 0) 
+  })
+
+  it('should readonly only certain tags', function(done){
+    var select = render(<Select value={[0,1]} data={dataList} readOnly={[1]}  textField='label' valueField='id'/>)
+      , input  = findType(select, require('../src/select/search-input.jsx')).getDOMNode()
+      , tags   = findType(select, TagList).getDOMNode();
+
+    expect(tags.children.length).to.be(2)
+
+    trigger.click(tags.children[1].children[1]) // click button
+
+    setTimeout(function() {
+      expect(select.state.open).to.be(true)
+      expect(tags.children.length).to.be(2)
+      expect(select.getDOMNode().className).to.match(/\brw-state-focus\b/)
+
+      done()
+    }, 10) 
+  })
+
+  it('should change values on key down', function(){
+    var change = sinon.spy()
+      , select = render(<Select value={[0,1,2]} data={dataList} textField='label' valueField='id' onChange={change}/>)
+      , tags   = findType(select, TagList).getDOMNode();
+
+    trigger.keyDown(select.getDOMNode(), { key: 'ArrowLeft'})
+
+    expect(tags.children[2].className).to.match(/\brw-state-focus\b/)
+    expect(tags.children[1].className).to.not.match(/\brw-state-focus\b/)
+
+    trigger.keyDown(select.getDOMNode(), { key: 'ArrowLeft'})
+
+    expect(tags.children[1].className).to.match(/\brw-state-focus\b/)
+    expect(tags.children[2].className).to.not.match(/\brw-state-focus\b/)
+
+    trigger.keyDown(select.getDOMNode(), { key: 'ArrowRight'})
+
+    expect(tags.children[2].className).to.match(/\brw-state-focus\b/)
+    expect(tags.children[1].className).to.not.match(/\brw-state-focus\b/)
+
+    trigger.keyDown(select.getDOMNode(), { key: 'Home'})
+
+    expect(tags.children[0].className).to.match(/\brw-state-focus\b/)
+    expect(tags.children[1].className).to.not.match(/\brw-state-focus\b/)
+    
+    trigger.keyDown(select.getDOMNode(), { key: 'Delete'})
+
+    expect(change.calledOnce).to.be(true)
+    expect(change.args[0][0]).to.eql(dataList.slice(1, 3))
+    change.reset()
+
+    trigger.keyDown(select.getDOMNode(), { key: 'End'})
+
+    expect(tags.children[2].className).to.match(/\brw-state-focus\b/)
+    expect(tags.children[1].className).to.not.match(/\brw-state-focus\b/)
+
+    trigger.keyDown(select.getDOMNode(), { key: 'Backspace'})
+
+    expect(change.calledOnce).to.be(true)
+    expect(change.args[0][0]).to.eql(dataList.slice(0, 2))
+    change.reset()
+
+    trigger.keyDown(select.getDOMNode(), { key: 'ArrowDown'})
+    expect(select.state.open).to.be(true)
+  })
+
+})
\ No newline at end of file

fix disabled, and readOnly props for each widget