fix(ivy): DebugNode.properties not preserving type of values (#29914)

Fixes the `DebugNode.properties` casting all of the values to a string.

This PR resolves FW-1253.

PR Close #29914
This commit is contained in:
Kristiyan Kostadinov 2019-04-15 21:59:51 +02:00 committed by Alex Rickabaugh
parent ca755a6b72
commit 5d824c4153
2 changed files with 31 additions and 5 deletions

View File

@ -538,23 +538,26 @@ function collectPropertyBindings(
let bindingIndex = getFirstBindingIndex(tNode.propertyMetadataStartIndex, tData); let bindingIndex = getFirstBindingIndex(tNode.propertyMetadataStartIndex, tData);
while (bindingIndex < tNode.propertyMetadataEndIndex) { while (bindingIndex < tNode.propertyMetadataEndIndex) {
let value = ''; let value: any;
let propMetadata = tData[bindingIndex] as string; let propMetadata = tData[bindingIndex] as string;
while (!isPropMetadataString(propMetadata)) { while (!isPropMetadataString(propMetadata)) {
// This is the first value for an interpolation. We need to build up // This is the first value for an interpolation. We need to build up
// the full interpolation by combining runtime values in LView with // the full interpolation by combining runtime values in LView with
// the static interstitial values stored in TData. // the static interstitial values stored in TData.
value += renderStringify(lView[bindingIndex]) + tData[bindingIndex]; value = (value || '') + renderStringify(lView[bindingIndex]) + tData[bindingIndex];
propMetadata = tData[++bindingIndex] as string; propMetadata = tData[++bindingIndex] as string;
} }
value += lView[bindingIndex]; value = value === undefined ? lView[bindingIndex] : value += lView[bindingIndex];
// Property metadata string has 3 parts: property name, prefix, and suffix // Property metadata string has 3 parts: property name, prefix, and suffix
const metadataParts = propMetadata.split(INTERPOLATION_DELIMITER); const metadataParts = propMetadata.split(INTERPOLATION_DELIMITER);
const propertyName = metadataParts[0]; const propertyName = metadataParts[0];
// Attr bindings don't have property names and should be skipped // Attr bindings don't have property names and should be skipped
if (propertyName) { if (propertyName) {
// Wrap value with prefix and suffix (will be '' for normal bindings) // Wrap value with prefix and suffix (will be '' for normal bindings), if they're defined.
properties[propertyName] = metadataParts[1] + value + metadataParts[2]; // Avoid wrapping for normal bindings so that the value doesn't get cast to a string.
properties[propertyName] = (metadataParts[1] && metadataParts[2]) ?
metadataParts[1] + value + metadataParts[2] :
value;
} }
bindingIndex++; bindingIndex++;
} }

View File

@ -195,6 +195,20 @@ class TestCmptWithViewContainerRef {
constructor(private vcref: ViewContainerRef) {} constructor(private vcref: ViewContainerRef) {}
} }
@Component({
template: `
<button
[disabled]="disabled"
[tabIndex]="tabIndex"
[title]="title">Click me</button>
`
})
class TestCmptWithPropBindings {
disabled = true;
tabIndex = 1337;
title = 'hello';
}
{ {
describe('debug element', () => { describe('debug element', () => {
let fixture: ComponentFixture<any>; let fixture: ComponentFixture<any>;
@ -218,6 +232,7 @@ class TestCmptWithViewContainerRef {
HostClassBindingCmp, HostClassBindingCmp,
TestCmptWithViewContainerRef, TestCmptWithViewContainerRef,
SimpleContentComp, SimpleContentComp,
TestCmptWithPropBindings,
], ],
providers: [Logger], providers: [Logger],
schemas: [NO_ERRORS_SCHEMA], schemas: [NO_ERRORS_SCHEMA],
@ -566,6 +581,14 @@ class TestCmptWithViewContainerRef {
expect(debugElement.properties.className).toBeFalsy(); expect(debugElement.properties.className).toBeFalsy();
}); });
it('should preserve the type of the property values', () => {
const fixture = TestBed.createComponent(TestCmptWithPropBindings);
fixture.detectChanges();
const button = fixture.debugElement.query(By.css('button'));
expect(button.properties).toEqual({disabled: true, tabIndex: 1337, title: 'hello'});
});
describe('componentInstance on DebugNode', () => { describe('componentInstance on DebugNode', () => {
it('should return component associated with a node if a node is a component host', () => { it('should return component associated with a node if a node is a component host', () => {