ssrRenderAttrs.spec.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /**
  2. * @jest-environment node
  3. */
  4. import {
  5. ssrRenderAttrs,
  6. ssrRenderClass,
  7. ssrRenderStyle,
  8. ssrRenderAttr
  9. } from '../src/helpers/ssrRenderAttrs'
  10. import { escapeHtml } from '@vue/shared'
  11. describe('ssr: renderAttrs', () => {
  12. test('ignore reserved props', () => {
  13. expect(
  14. ssrRenderAttrs({
  15. key: 1,
  16. ref: () => {},
  17. onClick: () => {}
  18. })
  19. ).toBe('')
  20. })
  21. test('normal attrs', () => {
  22. expect(
  23. ssrRenderAttrs({
  24. id: 'foo',
  25. title: 'bar'
  26. })
  27. ).toBe(` id="foo" title="bar"`)
  28. })
  29. test('empty value attrs', () => {
  30. expect(
  31. ssrRenderAttrs({
  32. 'data-v-abc': ''
  33. })
  34. ).toBe(` data-v-abc`)
  35. })
  36. test('escape attrs', () => {
  37. expect(
  38. ssrRenderAttrs({
  39. id: '"><script'
  40. })
  41. ).toBe(` id="&quot;&gt;&lt;script"`)
  42. })
  43. test('boolean attrs', () => {
  44. expect(
  45. ssrRenderAttrs({
  46. checked: true,
  47. multiple: false,
  48. readonly: 0,
  49. disabled: ''
  50. })
  51. ).toBe(` checked disabled`) // boolean attr w/ false should be ignored
  52. })
  53. test('ignore falsy values', () => {
  54. expect(
  55. ssrRenderAttrs({
  56. foo: false,
  57. title: null,
  58. baz: undefined
  59. })
  60. ).toBe(` foo="false"`) // non boolean should render `false` as is
  61. })
  62. test('ignore non-renderable values', () => {
  63. expect(
  64. ssrRenderAttrs({
  65. foo: {},
  66. bar: [],
  67. baz: () => {}
  68. })
  69. ).toBe(``)
  70. })
  71. test('props to attrs', () => {
  72. expect(
  73. ssrRenderAttrs({
  74. readOnly: true, // simple lower case conversion
  75. htmlFor: 'foobar' // special cases
  76. })
  77. ).toBe(` readonly for="foobar"`)
  78. })
  79. test('preserve name on custom element', () => {
  80. expect(
  81. ssrRenderAttrs(
  82. {
  83. fooBar: 'ok'
  84. },
  85. 'my-el'
  86. )
  87. ).toBe(` fooBar="ok"`)
  88. })
  89. })
  90. describe('ssr: renderAttr', () => {
  91. test('basic', () => {
  92. expect(ssrRenderAttr('foo', 'bar')).toBe(` foo="bar"`)
  93. })
  94. test('null and undefined', () => {
  95. expect(ssrRenderAttr('foo', null)).toBe(``)
  96. expect(ssrRenderAttr('foo', undefined)).toBe(``)
  97. })
  98. test('escape', () => {
  99. expect(ssrRenderAttr('foo', '<script>')).toBe(
  100. ` foo="${escapeHtml(`<script>`)}"`
  101. )
  102. })
  103. })
  104. describe('ssr: renderClass', () => {
  105. test('via renderProps', () => {
  106. expect(
  107. ssrRenderAttrs({
  108. class: ['foo', 'bar']
  109. })
  110. ).toBe(` class="foo bar"`)
  111. })
  112. test('standalone', () => {
  113. expect(ssrRenderClass(`foo`)).toBe(`foo`)
  114. expect(ssrRenderClass([`foo`, `bar`])).toBe(`foo bar`)
  115. expect(ssrRenderClass({ foo: true, bar: false })).toBe(`foo`)
  116. expect(ssrRenderClass([{ foo: true, bar: false }, `baz`])).toBe(`foo baz`)
  117. })
  118. test('escape class values', () => {
  119. expect(ssrRenderClass(`"><script`)).toBe(`&quot;&gt;&lt;script`)
  120. })
  121. })
  122. describe('ssr: renderStyle', () => {
  123. test('via renderProps', () => {
  124. expect(
  125. ssrRenderAttrs({
  126. style: {
  127. color: 'red'
  128. }
  129. })
  130. ).toBe(` style="color:red;"`)
  131. })
  132. test('standalone', () => {
  133. expect(ssrRenderStyle(`color:red`)).toBe(`color:red`)
  134. expect(
  135. ssrRenderStyle({
  136. color: `red`
  137. })
  138. ).toBe(`color:red;`)
  139. expect(
  140. ssrRenderStyle([
  141. { color: `red` },
  142. { fontSize: `15px` } // case conversion
  143. ])
  144. ).toBe(`color:red;font-size:15px;`)
  145. })
  146. test('number handling', () => {
  147. expect(
  148. ssrRenderStyle({
  149. fontSize: 15, // should be ignored since font-size requires unit
  150. opacity: 0.5
  151. })
  152. ).toBe(`opacity:0.5;`)
  153. })
  154. test('escape inline CSS', () => {
  155. expect(ssrRenderStyle(`"><script`)).toBe(`&quot;&gt;&lt;script`)
  156. expect(
  157. ssrRenderStyle({
  158. color: `"><script`
  159. })
  160. ).toBe(`color:&quot;&gt;&lt;script;`)
  161. })
  162. })