modules.spec.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877
  1. import Vue from 'vue'
  2. import Vuex from '../../src/index'
  3. const TEST = 'TEST'
  4. describe('Modules', () => {
  5. describe('module registration', () => {
  6. it('dynamic module registration', () => {
  7. const store = new Vuex.Store({
  8. strict: true,
  9. modules: {
  10. foo: {
  11. state: { bar: 1 },
  12. mutations: { inc: state => state.bar++ },
  13. actions: { incFoo: ({ commit }) => commit('inc') },
  14. getters: { bar: state => state.bar }
  15. }
  16. }
  17. })
  18. expect(() => {
  19. store.registerModule('hi', {
  20. state: { a: 1 },
  21. mutations: { inc: state => state.a++ },
  22. actions: { inc: ({ commit }) => commit('inc') },
  23. getters: { a: state => state.a }
  24. })
  25. }).not.toThrow()
  26. expect(store._mutations.inc.length).toBe(2)
  27. expect(store.state.hi.a).toBe(1)
  28. expect(store.getters.a).toBe(1)
  29. // assert initial modules work as expected after dynamic registration
  30. expect(store.state.foo.bar).toBe(1)
  31. expect(store.getters.bar).toBe(1)
  32. // test dispatching actions defined in dynamic module
  33. store.dispatch('inc')
  34. expect(store.state.hi.a).toBe(2)
  35. expect(store.getters.a).toBe(2)
  36. expect(store.state.foo.bar).toBe(2)
  37. expect(store.getters.bar).toBe(2)
  38. // unregister
  39. store.unregisterModule('hi')
  40. expect(store.state.hi).toBeUndefined()
  41. expect(store.getters.a).toBeUndefined()
  42. expect(store._mutations.inc.length).toBe(1)
  43. expect(store._actions.inc).toBeUndefined()
  44. // assert initial modules still work as expected after unregister
  45. store.dispatch('incFoo')
  46. expect(store.state.foo.bar).toBe(3)
  47. expect(store.getters.bar).toBe(3)
  48. })
  49. it('dynamic module registration with namespace inheritance', () => {
  50. const store = new Vuex.Store({
  51. modules: {
  52. a: {
  53. namespaced: true
  54. }
  55. }
  56. })
  57. const actionSpy = jest.fn()
  58. const mutationSpy = jest.fn()
  59. store.registerModule(['a', 'b'], {
  60. state: { value: 1 },
  61. getters: { foo: state => state.value },
  62. actions: { foo: actionSpy },
  63. mutations: { foo: mutationSpy }
  64. })
  65. expect(store.state.a.b.value).toBe(1)
  66. expect(store.getters['a/foo']).toBe(1)
  67. store.dispatch('a/foo')
  68. expect(actionSpy).toHaveBeenCalled()
  69. store.commit('a/foo')
  70. expect(mutationSpy).toHaveBeenCalled()
  71. })
  72. it('dynamic module existance test', () => {
  73. const store = new Vuex.Store({})
  74. store.registerModule('bonjour', {})
  75. expect(store.hasModule('bonjour')).toBe(true)
  76. store.unregisterModule('bonjour')
  77. expect(store.hasModule('bonjour')).toBe(false)
  78. })
  79. it('dynamic module existance test with nested modules', () => {
  80. const store = new Vuex.Store({})
  81. store.registerModule('a', {})
  82. store.registerModule(['a', 'b'], {})
  83. expect(store.hasModule(['a'])).toBe(true)
  84. expect(store.hasModule(['a', 'b'])).toBe(true)
  85. expect(store.hasModule(['c'])).toBe(false)
  86. expect(store.hasModule(['c', 'd'])).toBe(false)
  87. })
  88. it('dynamic module registration preserving hydration', () => {
  89. const store = new Vuex.Store({})
  90. store.replaceState({ a: { foo: 'state' }})
  91. const actionSpy = jest.fn()
  92. const mutationSpy = jest.fn()
  93. store.registerModule('a', {
  94. namespaced: true,
  95. getters: { foo: state => state.foo },
  96. actions: { foo: actionSpy },
  97. mutations: { foo: mutationSpy }
  98. }, { preserveState: true })
  99. expect(store.state.a.foo).toBe('state')
  100. expect(store.getters['a/foo']).toBe('state')
  101. store.dispatch('a/foo')
  102. expect(actionSpy).toHaveBeenCalled()
  103. store.commit('a/foo')
  104. expect(mutationSpy).toHaveBeenCalled()
  105. })
  106. })
  107. // #524
  108. it('should not fire an unrelated watcher', done => {
  109. const spy = jest.fn()
  110. const store = new Vuex.Store({
  111. modules: {
  112. a: {
  113. state: { value: 1 }
  114. },
  115. b: {}
  116. }
  117. })
  118. store.watch(state => state.a, spy)
  119. store.registerModule(['b', 'c'], {
  120. state: { value: 2 }
  121. })
  122. Vue.nextTick(() => {
  123. expect(spy).not.toHaveBeenCalled()
  124. done()
  125. })
  126. })
  127. describe('modules usage', () => {
  128. it('state as function (multiple module in same store)', () => {
  129. const module = {
  130. state () {
  131. return { a: 0 }
  132. },
  133. mutations: {
  134. [TEST] (state, n) {
  135. state.a += n
  136. }
  137. }
  138. }
  139. const store = new Vuex.Store({
  140. modules: {
  141. one: module,
  142. two: module
  143. }
  144. })
  145. expect(store.state.one.a).toBe(0)
  146. expect(store.state.two.a).toBe(0)
  147. store.commit(TEST, 1)
  148. expect(store.state.one.a).toBe(1)
  149. expect(store.state.two.a).toBe(1)
  150. })
  151. it('state as function (same module in multiple stores)', () => {
  152. const module = {
  153. state () {
  154. return { a: 0 }
  155. },
  156. mutations: {
  157. [TEST] (state, n) {
  158. state.a += n
  159. }
  160. }
  161. }
  162. const storeA = new Vuex.Store({
  163. modules: {
  164. foo: module
  165. }
  166. })
  167. const storeB = new Vuex.Store({
  168. modules: {
  169. bar: module
  170. }
  171. })
  172. expect(storeA.state.foo.a).toBe(0)
  173. expect(storeB.state.bar.a).toBe(0)
  174. storeA.commit(TEST, 1)
  175. expect(storeA.state.foo.a).toBe(1)
  176. expect(storeB.state.bar.a).toBe(0)
  177. storeB.commit(TEST, 2)
  178. expect(storeA.state.foo.a).toBe(1)
  179. expect(storeB.state.bar.a).toBe(2)
  180. })
  181. it('module: mutation', function () {
  182. const mutations = {
  183. [TEST] (state, n) {
  184. state.a += n
  185. }
  186. }
  187. const store = new Vuex.Store({
  188. state: {
  189. a: 1
  190. },
  191. mutations,
  192. modules: {
  193. nested: {
  194. state: { a: 2 },
  195. mutations,
  196. modules: {
  197. one: {
  198. state: { a: 3 },
  199. mutations
  200. },
  201. nested: {
  202. modules: {
  203. two: {
  204. state: { a: 4 },
  205. mutations
  206. },
  207. three: {
  208. state: { a: 5 },
  209. mutations
  210. }
  211. }
  212. }
  213. }
  214. },
  215. four: {
  216. state: { a: 6 },
  217. mutations
  218. }
  219. }
  220. })
  221. store.commit(TEST, 1)
  222. expect(store.state.a).toBe(2)
  223. expect(store.state.nested.a).toBe(3)
  224. expect(store.state.nested.one.a).toBe(4)
  225. expect(store.state.nested.nested.two.a).toBe(5)
  226. expect(store.state.nested.nested.three.a).toBe(6)
  227. expect(store.state.four.a).toBe(7)
  228. })
  229. it('module: action', function () {
  230. let calls = 0
  231. const makeAction = n => {
  232. return {
  233. [TEST] ({ state, rootState }) {
  234. calls++
  235. expect(state.a).toBe(n)
  236. expect(rootState).toBe(store.state)
  237. }
  238. }
  239. }
  240. const store = new Vuex.Store({
  241. state: {
  242. a: 1
  243. },
  244. actions: makeAction(1),
  245. modules: {
  246. nested: {
  247. state: { a: 2 },
  248. actions: makeAction(2),
  249. modules: {
  250. one: {
  251. state: { a: 3 },
  252. actions: makeAction(3)
  253. },
  254. nested: {
  255. modules: {
  256. two: {
  257. state: { a: 4 },
  258. actions: makeAction(4)
  259. },
  260. three: {
  261. state: { a: 5 },
  262. actions: makeAction(5)
  263. }
  264. }
  265. }
  266. }
  267. },
  268. four: {
  269. state: { a: 6 },
  270. actions: makeAction(6)
  271. }
  272. }
  273. })
  274. store.dispatch(TEST)
  275. expect(calls).toBe(6)
  276. })
  277. it('module: getters', function () {
  278. const makeGetter = n => ({
  279. [`getter${n}`]: (state, getters, rootState) => {
  280. expect(getters.constant).toBe(0)
  281. expect(rootState).toBe(store.state)
  282. return state.a
  283. }
  284. })
  285. const store = new Vuex.Store({
  286. state: {
  287. a: 1
  288. },
  289. getters: {
  290. constant: () => 0,
  291. ...makeGetter(1)
  292. },
  293. modules: {
  294. nested: {
  295. state: { a: 2 },
  296. getters: makeGetter(2),
  297. modules: {
  298. one: {
  299. state: { a: 3 },
  300. getters: makeGetter(3)
  301. },
  302. nested: {
  303. modules: {
  304. two: {
  305. state: { a: 4 },
  306. getters: makeGetter(4)
  307. },
  308. three: {
  309. state: { a: 5 },
  310. getters: makeGetter(5)
  311. }
  312. }
  313. }
  314. }
  315. },
  316. four: {
  317. state: { a: 6 },
  318. getters: makeGetter(6)
  319. }
  320. }
  321. })
  322. ;[1, 2, 3, 4, 5, 6].forEach(n => {
  323. expect(store.getters[`getter${n}`]).toBe(n)
  324. })
  325. })
  326. it('module: namespace', () => {
  327. const actionSpy = jest.fn()
  328. const mutationSpy = jest.fn()
  329. const store = new Vuex.Store({
  330. modules: {
  331. a: {
  332. namespaced: true,
  333. state: {
  334. a: 1
  335. },
  336. getters: {
  337. b: () => 2
  338. },
  339. actions: {
  340. [TEST]: actionSpy
  341. },
  342. mutations: {
  343. [TEST]: mutationSpy
  344. }
  345. }
  346. }
  347. })
  348. expect(store.state.a.a).toBe(1)
  349. expect(store.getters['a/b']).toBe(2)
  350. store.dispatch('a/' + TEST)
  351. expect(actionSpy).toHaveBeenCalled()
  352. store.commit('a/' + TEST)
  353. expect(mutationSpy).toHaveBeenCalled()
  354. })
  355. it('module: nested namespace', () => {
  356. // mock module generator
  357. const actionSpys = []
  358. const mutationSpys = []
  359. const createModule = (name, namespaced, children) => {
  360. const actionSpy = jest.fn()
  361. const mutationSpy = jest.fn()
  362. actionSpys.push(actionSpy)
  363. mutationSpys.push(mutationSpy)
  364. return {
  365. namespaced,
  366. state: {
  367. [name]: true
  368. },
  369. getters: {
  370. [name]: state => state[name]
  371. },
  372. actions: {
  373. [name]: actionSpy
  374. },
  375. mutations: {
  376. [name]: mutationSpy
  377. },
  378. modules: children
  379. }
  380. }
  381. // mock module
  382. const modules = {
  383. a: createModule('a', true, { // a/a
  384. b: createModule('b', false, { // a/b - does not add namespace
  385. c: createModule('c', true) // a/c/c
  386. }),
  387. d: createModule('d', true) // a/d/d
  388. })
  389. }
  390. const store = new Vuex.Store({ modules })
  391. const expectedTypes = [
  392. 'a/a', 'a/b', 'a/c/c', 'a/d/d'
  393. ]
  394. // getters
  395. expectedTypes.forEach(type => {
  396. expect(store.getters[type]).toBe(true)
  397. })
  398. // actions
  399. expectedTypes.forEach(type => {
  400. store.dispatch(type)
  401. })
  402. actionSpys.forEach(spy => {
  403. expect(spy).toHaveBeenCalledTimes(1)
  404. })
  405. // mutations
  406. expectedTypes.forEach(type => {
  407. store.commit(type)
  408. })
  409. mutationSpys.forEach(spy => {
  410. expect(spy).toHaveBeenCalledTimes(1)
  411. })
  412. })
  413. it('module: getters are namespaced in namespaced module', () => {
  414. const store = new Vuex.Store({
  415. state: { value: 'root' },
  416. getters: {
  417. foo: state => state.value
  418. },
  419. modules: {
  420. a: {
  421. namespaced: true,
  422. state: { value: 'module' },
  423. getters: {
  424. foo: state => state.value,
  425. bar: (state, getters) => getters.foo,
  426. baz: (state, getters, rootState, rootGetters) => rootGetters.foo
  427. }
  428. }
  429. }
  430. })
  431. expect(store.getters['a/foo']).toBe('module')
  432. expect(store.getters['a/bar']).toBe('module')
  433. expect(store.getters['a/baz']).toBe('root')
  434. })
  435. it('module: action context is namespaced in namespaced module', done => {
  436. const rootActionSpy = jest.fn()
  437. const rootMutationSpy = jest.fn()
  438. const moduleActionSpy = jest.fn()
  439. const moduleMutationSpy = jest.fn()
  440. const store = new Vuex.Store({
  441. state: { value: 'root' },
  442. getters: { foo: state => state.value },
  443. actions: { foo: rootActionSpy },
  444. mutations: { foo: rootMutationSpy },
  445. modules: {
  446. a: {
  447. namespaced: true,
  448. state: { value: 'module' },
  449. getters: { foo: state => state.value },
  450. actions: {
  451. foo: moduleActionSpy,
  452. test ({ dispatch, commit, getters, rootGetters }) {
  453. expect(getters.foo).toBe('module')
  454. expect(rootGetters.foo).toBe('root')
  455. dispatch('foo')
  456. expect(moduleActionSpy).toHaveBeenCalledTimes(1)
  457. dispatch('foo', null, { root: true })
  458. expect(rootActionSpy).toHaveBeenCalledTimes(1)
  459. commit('foo')
  460. expect(moduleMutationSpy).toHaveBeenCalledTimes(1)
  461. commit('foo', null, { root: true })
  462. expect(rootMutationSpy).toHaveBeenCalledTimes(1)
  463. done()
  464. }
  465. },
  466. mutations: { foo: moduleMutationSpy }
  467. }
  468. }
  469. })
  470. store.dispatch('a/test')
  471. })
  472. it('module: use other module that has same namespace', done => {
  473. const actionSpy = jest.fn()
  474. const mutationSpy = jest.fn()
  475. const store = new Vuex.Store({
  476. modules: {
  477. parent: {
  478. namespaced: true,
  479. modules: {
  480. a: {
  481. state: { value: 'a' },
  482. getters: { foo: state => state.value },
  483. actions: { foo: actionSpy },
  484. mutations: { foo: mutationSpy }
  485. },
  486. b: {
  487. state: { value: 'b' },
  488. getters: { bar: (state, getters) => getters.foo },
  489. actions: {
  490. test ({ dispatch, commit, getters }) {
  491. expect(getters.foo).toBe('a')
  492. expect(getters.bar).toBe('a')
  493. dispatch('foo')
  494. expect(actionSpy).toHaveBeenCalled()
  495. commit('foo')
  496. expect(mutationSpy).toHaveBeenCalled()
  497. done()
  498. }
  499. }
  500. }
  501. }
  502. }
  503. }
  504. })
  505. store.dispatch('parent/test')
  506. })
  507. it('module: warn when module overrides state', () => {
  508. jest.spyOn(console, 'warn').mockImplementation()
  509. const store = new Vuex.Store({
  510. modules: {
  511. foo: {
  512. state () {
  513. return { value: 1 }
  514. },
  515. modules: {
  516. value: {
  517. state: () => 2
  518. }
  519. }
  520. }
  521. }
  522. })
  523. expect(store.state.foo.value).toBe(2)
  524. expect(console.warn).toHaveBeenCalledWith(
  525. `[vuex] state field "value" was overridden by a module with the same name at "foo.value"`
  526. )
  527. })
  528. it('dispatching multiple actions in different modules', done => {
  529. const store = new Vuex.Store({
  530. modules: {
  531. a: {
  532. actions: {
  533. [TEST] () {
  534. return 1
  535. }
  536. }
  537. },
  538. b: {
  539. actions: {
  540. [TEST] () {
  541. return new Promise(r => r(2))
  542. }
  543. }
  544. }
  545. }
  546. })
  547. store.dispatch(TEST).then(res => {
  548. expect(res[0]).toBe(1)
  549. expect(res[1]).toBe(2)
  550. done()
  551. })
  552. })
  553. it('root actions dispatched in namespaced modules', done => {
  554. const store = new Vuex.Store({
  555. modules: {
  556. a: {
  557. namespaced: true,
  558. actions: {
  559. [TEST]: {
  560. root: true,
  561. handler () {
  562. return 1
  563. }
  564. }
  565. }
  566. },
  567. b: {
  568. namespaced: true,
  569. actions: {
  570. [TEST]: {
  571. root: true,
  572. handler () {
  573. return new Promise(r => r(2))
  574. }
  575. }
  576. }
  577. },
  578. c: {
  579. namespaced: true,
  580. actions: {
  581. [TEST]: {
  582. handler () {
  583. // Should not be called
  584. return 3
  585. }
  586. }
  587. }
  588. },
  589. d: {
  590. namespaced: true,
  591. actions: {
  592. [TEST] () {
  593. // Should not be called
  594. return 4
  595. }
  596. }
  597. }
  598. }
  599. })
  600. store.dispatch(TEST).then(res => {
  601. expect(res.length).toBe(2)
  602. expect(res[0]).toBe(1)
  603. expect(res[1]).toBe(2)
  604. done()
  605. })
  606. })
  607. it('plugins', function () {
  608. let initState
  609. const actionSpy = jest.fn()
  610. const mutations = []
  611. const subscribeActionSpy = jest.fn()
  612. const store = new Vuex.Store({
  613. state: {
  614. a: 1
  615. },
  616. mutations: {
  617. [TEST] (state, n) {
  618. state.a += n
  619. }
  620. },
  621. actions: {
  622. [TEST]: actionSpy
  623. },
  624. plugins: [
  625. store => {
  626. initState = store.state
  627. store.subscribe((mut, state) => {
  628. expect(state).toBe(state)
  629. mutations.push(mut)
  630. })
  631. store.subscribeAction(subscribeActionSpy)
  632. }
  633. ]
  634. })
  635. expect(initState).toBe(store.state)
  636. store.commit(TEST, 2)
  637. store.dispatch(TEST, 2)
  638. expect(mutations.length).toBe(1)
  639. expect(mutations[0].type).toBe(TEST)
  640. expect(mutations[0].payload).toBe(2)
  641. expect(actionSpy).toHaveBeenCalled()
  642. expect(subscribeActionSpy).toHaveBeenCalledWith(
  643. { type: TEST, payload: 2 },
  644. store.state
  645. )
  646. })
  647. it('action before/after subscribers', (done) => {
  648. const beforeSpy = jest.fn()
  649. const afterSpy = jest.fn()
  650. const store = new Vuex.Store({
  651. actions: {
  652. [TEST]: () => Promise.resolve()
  653. },
  654. plugins: [
  655. store => {
  656. store.subscribeAction({
  657. before: beforeSpy,
  658. after: afterSpy
  659. })
  660. }
  661. ]
  662. })
  663. store.dispatch(TEST, 2)
  664. expect(beforeSpy).toHaveBeenCalledWith(
  665. { type: TEST, payload: 2 },
  666. store.state
  667. )
  668. expect(afterSpy).not.toHaveBeenCalled()
  669. Vue.nextTick(() => {
  670. expect(afterSpy).toHaveBeenCalledWith(
  671. { type: TEST, payload: 2 },
  672. store.state
  673. )
  674. done()
  675. })
  676. })
  677. })
  678. it('action error subscribers', (done) => {
  679. const beforeSpy = jest.fn()
  680. const afterSpy = jest.fn()
  681. const errorSpy = jest.fn()
  682. const error = new Error()
  683. const store = new Vuex.Store({
  684. actions: {
  685. [TEST]: () => Promise.reject(error)
  686. },
  687. plugins: [
  688. store => {
  689. store.subscribeAction({
  690. before: beforeSpy,
  691. after: afterSpy,
  692. error: errorSpy
  693. })
  694. }
  695. ]
  696. })
  697. store.dispatch(TEST, 2).catch(() => {
  698. expect(beforeSpy).toHaveBeenCalledWith(
  699. { type: TEST, payload: 2 },
  700. store.state
  701. )
  702. expect(afterSpy).not.toHaveBeenCalled()
  703. Vue.nextTick(() => {
  704. expect(afterSpy).not.toHaveBeenCalledWith(
  705. { type: TEST, payload: 2 },
  706. store.state
  707. )
  708. expect(errorSpy).toHaveBeenCalledWith(
  709. { type: TEST, payload: 2 },
  710. store.state,
  711. error
  712. )
  713. done()
  714. })
  715. })
  716. })
  717. it('asserts a mutation should be a function', () => {
  718. expect(() => {
  719. new Vuex.Store({
  720. mutations: {
  721. test: null
  722. }
  723. })
  724. }).toThrowError(
  725. /mutations should be function but "mutations\.test" is null/
  726. )
  727. expect(() => {
  728. new Vuex.Store({
  729. modules: {
  730. foo: {
  731. modules: {
  732. bar: {
  733. mutations: {
  734. test: 123
  735. }
  736. }
  737. }
  738. }
  739. }
  740. })
  741. }).toThrowError(
  742. /mutations should be function but "mutations\.test" in module "foo\.bar" is 123/
  743. )
  744. })
  745. it('asserts an action should be a function', () => {
  746. expect(() => {
  747. new Vuex.Store({
  748. actions: {
  749. test: 'test'
  750. }
  751. })
  752. }).toThrowError(
  753. /actions should be function or object with "handler" function but "actions\.test" is "test"/
  754. )
  755. expect(() => {
  756. new Vuex.Store({
  757. modules: {
  758. foo: {
  759. modules: {
  760. bar: {
  761. actions: {
  762. test: 'error'
  763. }
  764. }
  765. }
  766. }
  767. }
  768. })
  769. }).toThrowError(
  770. /actions should be function or object with "handler" function but "actions\.test" in module "foo\.bar" is "error"/
  771. )
  772. })
  773. it('asserts a getter should be a function', () => {
  774. expect(() => {
  775. new Vuex.Store({
  776. getters: {
  777. test: undefined
  778. }
  779. })
  780. }).toThrowError(
  781. /getters should be function but "getters\.test" is undefined/
  782. )
  783. expect(() => {
  784. new Vuex.Store({
  785. modules: {
  786. foo: {
  787. modules: {
  788. bar: {
  789. getters: {
  790. test: true
  791. }
  792. }
  793. }
  794. }
  795. }
  796. })
  797. }).toThrowError(
  798. /getters should be function but "getters\.test" in module "foo\.bar" is true/
  799. )
  800. })
  801. })