helpers.spec.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587
  1. import { mount } from 'test/helpers'
  2. import Vuex, { mapState, mapMutations, mapGetters, mapActions, createNamespacedHelpers } from '@/index'
  3. describe('Helpers', () => {
  4. it('mapState (array)', () => {
  5. const store = new Vuex.Store({
  6. state: {
  7. a: 1
  8. }
  9. })
  10. const vm = mount(store, {
  11. computed: mapState(['a'])
  12. })
  13. expect(vm.a).toBe(1)
  14. store.state.a++
  15. expect(vm.a).toBe(2)
  16. })
  17. it('mapState (object)', () => {
  18. const store = new Vuex.Store({
  19. state: {
  20. a: 1
  21. },
  22. getters: {
  23. b: () => 2
  24. }
  25. })
  26. const vm = mount(store, {
  27. computed: mapState({
  28. a: (state, getters) => {
  29. return state.a + getters.b
  30. }
  31. })
  32. })
  33. expect(vm.a).toBe(3)
  34. store.state.a++
  35. expect(vm.a).toBe(4)
  36. })
  37. it('mapState (with namespace)', () => {
  38. const store = new Vuex.Store({
  39. modules: {
  40. foo: {
  41. namespaced: true,
  42. state: { a: 1 },
  43. getters: {
  44. b: state => state.a + 1
  45. }
  46. }
  47. }
  48. })
  49. const vm = mount(store, {
  50. computed: mapState('foo', {
  51. a: (state, getters) => {
  52. return state.a + getters.b
  53. }
  54. })
  55. })
  56. expect(vm.a).toBe(3)
  57. store.state.foo.a++
  58. expect(vm.a).toBe(5)
  59. store.replaceState({
  60. foo: { a: 3 }
  61. })
  62. expect(vm.a).toBe(7)
  63. })
  64. // #708
  65. it('mapState (with namespace and a nested module)', () => {
  66. const store = new Vuex.Store({
  67. modules: {
  68. foo: {
  69. namespaced: true,
  70. state: { a: 1 },
  71. modules: {
  72. bar: {
  73. state: { b: 2 }
  74. }
  75. }
  76. }
  77. }
  78. })
  79. const vm = mount(store, {
  80. computed: mapState('foo', {
  81. value: state => state
  82. })
  83. })
  84. expect(vm.value.a).toBe(1)
  85. expect(vm.value.bar.b).toBe(2)
  86. expect(vm.value.b).toBeUndefined()
  87. })
  88. it('mapState (with undefined states)', () => {
  89. jest.spyOn(console, 'error').mockImplementation()
  90. const store = new Vuex.Store({
  91. modules: {
  92. foo: {
  93. namespaced: true,
  94. state: { a: 1 }
  95. }
  96. }
  97. })
  98. const vm = mount(store, {
  99. computed: mapState('foo')
  100. })
  101. expect(vm.a).toBeUndefined()
  102. expect(console.error).toHaveBeenCalledWith('[vuex] mapState: mapper parameter must be either an Array or an Object')
  103. })
  104. it('mapMutations (array)', () => {
  105. const store = new Vuex.Store({
  106. state: { count: 0 },
  107. mutations: {
  108. inc: state => state.count++,
  109. dec: state => state.count--
  110. }
  111. })
  112. const vm = mount(store, {
  113. methods: mapMutations(['inc', 'dec'])
  114. })
  115. vm.inc()
  116. expect(store.state.count).toBe(1)
  117. vm.dec()
  118. expect(store.state.count).toBe(0)
  119. })
  120. it('mapMutations (object)', () => {
  121. const store = new Vuex.Store({
  122. state: { count: 0 },
  123. mutations: {
  124. inc: state => state.count++,
  125. dec: state => state.count--
  126. }
  127. })
  128. const vm = mount(store, {
  129. methods: mapMutations({
  130. plus: 'inc',
  131. minus: 'dec'
  132. })
  133. })
  134. vm.plus()
  135. expect(store.state.count).toBe(1)
  136. vm.minus()
  137. expect(store.state.count).toBe(0)
  138. })
  139. it('mapMutations (function)', () => {
  140. const store = new Vuex.Store({
  141. state: { count: 0 },
  142. mutations: {
  143. inc (state, amount) {
  144. state.count += amount
  145. }
  146. }
  147. })
  148. const vm = mount(store, {
  149. methods: mapMutations({
  150. plus (commit, amount) {
  151. commit('inc', amount + 1)
  152. }
  153. })
  154. })
  155. vm.plus(42)
  156. expect(store.state.count).toBe(43)
  157. })
  158. it('mapMutations (with namespace)', () => {
  159. const store = new Vuex.Store({
  160. modules: {
  161. foo: {
  162. namespaced: true,
  163. state: { count: 0 },
  164. mutations: {
  165. inc: state => state.count++,
  166. dec: state => state.count--
  167. }
  168. }
  169. }
  170. })
  171. const vm = mount(store, {
  172. methods: mapMutations('foo', {
  173. plus: 'inc',
  174. minus: 'dec'
  175. })
  176. })
  177. vm.plus()
  178. expect(store.state.foo.count).toBe(1)
  179. vm.minus()
  180. expect(store.state.foo.count).toBe(0)
  181. })
  182. it('mapMutations (function with namepsace)', () => {
  183. const store = new Vuex.Store({
  184. modules: {
  185. foo: {
  186. namespaced: true,
  187. state: { count: 0 },
  188. mutations: {
  189. inc (state, amount) {
  190. state.count += amount
  191. }
  192. }
  193. }
  194. }
  195. })
  196. const vm = mount(store, {
  197. methods: mapMutations('foo', {
  198. plus (commit, amount) {
  199. commit('inc', amount + 1)
  200. }
  201. })
  202. })
  203. vm.plus(42)
  204. expect(store.state.foo.count).toBe(43)
  205. })
  206. it('mapMutations (with undefined mutations)', () => {
  207. jest.spyOn(console, 'error').mockImplementation()
  208. const store = new Vuex.Store({
  209. modules: {
  210. foo: {
  211. namespaced: true,
  212. state: { count: 0 },
  213. mutations: {
  214. inc: state => state.count++,
  215. dec: state => state.count--
  216. }
  217. }
  218. }
  219. })
  220. const vm = mount(store, {
  221. methods: mapMutations('foo')
  222. })
  223. expect(vm.inc).toBeUndefined()
  224. expect(vm.dec).toBeUndefined()
  225. expect(console.error).toHaveBeenCalledWith('[vuex] mapMutations: mapper parameter must be either an Array or an Object')
  226. })
  227. it('mapGetters (array)', () => {
  228. const store = new Vuex.Store({
  229. state: { count: 0 },
  230. mutations: {
  231. inc: state => state.count++,
  232. dec: state => state.count--
  233. },
  234. getters: {
  235. hasAny: ({ count }) => count > 0,
  236. negative: ({ count }) => count < 0
  237. }
  238. })
  239. const vm = mount(store, {
  240. computed: mapGetters(['hasAny', 'negative'])
  241. })
  242. expect(vm.hasAny).toBe(false)
  243. expect(vm.negative).toBe(false)
  244. store.commit('inc')
  245. expect(vm.hasAny).toBe(true)
  246. expect(vm.negative).toBe(false)
  247. store.commit('dec')
  248. store.commit('dec')
  249. expect(vm.hasAny).toBe(false)
  250. expect(vm.negative).toBe(true)
  251. })
  252. it('mapGetters (object)', () => {
  253. const store = new Vuex.Store({
  254. state: { count: 0 },
  255. mutations: {
  256. inc: state => state.count++,
  257. dec: state => state.count--
  258. },
  259. getters: {
  260. hasAny: ({ count }) => count > 0,
  261. negative: ({ count }) => count < 0
  262. }
  263. })
  264. const vm = mount(store, {
  265. computed: mapGetters({
  266. a: 'hasAny',
  267. b: 'negative'
  268. })
  269. })
  270. expect(vm.a).toBe(false)
  271. expect(vm.b).toBe(false)
  272. store.commit('inc')
  273. expect(vm.a).toBe(true)
  274. expect(vm.b).toBe(false)
  275. store.commit('dec')
  276. store.commit('dec')
  277. expect(vm.a).toBe(false)
  278. expect(vm.b).toBe(true)
  279. })
  280. it('mapGetters (with namespace)', () => {
  281. const store = new Vuex.Store({
  282. modules: {
  283. foo: {
  284. namespaced: true,
  285. state: { count: 0 },
  286. mutations: {
  287. inc: state => state.count++,
  288. dec: state => state.count--
  289. },
  290. getters: {
  291. hasAny: ({ count }) => count > 0,
  292. negative: ({ count }) => count < 0
  293. }
  294. }
  295. }
  296. })
  297. const vm = mount(store, {
  298. computed: mapGetters('foo', {
  299. a: 'hasAny',
  300. b: 'negative'
  301. })
  302. })
  303. expect(vm.a).toBe(false)
  304. expect(vm.b).toBe(false)
  305. store.commit('foo/inc')
  306. expect(vm.a).toBe(true)
  307. expect(vm.b).toBe(false)
  308. store.commit('foo/dec')
  309. store.commit('foo/dec')
  310. expect(vm.a).toBe(false)
  311. expect(vm.b).toBe(true)
  312. })
  313. it('mapGetters (with namespace and nested module)', () => {
  314. const store = new Vuex.Store({
  315. modules: {
  316. foo: {
  317. namespaced: true,
  318. modules: {
  319. bar: {
  320. namespaced: true,
  321. state: { count: 0 },
  322. mutations: {
  323. inc: state => state.count++,
  324. dec: state => state.count--
  325. },
  326. getters: {
  327. hasAny: ({ count }) => count > 0,
  328. negative: ({ count }) => count < 0
  329. }
  330. },
  331. cat: {
  332. state: { count: 9 },
  333. getters: {
  334. count: ({ count }) => count
  335. }
  336. }
  337. }
  338. }
  339. }
  340. })
  341. const vm = mount(store, {
  342. computed: {
  343. ...mapGetters('foo/bar', [
  344. 'hasAny',
  345. 'negative'
  346. ]),
  347. ...mapGetters('foo', [
  348. 'count'
  349. ])
  350. }
  351. })
  352. expect(vm.hasAny).toBe(false)
  353. expect(vm.negative).toBe(false)
  354. store.commit('foo/bar/inc')
  355. expect(vm.hasAny).toBe(true)
  356. expect(vm.negative).toBe(false)
  357. store.commit('foo/bar/dec')
  358. store.commit('foo/bar/dec')
  359. expect(vm.hasAny).toBe(false)
  360. expect(vm.negative).toBe(true)
  361. expect(vm.count).toBe(9)
  362. })
  363. it('mapGetters (with undefined getters)', () => {
  364. jest.spyOn(console, 'error').mockImplementation()
  365. const store = new Vuex.Store({
  366. modules: {
  367. foo: {
  368. namespaced: true,
  369. state: { count: 0 },
  370. mutations: {
  371. inc: state => state.count++,
  372. dec: state => state.count--
  373. },
  374. getters: {
  375. hasAny: ({ count }) => count > 0,
  376. negative: ({ count }) => count < 0
  377. }
  378. }
  379. }
  380. })
  381. const vm = mount(store, {
  382. computed: mapGetters('foo')
  383. })
  384. expect(vm.a).toBeUndefined()
  385. expect(vm.b).toBeUndefined()
  386. expect(console.error).toHaveBeenCalledWith('[vuex] mapGetters: mapper parameter must be either an Array or an Object')
  387. })
  388. it('mapActions (array)', () => {
  389. const a = jest.fn()
  390. const b = jest.fn()
  391. const store = new Vuex.Store({
  392. actions: {
  393. a,
  394. b
  395. }
  396. })
  397. const vm = mount(store, {
  398. methods: mapActions(['a', 'b'])
  399. })
  400. vm.a()
  401. expect(a).toHaveBeenCalled()
  402. expect(b).not.toHaveBeenCalled()
  403. vm.b()
  404. expect(b).toHaveBeenCalled()
  405. })
  406. it('mapActions (object)', () => {
  407. const a = jest.fn()
  408. const b = jest.fn()
  409. const store = new Vuex.Store({
  410. actions: {
  411. a,
  412. b
  413. }
  414. })
  415. const vm = mount(store, {
  416. methods: mapActions({
  417. foo: 'a',
  418. bar: 'b'
  419. })
  420. })
  421. vm.foo()
  422. expect(a).toHaveBeenCalled()
  423. expect(b).not.toHaveBeenCalled()
  424. vm.bar()
  425. expect(b).toHaveBeenCalled()
  426. })
  427. it('mapActions (function)', () => {
  428. const a = jest.fn()
  429. const store = new Vuex.Store({
  430. actions: { a }
  431. })
  432. const vm = mount(store, {
  433. methods: mapActions({
  434. foo (dispatch, arg) {
  435. dispatch('a', arg + 'bar')
  436. }
  437. })
  438. })
  439. vm.foo('foo')
  440. expect(a.mock.calls[0][1]).toBe('foobar')
  441. })
  442. it('mapActions (with namespace)', () => {
  443. const a = jest.fn()
  444. const b = jest.fn()
  445. const store = new Vuex.Store({
  446. modules: {
  447. foo: {
  448. namespaced: true,
  449. actions: {
  450. a,
  451. b
  452. }
  453. }
  454. }
  455. })
  456. const vm = mount(store, {
  457. methods: mapActions('foo/', {
  458. foo: 'a',
  459. bar: 'b'
  460. })
  461. })
  462. vm.foo()
  463. expect(a).toHaveBeenCalled()
  464. expect(b).not.toHaveBeenCalled()
  465. vm.bar()
  466. expect(b).toHaveBeenCalled()
  467. })
  468. it('mapActions (function with namespace)', () => {
  469. const a = jest.fn()
  470. const store = new Vuex.Store({
  471. modules: {
  472. foo: {
  473. namespaced: true,
  474. actions: { a }
  475. }
  476. }
  477. })
  478. const vm = mount(store, {
  479. methods: mapActions('foo/', {
  480. foo (dispatch, arg) {
  481. dispatch('a', arg + 'bar')
  482. }
  483. })
  484. })
  485. vm.foo('foo')
  486. expect(a.mock.calls[0][1]).toBe('foobar')
  487. })
  488. it('mapActions (with undefined actions)', () => {
  489. jest.spyOn(console, 'error').mockImplementation()
  490. const a = jest.fn()
  491. const store = new Vuex.Store({
  492. modules: {
  493. foo: {
  494. namespaced: true,
  495. actions: {
  496. a
  497. }
  498. }
  499. }
  500. })
  501. const vm = mount(store, {
  502. methods: mapActions('foo/')
  503. })
  504. expect(vm.a).toBeUndefined()
  505. expect(a).not.toHaveBeenCalled()
  506. expect(console.error).toHaveBeenCalledWith('[vuex] mapActions: mapper parameter must be either an Array or an Object')
  507. })
  508. it('createNamespacedHelpers', () => {
  509. const actionA = jest.fn()
  510. const actionB = jest.fn()
  511. const store = new Vuex.Store({
  512. modules: {
  513. foo: {
  514. namespaced: true,
  515. state: { count: 0 },
  516. getters: {
  517. isEven: state => state.count % 2 === 0
  518. },
  519. mutations: {
  520. inc: state => state.count++,
  521. dec: state => state.count--
  522. },
  523. actions: {
  524. actionA,
  525. actionB
  526. }
  527. }
  528. }
  529. })
  530. const {
  531. mapState,
  532. mapGetters,
  533. mapMutations,
  534. mapActions
  535. } = createNamespacedHelpers('foo/')
  536. const vm = mount(store, {
  537. computed: {
  538. ...mapState(['count']),
  539. ...mapGetters(['isEven'])
  540. },
  541. methods: {
  542. ...mapMutations(['inc', 'dec']),
  543. ...mapActions(['actionA', 'actionB'])
  544. }
  545. })
  546. expect(vm.count).toBe(0)
  547. expect(vm.isEven).toBe(true)
  548. store.state.foo.count++
  549. expect(vm.count).toBe(1)
  550. expect(vm.isEven).toBe(false)
  551. vm.inc()
  552. expect(store.state.foo.count).toBe(2)
  553. expect(store.getters['foo/isEven']).toBe(true)
  554. vm.dec()
  555. expect(store.state.foo.count).toBe(1)
  556. expect(store.getters['foo/isEven']).toBe(false)
  557. vm.actionA()
  558. expect(actionA).toHaveBeenCalled()
  559. expect(actionB).not.toHaveBeenCalled()
  560. vm.actionB()
  561. expect(actionB).toHaveBeenCalled()
  562. })
  563. })