history.spec.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. import { haveText, html, test } from '../../utils'
  2. test('value is reflected in query string upon changing',
  3. [html`
  4. <div x-data="{ count: $queryString(1) }">
  5. <button @click="count++">Inc</button>
  6. <h1 @click="count--">Dec</h1>
  7. <span x-text="count"></span>
  8. </div>
  9. `],
  10. ({ get, url, go }) => {
  11. get('span').should(haveText('1'))
  12. url().should('not.include', '?count=1')
  13. get('button').click()
  14. get('span').should(haveText('2'))
  15. url().should('include', '?count=2')
  16. get('button').click()
  17. get('span').should(haveText('3'))
  18. url().should('include', '?count=3')
  19. get('h1').click()
  20. get('h1').click()
  21. get('span').should(haveText('1'))
  22. url().should('not.include', '?count=1')
  23. },
  24. )
  25. test('can configure always making the query string value present',
  26. [html`
  27. <div x-data="{ count: $queryString(1).alwaysShow() }">
  28. <button @click="count++">Inc</button>
  29. <h1 @click="count--">Dec</h1>
  30. <span x-text="count"></span>
  31. </div>
  32. `],
  33. ({ get, url, go }) => {
  34. get('span').should(haveText('1'))
  35. url().should('include', '?count=1')
  36. get('button').click()
  37. get('span').should(haveText('2'))
  38. url().should('include', '?count=2')
  39. get('h1').click()
  40. get('span').should(haveText('1'))
  41. url().should('include', '?count=1')
  42. },
  43. )
  44. test('value is persisted across requests',
  45. [html`
  46. <div x-data="{ count: $queryString(1) }">
  47. <button @click="count++">Inc</button>
  48. <span x-text="count"></span>
  49. </div>
  50. `],
  51. ({ get, url, go }, reload) => {
  52. get('span').should(haveText('1'))
  53. url().should('not.include', '?count=1')
  54. get('button').click()
  55. get('span').should(haveText('2'))
  56. url().should('include', '?count=2')
  57. reload()
  58. url().should('include', '?count=2')
  59. get('span').should(haveText('2'))
  60. },
  61. )
  62. test('can provide an alias',
  63. [html`
  64. <div x-data="{ count: $queryString(1).as('tnuoc') }">
  65. <button @click="count++">Inc</button>
  66. <span x-text="count"></span>
  67. </div>
  68. `],
  69. ({ get, url, go }) => {
  70. get('span').should(haveText('1'))
  71. url().should('not.include', '?tnuoc=1')
  72. get('button').click()
  73. get('span').should(haveText('2'))
  74. url().should('include', '?tnuoc=2')
  75. },
  76. )
  77. test('can use pushState',
  78. [html`
  79. <div x-data="{ count: $queryString(1).usePush() }">
  80. <button @click="count++">Inc</button>
  81. <span x-text="count"></span>
  82. </div>
  83. `],
  84. ({ get, url, go }) => {
  85. get('span').should(haveText('1'))
  86. url().should('not.include', '?count=1')
  87. get('button').click()
  88. get('span').should(haveText('2'))
  89. url().should('include', '?count=2')
  90. go('back')
  91. get('span').should(haveText('1'))
  92. url().should('not.include', '?count=1')
  93. go('forward')
  94. get('span').should(haveText('2'))
  95. url().should('include', '?count=2')
  96. },
  97. )
  98. test('can go back and forth with multiple components',
  99. [html`
  100. <div x-data="{ foo: $queryString(1).usePush() }" id="foo">
  101. <button @click="foo++">Inc</button>
  102. <span x-text="foo"></span>
  103. </div>
  104. <div x-data="{ bar: $queryString(1).usePush() }" id="bar">
  105. <button @click="bar++">Inc</button>
  106. <span x-text="bar"></span>
  107. </div>
  108. `],
  109. ({ get, url, go }) => {
  110. get('#foo span').should(haveText('1'))
  111. url().should('not.include', 'foo=1')
  112. get('#foo button').click()
  113. get('#foo span').should(haveText('2'))
  114. url().should('include', 'foo=2')
  115. get('#bar span').should(haveText('1'))
  116. url().should('not.include', 'bar=1')
  117. get('#bar button').click()
  118. get('#bar span').should(haveText('2'))
  119. url().should('include', 'bar=2')
  120. go('back')
  121. get('#bar span').should(haveText('1'))
  122. url().should('not.include', 'bar=1')
  123. get('#foo span').should(haveText('2'))
  124. url().should('include', 'foo=2')
  125. go('back')
  126. get('#bar span').should(haveText('1'))
  127. url().should('not.include', 'bar=1')
  128. get('#foo span').should(haveText('1'))
  129. url().should('not.include', 'foo=1')
  130. },
  131. )
  132. test('supports arrays',
  133. [html`
  134. <div x-data="{ items: $queryString(['foo']) }">
  135. <button @click="items.push('bar')">Inc</button>
  136. <span x-text="JSON.stringify(items)"></span>
  137. </div>
  138. `],
  139. ({ get, url, go }, reload) => {
  140. get('span').should(haveText('["foo"]'))
  141. url().should('not.include', '?items')
  142. get('button').click()
  143. get('span').should(haveText('["foo","bar"]'))
  144. url().should('include', '?items[0]=foo&items[1]=bar')
  145. reload()
  146. url().should('include', '?items[0]=foo&items[1]=bar')
  147. get('span').should(haveText('["foo","bar"]'))
  148. },
  149. )
  150. test('supports deep arrays',
  151. [html`
  152. <div x-data="{ items: $queryString(['foo', ['bar', 'baz']]) }">
  153. <button @click="items[1].push('bob')">Inc</button>
  154. <span x-text="JSON.stringify(items)"></span>
  155. </div>
  156. `],
  157. ({ get, url, go }, reload) => {
  158. get('span').should(haveText('["foo",["bar","baz"]]'))
  159. url().should('not.include', '?items')
  160. get('button').click()
  161. get('span').should(haveText('["foo",["bar","baz","bob"]]'))
  162. url().should('include', '?items[0]=foo&items[1][0]=bar&items[1][1]=baz&items[1][2]=bob')
  163. reload()
  164. url().should('include', '?items[0]=foo&items[1][0]=bar&items[1][1]=baz&items[1][2]=bob')
  165. get('span').should(haveText('["foo",["bar","baz","bob"]]'))
  166. },
  167. )
  168. test('supports objects',
  169. [html`
  170. <div x-data="{ items: $queryString({ foo: 'bar' }) }">
  171. <button @click="items.bob = 'lob'">Inc</button>
  172. <span x-text="JSON.stringify(items)"></span>
  173. </div>
  174. `],
  175. ({ get, url, go }, reload) => {
  176. get('span').should(haveText('{"foo":"bar"}'))
  177. url().should('not.include', '?items')
  178. get('button').click()
  179. get('span').should(haveText('{"foo":"bar","bob":"lob"}'))
  180. url().should('include', '?items[foo]=bar&items[bob]=lob')
  181. reload()
  182. url().should('include', '?items[foo]=bar&items[bob]=lob')
  183. get('span').should(haveText('{"foo":"bar","bob":"lob"}'))
  184. },
  185. )
  186. test('encodes values according to RFC 1738 (plus signs for spaces)',
  187. [html`
  188. <div x-data="{ foo: $queryString('hey&there').alwaysShow(), bar: $queryString('hey there').alwaysShow() }">
  189. <span x-text="JSON.stringify(foo)+JSON.stringify(bar)"></span>
  190. </div>
  191. `],
  192. ({ get, url, go }, reload) => {
  193. url().should('include', '?foo=hey%26there&bar=hey+there')
  194. get('span').should(haveText('"hey&there""hey there"'))
  195. reload()
  196. url().should('include', '?foo=hey%26there&bar=hey+there')
  197. get('span').should(haveText('"hey&there""hey there"'))
  198. },
  199. )