第1页
React 应用实践
Coding · WebIDE
第2页
刘辉 (@hulufei)
第3页
第4页
第5页
Components
第6页
第7页
<WebIDE />
var App = React.createClass({
render: function() {
return (
<div>
<Menu />
<Tree />
...
</div>
)
}
})
JSX
var Menu = React.createClass(...)
var Tree = React.createClass(...)
// ...
第8页
第9页
Flux
Store
Action
View
emitChange
第10页
第11页
<SettingModal />
第12页
<Editor />
第13页
Editor Settings
SettingStore
<SettingModal />
<Editor />
SettingActions
emitChange
第14页
Addons
Bridge
第15页
Async Requests
Reads
Writes
第16页
Reads
Store
Components
Server
API Layer
Store.getData()
request.get(url)
.catch(errorAction)
第17页
Writes
Action
Components
Server
API Layer
Action.update()
request.post(url).catch(errorAction)
第18页
Writing Testable JavaScript
is hard
, once
第19页
Writing Testable JavaScript
Loose Coupling
第20页
Testing Flux Application
Testing Stores
Testing Components
第21页
Tools
Karma as test runner
Mocha as test framework
Sinon as test mocks
Chai as assertion library
Rewire as dependency injection
👉https://github.com/hulufei/karma-react-boilerplate
第22页
Testing Stores
Data persistency
Dispatch actions
第23页
beforeEach ->
sinon.spy AppDispatcher, 'register'
@callback = AppDispatcher.register.args[0][0]
rewire = require 'rewire'
# Test cases
fakeAction = { actionType: 'ACTION_TYPE' }
@callback fakeAction
expect(@store.getData()).to.be.equal 'something'
# Reset data
@store = rewire '../stores/SomeStore'
@store.__set__ '_data', 'fake store data'
第24页
–http://martinfowler.com/articles/asyncJS.html
“Aggressively limit the number of truly asynchronous tests you write and maintain.”
Testing Async Requests
第25页
Testing Async Requests
Stub API Layer
Use Promise
第26页
Stub API
API = require './utils/api'
stub = sinon.stub API, 'fetch'
stub.returns(Promise.resolve fakedResponse)
expect(stub).to.be.calledOnce
expect(data).to.eql fakedResponse
stub.returns(Promise.reject 'fake error')
expect(data).to.be.rejected
data = Store.getData()
第27页
Testing Components
DOM verify
DOM events simulate
第28页
React = require 'react/addons'
ContextMenu = require '../index'
TestUtils = React.addons.TestUtils
describe 'ContextMenu', ->
beforeEach ->
ContextMenuElement = React.createElement ContextMenu
@contextMenuComponent = TestUtils.renderIntoDocument ContextMenuElement
@el = React.findDOMNode @contextMenuComponent
it 'should render empty context menu', ->
expect(@el.className).to.contain 'context-menu'
expect(@el.className).to.contain 'hide'
it 'should invoke callback on menu close', ->
closeSpy = sinon.spy()
ContextMenuElement = React.createElement ContextMenu,
onMenuClose: closeSpy
component = TestUtils.renderIntoDocument ContextMenuElement
el = React.findDOMNode component
TestUtils.Simulate.blur el
expect(closeSpy).to.called.once
beforeEach ->
ContextMenuElement = React.createElement ContextMenu
@contextMenuComponent = TestUtils.renderIntoDocument ContextMenuElement
TestUtils.Simulate.blur el
expect(closeSpy).to.called.once
expect(@el.className).to.contain 'context-menu'
expect(@el.className).to.contain 'hide'
第29页
Awesome React
Immutable.js
Server side rendering
React styling
Relay and GraphQL
…
第30页
Q&A
关注我们