modules.spec.js 23 KB

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