patchStyle.spec.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  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. // JSDOM doesn't support custom properties on style object so we have to
  62. // mock it here.
  63. function mockElementWithStyle() {
  64. const store: any = {}
  65. return {
  66. style: {
  67. display: '',
  68. WebkitTransition: '',
  69. setProperty(key: string, val: string) {
  70. store[key] = val
  71. },
  72. getPropertyValue(key: string) {
  73. return store[key]
  74. }
  75. }
  76. }
  77. }
  78. it('CSS custom properties', () => {
  79. const el = mockElementWithStyle()
  80. patchProp(el as any, 'style', {}, { '--theme': 'red' } as any)
  81. expect(el.style.getPropertyValue('--theme')).toBe('red')
  82. })
  83. it('auto vendor prefixing', () => {
  84. const el = mockElementWithStyle()
  85. patchProp(el as any, 'style', {}, { transition: 'all 1s' })
  86. expect(el.style.WebkitTransition).toBe('all 1s')
  87. })
  88. it('multiple values', () => {
  89. const el = mockElementWithStyle()
  90. patchProp(
  91. el as any,
  92. 'style',
  93. {},
  94. { display: ['-webkit-box', '-ms-flexbox', 'flex'] }
  95. )
  96. expect(el.style.display).toBe('flex')
  97. })
  98. })