| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- import { patchProp } from '../src/patchProp'
- describe(`runtime-dom: style patching`, () => {
- it('string', () => {
- const el = document.createElement('div')
- patchProp(el, 'style', {}, 'color:red')
- expect(el.style.cssText.replace(/\s/g, '')).toBe('color:red;')
- })
- // #1309
- it('should not patch same string style', () => {
- const el = document.createElement('div')
- const fn = vi.fn()
- const value = (el.style.cssText = 'color:red;')
- Object.defineProperty(el.style, 'cssText', {
- get(): any {
- return value
- },
- set: fn,
- })
- patchProp(el, 'style', value, value)
- expect(el.style.cssText.replace(/\s/g, '')).toBe('color:red;')
- expect(fn).not.toBeCalled()
- })
- it('plain object', () => {
- const el = document.createElement('div')
- patchProp(el, 'style', {}, { color: 'red' })
- expect(el.style.cssText.replace(/\s/g, '')).toBe('color:red;')
- })
- it('camelCase', () => {
- const el = document.createElement('div')
- patchProp(el, 'style', {}, { marginRight: '10px' })
- expect(el.style.cssText.replace(/\s/g, '')).toBe('margin-right:10px;')
- })
- it('remove if falsy value', () => {
- const el = document.createElement('div')
- patchProp(el, 'style', null, {
- color: undefined,
- borderRadius: null,
- })
- expect(el.style.cssText.replace(/\s/g, '')).toBe('')
- patchProp(
- el,
- 'style',
- { color: 'red' },
- { color: null, borderRadius: undefined },
- )
- expect(el.style.cssText.replace(/\s/g, '')).toBe('')
- })
- it('!important', () => {
- const el = document.createElement('div')
- patchProp(el, 'style', {}, { color: 'red !important' })
- expect(el.style.cssText.replace(/\s/g, '')).toBe('color:red!important;')
- })
- it('camelCase with !important', () => {
- const el = document.createElement('div')
- patchProp(el, 'style', {}, { marginRight: '10px !important' })
- expect(el.style.cssText.replace(/\s/g, '')).toBe(
- 'margin-right:10px!important;',
- )
- })
- it('object with multiple entries', () => {
- const el = document.createElement('div')
- patchProp(el, 'style', {}, { color: 'red', marginRight: '10px' })
- expect(el.style.getPropertyValue('color')).toBe('red')
- expect(el.style.getPropertyValue('margin-right')).toBe('10px')
- })
- it('patch with falsy style value', () => {
- const el = document.createElement('div')
- patchProp(el as any, 'style', { width: '100px' }, { width: 0 })
- expect(el.style.width).toBe('0px')
- })
- it('should remove style attribute on falsy value', () => {
- const el = document.createElement('div')
- el.style.cssText = 'color: red;'
- patchProp(el as any, 'style', {}, null)
- expect(el.hasAttribute('style')).toBe(false)
- expect(el.style.cssText).toBe('')
- })
- it('should warn for trailing semicolons', () => {
- const el = document.createElement('div')
- patchProp(el, 'style', null, { color: 'red;' })
- expect(
- `Unexpected semicolon at the end of 'color' style value: 'red;'`,
- ).toHaveBeenWarned()
- patchProp(el, 'style', null, { '--custom': '100; ' })
- expect(
- `Unexpected semicolon at the end of '--custom' style value: '100; '`,
- ).toHaveBeenWarned()
- })
- it('should not warn for escaped trailing semicolons', () => {
- const el = document.createElement('div')
- patchProp(el, 'style', null, { '--custom': '100\\;' })
- expect(el.style.getPropertyValue('--custom')).toBe('100\\;')
- })
- it('shorthand properties', () => {
- const el = document.createElement('div')
- patchProp(
- el as any,
- 'style',
- { borderBottom: '1px solid red' },
- { border: '1px solid green' },
- )
- expect(el.style.border).toBe('1px solid green')
- expect(el.style.borderBottom).toBe('1px solid green')
- })
- // JSDOM doesn't support custom properties on style object so we have to
- // mock it here.
- function mockElementWithStyle() {
- const store: any = {}
- return {
- style: {
- display: '',
- WebkitTransition: '',
- setProperty(key: string, val: string) {
- store[key] = val
- },
- getPropertyValue(key: string) {
- return store[key]
- },
- },
- }
- }
- it('CSS custom properties', () => {
- const el = mockElementWithStyle()
- patchProp(el as any, 'style', {}, { '--theme': 'red' } as any)
- expect(el.style.getPropertyValue('--theme')).toBe('red')
- })
- it('auto vendor prefixing', () => {
- const el = mockElementWithStyle()
- patchProp(el as any, 'style', {}, { transition: 'all 1s' })
- expect(el.style.WebkitTransition).toBe('all 1s')
- })
- it('multiple values', () => {
- const el = mockElementWithStyle()
- patchProp(
- el as any,
- 'style',
- {},
- { display: ['-webkit-box', '-ms-flexbox', 'flex'] },
- )
- expect(el.style.display).toBe('flex')
- })
- it('should clear previous css string value', () => {
- const el = document.createElement('div')
- patchProp(el, 'style', {}, 'color:red')
- expect(el.style.cssText.replace(/\s/g, '')).toBe('color:red;')
- patchProp(el, 'style', 'color:red', { fontSize: '12px' })
- expect(el.style.cssText.replace(/\s/g, '')).toBe('font-size:12px;')
- })
- })
|