ReduxStore.test.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. const ReduxStore = require('./ReduxStore')
  2. const Redux = require('redux')
  3. describe('ReduxStore', () => {
  4. function createStore (reducers = {}) {
  5. const reducer = Redux.combineReducers(Object.assign({}, reducers, {
  6. uppy: ReduxStore.reducer
  7. }))
  8. return Redux.createStore(reducer)
  9. }
  10. it('can be created with or without new', () => {
  11. const r = createStore()
  12. let store = ReduxStore({ store: r })
  13. expect(typeof store).toBe('object')
  14. store = new ReduxStore({ store: r })
  15. expect(typeof store).toBe('object')
  16. })
  17. it('merges in state using `setState`', () => {
  18. const r = createStore()
  19. const store = ReduxStore({ store: r })
  20. expect(store.getState()).toEqual({})
  21. store.setState({
  22. a: 1,
  23. b: 2
  24. })
  25. expect(store.getState()).toEqual({ a: 1, b: 2 })
  26. store.setState({ b: 3 })
  27. expect(store.getState()).toEqual({ a: 1, b: 3 })
  28. })
  29. it('notifies subscriptions when state changes', () => {
  30. let expected = []
  31. let calls = 0
  32. function listener (prevState, nextState, patch) {
  33. calls++
  34. expect([ prevState, nextState, patch ]).toEqual(expected)
  35. }
  36. const r = createStore()
  37. const store = ReduxStore({ store: r })
  38. store.subscribe(listener)
  39. expected = [{}, { a: 1, b: 2 }, { a: 1, b: 2 }]
  40. store.setState({
  41. a: 1,
  42. b: 2
  43. })
  44. expected = [{ a: 1, b: 2 }, { a: 1, b: 3 }, { b: 3 }]
  45. store.setState({ b: 3 })
  46. expect(calls).toBe(2)
  47. })
  48. it('fires `subscribe` if state is modified externally (eg redux devtools)', () => {
  49. const reducer = Redux.combineReducers({ uppy: ReduxStore.reducer })
  50. const r = Redux.createStore((state, action) => {
  51. // Add a `SET` action that can change Uppy state without going through the Uppy reducer or action creator.
  52. // Emulates Redux Devtools.
  53. if (action.type === 'SET') return action.payload
  54. return reducer(state, action)
  55. })
  56. let expected = []
  57. let calls = 0
  58. function listener (prevState, nextState, patch) {
  59. calls++
  60. expect([ prevState, nextState, patch ]).toEqual(expected)
  61. }
  62. const store = ReduxStore({ store: r })
  63. store.subscribe(listener)
  64. expected = [{}, { a: 1 }, { a: 1 }]
  65. store.setState({ a: 1 })
  66. expected = [{ a: 1 }, { b: 2 }, { b: 2 }]
  67. // redux-devtools's `JUMP_TO_STATE` is similar to this.
  68. r.dispatch({
  69. type: 'SET',
  70. payload: {
  71. uppy: {
  72. [store._id]: { b: 2 }
  73. }
  74. }
  75. })
  76. expect(calls).toBe(2)
  77. })
  78. it('can mount in a custom state key', () => {
  79. const reducer = Redux.combineReducers({
  80. hello: ReduxStore.reducer
  81. })
  82. const r = Redux.createStore(reducer)
  83. const store = ReduxStore({
  84. store: r,
  85. id: 'world',
  86. selector: state => state.hello.world
  87. })
  88. store.setState({ a: 1 })
  89. expect(r.getState()).toEqual({
  90. hello: {
  91. world: {
  92. a: 1
  93. }
  94. }
  95. })
  96. })
  97. })