// 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.Collections.Specialized; using System.Dynamic; using System.Linq; using System.Text; using System.Web.TestUtil; using System.Web.WebPages; using Microsoft.TestCommon; using Moq; using Xunit; using Assert = Microsoft.TestCommon.AssertEx; namespace System.Web.Helpers.Test { public class WebGridTest { [Fact] public void AjaxCheckedOnlyOnce() { var grid = new WebGrid(GetContext(), ajaxUpdateContainerId: "grid") .Bind(new[] { new { First = "First", Second = "Second" } }); string html = grid.Table().ToString(); Assert.True(html.Contains(" { grid.Column(columnName: String.Empty, format: null); }, "columnName", "The column name cannot be null or an empty string unless a custom format is specified."); } [Fact] public void ColumnThrowsIfColumnNameIsNullAndNoFormat() { var grid = new WebGrid(GetContext()).Bind(new object[0]); Assert.ThrowsArgument(() => { grid.Column(columnName: null, format: null); }, "columnName", "The column name cannot be null or an empty string unless a custom format is specified."); } [Fact] public void BindThrowsIfSourceIsNull() { Assert.ThrowsArgumentNull(() => { new WebGrid(GetContext()).Bind(null); }, "source"); } [Fact] public void ConstructorThrowsIfRowsPerPageIsLessThanOne() { Assert.ThrowsArgumentOutOfRange(() => { new WebGrid(GetContext(), rowsPerPage: 0); }, "rowsPerPage", "Value must be greater than or equal to 1.", allowDerivedExceptions: true); } [Fact] public void GetHtmlDefaults() { var grid = new WebGrid(GetContext(), rowsPerPage: 1) .Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); var html = grid.GetHtml(); UnitTestHelper.AssertEqualsIgnoreWhitespace( "" + "" + "" + "" + "" + "" + "" + "" + "" + "
P1P2P3
1 2 >
123
", html.ToString()); XhtmlAssert.Validate1_1(html); } [Fact] public void WebGridProducesValidHtmlWhenSummaryIsSpecified() { var grid = new WebGrid(GetContext(), rowsPerPage: 1) .Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); var caption = "WebGrid With Caption"; var html = grid.GetHtml(caption: caption); UnitTestHelper.AssertEqualsIgnoreWhitespace( "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "
" + caption + "
P1P2P3
1 2 >
123
", html.ToString()); XhtmlAssert.Validate1_1(html); } [Fact] public void WebGridEncodesCaptionText() { var grid = new WebGrid(GetContext(), rowsPerPage: 1) .Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); var caption = "WebGrid <> With Caption"; var html = grid.GetHtml(caption: caption); UnitTestHelper.AssertEqualsIgnoreWhitespace( "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "
WebGrid <> With Caption
P1P2P3
1 2 >
123
", html.ToString()); XhtmlAssert.Validate1_1(html); } [Fact] public void GetHtmlWhenPageCountIsOne() { var grid = new WebGrid(GetContext()) .Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" } }); var html = grid.GetHtml(); UnitTestHelper.AssertEqualsIgnoreWhitespace( "" + "" + "" + "" + "" + "" + "
P1P2P3
123
", html.ToString()); XhtmlAssert.Validate1_1(html); } [Fact] public void GetHtmlWhenPagingAndSortingAreDisabled() { var grid = new WebGrid(GetContext(), rowsPerPage: 1, canPage: false, canSort: false) .Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); var html = grid.GetHtml(); UnitTestHelper.AssertEqualsIgnoreWhitespace( "" + "" + "" + "" + "" + "" + "" + "" + "" + "
P1P2P3
123
456
", html.ToString()); XhtmlAssert.Validate1_1(html); } [Fact] public void PageIndexCanBeReset() { NameValueCollection queryString = new NameValueCollection(); queryString["page"] = "2"; var grid = new WebGrid(GetContext(queryString), rowsPerPage: 1) .Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); Assert.Equal(1, grid.PageIndex); grid.PageIndex = 0; Assert.Equal(0, grid.PageIndex); // verify that selection link has updated page Assert.Equal("?page=1&row=1", grid.Rows.FirstOrDefault().GetSelectUrl()); } [Fact] public void PageIndexCanBeResetToSameValue() { NameValueCollection queryString = new NameValueCollection(); queryString["page"] = "2"; var grid = new WebGrid(GetContext(queryString), rowsPerPage: 1) .Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); grid.PageIndex = 0; Assert.Equal(0, grid.PageIndex); } [Fact] public void PageIndexDefaultsToZero() { var grid = new WebGrid(GetContext(), rowsPerPage: 1) .Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); Assert.Equal(0, grid.PageIndex); Assert.Equal(1, grid.Rows.Count); Assert.Equal(1, grid.Rows.First()["P1"]); } [Fact] public void SetPageIndexThrowsExceptionWhenValueIsNegative() { var grid = new WebGrid(GetContext(), rowsPerPage: 1) .Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); Assert.ThrowsArgumentOutOfRange(() => { grid.PageIndex = -1; }, "value", "Value must be between 0 and 1."); } [Fact] public void SetPageIndexThrowsExceptionWhenValueIsEqualToPageCount() { var grid = new WebGrid(GetContext(), rowsPerPage: 1) .Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); Assert.ThrowsArgumentOutOfRange(() => { grid.PageIndex = grid.PageCount; }, "value", "Value must be between 0 and 1."); } [Fact] public void SetPageIndexThrowsExceptionWhenValueIsGreaterToPageCount() { var grid = new WebGrid(GetContext(), rowsPerPage: 1) .Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); Assert.ThrowsArgumentOutOfRange(() => { grid.PageIndex = grid.PageCount + 1; }, "value", "Value must be between 0 and 1."); } [Fact] public void SetPageIndexThrowsExceptionWhenPagingIsDisabled() { var grid = new WebGrid(GetContext(), canPage: false) .Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); Assert.Throws(() => { grid.PageIndex = 1; }, "This operation is not supported when paging is disabled for the \"WebGrid\" object."); } [Fact] public void PageIndexResetsToLastPageWhenQueryStringValueGreaterThanPageCount() { NameValueCollection queryString = new NameValueCollection(); queryString["page"] = "3"; var grid = new WebGrid(GetContext(queryString), rowsPerPage: 1) .Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); Assert.Equal(1, grid.PageIndex); Assert.Equal(1, grid.Rows.Count); Assert.Equal(4, grid.Rows.First()["P1"]); } [Fact] public void PageIndexResetWhenQueryStringValueIsInvalid() { NameValueCollection queryString = new NameValueCollection(); queryString["page"] = "NotAnInt"; var grid = new WebGrid(GetContext(queryString), rowsPerPage: 1) .Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); Assert.Equal(0, grid.PageIndex); Assert.Equal(1, grid.Rows.Count); Assert.Equal(1, grid.Rows.First()["P1"]); } [Fact] public void PageIndexResetWhenQueryStringValueLessThanOne() { NameValueCollection queryString = new NameValueCollection(); queryString["page"] = "0"; var grid = new WebGrid(GetContext(queryString), rowsPerPage: 1) .Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); Assert.Equal(0, grid.PageIndex); Assert.Equal(1, grid.Rows.Count); Assert.Equal(1, grid.Rows.First()["P1"]); } [Fact] public void PageIndexUsesCustomQueryString() { NameValueCollection queryString = new NameValueCollection(); queryString["g_pg"] = "2"; var grid = new WebGrid(GetContext(queryString), rowsPerPage: 1, fieldNamePrefix: "g_", pageFieldName: "pg") .Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); Assert.Equal(1, grid.PageIndex); Assert.Equal(1, grid.Rows.Count); Assert.Equal(4, grid.Rows.First()["P1"]); } [Fact] public void PageIndexUsesQueryString() { NameValueCollection queryString = new NameValueCollection(); queryString["page"] = "2"; var grid = new WebGrid(GetContext(queryString), rowsPerPage: 1) .Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); Assert.Equal(1, grid.PageIndex); Assert.Equal(1, grid.Rows.Count); Assert.Equal(4, grid.Rows.First()["P1"]); } [Fact] public void GetPageCountWhenPagingIsTurnedOn() { var grid = new WebGrid(GetContext(), canPage: true, rowsPerPage: 1) .Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); Assert.Equal(2, grid.PageCount); } [Fact] public void GetPageIndexWhenPagingIsTurnedOn() { var grid = new WebGrid(GetContext(), canPage: true, rowsPerPage: 1) .Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" }, new { P1 = 4, P2 = '5', P3 = "6" }, }); grid.PageIndex = 1; Assert.Equal(1, grid.PageIndex); Assert.Equal(3, grid.PageCount); grid.PageIndex = 2; Assert.Equal(2, grid.PageIndex); } [Fact] public void GetPageCountWhenPagingIsTurnedOff() { var grid = new WebGrid(GetContext(), canPage: false, rowsPerPage: 1) .Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); Assert.Equal(1, grid.PageCount); } [Fact] public void GetPageIndexWhenPagingIsTurnedOff() { var grid = new WebGrid(GetContext(), canPage: false, rowsPerPage: 1) .Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" }, new { P1 = 4, P2 = '5', P3 = "6" }, }); Assert.Equal(0, grid.PageIndex); Assert.Equal(1, grid.PageCount); } [Fact] public void PageUrlResetsSelection() { NameValueCollection queryString = new NameValueCollection(); queryString["page"] = "0"; queryString["row"] = "0"; queryString["sort"] = "P1"; queryString["sortdir"] = "DESC"; var grid = new WebGrid(GetContext(queryString), rowsPerPage: 1) .Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); string url = grid.GetPageUrl(1); Assert.Equal("?page=2&sort=P1&sortdir=DESC", url); } [Fact] public void PageUrlResetsSelectionForAjax() { string expected40 = "$("#grid-container").swhgLoad("?page=2&sort=P1&sortdir=DESC","#grid-container");"; string expected45 = "$("#grid-container").swhgLoad("?page=2\\u0026sort=P1\\u0026sortdir=DESC","#grid-container");"; NameValueCollection queryString = new NameValueCollection(); queryString["page"] = "0"; queryString["row"] = "0"; queryString["sort"] = "P1"; queryString["sortdir"] = "DESC"; var grid = new WebGrid(GetContext(queryString), rowsPerPage: 1, ajaxUpdateContainerId: "grid-container") .Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); string html = grid.GetContainerUpdateScript(grid.GetPageUrl(1)).ToString(); // Assert Assert.Equal(RuntimeEnvironment.IsVersion45Installed ? expected45 : expected40, html); } [Fact] public void PageUrlResetsSelectionForAjaxWithCallback() { string expected40 = "$("#grid").swhgLoad("?page=2&sort=P1&sortdir=DESC","#grid",myCallback);"; string expected45 = "$("#grid").swhgLoad("?page=2\\u0026sort=P1\\u0026sortdir=DESC","#grid",myCallback);"; NameValueCollection queryString = new NameValueCollection(); queryString["page"] = "0"; queryString["row"] = "0"; queryString["sort"] = "P1"; queryString["sortdir"] = "DESC"; var grid = new WebGrid(GetContext(queryString), rowsPerPage: 1, ajaxUpdateContainerId: "grid", ajaxUpdateCallback: "myCallback") .Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); string html = grid.GetContainerUpdateScript(grid.GetPageUrl(1)).ToString(); // Assert Assert.Equal(RuntimeEnvironment.IsVersion45Installed ? expected45 : expected40, html); } [Fact] public void PageUrlThrowsIfIndexGreaterThanOrEqualToPageCount() { var grid = new WebGrid(GetContext(), rowsPerPage: 1).Bind(new[] { new { }, new { } }); Assert.ThrowsArgumentOutOfRange(() => { grid.GetPageUrl(2); }, "pageIndex", "Value must be between 0 and 1."); } [Fact] public void PageUrlThrowsIfIndexLessThanZero() { var grid = new WebGrid(GetContext(), rowsPerPage: 1).Bind(new[] { new { }, new { } }); Assert.ThrowsArgumentOutOfRange(() => { grid.GetPageUrl(-1); }, "pageIndex", "Value must be between 0 and 1."); } [Fact] public void PageUrlThrowsIfPagingIsDisabled() { var grid = new WebGrid(GetContext(), rowsPerPage: 1, canPage: false).Bind(new[] { new { }, new { } }); Assert.Throws(() => { grid.GetPageUrl(2); }, "This operation is not supported when paging is disabled for the \"WebGrid\" object."); } [Fact] public void PagerRenderingDefaults() { var grid = new WebGrid(GetContext(), rowsPerPage: 1).Bind(new[] { new { }, new { }, new { }, new { } }); var html = grid.Pager(); Assert.Equal( "1 " + "2 " + "3 " + "4 " + "> ", html.ToString()); XhtmlAssert.Validate1_1(html, wrapper: "div"); } [Fact] public void PagerRenderingOnFirstShowingAll() { var grid = new WebGrid(GetContext(), rowsPerPage: 1).Bind(new[] { new { }, new { }, new { }, new { } }); var html = grid.Pager(WebGridPagerModes.All, numericLinksCount: 5); Assert.Equal( "1 " + "2 " + "3 " + "4 " + "> " + ">>", html.ToString()); XhtmlAssert.Validate1_1(html, wrapper: "div"); } [Fact] public void PagerRenderingOnNextToLastShowingAll() { NameValueCollection queryString = new NameValueCollection(); queryString["page"] = "3"; var grid = new WebGrid(GetContext(queryString), rowsPerPage: 1).Bind(new[] { new { }, new { }, new { }, new { } }); var html = grid.Pager(WebGridPagerModes.All, numericLinksCount: 4); Assert.Equal( "<< " + "< " + "1 " + "2 " + "3 " + "4 " + "> ", html.ToString()); XhtmlAssert.Validate1_1(html, wrapper: "div"); } [Fact] public void PagerRenderingOnMiddleShowingAll() { NameValueCollection queryString = new NameValueCollection(); queryString["page"] = "3"; var grid = new WebGrid(GetContext(queryString), rowsPerPage: 1).Bind(new[] { new { }, new { }, new { }, new { } }); var html = grid.Pager(WebGridPagerModes.All, numericLinksCount: 3); Assert.Equal( "<< " + "< " + "2 " + "3 " + "4 " + "> ", html.ToString()); XhtmlAssert.Validate1_1(html, wrapper: "div"); } [Fact] public void PagerRenderingOnSecondHidingFirstLast() { NameValueCollection queryString = new NameValueCollection(); queryString["page"] = "2"; var grid = new WebGrid(GetContext(queryString), rowsPerPage: 1).Bind(new[] { new { }, new { }, new { }, new { } }); var html = grid.Pager(WebGridPagerModes.NextPrevious | WebGridPagerModes.Numeric, numericLinksCount: 2); Assert.Equal( "< " + "2 " + "3 " + "> ", html.ToString()); XhtmlAssert.Validate1_1(html, wrapper: "div"); } [Fact] public void PagerRenderingOnLastHidingFirstLast() { NameValueCollection queryString = new NameValueCollection(); queryString["page"] = "4"; var grid = new WebGrid(GetContext(queryString), rowsPerPage: 1).Bind(new[] { new { }, new { }, new { }, new { } }); var html = grid.Pager(WebGridPagerModes.NextPrevious | WebGridPagerModes.Numeric, numericLinksCount: 1); Assert.Equal( "< " + "4 ", html.ToString()); XhtmlAssert.Validate1_1(html, wrapper: "div"); } [Fact] public void PagerRenderingOnMiddleHidingNextPrevious() { NameValueCollection queryString = new NameValueCollection(); queryString["page"] = "3"; var grid = new WebGrid(GetContext(queryString), rowsPerPage: 1).Bind(new[] { new { }, new { }, new { }, new { } }); var html = grid.Pager(WebGridPagerModes.FirstLast | WebGridPagerModes.Numeric, numericLinksCount: 0); Assert.Equal( "<< ", html.ToString()); XhtmlAssert.Validate1_1(html, wrapper: "div"); } [Fact] public void PagerRenderingOnMiddleWithLinksCountGreaterThanPageCount() { NameValueCollection queryString = new NameValueCollection(); queryString["page"] = "3"; var grid = new WebGrid(GetContext(queryString), rowsPerPage: 1).Bind(new[] { new { }, new { }, new { }, new { } }); var html = grid.Pager(WebGridPagerModes.Numeric, numericLinksCount: 6); Assert.Equal( "1 " + "2 " + "3 " + "4 ", html.ToString()); XhtmlAssert.Validate1_1(html, wrapper: "div"); } [Fact] public void PagerRenderingHidingAll() { var grid = new WebGrid(GetContext(), rowsPerPage: 2).Bind(new[] { new { }, new { }, new { }, new { } }); var html = grid.Pager(WebGridPagerModes.Numeric, numericLinksCount: 0); Assert.Equal("", html.ToString()); } [Fact] public void PagerRenderingTextOverrides() { NameValueCollection queryString = new NameValueCollection(); queryString["page"] = "3"; var grid = new WebGrid(GetContext(queryString), rowsPerPage: 1).Bind(new[] { new { }, new { }, new { }, new { }, new { } }); var html = grid.Pager(WebGridPagerModes.FirstLast | WebGridPagerModes.NextPrevious, firstText: "first", previousText: "previous", nextText: "next", lastText: "last"); Assert.Equal( "first " + "previous " + "next " + "last", html.ToString()); XhtmlAssert.Validate1_1(html, wrapper: "div"); } [Fact] public void PagerThrowsIfTextSetAndModeNotEnabled() { var grid = new WebGrid(GetContext(), rowsPerPage: 1).Bind(new[] { new { }, new { } }); Assert.ThrowsArgument(() => { grid.Pager(firstText: "first"); }, "firstText", "To use this argument, pager mode \"FirstLast\" must be enabled."); Assert.ThrowsArgument(() => { grid.Pager(mode: WebGridPagerModes.Numeric, previousText: "previous"); }, "previousText", "To use this argument, pager mode \"NextPrevious\" must be enabled."); Assert.ThrowsArgument(() => { grid.Pager(mode: WebGridPagerModes.Numeric, nextText: "next"); }, "nextText", "To use this argument, pager mode \"NextPrevious\" must be enabled."); Assert.ThrowsArgument(() => { grid.Pager(lastText: "last"); }, "lastText", "To use this argument, pager mode \"FirstLast\" must be enabled."); } [Fact] public void PagerThrowsIfNumericLinkCountIsLessThanZero() { var grid = new WebGrid(GetContext(), rowsPerPage: 1).Bind(new[] { new { }, new { } }); Assert.ThrowsArgumentOutOfRange(() => { grid.Pager(numericLinksCount: -1); }, "numericLinksCount", "Value must be greater than or equal to 0."); } [Fact] public void PagerThrowsIfPagingIsDisabled() { var grid = new WebGrid(GetContext(), rowsPerPage: 1, canPage: false).Bind(new[] { new { }, new { } }); Assert.Throws(() => { grid.Pager(); }, "This operation is not supported when paging is disabled for the \"WebGrid\" object."); } [Fact] public void PagerWithAjax() { var grid = new WebGrid(GetContext(), rowsPerPage: 1, ajaxUpdateContainerId: "grid") .Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); string html = grid.Pager().ToString(); Assert.True(html.Contains("(() => { grid.PageIndex = 1; }, message); Assert.Throws(() => { grid.SelectedIndex = 0; }, message); Assert.Throws(() => { grid.SortColumn = "P1"; }, message); Assert.Throws(() => { grid.SortDirection = SortDirection.Descending; }, message); } [Fact] public void RowColumnsAreDynamicMembersForDynamics() { var grid = new WebGrid(GetContext()).Bind(Dynamics( new { P1 = 1, P2 = '2', P3 = "3" } )); dynamic row = grid.Rows.First(); Assert.Equal(1, row.P1); Assert.Equal('2', row.P2); Assert.Equal("3", row.P3); } [Fact] public void RowColumnsAreDynamicMembersForNonDynamics() { var grid = new WebGrid(GetContext()).Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" } }); dynamic row = grid.Rows.First(); Assert.Equal(1, row.P1); Assert.Equal('2', row.P2); Assert.Equal("3", row.P3); } [Fact] public void RowExposesRowIndex() { var grid = new WebGrid(GetContext()).Bind(new[] { new { }, new { }, new { } }); dynamic row = grid.Rows.First(); Assert.Equal(0, row["ROW"]); row = grid.Rows.Skip(1).First(); Assert.Equal(1, row.ROW); row = grid.Rows.Skip(2).First(); Assert.Equal(2, row.ROW); } [Fact] public void RowExposesUnderlyingValue() { var sb = new StringBuilder("Foo"); sb.Append("Bar"); var grid = new WebGrid(GetContext()).Bind(new[] { sb }); var row = grid.Rows.First(); Assert.Equal(sb, row.Value); Assert.Equal("FooBar", row.ToString()); Assert.Equal(grid, row.WebGrid); } [Fact] public void RowIndexerThrowsWhenColumnNameIsEmpty() { var grid = new WebGrid(GetContext()).Bind(new[] { new { } }); var row = grid.Rows.First(); Assert.ThrowsArgumentNullOrEmptyString(() => { var value = row[String.Empty]; }, "name"); } [Fact] public void RowIndexerThrowsWhenColumnNameIsNull() { var grid = new WebGrid(GetContext()).Bind(new[] { new { } }); var row = grid.Rows.First(); Assert.ThrowsArgumentNullOrEmptyString(() => { var value = row[null]; }, "name"); } [Fact] // todo - should throw ArgumentException? public void RowIndexerThrowsWhenColumnNotFound() { var grid = new WebGrid(GetContext()).Bind(new[] { new { } }); var row = grid.Rows.First(); Assert.Throws(() => { var value = row["NotAColumn"]; }); } [Fact] public void RowIndexerThrowsWhenGreaterThanColumnCount() { var grid = new WebGrid(GetContext()).Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" } }); var row = grid.Rows.First(); Assert.Throws(() => { var value = row[4]; }); } [Fact] public void RowIndexerThrowsWhenLessThanZero() { var grid = new WebGrid(GetContext()).Bind(new[] { new { } }); var row = grid.Rows.First(); Assert.Throws(() => { var value = row[-1]; }); } [Fact] public void RowIsEnumerableForDynamics() { var grid = new WebGrid(GetContext()).Bind(Dynamics( new { P1 = 1, P2 = '2', P3 = "3" } )); int i = 0; foreach (var col in (IEnumerable)grid.Rows.First()) { i++; } Assert.Equal(3, i); } [Fact] public void RowIsEnumerableForNonDynamics() { var grid = new WebGrid(GetContext()).Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" } }); int i = 0; foreach (var col in grid.Rows.First()) { i++; } Assert.Equal(3, i); } [Fact] public void RowIsIndexableByColumnForDynamics() { var grid = new WebGrid(GetContext()).Bind(Dynamics( new { P1 = 1, P2 = '2', P3 = "3" } )); var row = grid.Rows.First(); Assert.Equal(1, row["P1"]); Assert.Equal('2', row["P2"]); Assert.Equal("3", row["P3"]); } [Fact] public void RowIsIndexableByColumnForNonDynamics() { var grid = new WebGrid(GetContext()).Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" } }); var row = grid.Rows.First(); Assert.Equal(1, row["P1"]); Assert.Equal('2', row["P2"]); Assert.Equal("3", row["P3"]); } [Fact] public void RowIsIndexableByIndexForDynamics() { var grid = new WebGrid(GetContext()).Bind(Dynamics( new { P1 = 1, P2 = '2', P3 = "3" } )); var row = grid.Rows.First(); Assert.Equal(1, row[0]); Assert.Equal('2', row[1]); Assert.Equal("3", row[2]); } [Fact] public void RowIsIndexableByIndexForNonDynamics() { var grid = new WebGrid(GetContext()).Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" } }); var row = grid.Rows.First(); Assert.Equal(1, row[0]); Assert.Equal('2', row[1]); Assert.Equal("3", row[2]); } [Fact] public void RowsNotPagedWhenPagingIsDisabled() { NameValueCollection queryString = new NameValueCollection(); queryString["page"] = "2"; var grid = new WebGrid(GetContext(queryString), rowsPerPage: 1, canPage: false) .Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); // review: should we reset PageIndex or Sort when operation disabled? Assert.Equal(0, grid.PageIndex); Assert.Equal(2, grid.Rows.Count); Assert.Equal(1, grid.Rows.First()["P1"]); Assert.Equal(4, grid.Rows.Skip(1).First()["P1"]); } [Fact] // todo - should throw ArgumentException? public void RowTryGetMemberReturnsFalseWhenColumnNotFound() { var grid = new WebGrid(GetContext()).Bind(new[] { new { } }); var row = grid.Rows.First(); object value = null; Assert.False(row.TryGetMember("NotAColumn", out value)); } [Fact] public void SelectedIndexCanBeReset() { NameValueCollection queryString = new NameValueCollection(); queryString["row"] = "2"; var grid = new WebGrid(GetContext(queryString)).Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); Assert.Equal(1, grid.SelectedIndex); grid.SelectedIndex = 0; Assert.Equal(0, grid.SelectedIndex); } [Fact] public void SelectedIndexCanBeResetToSameValue() { NameValueCollection queryString = new NameValueCollection(); queryString["row"] = "2"; var grid = new WebGrid(GetContext(queryString)).Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); grid.SelectedIndex = -1; Assert.Equal(-1, grid.SelectedIndex); } [Fact] public void SelectedIndexDefaultsToNegative() { var grid = new WebGrid(GetContext()).Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); Assert.False(grid.HasSelection); Assert.Equal(-1, grid.SelectedIndex); Assert.Equal(null, grid.SelectedRow); } [Fact] public void SelectedIndexResetWhenQueryStringValueGreaterThanRowsPerPage() { NameValueCollection queryString = new NameValueCollection(); queryString["row"] = "3"; var grid = new WebGrid(GetContext(queryString), rowsPerPage: 2).Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); Assert.False(grid.HasSelection); Assert.Equal(-1, grid.SelectedIndex); Assert.Equal(null, grid.SelectedRow); } [Fact] public void SelectedIndexPersistsWhenPagingTurnedOff() { NameValueCollection queryString = new NameValueCollection(); queryString["row"] = "3"; var grid = new WebGrid(GetContext(queryString), rowsPerPage: 2, canPage: false).Bind(new[] { new { }, new { }, new { }, new { } }); grid.SelectedIndex = 3; Assert.Equal(3, grid.SelectedIndex); } [Fact] public void SelectedIndexResetWhenQueryStringValueIsInvalid() { NameValueCollection queryString = new NameValueCollection(); queryString["row"] = "NotAnInt"; var grid = new WebGrid(GetContext(queryString)).Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); Assert.False(grid.HasSelection); Assert.Equal(-1, grid.SelectedIndex); Assert.Equal(null, grid.SelectedRow); } [Fact] public void SelectedIndexResetWhenQueryStringValueLessThanOne() { NameValueCollection queryString = new NameValueCollection(); queryString["row"] = "0"; var grid = new WebGrid(GetContext(queryString)).Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); Assert.False(grid.HasSelection); Assert.Equal(-1, grid.SelectedIndex); Assert.Equal(null, grid.SelectedRow); } [Fact] public void SelectedIndexUsesCustomQueryString() { NameValueCollection queryString = new NameValueCollection(); queryString["g_sel"] = "2"; var grid = new WebGrid(GetContext(queryString), fieldNamePrefix: "g_", selectionFieldName: "sel").Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); Assert.True(grid.HasSelection); Assert.Equal(1, grid.SelectedIndex); Assert.NotNull(grid.SelectedRow); Assert.Equal(4, grid.SelectedRow["P1"]); } [Fact] public void SelectedIndexUsesQueryString() { NameValueCollection queryString = new NameValueCollection(); queryString["row"] = "2"; var grid = new WebGrid(GetContext(queryString)).Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); Assert.True(grid.HasSelection); Assert.Equal(1, grid.SelectedIndex); Assert.NotNull(grid.SelectedRow); Assert.Equal(4, grid.SelectedRow["P1"]); } [Fact] public void SelectLink() { NameValueCollection queryString = new NameValueCollection(); queryString["page"] = "1"; queryString["row"] = "1"; queryString["sort"] = "P1"; queryString["sortdir"] = "DESC"; var grid = new WebGrid(GetContext(queryString)).Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); string html = grid.Rows[1].GetSelectLink().ToString(); Assert.Equal("Select", html.ToString()); } [Fact] public void SortCanBeReset() { NameValueCollection queryString = new NameValueCollection(); queryString["sort"] = "P1"; var grid = new WebGrid(GetContext(queryString)).Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); Assert.Equal("P1", grid.SortColumn); grid.SortColumn = "P2"; Assert.Equal("P2", grid.SortColumn); // verify that selection and page links have updated sort Assert.Equal("?sort=P2&row=1", grid.Rows.FirstOrDefault().GetSelectUrl()); Assert.Equal("?sort=P2&page=1", grid.GetPageUrl(0)); } [Fact] public void SortCanBeResetToNull() { NameValueCollection queryString = new NameValueCollection(); queryString["sort"] = "P1"; var grid = new WebGrid(GetContext(queryString)).Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); Assert.Equal("P1", grid.SortColumn); grid.SortColumn = null; Assert.Equal(String.Empty, grid.SortColumn); // verify that selection and page links have updated sort Assert.Equal("?row=1", grid.Rows.FirstOrDefault().GetSelectUrl()); Assert.Equal("?page=1", grid.GetPageUrl(0)); } [Fact] public void SortCanBeResetToSameValue() { NameValueCollection queryString = new NameValueCollection(); queryString["sort"] = "P1"; var grid = new WebGrid(GetContext(queryString)).Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); grid.SortColumn = String.Empty; Assert.Equal(String.Empty, grid.SortColumn); } [Fact] public void SortColumnDefaultsToEmpty() { var grid = new WebGrid(GetContext()).Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" } }); Assert.Equal(String.Empty, grid.SortColumn); } [Fact] public void SortColumnResetWhenQueryStringValueIsInvalid() { NameValueCollection queryString = new NameValueCollection(); queryString["sort"] = "P4"; var grid = new WebGrid(GetContext(queryString)).Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" } }); Assert.Equal("", grid.SortColumn); } [Fact] public void SortColumnUsesCustomQueryString() { NameValueCollection queryString = new NameValueCollection(); queryString["g_st"] = "P2"; var grid = new WebGrid(GetContext(queryString), fieldNamePrefix: "g_", sortFieldName: "st").Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" } }); Assert.Equal("P2", grid.SortColumn); } [Fact] public void SortColumnUsesQueryString() { NameValueCollection queryString = new NameValueCollection(); queryString["sort"] = "P2"; var grid = new WebGrid(GetContext(queryString)).Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" } }); Assert.Equal("P2", grid.SortColumn); } [Fact] public void SortDirectionCanBeReset() { NameValueCollection queryString = new NameValueCollection(); queryString["sortdir"] = "DESC"; var grid = new WebGrid(GetContext(queryString)).Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" }, new { P1 = 4, P2 = '5', P3 = "6" } }); Assert.Equal(SortDirection.Descending, grid.SortDirection); grid.SortDirection = SortDirection.Ascending; Assert.Equal(SortDirection.Ascending, grid.SortDirection); // verify that selection and page links have updated sort Assert.Equal("?sortdir=ASC&row=1", grid.Rows.FirstOrDefault().GetSelectUrl()); Assert.Equal("?sortdir=ASC&page=1", grid.GetPageUrl(0)); } [Fact] public void SortDirectionDefaultsToAscending() { var grid = new WebGrid(GetContext()).Bind(new object[0]); Assert.Equal(SortDirection.Ascending, grid.SortDirection); } [Fact] public void SortDirectionResetWhenQueryStringValueIsInvalid() { NameValueCollection queryString = new NameValueCollection(); queryString["sortdir"] = "NotASortDir"; var grid = new WebGrid(GetContext(queryString)).Bind(new object[0]); Assert.Equal(SortDirection.Ascending, grid.SortDirection); } [Fact] public void SortDirectionUsesQueryStringOfAsc() { NameValueCollection queryString = new NameValueCollection(); queryString["sortdir"] = "aSc"; var grid = new WebGrid(GetContext(queryString)).Bind(new object[0]); Assert.Equal(SortDirection.Ascending, grid.SortDirection); } [Fact] public void SortDirectionUsesQueryStringOfAscending() { NameValueCollection queryString = new NameValueCollection(); queryString["sortdir"] = "AScendING"; var grid = new WebGrid(GetContext(queryString)).Bind(new object[0]); Assert.Equal(SortDirection.Ascending, grid.SortDirection); } [Fact] public void SortDirectionUsesQueryStringOfDesc() { NameValueCollection queryString = new NameValueCollection(); queryString["sortdir"] = "DeSc"; var grid = new WebGrid(GetContext(queryString)).Bind(new object[0]); Assert.Equal(SortDirection.Descending, grid.SortDirection); } [Fact] public void SortDirectionUsesQueryStringOfDescending() { NameValueCollection queryString = new NameValueCollection(); queryString["g_sd"] = "DeScendING"; var grid = new WebGrid(GetContext(queryString), fieldNamePrefix: "g_", sortDirectionFieldName: "sd").Bind(new object[0]); Assert.Equal(SortDirection.Descending, grid.SortDirection); } [Fact] public void SortDisabledIfSortIsEmpty() { var grid = new WebGrid(GetContext(), defaultSort: String.Empty).Bind(Dynamics( new { FirstName = "Joe", LastName = "Smith" }, new { FirstName = "Bob", LastName = "Johnson" }, new { FirstName = "Sam", LastName = "Jones" }, new { FirstName = "Tom", LastName = "Anderson" } )); Assert.Equal("Joe", grid.Rows[0]["FirstName"]); Assert.Equal("Bob", grid.Rows[1]["FirstName"]); Assert.Equal("Sam", grid.Rows[2]["FirstName"]); Assert.Equal("Tom", grid.Rows[3]["FirstName"]); } [Fact] public void SortDisabledIfSortIsNull() { var grid = new WebGrid(GetContext(), defaultSort: null).Bind(Dynamics( new { FirstName = "Joe", LastName = "Smith" }, new { FirstName = "Bob", LastName = "Johnson" }, new { FirstName = "Sam", LastName = "Jones" }, new { FirstName = "Tom", LastName = "Anderson" } )); Assert.Equal("Joe", grid.Rows[0]["FirstName"]); Assert.Equal("Bob", grid.Rows[1]["FirstName"]); Assert.Equal("Sam", grid.Rows[2]["FirstName"]); Assert.Equal("Tom", grid.Rows[3]["FirstName"]); } [Fact] public void SortForDynamics() { var grid = new WebGrid(GetContext(), defaultSort: "FirstName").Bind(Dynamics( new { FirstName = "Joe", LastName = "Smith" }, new { FirstName = "Bob", LastName = "Johnson" }, new { FirstName = "Sam", LastName = "Jones" }, new { FirstName = "Tom", LastName = "Anderson" } )); Assert.Equal("Bob", grid.Rows[0]["FirstName"]); Assert.Equal("Joe", grid.Rows[1]["FirstName"]); Assert.Equal("Sam", grid.Rows[2]["FirstName"]); Assert.Equal("Tom", grid.Rows[3]["FirstName"]); } [Fact] public void SortForDynamicsDescending() { NameValueCollection queryString = new NameValueCollection(); queryString["sort"] = "LastName"; queryString["sortdir"] = "DESCENDING"; var grid = new WebGrid(GetContext(queryString), defaultSort: "FirstName").Bind(Dynamics( new { FirstName = "Joe", LastName = "Smith" }, new { FirstName = "Bob", LastName = "Johnson" }, new { FirstName = "Sam", LastName = "Jones" }, new { FirstName = "Tom", LastName = "Anderson" } )); Assert.Equal("Smith", grid.Rows[0]["LastName"]); Assert.Equal("Jones", grid.Rows[1]["LastName"]); Assert.Equal("Johnson", grid.Rows[2]["LastName"]); Assert.Equal("Anderson", grid.Rows[3]["LastName"]); } [Fact] public void SortForNonDynamicNavigationColumn() { NameValueCollection queryString = new NameValueCollection(); queryString["sort"] = "Not.A.Column"; var grid = new WebGrid(GetContext(queryString), defaultSort: "Person.FirstName").Bind(new[] { new { Person = new { FirstName = "Joe", LastName = "Smith" } }, new { Person = new { FirstName = "Bob", LastName = "Johnson" } }, new { Person = new { FirstName = "Sam", LastName = "Jones" } }, new { Person = new { FirstName = "Tom", LastName = "Anderson" } } }); Assert.Equal("Not.A.Column", grid.SortColumn); // navigation columns are validated during sort Assert.Equal("Bob", grid.Rows[0]["Person.FirstName"]); Assert.Equal("Joe", grid.Rows[1]["Person.FirstName"]); Assert.Equal("Sam", grid.Rows[2]["Person.FirstName"]); Assert.Equal("Tom", grid.Rows[3]["Person.FirstName"]); } [Fact] public void SortForNonDynamics() { var grid = new WebGrid(GetContext(), defaultSort: "FirstName").Bind(new[] { new { FirstName = "Joe", LastName = "Smith" }, new { FirstName = "Bob", LastName = "Johnson" }, new { FirstName = "Sam", LastName = "Jones" }, new { FirstName = "Tom", LastName = "Anderson" } }); Assert.Equal("Bob", grid.Rows[0]["FirstName"]); Assert.Equal("Joe", grid.Rows[1]["FirstName"]); Assert.Equal("Sam", grid.Rows[2]["FirstName"]); Assert.Equal("Tom", grid.Rows[3]["FirstName"]); } [Fact] public void SortForNonDynamicsDescending() { NameValueCollection queryString = new NameValueCollection(); queryString["sort"] = "LastName"; queryString["sortdir"] = "DESCENDING"; var grid = new WebGrid(GetContext(queryString), defaultSort: "FirstName").Bind(new[] { new { FirstName = "Joe", LastName = "Smith" }, new { FirstName = "Bob", LastName = "Johnson" }, new { FirstName = "Sam", LastName = "Jones" }, new { FirstName = "Tom", LastName = "Anderson" } }); Assert.Equal("Smith", grid.Rows[0]["LastName"]); Assert.Equal("Jones", grid.Rows[1]["LastName"]); Assert.Equal("Johnson", grid.Rows[2]["LastName"]); Assert.Equal("Anderson", grid.Rows[3]["LastName"]); } [Fact] public void SortForNonDynamicsEnumerable() { var grid = new WebGrid(GetContext(), defaultSort: "FirstName").Bind(new[] { new { FirstName = "Joe", LastName = "Smith" }, new { FirstName = "Bob", LastName = "Johnson" }, new { FirstName = "Sam", LastName = "Jones" }, new { FirstName = "Tom", LastName = "Anderson" } }.ToList()); Assert.Equal("Bob", grid.Rows[0]["FirstName"]); Assert.Equal("Joe", grid.Rows[1]["FirstName"]); Assert.Equal("Sam", grid.Rows[2]["FirstName"]); Assert.Equal("Tom", grid.Rows[3]["FirstName"]); } [Fact] public void SortForNonDynamicsEnumerableDescending() { NameValueCollection queryString = new NameValueCollection(); queryString["sort"] = "LastName"; queryString["sortdir"] = "DESCENDING"; var grid = new WebGrid(GetContext(queryString), defaultSort: "FirstName").Bind(new[] { new { FirstName = "Joe", LastName = "Smith" }, new { FirstName = "Bob", LastName = "Johnson" }, new { FirstName = "Sam", LastName = "Jones" }, new { FirstName = "Tom", LastName = "Anderson" } }.ToList()); Assert.Equal("Smith", grid.Rows[0]["LastName"]); Assert.Equal("Jones", grid.Rows[1]["LastName"]); Assert.Equal("Johnson", grid.Rows[2]["LastName"]); Assert.Equal("Anderson", grid.Rows[3]["LastName"]); } [Fact] public void SortForNonGenericEnumerable() { var grid = new WebGrid(GetContext(), defaultSort: "FirstName").Bind(new NonGenericEnumerable(new[] { new Person { FirstName = "Joe", LastName = "Smith" }, new Person { FirstName = "Bob", LastName = "Johnson" }, new Person { FirstName = "Sam", LastName = "Jones" }, new Person { FirstName = "Tom", LastName = "Anderson" } })); Assert.Equal("Bob", grid.Rows[0]["FirstName"]); Assert.Equal("Joe", grid.Rows[1]["FirstName"]); Assert.Equal("Sam", grid.Rows[2]["FirstName"]); Assert.Equal("Tom", grid.Rows[3]["FirstName"]); } [Fact] public void SortForNonGenericEnumerableDescending() { NameValueCollection queryString = new NameValueCollection(); queryString["sort"] = "LastName"; queryString["sortdir"] = "DESCENDING"; var grid = new WebGrid(GetContext(queryString), defaultSort: "FirstName").Bind(new NonGenericEnumerable(new[] { new Person { FirstName = "Joe", LastName = "Smith" }, new Person { FirstName = "Bob", LastName = "Johnson" }, new Person { FirstName = "Sam", LastName = "Jones" }, new Person { FirstName = "Tom", LastName = "Anderson" } })); Assert.Equal("Smith", grid.Rows[0]["LastName"]); Assert.Equal("Jones", grid.Rows[1]["LastName"]); Assert.Equal("Johnson", grid.Rows[2]["LastName"]); Assert.Equal("Anderson", grid.Rows[3]["LastName"]); } [Fact] public void SortUrlDefaults() { var grid = new WebGrid(GetContext()).Bind(new[] { new { FirstName = "Bob" } }); string html = grid.GetSortUrl("FirstName"); Assert.Equal("?sort=FirstName&sortdir=ASC", html.ToString()); } [Fact] public void SortUrlThrowsIfColumnNameIsEmpty() { var grid = new WebGrid(GetContext()).Bind(new[] { new { }, new { } }); Assert.ThrowsArgumentNullOrEmptyString(() => { grid.GetSortUrl(String.Empty); }, "column"); } [Fact] public void SortUrlThrowsIfColumnNameIsNull() { var grid = new WebGrid(GetContext()).Bind(new[] { new { }, new { } }); Assert.ThrowsArgumentNullOrEmptyString(() => { grid.GetSortUrl(null); }, "column"); } [Fact] public void SortUrlThrowsIfSortingIsDisabled() { var grid = new WebGrid(GetContext(), canSort: false).Bind(new[] { new { P1 = 1 }, new { P1 = 2 } }); Assert.Throws(() => { grid.GetSortUrl("P1"); }, "This operation is not supported when sorting is disabled for the \"WebGrid\" object."); } [Fact] public void SortWhenSortIsDisabled() { var grid = new WebGrid(GetContext(), defaultSort: "FirstName", canSort: false).Bind(new[] { new { FirstName = "Joe", LastName = "Smith" }, new { FirstName = "Bob", LastName = "Johnson" }, new { FirstName = "Sam", LastName = "Jones" }, new { FirstName = "Tom", LastName = "Anderson" } }); Assert.Equal("Joe", grid.Rows[0]["FirstName"]); Assert.Equal("Bob", grid.Rows[1]["FirstName"]); Assert.Equal("Sam", grid.Rows[2]["FirstName"]); Assert.Equal("Tom", grid.Rows[3]["FirstName"]); } [Fact] public void SortWithNullValues() { var data = new[] { new { FirstName = (object)"Joe", LastName = "Smith" }, new { FirstName = (object)"Bob", LastName = "Johnson" }, new { FirstName = (object)null, LastName = "Jones" } }; var grid = new WebGrid(GetContext(), defaultSort: "FirstName").Bind(data); Assert.Equal("Jones", grid.Rows[0]["LastName"]); Assert.Equal("Bob", grid.Rows[1]["FirstName"]); Assert.Equal("Joe", grid.Rows[2]["FirstName"]); grid = new WebGrid(GetContext(), defaultSort: "FirstName desc").Bind(data); Assert.Equal("Joe", grid.Rows[0]["FirstName"]); Assert.Equal("Bob", grid.Rows[1]["FirstName"]); Assert.Equal("Jones", grid.Rows[2]["LastName"]); } [Fact] public void SortWithMultipleNullValues() { var data = new[] { new { FirstName = (object)"Joe", LastName = "Smith" }, new { FirstName = (object)"Bob", LastName = "Johnson" }, new { FirstName = (object)null, LastName = "Hughes" }, new { FirstName = (object)null, LastName = "Jones" } }; var grid = new WebGrid(GetContext(), defaultSort: "FirstName").Bind(data); Assert.Equal("Hughes", grid.Rows[0]["LastName"]); Assert.Equal("Jones", grid.Rows[1]["LastName"]); Assert.Equal("Bob", grid.Rows[2]["FirstName"]); Assert.Equal("Joe", grid.Rows[3]["FirstName"]); grid = new WebGrid(GetContext(), defaultSort: "FirstName desc").Bind(data); Assert.Equal("Joe", grid.Rows[0]["FirstName"]); Assert.Equal("Bob", grid.Rows[1]["FirstName"]); Assert.Equal("Hughes", grid.Rows[2]["LastName"]); Assert.Equal("Jones", grid.Rows[3]["LastName"]); } [Fact] public void SortWithMixedValuesDoesNotThrow() { var data = new[] { new { FirstName = (object)1, LastName = "Smith" }, new { FirstName = (object)"Bob", LastName = "Johnson" }, new { FirstName = (object)DBNull.Value, LastName = "Jones" } }; var grid = new WebGrid(GetContext(), defaultSort: "FirstName").Bind(data); Assert.NotNull(grid.Rows); Assert.Equal("Smith", grid.Rows[0]["LastName"]); Assert.Equal("Johnson", grid.Rows[1]["LastName"]); Assert.Equal("Jones", grid.Rows[2]["LastName"]); } [Fact] public void SortWithUnsortableDoesNotThrow() { var object1 = new object(); var object2 = new object(); var data = new[] { new { Value = object1 }, new { Value = object2 } }; var grid = new WebGrid(GetContext(), defaultSort: "Value").Bind(data); Assert.NotNull(grid.Rows); Assert.Equal(object1, grid.Rows[0]["Value"]); Assert.Equal(object2, grid.Rows[1]["Value"]); } [Fact] public void TableRenderingWithColumnTemplates() { var grid = new WebGrid(GetContext(), rowsPerPage: 3).Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" } }); var html = grid.Table(displayHeader: false, columns: new[] { grid.Column("P1", format: item => { return "P1: " + item.P1 + ""; }), grid.Column("P2", format: item => { return new HtmlString("P2: " + item.P2 + ""); }), grid.Column("P3", format: item => { return new HelperResult(tw => { tw.Write("P3: " + item.P3 + ""); }); }) }); UnitTestHelper.AssertEqualsIgnoreWhitespace( "" + "" + "" + "" + "
<span>P1: 1</span>P2: 2P3: 3
", html.ToString()); XhtmlAssert.Validate1_1(html); } [Fact] public void TableRenderingWithDefaultCellValueOfCustom() { var grid = new WebGrid(GetContext(), rowsPerPage: 3).Bind(new[] { new { P1 = String.Empty, P2 = (string)null }, }); var html = grid.Table(fillEmptyRows: true, emptyRowCellValue: "N/A", displayHeader: false); UnitTestHelper.AssertEqualsIgnoreWhitespace( "" + "" + "" + "" + "
N/AN/A
N/AN/A
", html.ToString()); XhtmlAssert.Validate1_1(html); } [Fact] public void TableRenderingWithDefaultCellValueOfEmpty() { var grid = new WebGrid(GetContext(), rowsPerPage: 3).Bind(new[] { new { P1 = String.Empty, P2 = (string)null } }); var html = grid.Table(fillEmptyRows: true, emptyRowCellValue: "", displayHeader: false); UnitTestHelper.AssertEqualsIgnoreWhitespace( "" + "" + "" + "" + "
", html.ToString()); XhtmlAssert.Validate1_1(html); } [Fact] public void TableRenderingWithDefaultCellValueOfNbsp() { var grid = new WebGrid(GetContext(), rowsPerPage: 3).Bind(new[] { new { P1 = String.Empty, P2 = (string)null } }); var html = grid.Table(fillEmptyRows: true, displayHeader: false); UnitTestHelper.AssertEqualsIgnoreWhitespace( "" + "" + "" + "" + "
  
  
", html.ToString()); XhtmlAssert.Validate1_1(html); } [Fact] public void TableRenderingWithExclusions() { var grid = new WebGrid(GetContext()).Bind(new[] { new { P1 = 1, P2 = '2', P3 = "3" } }); var html = grid.Table(exclusions: new string[] { "P2" }); UnitTestHelper.AssertEqualsIgnoreWhitespace( "" + "" + "" + "" + "" + "" + "
P1P3
13
", html.ToString()); XhtmlAssert.Validate1_1(html); } [Fact] public void TableRenderingWithNoStylesAndFillEmptyRows() { var grid = new WebGrid(GetContext(), rowsPerPage: 3).Bind(new[] { new { FirstName = "Joe", LastName = "Smith" } }); var html = grid.Table(fillEmptyRows: true); UnitTestHelper.AssertEqualsIgnoreWhitespace( "" + "" + "" + "" + "" + "" + "" + "" + "
FirstNameLastName
JoeSmith
  
  
", html.ToString()); XhtmlAssert.Validate1_1(html); } [Fact] public void TableRenderingWithSortingDisabled() { var grid = new WebGrid(GetContext(), canSort: false).Bind(new[] { new { FirstName = "Joe", LastName = "Smith" } }); var html = grid.Table(); UnitTestHelper.AssertEqualsIgnoreWhitespace( "" + "" + "" + "" + "" + "" + "
FirstNameLastName
JoeSmith
", html.ToString()); XhtmlAssert.Validate1_1(html); } [Fact] public void TableRenderingWithAttributes() { var grid = new WebGrid(GetContext()).Bind(new[] { new { FirstName = "Joe", LastName = "Smith" } }); var html = grid.Table(htmlAttributes: new { id = "my-table-id", summary = "Table summary" }); UnitTestHelper.AssertEqualsIgnoreWhitespace( "" + "" + "" + "" + "" + "" + "
FirstNameLastName
JoeSmith
", html.ToString()); XhtmlAssert.Validate1_1(html); } [Fact] public void TableRenderingEncodesAttributes() { var grid = new WebGrid(GetContext()).Bind(new[] { new { FirstName = "Joe", LastName = "Smith" } }); var html = grid.Table(htmlAttributes: new { summary = "\"" + "" + "" + "" + "" + "" + "
FirstNameLastName
JoeSmith
", html.ToString()); XhtmlAssert.Validate1_1(html); } [Fact] public void TableRenderingIsNotAffectedWhenAttributesIsNull() { var grid = new WebGrid(GetContext()).Bind(new[] { new { FirstName = "Joe", LastName = "Smith" } }); var html = grid.Table(htmlAttributes: null); UnitTestHelper.AssertEqualsIgnoreWhitespace( "" + "" + "" + "" + "" + "" + "
FirstNameLastName
JoeSmith
", html.ToString()); XhtmlAssert.Validate1_1(html); } [Fact] public void TableRenderingIsNotAffectedWhenAttributesIsEmpty() { var grid = new WebGrid(GetContext()).Bind(new[] { new { FirstName = "Joe", LastName = "Smith" } }); var html = grid.Table(htmlAttributes: new { }); UnitTestHelper.AssertEqualsIgnoreWhitespace( "" + "" + "" + "" + "" + "" + "
FirstNameLastName
JoeSmith
", html.ToString()); XhtmlAssert.Validate1_1(html); } [Fact] public void TableRenderingWithStyles() { NameValueCollection queryString = new NameValueCollection(); queryString["row"] = "1"; var grid = new WebGrid(GetContext(queryString), rowsPerPage: 4).Bind(new[] { new { FirstName = "Joe", LastName = "Smith" }, new { FirstName = "Bob", LastName = "Johnson" } }); var html = grid.Table(tableStyle: "tbl", headerStyle: "hdr", footerStyle: "ftr", rowStyle: "row", alternatingRowStyle: "arow", selectedRowStyle: "sel", fillEmptyRows: true, footer: item => "footer text", columns: new[] { grid.Column("firstName", style: "c1", canSort: false), grid.Column("lastName", style: "c2", canSort: false) }); UnitTestHelper.AssertEqualsIgnoreWhitespace( "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "
firstNamelastName
footer text
JoeSmith
BobJohnson
  
  
", html.ToString()); XhtmlAssert.Validate1_1(html); } [Fact] public void TableWithAjax() { var grid = new WebGrid(GetContext(), ajaxUpdateContainerId: "grid").Bind(new[] { new { First = "First", Second = "Second" } }); string html = grid.Table().ToString(); Assert.True(html.Contains("(() => { var rows = grid.Rows; }, errorMessage); Assert.Throws(() => { int count = grid.TotalRowCount; }, errorMessage); Assert.Throws(() => grid.GetHtml().ToString(), errorMessage); Assert.Throws(() => grid.Pager().ToString(), errorMessage); Assert.Throws(() => grid.Table().ToString(), errorMessage); Assert.Throws(() => { grid.SelectedIndex = 1; var row = grid.SelectedRow; }, errorMessage); } [Fact] public void WebGridThrowsIfBindingIsPerformedWhenAlreadyBound() { // Arrange var grid = new WebGrid(GetContext()); var values = Enumerable.Range(0, 10).Cast(); // Act grid.Bind(values); // Assert Assert.Throws(() => grid.Bind(values), "The WebGrid instance is already bound to a data source."); } [Fact] public void GetElementTypeReturnsDynamicTypeIfElementIsDynamic() { // Arrange IEnumerable elements = Dynamics(new[] { new Person { FirstName = "Foo", LastName = "Bar" } }); // Act Type type = WebGrid.GetElementType(elements); // Assert Assert.Equal(typeof(IDynamicMetaObjectProvider), type); } [Fact] public void GetElementTypeReturnsEnumerableTypeIfFirstInstanceIsNotDynamic() { // Arrange IEnumerable elements = Iterator(); // Act Type type = WebGrid.GetElementType(elements); // Assert Assert.Equal(typeof(Person), type); } [Fact] public void TableThrowsIfQueryStringDerivedSortColumnIsExcluded() { // Arrange NameValueCollection collection = new NameValueCollection(); collection["sort"] = "Salary"; var context = GetContext(collection); IList employees = new List(); employees.Add(new Employee { Name = "A", Salary = 5, Manager = new Employee { Name = "-" } }); employees.Add(new Employee { Name = "B", Salary = 20, Manager = employees[0] }); employees.Add(new Employee { Name = "C", Salary = 15, Manager = employees[0] }); employees.Add(new Employee { Name = "D", Salary = 5, Manager = employees[1] }); var grid = new WebGrid(context, defaultSort: "Name").Bind(employees); // Act and Assert Assert.Throws(() => grid.GetHtml(exclusions: new[] { "Salary" }), "Column \"Salary\" does not exist."); } [Fact] public void TableThrowsIfQueryStringDerivedSortColumnDoesNotExistInColumnsArgument() { // Arrange NameValueCollection collection = new NameValueCollection(); collection["sort"] = "Salary"; var context = GetContext(collection); IList employees = new List(); employees.Add(new Employee { Name = "A", Salary = 5, Manager = new Employee { Name = "-" } }); employees.Add(new Employee { Name = "B", Salary = 20, Manager = employees[0] }); employees.Add(new Employee { Name = "C", Salary = 15, Manager = employees[0] }); employees.Add(new Employee { Name = "D", Salary = 5, Manager = employees[1] }); var grid = new WebGrid(context, canSort: true, defaultSort: "Name").Bind(employees); // Act and Assert Assert.Throws( () => grid.Table(columns: new[] { new WebGridColumn { ColumnName = "Name" }, new WebGridColumn { ColumnName = "Manager.Name" } }), "Column \"Salary\" does not exist."); } [Fact] public void TableDoesNotThrowIfQueryStringDerivedSortColumnIsVisibleButNotSortable() { // Arrange NameValueCollection collection = new NameValueCollection(); collection["sort"] = "Salary"; collection["sortDir"] = "Desc"; var context = GetContext(collection); IList employees = new List(); employees.Add(new Employee { Name = "A", Salary = 5, Manager = new Employee { Name = "-" } }); employees.Add(new Employee { Name = "B", Salary = 20, Manager = employees[0] }); employees.Add(new Employee { Name = "C", Salary = 15, Manager = employees[0] }); employees.Add(new Employee { Name = "D", Salary = 10, Manager = employees[1] }); var grid = new WebGrid(context, canSort: true).Bind(employees); // Act var html = grid.Table(columns: new[] { new WebGridColumn { ColumnName = "Salary", CanSort = false } }); // Assert Assert.NotNull(html); Assert.Equal(grid.Rows[0]["Salary"], 20); Assert.Equal(grid.Rows[1]["Salary"], 15); Assert.Equal(grid.Rows[2]["Salary"], 10); Assert.Equal(grid.Rows[3]["Salary"], 5); } [Fact] public void TableThrowsIfComplexPropertyIsUnsortable() { // Arrange NameValueCollection collection = new NameValueCollection(); collection["sort"] = "Manager.Salary"; var context = GetContext(collection); IList employees = new List(); employees.Add(new Employee { Name = "A", Salary = 5, Manager = new Employee { Name = "-" } }); employees.Add(new Employee { Name = "B", Salary = 20, Manager = employees[0] }); employees.Add(new Employee { Name = "C", Salary = 15, Manager = employees[0] }); employees.Add(new Employee { Name = "D", Salary = 5, Manager = employees[1] }); var grid = new WebGrid(context).Bind(employees, columnNames: new[] { "Name", "Manager.Name" }); // Act and Assert Assert.Throws(() => grid.GetHtml(), "Column \"Manager.Salary\" does not exist."); } [Fact] public void TableDoesNotThrowIfUnsortableColumnIsExplicitlySpecifiedByUser() { // Arrange var context = GetContext(); IList employees = new List(); employees.Add(new Employee { Name = "A", Salary = 5, Manager = new Employee { Name = "-" } }); employees.Add(new Employee { Name = "C", Salary = 15, Manager = employees[0] }); employees.Add(new Employee { Name = "D", Salary = 10, Manager = employees[1] }); // Act var grid = new WebGrid(context).Bind(employees, columnNames: new[] { "Name", "Manager.Name" }); grid.SortColumn = "Salary"; var html = grid.Table(); // Assert Assert.Equal(grid.Rows[0]["Salary"], 5); Assert.Equal(grid.Rows[1]["Salary"], 10); Assert.Equal(grid.Rows[2]["Salary"], 15); UnitTestHelper.AssertEqualsIgnoreWhitespace( "" + "" + "" + "" + "" + "" + "" + "
NameManager.Name
A-
DC
CA
", html.ToString()); } [Fact] public void TableDoesNotThrowIfUnsortableColumnIsDefaultSortColumn() { // Arrange var context = GetContext(); IList employees = new List(); employees.Add(new Employee { Name = "A", Salary = 5, Manager = new Employee { Name = "-" } }); employees.Add(new Employee { Name = "C", Salary = 15, Manager = employees[0] }); employees.Add(new Employee { Name = "D", Salary = 10, Manager = employees[1] }); // Act var grid = new WebGrid(context, defaultSort: "Salary").Bind(employees, columnNames: new[] { "Name", "Manager.Name" }); var html = grid.Table(); // Assert Assert.Equal(grid.Rows[0]["Salary"], 5); Assert.Equal(grid.Rows[1]["Salary"], 10); Assert.Equal(grid.Rows[2]["Salary"], 15); UnitTestHelper.AssertEqualsIgnoreWhitespace( "" + "" + "" + "" + "" + "" + "" + "
NameManager.Name
A-
DC
CA
", html.ToString()); } private static IEnumerable Iterator() { yield return new Person { FirstName = "Foo", LastName = "Bar" }; } [Fact] public void GetElementTypeReturnsEnumerableTypeIfCollectionPassedImplementsEnumerable() { // Arrange IList listElements = new List { new Person { FirstName = "Foo", LastName = "Bar" } }; HashSet setElements = new HashSet { new DynamicWrapper(new Person { FirstName = "Foo", LastName = "Bar" }) }; // Act Type listType = WebGrid.GetElementType(listElements); Type setType = WebGrid.GetElementType(setElements); // Assert Assert.Equal(typeof(Person), listType); Assert.Equal(typeof(IDynamicMetaObjectProvider), setType); } [Fact] public void GetElementTypeReturnsEnumerableTypeIfCollectionImplementsEnumerable() { // Arrange IEnumerable elements = new NonGenericEnumerable(new[] { new Person { FirstName = "Foo", LastName = "Bar" } }); ; // Act Type type = WebGrid.GetElementType(elements); // Assert Assert.Equal(typeof(Person), type); } [Fact] public void GetElementTypeReturnsEnumerableTypeIfCollectionIsIEnumerable() { // Arrange IEnumerable elements = new GenericEnumerable(new[] { new Person { FirstName = "Foo", LastName = "Bar" } }); ; // Act Type type = WebGrid.GetElementType(elements); // Assert Assert.Equal(typeof(Person), type); } [Fact] public void GetElementTypeDoesNotThrowIfTypeIsNotGeneric() { // Arrange IEnumerable elements = new[] { new Person { FirstName = "Foo", LastName = "Bar" } }; // Act Type type = WebGrid.GetElementType(elements); // Assert Assert.Equal(typeof(Person), type); } private static IEnumerable Dynamics(params object[] objects) { return (from o in objects select new DynamicWrapper(o)).ToArray(); } private static HttpContextBase GetContext(NameValueCollection queryString = null) { Mock requestMock = new Mock(); requestMock.Setup(request => request.QueryString).Returns(queryString ?? new NameValueCollection()); Mock contextMock = new Mock(); contextMock.Setup(context => context.Request).Returns(requestMock.Object); contextMock.Setup(context => context.Items).Returns(new Hashtable()); return contextMock.Object; } class Person { public string FirstName { get; set; } public string LastName { get; set; } } private class Employee { public string Name { get; set; } public int Salary { get; set; } public Employee Manager { get; set; } } class NonGenericEnumerable : IEnumerable { private IEnumerable _source; public NonGenericEnumerable(IEnumerable source) { _source = source; } public IEnumerator GetEnumerator() { return _source.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } class GenericEnumerable : IEnumerable { private IEnumerable _source; public GenericEnumerable(IEnumerable source) { _source = source; } public IEnumerator GetEnumerator() { return _source.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } } }