1
0
Evan You 9 жил өмнө
parent
commit
481d7c86fd
3 өөрчлөгдсөн 167 нэмэгдсэн , 0 устгасан
  1. 1 0
      docs/en/api.md
  2. 36 0
      docs/en/forms.md
  3. 130 0
      docs/en/testing.md

+ 1 - 0
docs/en/api.md

@@ -0,0 +1 @@
+# API Reference

+ 36 - 0
docs/en/forms.md

@@ -0,0 +1,36 @@
+# Form Handling
+
+When using Vuex in strict mode, it could be a bit tricky to use `v-model` on a piece of state that belongs to Vuex:
+
+``` html
+<input v-model="obj.message">
+```
+
+Assuming `obj` is a computed property that returns an Object from Vuex state, the `v-model` here will attempt to directly mutate `obj.message` when the user types in the input. In strict mode, this will result in en error because the mutation is not performed inside an explicit Vuex mutation handler.
+
+The "Vuex way" to deal with it is binding the `<input>`'s value and call an action on the `input` or `change` event:
+
+``` html
+<input :value="obj.message" @input="updateMessage">
+```
+``` js
+// ...
+methods: {
+  updateMessage: function (e) {
+    vuex.actions.updateMessage(e.target.value)
+  }
+}
+```
+
+Assuming the `updateMessage` action simply dispatches `'UPDATE_MESSAGE'`, here's the mutation handler:
+
+``` js
+// ...
+mutations: {
+  UPDATE_MESSAGE (state, message) {
+    state.obj.message = message
+  }
+}
+```
+
+Admittedly, this is quite a bit more verbose than a simple `v-model`, but such is the cost of making state changes explicit and track-able. At the same time, do note that Vuex doesn't demand putting all your state inside a Vuex instance - if you do not wish to track the mutations for form interactions at all, you can simply keep the form state outside of Vuex as component local state, which allows you to freely leverage `v-model`.

+ 130 - 0
docs/en/testing.md

@@ -0,0 +1,130 @@
+# Testing
+
+Mutations are very straightforward to test, because they are just functions that completely rely on their arguments. Actions can be a bit more tricky because they may call out to external APIs. When testing actions, we usually need to do some level of mocking - for example, we can abstract the API calls into a service and mock that service inside our tests. In order to easily mock dependencies, we can use Webpack and [inject-loader](https://github.com/plasticine/inject-loader) to bundle our test files.
+
+If your mutations and actions are written properly, the tests should have no direct dependency on Browser APIs after proper mocking. Thus you can simply bundle the tests with Webpack and run it directly in Node. Alternatively, you can use `mocha-loader` or Karma + `karma-webpack` to run the tests in real browsers.
+
+Example testing a mutation using Mocha + Chai (you can use any framework/assertion libraries you like):
+
+``` js
+// mutations.js
+export const INCREMENT = state => state.count++
+```
+
+``` js
+// mutations.spec.js
+import { expect } from 'chai'
+import { INCREMENT } from './mutations'
+
+describe('mutations', () => {
+  it('INCREMENT', () => {
+    // mock state
+    const state = { count: 0 }
+    // apply mutation
+    INCREMENT(state)
+    // assert result
+    expect(state.count).to.equal(1)
+  })
+})
+```
+
+Example testing an async action:
+
+``` js
+// actions.js
+import shop from '../api/shop'
+
+export const getAllProducts = () => dispatch => {
+  dispatch('REQUEST_PRODUCTS')
+  shop.getProducts(products => {
+    dispatch('RECEIVE_PRODUCTS', products)
+  })
+}
+```
+
+``` js
+// actions.spec.js
+
+// use require syntax for inline loaders.
+// with inject-loader, this returns a module factory
+// that allows us to inject mocked dependencies.
+import { expect } from 'chai'
+const actionsInjector = require('inject!babel!./actions')
+
+// create the module with our mocks
+const actions = actionsInjector({
+  '../api/shop': {
+    getProducts (cb) {
+      setTimeout(() => {
+        cb([ /* mocked response */ ])
+      }, 100)
+    }
+  }
+})
+
+// helper for testing action with expected mutations
+const testAction = (action, state, expectedMutations, done) => {
+  let count = 0
+  const mockedDispatch = (name, payload) => {
+    const mutation = expectedMutations[count]
+    expect(mutation.name).to.equal(name)
+    if (payload) {
+      expect(mutation.payload).to.deep.equal(payload)
+    }
+    count++
+    if (count >= expectedMutations.length) {
+      done()
+    }
+  }
+  action(mockedDispatch, state)
+}
+
+describe('actions', () => {
+  it('getAllProducts', done => {
+    testAction(actions.getAllProducts(), {}, [
+      { name: 'REQUEST_PRODUCTS' },
+      { name: 'RECEIVE_PRODUCTS', payload: [ /* mocked response */ ] }
+    ], done)
+  })
+})
+```
+
+### Running in Node
+
+Create the following webpack config:
+
+``` js
+module.exports = {
+  entry: './test.js',
+  output: {
+    path: __dirname,
+    filename: 'test-bundle.js'
+  },
+  module: {
+    loaders: [
+      {
+        test: /\.js$/,
+        loader: 'babel',
+        exclude: /node_modules/
+      }
+    ]
+  },
+  babel: {
+    presets: ['es2015']
+  }
+}
+```
+
+Then:
+
+``` bash
+webpack
+mocha test-bundle.js
+```
+
+### Running in Browser
+
+1. Install `mocha-loader`
+2. Change the `entry` from the Webpack config above to `'mocha!babel!./test.js'`. 
+3. Start `webpack-dev-server` using the config
+4. Go to `localhost:8080/webpack-dev-server/test-bundle`.