1 // Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
2 
3 using System.Collections.Generic;
4 using System.ComponentModel.DataAnnotations;
5 using Moq;
6 using Xunit;
7 using Assert = Microsoft.TestCommon.AssertEx;
8 
9 namespace System.Web.Mvc.Test
10 {
11     public class CompareAttributeTest
12     {
13         [Fact]
GuardClauses()14         public void GuardClauses()
15         {
16             //Act & Assert
17             Assert.ThrowsArgumentNull(
18                 delegate { new CompareAttribute(null); }, "otherProperty");
19 
20             Assert.ThrowsArgumentNullOrEmpty(
21                 delegate { CompareAttribute.FormatPropertyForClientValidation(null); }, "property");
22         }
23 
24         [Fact]
FormatPropertyForClientValidationPrependsStarDot()25         public void FormatPropertyForClientValidationPrependsStarDot()
26         {
27             string prepended = CompareAttribute.FormatPropertyForClientValidation("test");
28             Assert.Equal(prepended, "*.test");
29         }
30 
31         [Fact]
ValidateDoesNotThrowWhenComparedObjectsAreEqual()32         public void ValidateDoesNotThrowWhenComparedObjectsAreEqual()
33         {
34             object otherObject = new CompareObject("test");
35             CompareObject currentObject = new CompareObject("test");
36             ValidationContext testContext = new ValidationContext(otherObject, null, null);
37 
38             CompareAttribute attr = new CompareAttribute("CompareProperty");
39             attr.Validate(currentObject.CompareProperty, testContext);
40         }
41 
42         [Fact]
ValidateThrowsWhenComparedObjectsAreNotEqual()43         public void ValidateThrowsWhenComparedObjectsAreNotEqual()
44         {
45             CompareObject currentObject = new CompareObject("a");
46             object otherObject = new CompareObject("b");
47 
48             ValidationContext testContext = new ValidationContext(otherObject, null, null);
49             testContext.DisplayName = "CurrentProperty";
50 
51             CompareAttribute attr = new CompareAttribute("CompareProperty");
52             Assert.Throws<ValidationException>(
53                 delegate { attr.Validate(currentObject.CompareProperty, testContext); }, "'CurrentProperty' and 'CompareProperty' do not match.");
54         }
55 
56         [Fact]
ValidateThrowsWithOtherPropertyDisplayName()57         public void ValidateThrowsWithOtherPropertyDisplayName()
58         {
59             CompareObject currentObject = new CompareObject("a");
60             object otherObject = new CompareObject("b");
61 
62             ValidationContext testContext = new ValidationContext(otherObject, null, null);
63             testContext.DisplayName = "CurrentProperty";
64 
65             CompareAttribute attr = new CompareAttribute("ComparePropertyWithDisplayName");
66             Assert.Throws<ValidationException>(
67                 delegate { attr.Validate(currentObject.CompareProperty, testContext); }, "'CurrentProperty' and 'DisplayName' do not match.");
68         }
69 
70         [Fact]
ValidateUsesSetDisplayName()71         public void ValidateUsesSetDisplayName()
72         {
73             CompareObject currentObject = new CompareObject("a");
74             object otherObject = new CompareObject("b");
75 
76             ValidationContext testContext = new ValidationContext(otherObject, null, null);
77             testContext.DisplayName = "CurrentProperty";
78 
79             CompareAttribute attr = new CompareAttribute("ComparePropertyWithDisplayName");
80             attr.OtherPropertyDisplayName = "SetDisplayName";
81 
82             Assert.Throws<ValidationException>(
83                 delegate { attr.Validate(currentObject.CompareProperty, testContext); }, "'CurrentProperty' and 'SetDisplayName' do not match.");
84         }
85 
86         [Fact]
ValidateThrowsWhenPropertyNameIsUnknown()87         public void ValidateThrowsWhenPropertyNameIsUnknown()
88         {
89             CompareObject currentObject = new CompareObject("a");
90             object otherObject = new CompareObject("b");
91 
92             ValidationContext testContext = new ValidationContext(otherObject, null, null);
93             testContext.DisplayName = "CurrentProperty";
94 
95             CompareAttribute attr = new CompareAttribute("UnknownPropertyName");
96             Assert.Throws<ValidationException>(
97                 () => attr.Validate(currentObject.CompareProperty, testContext),
98                 "Could not find a property named UnknownPropertyName."
99                 );
100         }
101 
102         [Fact]
GetClientValidationRulesReturnsModelClientValidationEqualToRule()103         public void GetClientValidationRulesReturnsModelClientValidationEqualToRule()
104         {
105             Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
106             Mock<ModelMetadata> metadata = new Mock<ModelMetadata>(provider.Object, null, null, typeof(string), null);
107             metadata.Setup(m => m.DisplayName).Returns("CurrentProperty");
108 
109             CompareAttribute attr = new CompareAttribute("CompareProperty");
110             List<ModelClientValidationRule> ruleList = new List<ModelClientValidationRule>(attr.GetClientValidationRules(metadata.Object, null));
111 
112             Assert.Equal(ruleList.Count, 1);
113 
114             ModelClientValidationEqualToRule actualRule = ruleList[0] as ModelClientValidationEqualToRule;
115 
116             Assert.Equal("'CurrentProperty' and 'CompareProperty' do not match.", actualRule.ErrorMessage);
117             Assert.Equal("equalto", actualRule.ValidationType);
118             Assert.Equal("*.CompareProperty", actualRule.ValidationParameters["other"]);
119         }
120 
121         [Fact]
ModelClientValidationEqualToRuleErrorMessageUsesOtherPropertyDisplayName()122         public void ModelClientValidationEqualToRuleErrorMessageUsesOtherPropertyDisplayName()
123         {
124             Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
125             ModelMetadata metadata = new ModelMetadata(provider.Object, typeof(CompareObject), null, typeof(string), null);
126             metadata.DisplayName = "CurrentProperty";
127 
128             CompareAttribute attr = new CompareAttribute("ComparePropertyWithDisplayName");
129             List<ModelClientValidationRule> ruleList = new List<ModelClientValidationRule>(attr.GetClientValidationRules(metadata, null));
130 
131             Assert.Equal(ruleList.Count, 1);
132 
133             ModelClientValidationEqualToRule actualRule = ruleList[0] as ModelClientValidationEqualToRule;
134 
135             Assert.Equal("'CurrentProperty' and 'DisplayName' do not match.", actualRule.ErrorMessage);
136             Assert.Equal("equalto", actualRule.ValidationType);
137             Assert.Equal("*.ComparePropertyWithDisplayName", actualRule.ValidationParameters["other"]);
138         }
139 
140         [Fact]
ModelClientValidationEqualToRuleUsesSetDisplayName()141         public void ModelClientValidationEqualToRuleUsesSetDisplayName()
142         {
143             Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
144             ModelMetadata metadata = new ModelMetadata(provider.Object, typeof(CompareObject), null, typeof(string), null);
145             metadata.DisplayName = "CurrentProperty";
146 
147             CompareAttribute attr = new CompareAttribute("ComparePropertyWithDisplayName");
148             attr.OtherPropertyDisplayName = "SetDisplayName";
149 
150             List<ModelClientValidationRule> ruleList = new List<ModelClientValidationRule>(attr.GetClientValidationRules(metadata, null));
151             Assert.Equal(ruleList.Count, 1);
152             ModelClientValidationEqualToRule actualRule = ruleList[0] as ModelClientValidationEqualToRule;
153 
154             Assert.Equal("'CurrentProperty' and 'SetDisplayName' do not match.", actualRule.ErrorMessage);
155         }
156 
157         [Fact]
CompareAttributeCanBeDerivedFromAndOverrideIsValid()158         public void CompareAttributeCanBeDerivedFromAndOverrideIsValid()
159         {
160             object otherObject = new CompareObject("a");
161             CompareObject currentObject = new CompareObject("b");
162             ValidationContext testContext = new ValidationContext(otherObject, null, null);
163 
164             DerivedCompareAttribute attr = new DerivedCompareAttribute("CompareProperty");
165             attr.Validate(currentObject.CompareProperty, testContext);
166         }
167 
168         private class DerivedCompareAttribute : CompareAttribute
169         {
DerivedCompareAttribute(string otherProperty)170             public DerivedCompareAttribute(string otherProperty)
171                 : base(otherProperty)
172             {
173             }
174 
IsValid(object value)175             public override bool IsValid(object value)
176             {
177                 return false;
178             }
179 
IsValid(object value, ValidationContext context)180             protected override ValidationResult IsValid(object value, ValidationContext context)
181             {
182                 return null;
183             }
184         }
185 
186         private class CompareObject
187         {
188             public string CompareProperty { get; set; }
189 
190             [Display(Name = "DisplayName")]
191             public string ComparePropertyWithDisplayName { get; set; }
192 
CompareObject(string otherValue)193             public CompareObject(string otherValue)
194             {
195                 CompareProperty = otherValue;
196                 ComparePropertyWithDisplayName = otherValue;
197             }
198         }
199     }
200 }
201