Skip to content
This repository was archived by the owner on Dec 12, 2020. It is now read-only.

Commit 3e1cfeb

Browse files
amirrustambahmutov
authored andcommitted
fix: Vuex integration and add Counter example tests (#13)
* fix: vuex integration (#6) The inner Vue instance within Vuex Store must be refeshed by `resetStoreVM` to restore reactivity of the store state. This doesn’t fix stale mapped getters within components. That’s a separate WIP issue. * fix: stale mapped getter `evenOrOdd` (#6) Current mapped vuex getters within components become stale. To have a working Counter example, the computed mapped `evenOrOdd` is accessed directly via `$store`. This will be changed back once the stale mapped getter issue (WIP) is fixed. * feat: added example tests for Counter component Added tests to cover all the features within the component. Fixes #6 * minor: following better practices
1 parent 7f1db65 commit 3e1cfeb

File tree

3 files changed

+73
-11
lines changed

3 files changed

+73
-11
lines changed

components/Counter.vue

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
2-
<div id="app">
3-
Clicked: {{ $store.state.count }} times, count is {{ evenOrOdd }}.
2+
<div>
3+
Clicked: {{ $store.state.count }} times, count is {{ $store.getters.evenOrOdd }}.
44
<button @click="increment">+</button>
55
<button @click="decrement">-</button>
66
<button @click="incrementIfOdd">Increment if odd</button>

cypress/integration/counter-vuex-spec.js

+34-3
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,50 @@
22
// https://github.com/vuejs/vuex/tree/dev/examples/counter
33
import Counter from '../../components/Counter.vue'
44
import store from '../../components/store'
5-
const mountVue = require('../..')
5+
import Vuex from 'vuex'
6+
import mountVue from '../..'
67

78
/* eslint-env mocha */
89
describe('Vuex Counter', () => {
9-
const extensions = {
10+
const extensions = {
11+
plugins: [Vuex],
1012
components: {
1113
counter: Counter
1214
},
1315
}
1416
const template = '<counter />'
1517
beforeEach(mountVue({template, store}, {extensions}))
1618

19+
const getCount = () =>
20+
Cypress.vue.$store.state.count
21+
22+
const setCount = value =>
23+
Cypress.vue.$set(Cypress.vue.$store.state, 'count', value)
24+
1725
it('starts with zero', () => {
18-
cy.contains('button', '0')
26+
cy.contains('0 times')
27+
})
28+
29+
it('increments the counter on click of "+"', () => {
30+
cy.contains('button', '+').click()
31+
cy.contains('1 times')
32+
})
33+
34+
it('decrements the counter on click of "-"', () => {
35+
cy.contains('button', '-').click()
36+
cy.contains('0 times')
37+
})
38+
39+
it('increments the counter if count is odd', () => {
40+
setCount(3)
41+
cy.contains('odd')
42+
cy.contains('button', 'Increment if odd').click()
43+
cy.contains('even')
44+
})
45+
46+
it('asynchronously increments counter', () => {
47+
const count = getCount()
48+
cy.contains('button', 'Increment async').click()
49+
cy.contains(`${count + 1} times`)
1950
})
2051
})

src/index.js

+37-6
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,7 @@ const deleteCachedConstructors = component => {
4545
const getVuePath = options =>
4646
options.vue || options.vuePath || '../node_modules/vue/dist/vue.js'
4747

48-
const getVuexPath = options =>
49-
options.vuex || options.vuexPath
48+
const getVuexPath = options => options.vuex || options.vuexPath
5049

5150
const getPageHTML = options => {
5251
if (options.html) {
@@ -91,7 +90,7 @@ const getPageHTML = options => {
9190
<body>
9291
<div id="app"></div>
9392
<script src="${vue}"></script>
94-
${vuex ? vuex : ''}
93+
${vuex || ''}
9594
</body>
9695
</html>
9796
`
@@ -136,6 +135,36 @@ const isOptions = object => Object.keys(object).every(isOptionName)
136135

137136
const isConstructor = object => object && object._compiled
138137

138+
const hasStore = ({ store }) => store && store._vm
139+
140+
const forEachValue = (obj, fn) => {
141+
Object.keys(obj).forEach(key => fn(obj[key], key))
142+
}
143+
144+
const resetStoreVM = (Vue, { store }) => {
145+
// bind store public getters
146+
store.getters = {}
147+
const wrappedGetters = store._wrappedGetters
148+
const computed = {}
149+
forEachValue(wrappedGetters, (fn, key) => {
150+
// use computed to leverage its lazy-caching mechanism
151+
computed[key] = () => fn(store)
152+
Object.defineProperty(store.getters, key, {
153+
get: () => store._vm[key],
154+
enumerable: true // for local getters
155+
})
156+
})
157+
158+
store._watcherVM = new Vue()
159+
store._vm = new Vue({
160+
data: {
161+
$$state: store._vm._data.$$state
162+
},
163+
computed
164+
})
165+
return store
166+
}
167+
139168
// the double function allows mounting a component quickly
140169
// beforeEach(mountVue(component, options))
141170
const mountVue = (component, optionsOrProps = {}) => () => {
@@ -159,6 +188,10 @@ const mountVue = (component, optionsOrProps = {}) => () => {
159188
.window({ log: false })
160189
.its('Vue')
161190
.then(Vue => {
191+
// refresh inner Vue instance of Vuex store
192+
if (hasStore(component)) {
193+
component.store = resetStoreVM(Vue, component)
194+
}
162195
installMixins(Vue, options)
163196
installPlugins(Vue, options)
164197
registerGlobalComponents(Vue, options)
@@ -169,9 +202,7 @@ const mountVue = (component, optionsOrProps = {}) => () => {
169202
Cypress.vue = new Cmp(props).$mount('#app')
170203
copyStyles(Cmp)
171204
} else {
172-
debugger
173-
// Cypress.vue = new Vue(component).$mount('#app')
174-
const allOptions = Object.assign({}, component, {el: '#app'})
205+
const allOptions = Object.assign({}, component, { el: '#app' })
175206
Cypress.vue = new Vue(allOptions)
176207
copyStyles(component)
177208
}

0 commit comments

Comments
 (0)