diff --git a/Directory.Packages.props b/Directory.Packages.props
index c9af8a04..f1183d3b 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -16,6 +16,8 @@
+
+
diff --git a/IgniteUI.Blazor.Lite.slnx b/IgniteUI.Blazor.Lite.slnx
index b7807437..3452cb08 100644
--- a/IgniteUI.Blazor.Lite.slnx
+++ b/IgniteUI.Blazor.Lite.slnx
@@ -16,6 +16,7 @@
+
diff --git a/tests/IgniteUI.Blazor.Lite.IntegrationTests/ComboDataTest.cs b/tests/IgniteUI.Blazor.Lite.IntegrationTests/ComboDataTest.cs
new file mode 100644
index 00000000..0cc56367
--- /dev/null
+++ b/tests/IgniteUI.Blazor.Lite.IntegrationTests/ComboDataTest.cs
@@ -0,0 +1,181 @@
+using System.Text.Json;
+using IgniteUI.Blazor.Lite.IntegrationTests.Infrastructure;
+
+namespace IgniteUI.Blazor.Lite.IntegrationTests
+{
+ ///
+ /// Combo data-binding scenarios against the WebAssembly-rendered TestBed page
+ /// (/combo-data). Unlike the Server-rendered component sweep, data here crosses
+ /// the in-process (unmarshalled) channel — the same path a production WASM app uses.
+ /// Assertions read the live web component's data: what the user's combo shows.
+ ///
+ [Parallelizable(ParallelScope.Self)]
+ public class ComboDataTest : BlazorPageTest
+ {
+ [Test]
+ public async Task TypedFields_TransferToClient()
+ {
+ await OpenScenarioAsync("typed-products", expectedCount: 3);
+
+ var first = (await ClientDataAsync())[0];
+ Assert.Multiple(() =>
+ {
+ Assert.That(first.GetProperty("Id").GetInt32(), Is.EqualTo(1));
+ Assert.That(first.GetProperty("Name").GetString(), Is.EqualTo("Chai"));
+ Assert.That(first.GetProperty("Price").GetDouble(), Is.EqualTo(18.5));
+ Assert.That(first.GetProperty("Discontinued").GetBoolean(), Is.False);
+ Assert.That(first.GetProperty("UnitsSold").GetInt64(), Is.EqualTo(42_000_000_000));
+ // The client holds a JS Date; compare instants so the machine's timezone drops out.
+ Assert.That(ClientInstant(first.GetProperty("Restocked")), Is.EqualTo(new DateTime(2026, 1, 15).ToUniversalTime()));
+ });
+ }
+
+ [Test]
+ public async Task NullableFields_PreserveNullsAndValues()
+ {
+ await OpenScenarioAsync("nullable-readings", expectedCount: 3);
+
+ var data = await ClientDataAsync();
+ var full = data[0];
+ var empty = data[1];
+ var mixed = data[2];
+ Assert.Multiple(() =>
+ {
+ Assert.That(full.GetProperty("Quantity").GetInt32(), Is.EqualTo(5));
+ Assert.That(full.GetProperty("Value").GetDouble(), Is.EqualTo(2.5));
+ Assert.That(full.GetProperty("Flagged").GetBoolean(), Is.True);
+ Assert.That(ClientInstant(full.GetProperty("MeasuredOn")), Is.EqualTo(new DateTime(2026, 3, 3).ToUniversalTime()));
+
+ Assert.That(empty.GetProperty("Quantity").ValueKind, Is.EqualTo(JsonValueKind.Null));
+ Assert.That(empty.GetProperty("Value").ValueKind, Is.EqualTo(JsonValueKind.Null));
+ Assert.That(empty.GetProperty("Flagged").ValueKind, Is.EqualTo(JsonValueKind.Null));
+ Assert.That(empty.GetProperty("MeasuredOn").ValueKind, Is.EqualTo(JsonValueKind.Null));
+
+ Assert.That(mixed.GetProperty("Quantity").GetInt32(), Is.EqualTo(7));
+ Assert.That(mixed.GetProperty("Value").ValueKind, Is.EqualTo(JsonValueKind.Null));
+ Assert.That(mixed.GetProperty("Flagged").GetBoolean(), Is.False);
+ });
+ }
+
+ [Test]
+ public async Task NestedObjects_TransferNestedValues()
+ {
+ await OpenScenarioAsync("nested-orders", expectedCount: 2);
+
+ var data = await ClientDataAsync();
+ Assert.Multiple(() =>
+ {
+ Assert.That(data[0].GetProperty("Reference").GetString(), Is.EqualTo("ORD-1"));
+ Assert.That(data[0].GetProperty("Customer").GetProperty("Name").GetString(), Is.EqualTo("Maria"));
+ Assert.That(data[1].GetProperty("Customer").GetProperty("City").GetString(), Is.EqualTo("Madrid"));
+ });
+ }
+
+ [Test]
+ public async Task ObjectValues_SelectionTravelsBackAsDataItems()
+ {
+ await OpenScenarioAsync("objects-as-values", expectedCount: 3);
+
+ await Page.EvaluateAsync("() => document.querySelector('igc-combo').show()");
+ // Playwright's own click fails its actionability check on the combo's
+ // shadow-DOM items, so click through the DOM.
+ await Page.WaitForFunctionAsync("() => document.querySelector('igc-combo').shadowRoot.querySelector('igc-combo-item') !== null");
+ await Page.EvaluateAsync("() => document.querySelector('igc-combo').shadowRoot.querySelector('igc-combo-item').click()");
+ await Page.WaitForFunctionAsync(
+ "() => window.clientPageRef.invokeMethodAsync('GetLastValue').then(v => v.count === 1)");
+
+ var last = await Page.EvaluateAsync(
+ "() => window.clientPageRef.invokeMethodAsync('GetLastValue')");
+ Assert.Multiple(() =>
+ {
+ Assert.That(last.GetProperty("names")[0].GetString(), Is.EqualTo("Chai"));
+ Assert.That(last.GetProperty("sameInstances").GetBoolean(), Is.True,
+ "received values should resolve back to the bound data instances");
+ });
+ }
+
+ [Test]
+ [Ignore("Item types with public primitive-typed fields crash schema creation: JsonDataSourceSchema.Commit " +
+ "stores the typed field getters in a Func