Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 17cf04e

Browse files
matskoatscott
authored andcommitted
fix(animations): allow computeStyle to work on elements created in Node (#35810)
This patch is a follow-up patch to 35c9f0d. It changes the `computeStyle` function to handle situations where non string based values are returned from `window.getComputedStyle`. This situation usually ocurrs in Node-based test environments where the element or `window.getComputedStyle` is mocked out. PR Close #35810
1 parent c7d0567 commit 17cf04e

File tree

2 files changed

+33
-7
lines changed

2 files changed

+33
-7
lines changed

‎packages/animations/browser/src/render/shared.ts

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -248,26 +248,43 @@ export function hypenatePropsObject(object: {[key: string]: any}): {[key: string
248248
* for that.
249249
*/
250250
export function computeStyle(element: HTMLElement, prop: string): string {
251-
const gcs = window.getComputedStyle(element);
251+
const styles = window.getComputedStyle(element);
252252

253253
// this is casted to any because the `CSSStyleDeclaration` type is a fixed
254254
// set of properties and `prop` is a dynamic reference to a property within
255255
// the `CSSStyleDeclaration` list.
256-
let value = gcs[prop as any];
256+
let value = getComputedValue(styles, prop as keyof CSSStyleDeclaration);
257257

258258
// Firefox returns empty string values for `margin` and `padding` properties
259259
// when extracted using getComputedStyle (see similar issue here:
260260
// https://github.com/jquery/jquery/issues/3383). In this situation
261261
// we want to emulate the value that is returned by creating the top,
262262
// right, bottom and left properties as individual style lookups.
263263
if (value.length === 0 && (prop === 'margin' || prop === 'padding')) {
264+
const t = getComputedValue(styles, (prop + 'Top') as 'marginTop' | 'paddingTop');
265+
const r = getComputedValue(styles, (prop + 'Right') as 'marginRight' | 'paddingRight');
266+
const b = getComputedValue(styles, (prop + 'Bottom') as 'marginBottom' | 'paddingBottom');
267+
const l = getComputedValue(styles, (prop + 'Left') as 'marginLeft' | 'paddingLeft');
268+
264269
// reconstruct the padding/margin value as `top right bottom left`
265-
const propTop = (prop + 'Top') as 'marginTop' | 'paddingTop';
266-
const propRight = (prop + 'Right') as 'marginRight' | 'paddingRight';
267-
const propBottom = (prop + 'Bottom') as 'marginBottom' | 'paddingBottom';
268-
const propLeft = (prop + 'Left') as 'marginLeft' | 'paddingLeft';
269-
value = `${gcs[propTop]} ${gcs[propRight]} ${gcs[propBottom]} ${gcs[propLeft]}`;
270+
// we `trim()` the value because if all of the values above are
271+
// empty string values then we would like the return value to
272+
// also be an empty string.
273+
value = `${t} ${r} ${b} ${l}`.trim();
270274
}
271275

272276
return value;
273277
}
278+
279+
/**
280+
* Reads and returns the provided property style from the provided styles collection.
281+
*
282+
* This function is useful because it will return an empty string in the
283+
* event that the value obtained from the styles collection is a non-string
284+
* value (which is usually the case if the `styles` object is mocked out).
285+
*/
286+
function getComputedValue<K extends keyof CSSStyleDeclaration>(
287+
styles: CSSStyleDeclaration, prop: K): string {
288+
const value = styles[prop];
289+
return typeof value === 'string' ? value : '';
290+
}

‎packages/animations/browser/test/render/shared_spec.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,15 @@ describe('shared animations code', () => {
1111
if (isNode) return;
1212

1313
describe('computeStyle', () => {
14+
it('should return an empty string if the inner computed style value is not a string', () => {
15+
const gcsSpy = spyOn(window, 'getComputedStyle').and.returnValue(() => null);
16+
const elementLike = buildActualElement();
17+
expect(computeStyle(elementLike, 'width')).toEqual('');
18+
expect(computeStyle(elementLike, 'padding')).toEqual('');
19+
expect(computeStyle(elementLike, 'margin')).toEqual('');
20+
gcsSpy.and.callThrough();
21+
});
22+
1423
it('should compute the margin style into the form top,right,bottom,left', () => {
1524
const div = buildActualElement();
1625

0 commit comments

Comments
 (0)