|
8 | 8 |
|
9 | 9 | import {CommonModule, DOCUMENT} from '@angular/common'; |
10 | 10 | import {computeMsgId} from '@angular/compiler'; |
11 | | -import {Compiler, Component, ComponentFactoryResolver, Directive, DoCheck, ElementRef, EmbeddedViewRef, ErrorHandler, NO_ERRORS_SCHEMA, NgModule, OnInit, Pipe, PipeTransform, QueryList, RendererFactory2, RendererType2, Sanitizer, TemplateRef, ViewChild, ViewChildren, ViewContainerRef} from '@angular/core'; |
| 11 | +import {Compiler, Component, ComponentFactoryResolver, Directive, DoCheck, ElementRef, EmbeddedViewRef, ErrorHandler, NO_ERRORS_SCHEMA, NgModule, OnInit, Pipe, PipeTransform, QueryList, Renderer2, RendererFactory2, RendererType2, Sanitizer, TemplateRef, ViewChild, ViewChildren, ViewContainerRef, ɵsetDocument} from '@angular/core'; |
12 | 12 | import {Input} from '@angular/core/src/metadata'; |
13 | 13 | import {ngDevModeResetPerfCounters} from '@angular/core/src/util/ng_dev_mode'; |
14 | 14 | import {TestBed, TestComponentRenderer} from '@angular/core/testing'; |
15 | 15 | import {clearTranslations, loadTranslations} from '@angular/localize'; |
16 | | -import {By, DomSanitizer} from '@angular/platform-browser'; |
| 16 | +import {By, DomSanitizer, ɵDomRendererFactory2 as DomRendererFactory2} from '@angular/platform-browser'; |
17 | 17 | import {expect} from '@angular/platform-browser/testing/src/matchers'; |
18 | 18 | import {ivyEnabled, onlyInIvy} from '@angular/private/testing'; |
19 | 19 |
|
@@ -160,6 +160,97 @@ describe('ViewContainerRef', () => { |
160 | 160 | fixture.detectChanges(); |
161 | 161 | expect(fixture.debugElement.nativeElement.innerHTML).toContain('Hello'); |
162 | 162 | }); |
| 163 | + |
| 164 | + describe('element namespaces', () => { |
| 165 | + function runTestWithSelectors(svgSelector: string, mathMLSelector: string) { |
| 166 | + it('should be set correctly for host elements of dynamically created components', () => { |
| 167 | + @Component({ |
| 168 | + selector: svgSelector, |
| 169 | + template: '<svg><g></g></svg>', |
| 170 | + }) |
| 171 | + class SvgComp { |
| 172 | + } |
| 173 | + |
| 174 | + @Component({ |
| 175 | + selector: mathMLSelector, |
| 176 | + template: '<math><matrix></matrix></math>', |
| 177 | + }) |
| 178 | + class MathMLComp { |
| 179 | + } |
| 180 | + |
| 181 | + @NgModule({ |
| 182 | + entryComponents: [SvgComp, MathMLComp], |
| 183 | + declarations: [SvgComp, MathMLComp], |
| 184 | + // View Engine doesn't have MathML tags listed in `DomElementSchemaRegistry`, thus |
| 185 | + // throwing "unknown element" error (':math:matrix' is not a known element). Ignore |
| 186 | + // these errors by adding `NO_ERRORS_SCHEMA` to this NgModule. |
| 187 | + schemas: [NO_ERRORS_SCHEMA], |
| 188 | + }) |
| 189 | + class RootModule { |
| 190 | + } |
| 191 | + |
| 192 | + @Component({ |
| 193 | + template: ` |
| 194 | + <ng-container #svg></ng-container> |
| 195 | + <ng-container #mathml></ng-container> |
| 196 | + ` |
| 197 | + }) |
| 198 | + class TestComp { |
| 199 | + @ViewChild('svg', {read: ViewContainerRef}) svgVCRef !: ViewContainerRef; |
| 200 | + @ViewChild('mathml', {read: ViewContainerRef}) mathMLVCRef !: ViewContainerRef; |
| 201 | + |
| 202 | + constructor(public cfr: ComponentFactoryResolver) {} |
| 203 | + |
| 204 | + createDynamicComponents() { |
| 205 | + const svgFactory = this.cfr.resolveComponentFactory(SvgComp); |
| 206 | + this.svgVCRef.createComponent(svgFactory); |
| 207 | + |
| 208 | + const mathMLFactory = this.cfr.resolveComponentFactory(MathMLComp); |
| 209 | + this.mathMLVCRef.createComponent(mathMLFactory); |
| 210 | + } |
| 211 | + } |
| 212 | + |
| 213 | + function _document(): any { |
| 214 | + // Tell Ivy about the global document |
| 215 | + ɵsetDocument(document); |
| 216 | + return document; |
| 217 | + } |
| 218 | + |
| 219 | + TestBed.configureTestingModule({ |
| 220 | + declarations: [TestComp], |
| 221 | + imports: [RootModule], |
| 222 | + providers: [ |
| 223 | + {provide: DOCUMENT, useFactory: _document, deps: []}, |
| 224 | + // TODO(FW-811): switch back to default server renderer (i.e. remove the line below) |
| 225 | + // once it starts to support Ivy namespace format (URIs) correctly. For now, use |
| 226 | + // `DomRenderer` that supports Ivy namespace format. |
| 227 | + {provide: RendererFactory2, useClass: DomRendererFactory2} |
| 228 | + ], |
| 229 | + }); |
| 230 | + const fixture = TestBed.createComponent(TestComp); |
| 231 | + fixture.detectChanges(); |
| 232 | + |
| 233 | + fixture.componentInstance.createDynamicComponents(); |
| 234 | + fixture.detectChanges(); |
| 235 | + |
| 236 | + expect(fixture.nativeElement.querySelector('svg').namespaceURI) |
| 237 | + .toEqual('http://www.w3.org/2000/svg'); |
| 238 | + |
| 239 | + // View Engine doesn't set MathML namespace, since it's not present in the list of |
| 240 | + // known namespaces here: |
| 241 | + // https://github.com/angular/angular/blob/master/packages/platform-browser/src/dom/dom_renderer.ts#L14 |
| 242 | + if (ivyEnabled) { |
| 243 | + expect(fixture.nativeElement.querySelector('math').namespaceURI) |
| 244 | + .toEqual('http://www.w3.org/1998/MathML/'); |
| 245 | + } |
| 246 | + }); |
| 247 | + } |
| 248 | + |
| 249 | + runTestWithSelectors('svg[some-attr]', 'math[some-attr]'); |
| 250 | + |
| 251 | + // Also test with selector that has element name in uppercase |
| 252 | + runTestWithSelectors('SVG[some-attr]', 'MATH[some-attr]'); |
| 253 | + }); |
163 | 254 | }); |
164 | 255 |
|
165 | 256 | describe('insert', () => { |
|
0 commit comments