Skip to content

Commit 6847ec2

Browse files
authored
test(Table): add SearchItemMetaData unit test (#7774)
* refactor: 更新 InternalTable 内部拷贝方法 * test: 更新单元测试 * doc: 更新注释信息 * test: 提高代码覆盖率 * test: 提高代码覆盖率 * test: 增加 SearchFormItemMetaData 代码覆盖率 * test: 增加 GroupOrder 覆盖率 * doc: 代码格式化 * refactor: 增加 SearchItems 支持 * test: 增加 SearchItems 代码覆盖 * refactor: 增加 Order 逻辑 * test: 增加单元测试
1 parent 4e0b4bf commit 6847ec2

9 files changed

Lines changed: 93 additions & 8 deletions

File tree

src/BootstrapBlazor.Server/Components/Samples/Table/TablesSearch.razor.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,11 +159,12 @@ private Task<QueryData<Foo>> OnSearchModelQueryAsync(QueryPageOptions options)
159159
private Task<QueryData<Foo>> OnQueryAsync(QueryPageOptions options)
160160
{
161161
// 使用内置扩展方法 ToFilter 获得过滤条件
162-
// 目前 ToFilterFunc 无法解决大小写敏感问题
162+
// 解决大小写敏感问题使用参数 StringComparison.OrdinalIgnoreCase
163+
// 注意 EFCore 不支持 StringComparison.OrdinalIgnoreCase 需要使用 EF.Functions.Like 进行模糊搜索
163164
var items = Items.Where(options.ToFilterFunc<Foo>());
164165
if (!string.IsNullOrEmpty(options.SearchText))
165166
{
166-
// 使用 Linq 处理
167+
// 使用 Linq 处理 处理模糊搜索 处理大小写敏感问题使用参数 StringComparison.OrdinalIgnoreCase
167168
items = Items.Where(i =>
168169
(!string.IsNullOrEmpty(i.Name) && i.Name.Contains(options.SearchText, StringComparison.OrdinalIgnoreCase))
169170
|| (!string.IsNullOrEmpty(i.Address) && i.Address.Contains(options.SearchText, StringComparison.OrdinalIgnoreCase)));

src/BootstrapBlazor/Components/SearchForm/SearchForm.razor.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,12 +121,12 @@ public partial class SearchForm : IShowLabel
121121
.AddClass($"--bb-row-label-width: {LabelWidth}px;", LabelWidth.HasValue)
122122
.Build();
123123

124-
private IEnumerable<ISearchItem> UnsetGroupItems => Items.Where(i => string.IsNullOrEmpty(i.GroupName));
124+
private IEnumerable<ISearchItem> UnsetGroupItems => Items.Where(i => string.IsNullOrEmpty(i.GroupName)).OrderBy(i => i.Order);
125125

126126
private IEnumerable<KeyValuePair<string, IOrderedEnumerable<ISearchItem>>> GroupItems => Items
127127
.Where(i => !string.IsNullOrEmpty(i.GroupName))
128128
.GroupBy(i => i.GroupName).OrderBy(i => i.Key)
129-
.Select(i => new KeyValuePair<string, IOrderedEnumerable<ISearchItem>>(i.First().GroupName!, i.OrderBy(x => x.Order)));
129+
.Select(i => new KeyValuePair<string, IOrderedEnumerable<ISearchItem>>(i.First().GroupName!, i.OrderBy(x => x.GroupOrder)));
130130

131131
/// <summary>
132132
/// <inheritdoc/>

src/BootstrapBlazor/Components/Table/Table.razor.Search.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,11 +182,28 @@ private IEnumerable<ISearchItem> SearchFormItems
182182
NumberEndValueLabelText = SearchFormLocalizer[nameof(Components.SearchFormLocalizerOptions.NumberEndValueLabelText)]
183183
};
184184
}
185-
_searchItems ??= SearchItems ?? GetSearchColumns().Select(i => i.ParseSearchItem(SearchFormLocalizerOptions.Value)).ToList();
185+
_searchItems ??= GetSearchItems(SearchFormLocalizerOptions.Value);
186186
return _searchItems;
187187
}
188188
}
189189

