Skip to content

Commit bfbb42c

Browse files
Paulo FerroPaulo Ferro
authored andcommitted
Global quote type = Initial should not override attribute quote type on value set
1 parent 9ead5db commit bfbb42c

File tree

5 files changed

+273
-1
lines changed

5 files changed

+273
-1
lines changed

src/HtmlAgilityPack.Shared/HtmlAttribute.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,9 @@ public string Value
213213
_value = value;
214214
if (!string.IsNullOrEmpty(_value) && this.QuoteType == AttributeValueQuote.WithoutValue)
215215
{
216-
this.InternalQuoteType = this.OwnerDocument.GlobalAttributeValueQuote ?? AttributeValueQuote.DoubleQuote;
216+
this.InternalQuoteType = this.OwnerDocument.GlobalAttributeValueQuote != AttributeValueQuote.Initial ?
217+
(this.OwnerDocument.GlobalAttributeValueQuote ?? AttributeValueQuote.DoubleQuote)
218+
: AttributeValueQuote.DoubleQuote;
217219
}
218220

219221
if (_ownernode != null)

src/Tests/HtmlAgilityPack.Tests.NetStandard2_0/HtmlAgilityPack.Tests.NetStandard2_0.csproj

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@
66
<IsPackable>false</IsPackable>
77
</PropertyGroup>
88

9+
<ItemGroup>
10+
<None Remove="files\*" />
11+
<Content Include="files\*">
12+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
13+
</Content>
14+
</ItemGroup>
15+
916
<ItemGroup>
1017
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
1118
<PackageReference Include="xunit" Version="2.4.0" />
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
using System;
2+
using System.IO;
3+
using System.Linq;
4+
using System.Xml.XPath;
5+
using Xunit;
6+
7+
namespace HtmlAgilityPack.Tests.NetStandard2_0
8+
{
9+
public class HtmlDocumentPreserveOriginalTest
10+
{
11+
[Fact]
12+
public void PreserveEmptyAttributesTest()
13+
{
14+
var d = new HtmlDocument();
15+
d.OptionEmptyCollection = true;
16+
17+
d.GlobalAttributeValueQuote = AttributeValueQuote.Initial;
18+
19+
d.OptionDefaultUseOriginalName = true;
20+
//d.OptionPreserveEmptyAttributes = true;
21+
22+
var html = @"
23+
<form #editForm='ngForm' (ngSubmit)='OnSaveData()' name='globalForm' [dataSourceContext]='detailDataSourceContext'>
24+
<page editable (beginEdit)='OnBeginEdit()' (cancelEdit)='OnCancelEdit($event)'>
25+
26+
<page-header pageHeaderIcon='_Lea_ mdi mdi-code-json'>
27+
28+
<page-header-actions>
29+
<list-counter formErrorsCounter></list-counter>
30+
31+
<button mat-button *hasEveryPermission='permissionConstants.LeaProdutos.edit' enterEditButton>
32+
</button>
33+
34+
<button mat-button *hasEveryPermission='permissionConstants.LeaProdutos.edit' cancelEditButton>
35+
</button>
36+
37+
<button mat-button *hasEveryPermission='permissionConstants.LeaProdutos.edit' type='submit' confirmEditButton>
38+
</button>
39+
40+
<refresh-button></refresh-button>
41+
</page-header-actions>
42+
43+
</page-header>
44+
45+
<page-body>
46+
</page-body>
47+
48+
</page>
49+
</form>
50+
";
51+
d.LoadHtml(html);
52+
53+
var outer = d.DocumentNode.OuterHtml;
54+
55+
var xpath = XPathExpression.Compile("/form/page/page-header/page-header-actions/button[@enterEditButton]");
56+
var nodes = d.DocumentNode.SelectNodes(xpath);
57+
58+
Assert.Equal(1, nodes?.Count);
59+
Assert.Equal(html, d.DocumentNode.OuterHtml);
60+
}
61+
62+
[Fact]
63+
public void PreserveOriginalCasingTest()
64+
{
65+
var d = new HtmlDocument();
66+
d.OptionEmptyCollection = true;
67+
68+
d.GlobalAttributeValueQuote = AttributeValueQuote.Initial;
69+
70+
d.OptionDefaultUseOriginalName = true;
71+
//d.OptionPreserveEmptyAttributes = true;
72+
73+
var html = @"
74+
<form #editForm='ngForm' (ngSubmit)='OnSaveData()' name='globalForm' [dataSourceContext]='detailDataSourceContext'>
75+
<page editable (beginEdit)='OnBeginEdit()' (cancelEdit)='OnCancelEdit($event)'>
76+
77+
<page-Header pageHeaderIcon='_Lea_ mdi mdi-code-json'>
78+
79+
<page-Header-Actions>
80+
<list-counter formErrorsCounter></list-counter>
81+
82+
<button mat-button *hasEveryPermission='permissionConstants.LeaProdutos.edit' enterEditButton>
83+
</button>
84+
85+
<button mat-button *hasEveryPermission='permissionConstants.LeaProdutos.edit' cancelEditButton>
86+
</button>
87+
88+
<button mat-button *hasEveryPermission='permissionConstants.LeaProdutos.edit' type='submit' confirmEditButton>
89+
</button>
90+
91+
<refresh-button></refresh-button>
92+
</page-Header-Actions>
93+
94+
</page-Header>
95+
96+
<page-body>
97+
</page-body>
98+
99+
</page>
100+
</form>
101+
";
102+
d.LoadHtml(html);
103+
104+
var xpath = XPathExpression.Compile("/form/page/page-Header/page-Header-Actions/button[@enterEditButton]");
105+
var nodes = d.DocumentNode.SelectNodes(xpath);
106+
107+
Assert.Equal(1, nodes?.Count);
108+
Assert.Equal(html, d.DocumentNode.OuterHtml);
109+
}
110+
111+
112+
[Fact]
113+
public void PreserveOriginalQuoteTest()
114+
{
115+
var contentDirectory = Path.GetDirectoryName(typeof(HtmlDocumentPreserveOriginalTest).Assembly.Location).ToString() + "\\files\\";
116+
117+
var d = new HtmlDocument();
118+
d.OptionEmptyCollection = true;
119+
120+
d.GlobalAttributeValueQuote = AttributeValueQuote.Initial;
121+
d.OptionDefaultUseOriginalName = true;
122+
123+
var filePath = Path.Combine(contentDirectory, "attr_quote.html");
124+
var filePathExpected = Path.Combine(contentDirectory, "attr_quote_expected.html");
125+
d.Load(filePath);
126+
127+
var xpath = XPathExpression.Compile("/form/page/page-body/card/data-group/mat-form-field[@*[local-name() = 'xdt:Transform' and . = \"InsertAfter(mat-form-field[mat-select/@name = 'tipoProdutoId'])\"]]/mat-select/mat-option");
128+
var nodes = d.DocumentNode.SelectNodes(xpath);
129+
130+
Assert.Equal(1, nodes?.Count);
131+
132+
nodes[0].ParentNode.Attributes["required"].Value = "true";
133+
134+
Assert.Equal(File.ReadAllText(filePathExpected), d.DocumentNode.OuterHtml);
135+
136+
var clone = nodes[0].CloneNode(true);
137+
138+
var expectedOuterNode = @"<mat-option *ngFor=""let dimension of lea546CATBEM$ | async | filterDimensionByValue:( simulationRequest.tipoProdutoId | commonData:lea508SUBPROD$:'id':'code')"" [value]=""dimension.dimensionId"">
139+
140+
141+
{{ dimension.code }} - {{ dimension.description }}
142+
</mat-option>";
143+
144+
Assert.Equal(expectedOuterNode, clone.OuterHtml);
145+
146+
}
147+
148+
149+
[Fact]
150+
public void PreserveClonedEmptyAttributesTest()
151+
{
152+
var d = new HtmlDocument();
153+
d.GlobalAttributeValueQuote = AttributeValueQuote.Initial;
154+
d.OptionDefaultUseOriginalName = true;
155+
156+
var html = @"<list-counter formErrorsCounter></list-counter>";
157+
d.LoadHtml(html);
158+
159+
var cloned = d.DocumentNode.CloneNode(true);
160+
161+
Assert.Equal(@"<list-counter formErrorsCounter></list-counter>", cloned.OuterHtml);
162+
}
163+
164+
[Fact]
165+
public void PreserveQuoteTypeForLoadedAttributes()
166+
{
167+
var input = HtmlNode.CreateNode("<input checked></input>");
168+
var checkedAttribute = input.Attributes.First();
169+
170+
// Result is: Value: '' (empty string)
171+
Assert.Equal("", checkedAttribute.Value);
172+
173+
// Result is: QuoteType: WithoutValue
174+
Assert.Equal(AttributeValueQuote.WithoutValue, checkedAttribute.QuoteType);
175+
}
176+
}
177+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<form xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
2+
<page>
3+
4+
<page-body>
5+
<form #simulatorForm="ngForm" xdt:Transform="InsertBefore(/form/page/page-body/card[1])"
6+
fxFlex="50%" fxFlex.lt-md="100%"
7+
[dataSourceContext]="simulatorDataSourceContext" name="simulatorForm">
8+
<ng-container></ng-container>
9+
</form>
10+
<!--DADOS DE SIMULAÇÃO-->
11+
<card xdt:Transform="SetAttributes(*)"
12+
xdt:Locator="Condition(card-header/card-header-title-container/card-header-title = &quot;{{ 'Lea.Cotacoes.Cards.Dados de Simulação' | translate }}&quot;)"
13+
editable
14+
fxFlex="100%">
15+
<data-group>
16+
17+
<!-- INSERT CategoriaBem AFTER mat-form-field with mat-select@name = 'tipoProdutoId' -->
18+
<mat-form-field xdt:Transform="InsertAfter(mat-form-field[mat-select/@name = 'tipoProdutoId'])"
19+
fxFlex="50%" fxFlex.lt-md="50%" fxFlex.lt-sm="100%" *ngIf="!!simulationRequest.tipoProdutoId">
20+
<!-- CategoriaBem -->
21+
<mat-label>
22+
<span>{{ 'Lea.Cotacoes.Simulador.CodCategoriaBem' | translate}}</span>
23+
</mat-label>
24+
<mat-select name="codCategoriaBemId" required
25+
(selectionChange)="GetProductDetails()"
26+
[(ngModel)]="simulationRequest.categoriaBemId">
27+
<mat-option *ngFor="let dimension of lea546CATBEM$ | async | filterDimensionByValue:( simulationRequest.tipoProdutoId | commonData:lea508SUBPROD$:'id':'code')" [value]="dimension.dimensionId">
28+
29+
30+
{{ dimension.code }} - {{ dimension.description }}
31+
</mat-option>
32+
</mat-select>
33+
<span readOnlyValue>{{ simulationRequest.categoriaBemId | commonData:lea546CATBEM$:'id':'code-desc' }}</span>
34+
<field-error-alert matSuffix></field-error-alert>
35+
<mat-error></mat-error>
36+
</mat-form-field>
37+
38+
</data-group>
39+
40+
</card>
41+
42+
43+
</page-body>
44+
45+
46+
</page>
47+
</form>
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<form xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
2+
<page>
3+
4+
<page-body>
5+
<form #simulatorForm="ngForm" xdt:Transform="InsertBefore(/form/page/page-body/card[1])" fxFlex="50%" fxFlex.lt-md="100%" [dataSourceContext]="simulatorDataSourceContext" name="simulatorForm">
6+
<ng-container></ng-container>
7+
</form>
8+
<!--DADOS DE SIMULAÇÃO-->
9+
<card xdt:Transform="SetAttributes(*)" xdt:Locator="Condition(card-header/card-header-title-container/card-header-title = &quot;{{ 'Lea.Cotacoes.Cards.Dados de Simulação' | translate }}&quot;)" editable fxFlex="100%">
10+
<data-group>
11+
12+
<!-- INSERT CategoriaBem AFTER mat-form-field with mat-select@name = 'tipoProdutoId' -->
13+
<mat-form-field xdt:Transform="InsertAfter(mat-form-field[mat-select/@name = 'tipoProdutoId'])" fxFlex="50%" fxFlex.lt-md="50%" fxFlex.lt-sm="100%" *ngIf="!!simulationRequest.tipoProdutoId">
14+
<!-- CategoriaBem -->
15+
<mat-label>
16+
<span>{{ 'Lea.Cotacoes.Simulador.CodCategoriaBem' | translate}}</span>
17+
</mat-label>
18+
<mat-select name="codCategoriaBemId" required="true" (selectionChange)="GetProductDetails()" [(ngModel)]="simulationRequest.categoriaBemId">
19+
<mat-option *ngFor="let dimension of lea546CATBEM$ | async | filterDimensionByValue:( simulationRequest.tipoProdutoId | commonData:lea508SUBPROD$:'id':'code')" [value]="dimension.dimensionId">
20+
21+
22+
{{ dimension.code }} - {{ dimension.description }}
23+
</mat-option>
24+
</mat-select>
25+
<span readOnlyValue>{{ simulationRequest.categoriaBemId | commonData:lea546CATBEM$:'id':'code-desc' }}</span>
26+
<field-error-alert matSuffix></field-error-alert>
27+
<mat-error></mat-error>
28+
</mat-form-field>
29+
30+
</data-group>
31+
32+
</card>
33+
34+
35+
</page-body>
36+
37+
38+
</page>
39+
</form>

0 commit comments

Comments
 (0)