@@ -146,6 +146,141 @@ describe('ReactDOMComponent', () => {
146146 }
147147 } ) ;
148148
149+ it ( 'should warn for conflicting CSS shorthand updates' , ( ) => {
150+ const container = document . createElement ( 'div' ) ;
151+ ReactDOM . render (
152+ < div style = { { font : 'foo' , fontStyle : 'bar' } } /> ,
153+ container ,
154+ ) ;
155+ expect ( ( ) =>
156+ ReactDOM . render ( < div style = { { font : 'foo' } } /> , container ) ,
157+ ) . toWarnDev (
158+ 'Warning: Removing a style property during rerender (fontStyle) ' +
159+ 'when a conflicting property is set (font) can lead to styling ' +
160+ "bugs. To avoid this, don't mix shorthand and non-shorthand " +
161+ 'properties for the same value; instead, replace the shorthand ' +
162+ 'with separate values.' +
163+ '\n in div (at **)' ,
164+ ) ;
165+
166+ // These updates are OK and don't warn:
167+ ReactDOM . render (
168+ < div style = { { font : 'qux' , fontStyle : 'bar' } } /> ,
169+ container ,
170+ ) ;
171+ ReactDOM . render (
172+ < div style = { { font : 'foo' , fontStyle : 'baz' } } /> ,
173+ container ,
174+ ) ;
175+
176+ expect ( ( ) =>
177+ ReactDOM . render (
178+ < div style = { { font : 'qux' , fontStyle : 'baz' } } /> ,
179+ container ,
180+ ) ,
181+ ) . toWarnDev (
182+ 'Warning: Updating a style property during rerender (font) when ' +
183+ 'a conflicting property is set (fontStyle) can lead to styling ' +
184+ "bugs. To avoid this, don't mix shorthand and non-shorthand " +
185+ 'properties for the same value; instead, replace the shorthand ' +
186+ 'with separate values.' +
187+ '\n in div (at **)' ,
188+ ) ;
189+ expect ( ( ) =>
190+ ReactDOM . render ( < div style = { { fontStyle : 'baz' } } /> , container ) ,
191+ ) . toWarnDev (
192+ 'Warning: Removing a style property during rerender (font) when ' +
193+ 'a conflicting property is set (fontStyle) can lead to styling ' +
194+ "bugs. To avoid this, don't mix shorthand and non-shorthand " +
195+ 'properties for the same value; instead, replace the shorthand ' +
196+ 'with separate values.' +
197+ '\n in div (at **)' ,
198+ ) ;
199+
200+ // A bit of a special case: backgroundPosition isn't technically longhand
201+ // (it expands to backgroundPosition{X,Y} but so does background)
202+ ReactDOM . render (
203+ < div style = { { background : 'yellow' , backgroundPosition : 'center' } } /> ,
204+ container ,
205+ ) ;
206+ expect ( ( ) =>
207+ ReactDOM . render ( < div style = { { background : 'yellow' } } /> , container ) ,
208+ ) . toWarnDev (
209+ 'Warning: Removing a style property during rerender ' +
210+ '(backgroundPosition) when a conflicting property is set ' +
211+ "(background) can lead to styling bugs. To avoid this, don't mix " +
212+ 'shorthand and non-shorthand properties for the same value; ' +
213+ 'instead, replace the shorthand with separate values.' +
214+ '\n in div (at **)' ,
215+ ) ;
216+ ReactDOM . render (
217+ < div style = { { background : 'yellow' , backgroundPosition : 'center' } } /> ,
218+ container ,
219+ ) ;
220+ // But setting them at the same time is OK:
221+ ReactDOM . render (
222+ < div style = { { background : 'green' , backgroundPosition : 'top' } } /> ,
223+ container ,
224+ ) ;
225+ expect ( ( ) =>
226+ ReactDOM . render ( < div style = { { backgroundPosition : 'top' } } /> , container ) ,
227+ ) . toWarnDev (
228+ 'Warning: Removing a style property during rerender (background) ' +
229+ 'when a conflicting property is set (backgroundPosition) can lead ' +
230+ "to styling bugs. To avoid this, don't mix shorthand and " +
231+ 'non-shorthand properties for the same value; instead, replace the ' +
232+ 'shorthand with separate values.' +
233+ '\n in div (at **)' ,
234+ ) ;
235+
236+ // A bit of an even more special case: borderLeft and borderStyle overlap.
237+ ReactDOM . render (
238+ < div style = { { borderStyle : 'dotted' , borderLeft : '1px solid red' } } /> ,
239+ container ,
240+ ) ;
241+ expect ( ( ) =>
242+ ReactDOM . render (
243+ < div style = { { borderLeft : '1px solid red' } } /> ,
244+ container ,
245+ ) ,
246+ ) . toWarnDev (
247+ 'Warning: Removing a style property during rerender (borderStyle) ' +
248+ 'when a conflicting property is set (borderLeft) can lead to ' +
249+ "styling bugs. To avoid this, don't mix shorthand and " +
250+ 'non-shorthand properties for the same value; instead, replace the ' +
251+ 'shorthand with separate values.' +
252+ '\n in div (at **)' ,
253+ ) ;
254+ expect ( ( ) =>
255+ ReactDOM . render (
256+ < div style = { { borderStyle : 'dashed' , borderLeft : '1px solid red' } } /> ,
257+ container ,
258+ ) ,
259+ ) . toWarnDev (
260+ 'Warning: Updating a style property during rerender (borderStyle) ' +
261+ 'when a conflicting property is set (borderLeft) can lead to ' +
262+ "styling bugs. To avoid this, don't mix shorthand and " +
263+ 'non-shorthand properties for the same value; instead, replace the ' +
264+ 'shorthand with separate values.' +
265+ '\n in div (at **)' ,
266+ ) ;
267+ // But setting them at the same time is OK:
268+ ReactDOM . render (
269+ < div style = { { borderStyle : 'dotted' , borderLeft : '2px solid red' } } /> ,
270+ container ,
271+ ) ;
272+ expect ( ( ) =>
273+ ReactDOM . render ( < div style = { { borderStyle : 'dotted' } } /> , container ) ,
274+ ) . toWarnDev (
275+ 'Warning: Removing a style property during rerender (borderLeft) ' +
276+ 'when a conflicting property is set (borderStyle) can lead to ' +
277+ "styling bugs. To avoid this, don't mix shorthand and " +
278+ 'non-shorthand properties for the same value; instead, replace the ' +
279+ 'shorthand with separate values.' +
280+ '\n in div (at **)' ,
281+ ) ;
282+ } ) ;
283+
149284 it ( 'should warn for unknown prop' , ( ) => {
150285 const container = document . createElement ( 'div' ) ;
151286 expect ( ( ) =>
0 commit comments