190+
private IEnumerable<ISearchItem> GetSearchItems(SearchFormLocalizerOptions options)
191+
{
192+
if (SearchItems != null)
193+
{
194+
// TODO: 增加内部创建默认 ISearchItemMetaData 逻辑,减少用户使用成本
195+
//foreach (var item in SearchItems)
196+
//{
197+
// // 创建默认 ISearchItemMetaData
198+
// item.MetaData ??= column.BuildSearchMetaData(options);
199+
//}
200+
201+
return SearchItems;
202+
}
203+
204+
return GetSearchColumns().Select(i => i.ParseSearchItem(options)).ToList();
205+
}
206+
190207
private Task OnSearchFormFilterChanged(FilterKeyValueAction action)
191208
{
192209
_searchFilter = action;

src/BootstrapBlazor/Extensions/ITableColumnExtensions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ private static void CopyValue(this ITableColumn col, ITableColumn dest)
202202
if (col.IsRequiredWhenAdd.HasValue) dest.IsRequiredWhenAdd = col.IsRequiredWhenAdd;
203203
if (col.IsRequiredWhenEdit.HasValue) dest.IsRequiredWhenEdit = col.IsRequiredWhenEdit;
204204
if (col.IgnoreWhenExport.HasValue) dest.IgnoreWhenExport = col.IgnoreWhenExport;
205+
if (col.SearchFormItemMetaData != null) dest.SearchFormItemMetaData = col.SearchFormItemMetaData;
205206
}
206207

207208
/// <summary>

test/UnitTest/Attributes/AutoGenerateClassTest.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,9 @@ public void AutoGenerateColumn_Ok()
210210
attrInterface.IsRequiredWhenEdit = true;
211211
Assert.True(attrInterface.IsRequiredWhenEdit);
212212

213+
attrInterface.SearchFormItemMetaData = new StringSearchMetaData();
214+
Assert.NotNull(attrInterface.SearchFormItemMetaData);
215+
213216
var attrEditor = (IEditorItem)attr;
214217
attrEditor.Items = null;
215218
Assert.Null(attrEditor.Items);

test/UnitTest/Components/InternalTableColumnTest.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ public void InternalTableColumn_Ok()
8787
SetValue("IsRequiredWhenEdit", true);
8888
SetValue("LookupService", null);
8989
SetValue("IgnoreWhenExport", true);
90+
SetValue("SearchFormItemMetaData", new StringSearchMetaData());
9091

9192
void SetValue(string propertyName, object? val) => type!.GetProperty(propertyName)!.SetValue(instance, val);
9293
}

test/UnitTest/Components/SearchFormTest.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ public async Task Filter_Ok()
5555
await stringSearchMetaData.ValueChangedHandler("test1");
5656
Assert.Single(filterKeyValueAction.Filters);
5757
Assert.Equal("test1", filterKeyValueAction.Filters[0].FieldValue);
58+
59+
var searchForm = cut.Instance;
60+
Assert.NotNull(searchForm.Filter);
5861
}
5962

6063
[Fact]
@@ -73,7 +76,9 @@ public void LabelAlign_Ok()
7376
{
7477
new SearchItem(nameof(Foo.Name), typeof(string), "Name")
7578
{
79+
Text = "Name-Updated",
7680
GroupName = "Group1",
81+
GroupOrder = 1,
7782
MetaData = stringSearchMetaData
7883
},
7984
new SearchItem(nameof(Foo.Address), typeof(string), "Address")
@@ -93,7 +98,7 @@ public void LabelAlign_Ok()
9398
}
9499

95100
[Fact]
96-
public void ShowUnsetGroupItemsOnTop_Ok()
101+
public void Group_Ok()
97102
{
98103
var cut = Context.Render<SearchForm>(pb =>
99104
{
@@ -103,6 +108,7 @@ public void ShowUnsetGroupItemsOnTop_Ok()
103108
new SearchItem(nameof(Foo.Name), typeof(string), "Name")
104109
{
105110
GroupName = "Group1",
111+
GroupOrder= 1,
106112
MetaData = new StringSearchMetaData()
107113
},
108114
new SearchItem(nameof(Foo.Address), typeof(string), "Address")
@@ -111,6 +117,12 @@ public void ShowUnsetGroupItemsOnTop_Ok()
111117
}
112118
});
113119
});
120+
121+
// 查找标签一共有两个第一个应该是 Address 第二个应该是 Name
122+
var labels = cut.FindAll(".bb-search-form label");
123+
Assert.Equal(2, labels.Count);
124+
Assert.Equal("Address", labels[0].TextContent);
125+
Assert.Equal("Name", labels[1].TextContent);
114126
}
115127

116128
[Fact]

test/UnitTest/Components/TableTest.cs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,52 @@ public async Task UseSearchForm_Ok()
665665
await cut.InvokeAsync(() => table.Instance.QueryAsync());
666666
}
667667

668+
[Fact]
669+
public async Task SearchItems_Ok()
670+
{
671+
var localizer = Context.Services.GetRequiredService<IStringLocalizer<Foo>>();
672+
var cut = Context.Render<BootstrapBlazorRoot>(pb =>
673+
{
674+
pb.AddChildContent<Table<Foo>>(pb =>
675+
{
676+
pb.Add(a => a.RenderMode, TableRenderMode.Table);
677+
pb.Add(a => a.ShowToolbar, true);
678+
pb.Add(a => a.ShowSearch, true);
679+
pb.Add(a => a.UseSearchForm, true);
680+
pb.Add(a => a.SearchItems, new List<SearchItem>()
681+
{
682+
new SearchItem("Name", typeof(string), "名称") { MetaData = new StringSearchMetaData() }
683+
});
684+
pb.Add(a => a.SearchMode, SearchMode.Top);
685+
pb.Add(a => a.OnQueryAsync, OnQueryAsync(localizer));
686+
pb.Add(a => a.TableColumns, foo => builder =>
687+
{
688+
builder.OpenComponent<TableColumn<Foo, string>>(0);
689+
builder.AddAttribute(1, "Field", "");
690+
builder.AddAttribute(2, "FieldExpression", Utility.GenerateValueExpression(foo, "Name", typeof(string)));
691+
builder.CloseComponent();
692+
});
693+
});
694+
});
695+
696+
cut.Contains("bb-editor bb-search-form");
697+
698+
// 触发 Filter
699+
var searchForm = cut.FindComponent<SearchForm>();
700+
Assert.NotNull(searchForm);
701+
702+
var input = searchForm.FindComponent<BootstrapInput<string>>();
703+
Assert.NotNull(input);
704+
705+
var cb = input.Instance.OnValueChanged;
706+
Assert.NotNull(cb);
707+
await cb("test");
708+
709+
var table = cut.FindComponent<Table<Foo>>();
710+
Assert.NotNull(table);
711+
await cut.InvokeAsync(() => table.Instance.QueryAsync());
712+
}
713+
668714
[Fact]
669715
public void ShowToolbar_Ok()
670716
{

test/UnitTest/Extensions/ITableColumnExtensionsTest.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public void InheritValue_Ok()
2323
Sortable = true,
2424
TextEllipsis = true,
2525
ShowCopyColumn = true,
26-
Visible = false,
26+
Visible = false
2727
};
2828
col.InheritValue(attr);
2929
Assert.Equal(Alignment.Center, col.Align);
@@ -113,7 +113,9 @@ public void CopyValue_Ok()
113113
Required = true,
114114
RequiredErrorMessage = "test",
115115
IsRequiredWhenAdd = true,
116-
IsRequiredWhenEdit = true
116+
IsRequiredWhenEdit = true,
117+
118+
SearchFormItemMetaData = new StringSearchMetaData()
117119
};
118120
col.CopyValue(attr);
119121
Assert.NotNull(col.ComponentType);
@@ -183,6 +185,8 @@ public void CopyValue_Ok()
183185
Assert.NotNull(col.LookupService);
184186
Assert.Equal("test-key", col.LookupServiceKey);
185187
Assert.Equal(true, col.LookupServiceData);
188+
189+
Assert.NotNull(col.SearchFormItemMetaData);
186190
}
187191

188192
[Fact]

0 commit comments

Comments
 (0)