From 00f13cc074608b1e9524ee9b03c19f9c177d19c9 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Mon, 20 Jan 2020 21:22:38 +0100 Subject: [PATCH] fix(ivy): DebugNode.classes not working on SVG elements (#34872) Fixes Ivy throwing an error when trying to access the `DebugNode.classes` of an SVG element. The problem is that the `className` of an SVG element is an `SVGAnimatedString`, rather than a plain string. Fixes #34868. PR Close #34872 --- packages/core/src/debug/debug_node.ts | 10 +++++++--- packages/core/test/debug/debug_node_spec.ts | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/packages/core/src/debug/debug_node.ts b/packages/core/src/debug/debug_node.ts index 0b1e81d402..9806310d87 100644 --- a/packages/core/src/debug/debug_node.ts +++ b/packages/core/src/debug/debug_node.ts @@ -352,10 +352,14 @@ class DebugElement__POST_R3__ extends DebugNode__POST_R3__ implements DebugEleme get classes(): {[key: string]: boolean;} { const result: {[key: string]: boolean;} = {}; - const element = this.nativeElement as HTMLElement; - const classNames = element.className.split(' '); + const element = this.nativeElement as HTMLElement | SVGElement; - classNames.forEach((value: string) => result[value] = true); + // SVG elements return an `SVGAnimatedString` instead of a plain string for the `className`. + const className = element.className as string | SVGAnimatedString; + const classes = className && typeof className !== 'string' ? className.baseVal.split(' ') : + className.split(' '); + + classes.forEach((value: string) => result[value] = true); return result; } diff --git a/packages/core/test/debug/debug_node_spec.ts b/packages/core/test/debug/debug_node_spec.ts index d3c22df2da..c8e51f48d3 100644 --- a/packages/core/test/debug/debug_node_spec.ts +++ b/packages/core/test/debug/debug_node_spec.ts @@ -368,6 +368,22 @@ class TestCmptWithPropInterpolation { .toBeFalsy('Expected bound host CSS class "absent-class" to be absent'); }); + it('should list classes on SVG nodes', () => { + // Class bindings on SVG elements require a polyfill + // on IE which we don't include when running tests. + if (typeof SVGElement !== 'undefined' && !('classList' in SVGElement.prototype)) { + return; + } + + TestBed.overrideTemplate(TestApp, ``); + fixture = TestBed.createComponent(TestApp); + fixture.detectChanges(); + const classes = fixture.debugElement.children[0].classes; + + expect(classes['foo']).toBe(true); + expect(classes['bar']).toBe(true); + }); + it('should list element styles', () => { fixture = TestBed.createComponent(TestApp); fixture.detectChanges();