renderProps.spec.ts 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. import { renderProps, renderClass, renderStyle } from '../src'
  2. describe('ssr: renderProps', () => {
  3. test('ignore reserved props', () => {
  4. expect(
  5. renderProps({
  6. key: 1,
  7. ref: () => {},
  8. onClick: () => {}
  9. })
  10. ).toBe('')
  11. })
  12. test('normal attrs', () => {
  13. expect(
  14. renderProps({
  15. id: 'foo',
  16. title: 'bar'
  17. })
  18. ).toBe(` id="foo" title="bar"`)
  19. })
  20. test('escape attrs', () => {
  21. expect(
  22. renderProps({
  23. id: '"><script'
  24. })
  25. ).toBe(` id="&quot;&gt;&lt;script"`)
  26. })
  27. test('boolean attrs', () => {
  28. expect(
  29. renderProps({
  30. checked: true,
  31. multiple: false
  32. })
  33. ).toBe(` checked`) // boolean attr w/ false should be ignored
  34. })
  35. test('ignore falsy values', () => {
  36. expect(
  37. renderProps({
  38. foo: false,
  39. title: null,
  40. baz: undefined
  41. })
  42. ).toBe(` foo="false"`) // non boolean should render `false` as is
  43. })
  44. test('props to attrs', () => {
  45. expect(
  46. renderProps({
  47. readOnly: true, // simple lower case conversion
  48. htmlFor: 'foobar' // special cases
  49. })
  50. ).toBe(` readonly for="foobar"`)
  51. })
  52. test('preserve name on custom element', () => {
  53. expect(
  54. renderProps(
  55. {
  56. fooBar: 'ok'
  57. },
  58. 'my-el'
  59. )
  60. ).toBe(` fooBar="ok"`)
  61. })
  62. })
  63. describe('ssr: renderClass', () => {
  64. test('via renderProps', () => {
  65. expect(
  66. renderProps({
  67. class: ['foo', 'bar']
  68. })
  69. ).toBe(` class="foo bar"`)
  70. })
  71. test('standalone', () => {
  72. expect(renderClass(`foo`)).toBe(`foo`)
  73. expect(renderClass([`foo`, `bar`])).toBe(`foo bar`)
  74. expect(renderClass({ foo: true, bar: false })).toBe(`foo`)
  75. expect(renderClass([{ foo: true, bar: false }, `baz`])).toBe(`foo baz`)
  76. })
  77. test('escape class values', () => {
  78. expect(renderClass(`"><script`)).toBe(`&quot;&gt;&lt;script`)
  79. })
  80. })
  81. describe('ssr: renderStyle', () => {
  82. test('via renderProps', () => {
  83. expect(
  84. renderProps({
  85. style: {
  86. color: 'red'
  87. }
  88. })
  89. ).toBe(` style="color:red;"`)
  90. })
  91. test('standalone', () => {
  92. expect(renderStyle(`color:red`)).toBe(`color:red`)
  93. expect(
  94. renderStyle({
  95. color: `red`
  96. })
  97. ).toBe(`color:red;`)
  98. expect(
  99. renderStyle([
  100. { color: `red` },
  101. { fontSize: `15px` } // case conversion
  102. ])
  103. ).toBe(`color:red;font-size:15px;`)
  104. })
  105. test('number handling', () => {
  106. expect(
  107. renderStyle({
  108. fontSize: 15, // should be ignored since font-size requires unit
  109. opacity: 0.5
  110. })
  111. ).toBe(`opacity:0.5;`)
  112. })
  113. test('escape inline CSS', () => {
  114. expect(renderStyle(`"><script`)).toBe(`&quot;&gt;&lt;script`)
  115. expect(
  116. renderStyle({
  117. color: `"><script`
  118. })
  119. ).toBe(`color:&quot;&gt;&lt;script;`)
  120. })
  121. })