patchStyle.spec.ts 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import { patchProp } from '../src/patchProp'
  2. describe(`runtime-dom: style patching`, () => {
  3. it('string', () => {
  4. const el = document.createElement('div')
  5. patchProp(el, 'style', {}, 'color:red')
  6. expect(el.style.cssText.replace(/\s/g, '')).toBe('color:red;')
  7. })
  8. // #1309
  9. it('should not patch same string style', () => {
  10. const el = document.createElement('div')
  11. const fn = jest.fn()
  12. const value = (el.style.cssText = 'color:red;')
  13. Object.defineProperty(el.style, 'cssText', {
  14. get(): any {
  15. return value
  16. },
  17. set: fn
  18. })
  19. patchProp(el, 'style', value, value)
  20. expect(el.style.cssText.replace(/\s/g, '')).toBe('color:red;')
  21. expect(fn).not.toBeCalled()
  22. })
  23. it('plain object', () => {
  24. const el = document.createElement('div')
  25. patchProp(el, 'style', {}, { color: 'red' })
  26. expect(el.style.cssText.replace(/\s/g, '')).toBe('color:red;')
  27. })
  28. it('camelCase', () => {
  29. const el = document.createElement('div')
  30. patchProp(el, 'style', {}, { marginRight: '10px' })
  31. expect(el.style.cssText.replace(/\s/g, '')).toBe('margin-right:10px;')
  32. })
  33. it('remove if falsy value', () => {
  34. const el = document.createElement('div')
  35. patchProp(el, 'style', { color: 'red' }, { color: undefined })
  36. expect(el.style.cssText.replace(/\s/g, '')).toBe('')
  37. })
  38. it('!important', () => {
  39. const el = document.createElement('div')
  40. patchProp(el, 'style', {}, { color: 'red !important' })
  41. expect(el.style.cssText.replace(/\s/g, '')).toBe('color:red!important;')
  42. })
  43. it('camelCase with !important', () => {
  44. const el = document.createElement('div')
  45. patchProp(el, 'style', {}, { marginRight: '10px !important' })
  46. expect(el.style.cssText.replace(/\s/g, '')).toBe(
  47. 'margin-right:10px!important;'
  48. )
  49. })
  50. it('object with multiple entries', () => {
  51. const el = document.createElement('div')
  52. patchProp(el, 'style', {}, { color: 'red', marginRight: '10px' })
  53. expect(el.style.getPropertyValue('color')).toBe('red')
  54. expect(el.style.getPropertyValue('margin-right')).toBe('10px')
  55. })
  56. it('patch with falsy style value', () => {
  57. const el = document.createElement('div')
  58. patchProp(el as any, 'style', { width: '100px' }, { width: 0 })
  59. expect(el.style.width).toBe('0px')
  60. })
  61. it('should remove style attribute on falsy value', () => {
  62. const el = document.createElement('div')
  63. el.style.cssText = 'color: red;'
  64. patchProp(el as any, 'style', {}, null)
  65. expect(el.hasAttribute('style')).toBe(false)
  66. expect(el.style.cssText).toBe('')
  67. })
  68. // JSDOM doesn't support custom properties on style object so we have to
  69. // mock it here.
  70. function mockElementWithStyle() {
  71. const store: any = {}
  72. return {
  73. style: {
  74. display: '',
  75. WebkitTransition: '',
  76. setProperty(key: string, val: string) {
  77. store[key] = val
  78. },
  79. getPropertyValue(key: string) {
  80. return store[key]
  81. }
  82. }
  83. }
  84. }
  85. it('CSS custom properties', () => {
  86. const el = mockElementWithStyle()
  87. patchProp(el as any, 'style', {}, { '--theme': 'red' } as any)
  88. expect(el.style.getPropertyValue('--theme')).toBe('red')
  89. })
  90. it('auto vendor prefixing', () => {
  91. const el = mockElementWithStyle()
  92. patchProp(el as any, 'style', {}, { transition: 'all 1s' })
  93. expect(el.style.WebkitTransition).toBe('all 1s')
  94. })
  95. it('multiple values', () => {
  96. const el = mockElementWithStyle()
  97. patchProp(
  98. el as any,
  99. 'style',
  100. {},
  101. { display: ['-webkit-box', '-ms-flexbox', 'flex'] }
  102. )
  103. expect(el.style.display).toBe('flex')
  104. })
  105. })