Jo Shields a575963da9 Imported Upstream version 3.6.0
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
2014-08-13 10:39:27 +01:00

539 lines
16 KiB
C#

// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Web.TestUtil;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Mvc.Test
{
public class ViewDataDictionaryTest
{
[Fact]
public void ConstructorThrowsIfDictionaryIsNull()
{
// Act & assert
Assert.ThrowsArgumentNull(
delegate { new ViewDataDictionary((ViewDataDictionary)null); }, "dictionary");
}
[Fact]
public void ConstructorWithViewDataDictionaryCopiesModelAndModelState()
{
// Arrange
ViewDataDictionary originalVdd = new ViewDataDictionary();
object model = new object();
originalVdd.Model = model;
originalVdd["foo"] = "bar";
originalVdd.ModelState.AddModelError("key", "error");
// Act
ViewDataDictionary newVdd = new ViewDataDictionary(originalVdd);
// Assert
Assert.Equal(model, newVdd.Model);
Assert.True(newVdd.ModelState.ContainsKey("key"));
Assert.Equal("error", newVdd.ModelState["key"].Errors[0].ErrorMessage);
Assert.Equal("bar", newVdd["foo"]);
}
[Fact]
public void DictionaryInterface()
{
// Arrange
DictionaryHelper<string, object> helper = new DictionaryHelper<string, object>()
{
Creator = () => new ViewDataDictionary(),
Comparer = StringComparer.OrdinalIgnoreCase,
SampleKeys = new string[] { "foo", "bar", "baz", "quux", "QUUX" },
SampleValues = new object[] { 42, "string value", new DateTime(2001, 1, 1), new object(), 32m },
ThrowOnKeyNotFound = false
};
// Act & assert
helper.Execute();
}
[Fact]
public void EvalReturnsSimplePropertyValue()
{
var obj = new { Foo = "Bar" };
ViewDataDictionary vdd = new ViewDataDictionary(obj);
Assert.Equal("Bar", vdd.Eval("Foo"));
}
[Fact]
public void EvalWithModelAndDictionaryPropertyEvaluatesDictionaryValue()
{
var obj = new { Foo = new Dictionary<string, object> { { "Bar", "Baz" } } };
ViewDataDictionary vdd = new ViewDataDictionary(obj);
Assert.Equal("Baz", vdd.Eval("Foo.Bar"));
}
[Fact]
public void EvalEvaluatesDictionaryThenModel()
{
var obj = new { Foo = "NotBar" };
ViewDataDictionary vdd = new ViewDataDictionary(obj);
vdd.Add("Foo", "Bar");
Assert.Equal("Bar", vdd.Eval("Foo"));
}
[Fact]
public void EvalReturnsValueOfCompoundExpressionByFollowingObjectPath()
{
var obj = new { Foo = new { Bar = "Baz" } };
ViewDataDictionary vdd = new ViewDataDictionary(obj);
Assert.Equal("Baz", vdd.Eval("Foo.Bar"));
}
[Fact]
public void EvalReturnsNullIfExpressionDoesNotMatch()
{
var obj = new { Foo = new { Biz = "Baz" } };
ViewDataDictionary vdd = new ViewDataDictionary(obj);
Assert.Equal(null, vdd.Eval("Foo.Bar"));
}
[Fact]
public void EvalReturnsValueJustAdded()
{
ViewDataDictionary vdd = new ViewDataDictionary();
vdd.Add("Foo", "Blah");
Assert.Equal("Blah", vdd.Eval("Foo"));
}
[Fact]
public void EvalWithCompoundExpressionReturnsIndexedValue()
{
ViewDataDictionary vdd = new ViewDataDictionary();
vdd.Add("Foo.Bar", "Baz");
Assert.Equal("Baz", vdd.Eval("Foo.Bar"));
}
[Fact]
public void EvalWithCompoundExpressionReturnsPropertyOfAddedObject()
{
ViewDataDictionary vdd = new ViewDataDictionary();
vdd.Add("Foo", new { Bar = "Baz" });
Assert.Equal("Baz", vdd.Eval("Foo.Bar"));
}
[Fact]
public void EvalWithCompoundIndexExpressionReturnsEval()
{
ViewDataDictionary vdd = new ViewDataDictionary();
vdd.Add("Foo.Bar", new { Baz = "Quux" });
Assert.Equal("Quux", vdd.Eval("Foo.Bar.Baz"));
}
[Fact]
public void EvalWithCompoundIndexAndCompoundExpressionReturnsValue()
{
ViewDataDictionary vdd = new ViewDataDictionary();
vdd.Add("Foo.Bar", new { Baz = new { Blah = "Quux" } });
Assert.Equal("Quux", vdd.Eval("Foo.Bar.Baz.Blah"));
}
/// <summary>
/// Make sure that dict["foo.bar"] gets chosen before dict["foo"]["bar"]
/// </summary>
[Fact]
public void EvalChoosesValueInDictionaryOverOtherValue()
{
ViewDataDictionary vdd = new ViewDataDictionary();
vdd.Add("Foo", new { Bar = "Not Baz" });
vdd.Add("Foo.Bar", "Baz");
Assert.Equal("Baz", vdd.Eval("Foo.Bar"));
}
/// <summary>
/// Make sure that dict["foo.bar"]["baz"] gets chosen before dict["foo"]["bar"]["baz"]
/// </summary>
[Fact]
public void EvalChoosesCompoundValueInDictionaryOverOtherValues()
{
ViewDataDictionary vdd = new ViewDataDictionary();
vdd.Add("Foo", new { Bar = new { Baz = "Not Quux" } });
vdd.Add("Foo.Bar", new { Baz = "Quux" });
Assert.Equal("Quux", vdd.Eval("Foo.Bar.Baz"));
}
/// <summary>
/// Make sure that dict["foo.bar"]["baz"] gets chosen before dict["foo"]["bar.baz"]
/// </summary>
[Fact]
public void EvalChoosesCompoundValueInDictionaryOverOtherValuesWithCompoundProperty()
{
ViewDataDictionary vdd = new ViewDataDictionary();
vdd.Add("Foo", new Person());
vdd.Add("Foo.Bar", new { Baz = "Quux" });
Assert.Equal("Quux", vdd.Eval("Foo.Bar.Baz"));
}
[Fact]
public void EvalThrowsIfExpressionIsEmpty()
{
// Arrange
ViewDataDictionary vdd = new ViewDataDictionary();
// Act & Assert
Assert.ThrowsArgumentNullOrEmpty(
delegate { vdd.Eval(String.Empty); }, "expression");
}
[Fact]
public void EvalThrowsIfExpressionIsNull()
{
// Arrange
ViewDataDictionary vdd = new ViewDataDictionary();
// Act & Assert
Assert.ThrowsArgumentNullOrEmpty(
delegate { vdd.Eval(null); }, "expression");
}
[Fact]
public void EvalWithCompoundExpressionAndDictionarySubExpressionChoosesDictionaryValue()
{
ViewDataDictionary vdd = new ViewDataDictionary();
vdd.Add("Foo", new Dictionary<string, object> { { "Bar", "Baz" } });
Assert.Equal("Baz", vdd.Eval("Foo.Bar"));
}
[Fact]
public void EvalWithDictionaryAndNoMatchReturnsNull()
{
ViewDataDictionary vdd = new ViewDataDictionary();
vdd.Add("Foo", new Dictionary<string, object> { { "NotBar", "Baz" } });
object result = vdd.Eval("Foo.Bar");
Assert.Null(result);
}
[Fact]
public void EvalWithNestedDictionariesEvalCorrectly()
{
ViewDataDictionary vdd = new ViewDataDictionary();
vdd.Add("Foo", new Dictionary<string, object> { { "Bar", new Hashtable { { "Baz", "Quux" } } } });
Assert.Equal("Quux", vdd.Eval("Foo.Bar.Baz"));
}
[Fact]
public void EvalFormatWithNullValueReturnsEmptyString()
{
// Arrange
ViewDataDictionary vdd = new ViewDataDictionary();
// Act
string formattedValue = vdd.Eval("foo", "for{0}mat");
// Assert
Assert.Equal(String.Empty, formattedValue);
}
[Fact]
public void EvalFormatWithEmptyFormatReturnsViewData()
{
// Arrange
ViewDataDictionary vdd = new ViewDataDictionary();
vdd["foo"] = "value";
// Act
string formattedValue = vdd.Eval("foo", "");
// Assert
Assert.Equal("value", formattedValue);
}
[Fact]
public void EvalFormatWithFormatReturnsFormattedViewData()
{
// Arrange
ViewDataDictionary vdd = new ViewDataDictionary();
vdd["foo"] = "value";
// Act
string formattedValue = vdd.Eval("foo", "for{0}mat");
// Assert
Assert.Equal("forvaluemat", formattedValue);
}
[Fact]
public void EvalPropertyNamedModel()
{
// Arrange
ViewDataDictionary vdd = new ViewDataDictionary();
vdd["Title"] = "Home Page";
vdd["Message"] = "Welcome to ASP.NET MVC!";
vdd.Model = new TheQueryStringParam
{
Name = "The Name",
Value = "The Value",
Model = "The Model",
};
// Act
object o = vdd.Eval("Model");
// Assert
Assert.Equal("The Model", o);
}
[Fact]
public void EvalSubPropertyNamedValueInModel()
{
// Arrange
ViewDataDictionary vdd = new ViewDataDictionary();
vdd["Title"] = "Home Page";
vdd["Message"] = "Welcome to ASP.NET MVC!";
vdd.Model = new TheQueryStringParam
{
Name = "The Name",
Value = "The Value",
Model = "The Model",
};
// Act
object o = vdd.Eval("Value");
// Assert
Assert.Equal("The Value", o);
}
[Fact]
public void GetViewDataInfoFromDictionary()
{
// Arrange
ViewDataDictionary fooVdd = new ViewDataDictionary()
{
{ "Bar", "barValue" }
};
ViewDataDictionary vdd = new ViewDataDictionary()
{
{ "Foo", fooVdd }
};
// Act
ViewDataInfo info = vdd.GetViewDataInfo("foo.bar");
// Assert
Assert.NotNull(info);
Assert.Equal(fooVdd, info.Container);
Assert.Equal("barValue", info.Value);
}
[Fact]
public void GetViewDataInfoFromDictionaryWithMissingEntry()
{
// Arrange
ViewDataDictionary vdd = new ViewDataDictionary();
// Act
ViewDataInfo info = vdd.GetViewDataInfo("foo");
// Assert
Assert.Null(info);
}
[Fact]
public void GetViewDataInfoFromDictionaryWithNullEntry()
{
// Arrange
ViewDataDictionary vdd = new ViewDataDictionary()
{
{ "Foo", null }
};
// Act
ViewDataInfo info = vdd.GetViewDataInfo("foo");
// Assert
Assert.NotNull(info);
Assert.Equal(vdd, info.Container);
Assert.Null(info.Value);
}
[Fact]
public void GetViewDataInfoFromModel()
{
// Arrange
object model = new { foo = "fooValue" };
ViewDataDictionary vdd = new ViewDataDictionary(model);
PropertyDescriptor propDesc = TypeDescriptor.GetProperties(model).Find("foo", true /* ignoreCase */);
// Act
ViewDataInfo info = vdd.GetViewDataInfo("foo");
// Assert
Assert.NotNull(info);
Assert.Equal(model, info.Container);
Assert.Equal(propDesc, info.PropertyDescriptor);
Assert.Equal("fooValue", info.Value);
}
[Fact]
public void FabricatesModelMetadataFromModelWhenModelMetadataHasNotBeenSet()
{
// Arrange
object model = new { foo = "fooValue", bar = "barValue" };
ViewDataDictionary vdd = new ViewDataDictionary(model);
// Act
ModelMetadata metadata = vdd.ModelMetadata;
// Assert
Assert.NotNull(metadata);
Assert.Equal(model.GetType(), metadata.ModelType);
}
[Fact]
public void ReturnsExistingModelMetadata()
{
// Arrange
object model = new { foo = "fooValue", bar = "barValue" };
ModelMetadata originalMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, model.GetType());
ViewDataDictionary vdd = new ViewDataDictionary(model) { ModelMetadata = originalMetadata };
// Act
ModelMetadata metadata = vdd.ModelMetadata;
// Assert
Assert.Same(originalMetadata, metadata);
}
[Fact]
public void ModelMetadataIsNullIfModelMetadataHasNotBeenSetAndModelIsNull()
{
// Arrange
ViewDataDictionary vdd = new ViewDataDictionary();
// Act
ModelMetadata metadata = vdd.ModelMetadata;
// Assert
Assert.Null(metadata);
}
[Fact]
public void ModelMetadataCanBeFabricatedWithNullModelAndGenericViewDataDictionary()
{
// Arrange
ViewDataDictionary vdd = new ViewDataDictionary<Exception>();
// Act
ModelMetadata metadata = vdd.ModelMetadata;
// Assert
Assert.NotNull(metadata);
Assert.Equal(typeof(Exception), metadata.ModelType);
}
[Fact]
public void ModelSetterThrowsIfValueIsNullAndModelTypeIsNonNullable()
{
// Arrange
ViewDataDictionary vdd = new ViewDataDictionary<int>();
// Act & assert
Assert.Throws<InvalidOperationException>(
delegate { vdd.Model = null; },
@"The model item passed into the dictionary is null, but this dictionary requires a non-null model item of type 'System.Int32'.");
}
[Fact]
public void ChangingModelReplacesModelMetadata()
{
// Arrange
ViewDataDictionary vdd = new ViewDataDictionary(new Object());
ModelMetadata originalMetadata = vdd.ModelMetadata;
// Act
vdd.Model = "New Model";
// Assert
Assert.NotSame(originalMetadata, vdd.ModelMetadata);
}
public class TheQueryStringParam
{
public string Name { get; set; }
public string Value { get; set; }
public string Model { get; set; }
}
public class Person : CustomTypeDescriptor
{
public override PropertyDescriptorCollection GetProperties()
{
return new PropertyDescriptorCollection(new PersonPropertyDescriptor[] { new PersonPropertyDescriptor() });
}
}
public class PersonPropertyDescriptor : PropertyDescriptor
{
public PersonPropertyDescriptor()
: base("Bar.Baz", null)
{
}
public override object GetValue(object component)
{
return "Quux";
}
public override bool CanResetValue(object component)
{
return false;
}
public override Type ComponentType
{
get { return typeof(Person); }
}
public override bool IsReadOnly
{
get { return false; }
}
public override Type PropertyType
{
get { return typeof(string); }
}
public override void ResetValue(object component)
{
}
public override void SetValue(object component, object value)
{
}
public override bool ShouldSerializeValue(object component)
{
return true;
}
}
}
}