ssrDirectives.spec.ts 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. /**
  2. * @jest-environment node
  3. */
  4. import { renderToString } from '../src/renderToString'
  5. import {
  6. createApp,
  7. h,
  8. withDirectives,
  9. vShow,
  10. vModelText,
  11. vModelRadio,
  12. vModelCheckbox
  13. } from 'vue'
  14. describe('ssr: directives', () => {
  15. describe('template v-show', () => {
  16. test('basic', async () => {
  17. expect(
  18. await renderToString(
  19. createApp({
  20. template: `<div v-show="true"/>`
  21. })
  22. )
  23. ).toBe(`<div style=""></div>`)
  24. expect(
  25. await renderToString(
  26. createApp({
  27. template: `<div v-show="false"/>`
  28. })
  29. )
  30. ).toBe(`<div style="display:none;"></div>`)
  31. })
  32. test('with static style', async () => {
  33. expect(
  34. await renderToString(
  35. createApp({
  36. template: `<div style="color:red" v-show="false"/>`
  37. })
  38. )
  39. ).toBe(`<div style="color:red;display:none;"></div>`)
  40. })
  41. test('with dynamic style', async () => {
  42. expect(
  43. await renderToString(
  44. createApp({
  45. data: () => ({ style: { color: 'red' } }),
  46. template: `<div :style="style" v-show="false"/>`
  47. })
  48. )
  49. ).toBe(`<div style="color:red;display:none;"></div>`)
  50. })
  51. test('with static + dynamic style', async () => {
  52. expect(
  53. await renderToString(
  54. createApp({
  55. data: () => ({ style: { color: 'red' } }),
  56. template: `<div :style="style" style="font-size:12;" v-show="false"/>`
  57. })
  58. )
  59. ).toBe(`<div style="color:red;font-size:12;display:none;"></div>`)
  60. })
  61. })
  62. describe('template v-model', () => {
  63. test('text', async () => {
  64. expect(
  65. await renderToString(
  66. createApp({
  67. data: () => ({ text: 'hello' }),
  68. template: `<input v-model="text">`
  69. })
  70. )
  71. ).toBe(`<input value="hello">`)
  72. })
  73. test('radio', async () => {
  74. expect(
  75. await renderToString(
  76. createApp({
  77. data: () => ({ selected: 'foo' }),
  78. template: `<input type="radio" value="foo" v-model="selected">`
  79. })
  80. )
  81. ).toBe(`<input type="radio" value="foo" checked>`)
  82. expect(
  83. await renderToString(
  84. createApp({
  85. data: () => ({ selected: 'foo' }),
  86. template: `<input type="radio" value="bar" v-model="selected">`
  87. })
  88. )
  89. ).toBe(`<input type="radio" value="bar">`)
  90. // non-string values
  91. expect(
  92. await renderToString(
  93. createApp({
  94. data: () => ({ selected: 'foo' }),
  95. template: `<input type="radio" :value="{}" v-model="selected">`
  96. })
  97. )
  98. ).toBe(`<input type="radio">`)
  99. })
  100. test('checkbox', async () => {
  101. expect(
  102. await renderToString(
  103. createApp({
  104. data: () => ({ checked: true }),
  105. template: `<input type="checkbox" v-model="checked">`
  106. })
  107. )
  108. ).toBe(`<input type="checkbox" checked>`)
  109. expect(
  110. await renderToString(
  111. createApp({
  112. data: () => ({ checked: false }),
  113. template: `<input type="checkbox" v-model="checked">`
  114. })
  115. )
  116. ).toBe(`<input type="checkbox">`)
  117. expect(
  118. await renderToString(
  119. createApp({
  120. data: () => ({ checked: ['foo'] }),
  121. template: `<input type="checkbox" value="foo" v-model="checked">`
  122. })
  123. )
  124. ).toBe(`<input type="checkbox" value="foo" checked>`)
  125. expect(
  126. await renderToString(
  127. createApp({
  128. data: () => ({ checked: [] }),
  129. template: `<input type="checkbox" value="foo" v-model="checked">`
  130. })
  131. )
  132. ).toBe(`<input type="checkbox" value="foo">`)
  133. })
  134. test('textarea', async () => {
  135. expect(
  136. await renderToString(
  137. createApp({
  138. data: () => ({ foo: 'hello' }),
  139. template: `<textarea v-model="foo"/>`
  140. })
  141. )
  142. ).toBe(`<textarea>hello</textarea>`)
  143. })
  144. test('dynamic type', async () => {
  145. expect(
  146. await renderToString(
  147. createApp({
  148. data: () => ({ type: 'text', model: 'hello' }),
  149. template: `<input :type="type" v-model="model">`
  150. })
  151. )
  152. ).toBe(`<input type="text" value="hello">`)
  153. expect(
  154. await renderToString(
  155. createApp({
  156. data: () => ({ type: 'checkbox', model: true }),
  157. template: `<input :type="type" v-model="model">`
  158. })
  159. )
  160. ).toBe(`<input type="checkbox" checked>`)
  161. expect(
  162. await renderToString(
  163. createApp({
  164. data: () => ({ type: 'checkbox', model: false }),
  165. template: `<input :type="type" v-model="model">`
  166. })
  167. )
  168. ).toBe(`<input type="checkbox">`)
  169. expect(
  170. await renderToString(
  171. createApp({
  172. data: () => ({ type: 'checkbox', model: ['hello'] }),
  173. template: `<input :type="type" value="hello" v-model="model">`
  174. })
  175. )
  176. ).toBe(`<input type="checkbox" value="hello" checked>`)
  177. expect(
  178. await renderToString(
  179. createApp({
  180. data: () => ({ type: 'checkbox', model: [] }),
  181. template: `<input :type="type" value="hello" v-model="model">`
  182. })
  183. )
  184. ).toBe(`<input type="checkbox" value="hello">`)
  185. expect(
  186. await renderToString(
  187. createApp({
  188. data: () => ({ type: 'radio', model: 'hello' }),
  189. template: `<input :type="type" value="hello" v-model="model">`
  190. })
  191. )
  192. ).toBe(`<input type="radio" value="hello" checked>`)
  193. expect(
  194. await renderToString(
  195. createApp({
  196. data: () => ({ type: 'radio', model: 'hello' }),
  197. template: `<input :type="type" value="bar" v-model="model">`
  198. })
  199. )
  200. ).toBe(`<input type="radio" value="bar">`)
  201. })
  202. test('with v-bind', async () => {
  203. expect(
  204. await renderToString(
  205. createApp({
  206. data: () => ({
  207. obj: { type: 'radio', value: 'hello' },
  208. model: 'hello'
  209. }),
  210. template: `<input v-bind="obj" v-model="model">`
  211. })
  212. )
  213. ).toBe(`<input type="radio" value="hello" checked>`)
  214. })
  215. })
  216. describe('vnode v-show', () => {
  217. test('basic', async () => {
  218. expect(
  219. await renderToString(
  220. createApp({
  221. render() {
  222. return withDirectives(h('div'), [[vShow, true]])
  223. }
  224. })
  225. )
  226. ).toBe(`<div></div>`)
  227. expect(
  228. await renderToString(
  229. createApp({
  230. render() {
  231. return withDirectives(h('div'), [[vShow, false]])
  232. }
  233. })
  234. )
  235. ).toBe(`<div style="display:none;"></div>`)
  236. })
  237. test('with merge', async () => {
  238. expect(
  239. await renderToString(
  240. createApp({
  241. render() {
  242. return withDirectives(
  243. h('div', {
  244. style: {
  245. color: 'red'
  246. }
  247. }),
  248. [[vShow, false]]
  249. )
  250. }
  251. })
  252. )
  253. ).toBe(`<div style="color:red;display:none;"></div>`)
  254. })
  255. })
  256. describe('vnode v-model', () => {
  257. test('text', async () => {
  258. expect(
  259. await renderToString(
  260. createApp({
  261. render() {
  262. return withDirectives(h('input'), [[vModelText, 'hello']])
  263. }
  264. })
  265. )
  266. ).toBe(`<input value="hello">`)
  267. })
  268. test('radio', async () => {
  269. expect(
  270. await renderToString(
  271. createApp({
  272. render() {
  273. return withDirectives(
  274. h('input', { type: 'radio', value: 'hello' }),
  275. [[vModelRadio, 'hello']]
  276. )
  277. }
  278. })
  279. )
  280. ).toBe(`<input type="radio" value="hello" checked>`)
  281. expect(
  282. await renderToString(
  283. createApp({
  284. render() {
  285. return withDirectives(
  286. h('input', { type: 'radio', value: 'hello' }),
  287. [[vModelRadio, 'foo']]
  288. )
  289. }
  290. })
  291. )
  292. ).toBe(`<input type="radio" value="hello">`)
  293. })
  294. test('checkbox', async () => {
  295. expect(
  296. await renderToString(
  297. createApp({
  298. render() {
  299. return withDirectives(h('input', { type: 'checkbox' }), [
  300. [vModelCheckbox, true]
  301. ])
  302. }
  303. })
  304. )
  305. ).toBe(`<input type="checkbox" checked>`)
  306. expect(
  307. await renderToString(
  308. createApp({
  309. render() {
  310. return withDirectives(h('input', { type: 'checkbox' }), [
  311. [vModelCheckbox, false]
  312. ])
  313. }
  314. })
  315. )
  316. ).toBe(`<input type="checkbox">`)
  317. expect(
  318. await renderToString(
  319. createApp({
  320. render() {
  321. return withDirectives(
  322. h('input', { type: 'checkbox', value: 'foo' }),
  323. [[vModelCheckbox, ['foo']]]
  324. )
  325. }
  326. })
  327. )
  328. ).toBe(`<input type="checkbox" value="foo" checked>`)
  329. expect(
  330. await renderToString(
  331. createApp({
  332. render() {
  333. return withDirectives(
  334. h('input', { type: 'checkbox', value: 'foo' }),
  335. [[vModelCheckbox, []]]
  336. )
  337. }
  338. })
  339. )
  340. ).toBe(`<input type="checkbox" value="foo">`)
  341. })
  342. })
  343. test('custom directive w/ getSSRProps', async () => {
  344. expect(
  345. await renderToString(
  346. createApp({
  347. render() {
  348. return withDirectives(h('div'), [
  349. [
  350. {
  351. getSSRProps({ value }) {
  352. return { id: value }
  353. }
  354. },
  355. 'foo'
  356. ]
  357. ])
  358. }
  359. })
  360. )
  361. ).toBe(`<div id="foo"></div>`)
  362. })
  363. })