From 0fcbdbbee5de7cbd26be587643f4a8e200142e32 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 14 Feb 2026 23:55:40 +0000
Subject: [PATCH 1/2] Initial plan
From a51074ecf8c59fc3a93f756e6b871fe5deb509d1 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 15 Feb 2026 00:05:57 +0000
Subject: [PATCH 2/2] Add unit tests for operation name flow from client to
server
Co-authored-by: rockfordlhotka <2333134+rockfordlhotka@users.noreply.github.com>
---
.../DataPortal/OperationNameFlowTests.cs | 423 ++++++++++++++++++
1 file changed, 423 insertions(+)
create mode 100644 Source/tests/csla.netcore.test/DataPortal/OperationNameFlowTests.cs
diff --git a/Source/tests/csla.netcore.test/DataPortal/OperationNameFlowTests.cs b/Source/tests/csla.netcore.test/DataPortal/OperationNameFlowTests.cs
new file mode 100644
index 0000000000..ffa810e360
--- /dev/null
+++ b/Source/tests/csla.netcore.test/DataPortal/OperationNameFlowTests.cs
@@ -0,0 +1,423 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) Marimer LLC. All rights reserved.
+// Website: https://cslanet.com
+//
+// Tests for operation name computation and flow
+//-----------------------------------------------------------------------
+using System.Reflection;
+using Csla.Server;
+using Csla.TestHelpers;
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace Csla.Test.DataPortal
+{
+ [TestClass]
+ public class OperationNameFlowTests
+ {
+ private static TestDIContext _diContext = default!;
+
+ [ClassInitialize]
+ public static void ClassSetup(TestContext context)
+ {
+ _ = context;
+ _diContext = TestDIContextFactory.CreateDefaultContext();
+ }
+
+ #region Operation Name Computation Tests
+
+ [TestMethod]
+ public void ComputeOperationName_NoCriteria_ReturnsBaseName()
+ {
+ // Arrange
+ var method = typeof(TestRoot).GetMethod("DataPortal_Fetch", BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null);
+
+ // Act
+ var operationName = DataPortalOperationNameHelper.ComputeOperationName(method!);
+
+ // Assert
+ operationName.Should().Be("Fetch");
+ }
+
+ [TestMethod]
+ public void ComputeOperationName_SingleIntParameter_ReturnsCorrectName()
+ {
+ // Arrange
+ var method = typeof(TestRoot).GetMethod("DataPortal_Fetch", BindingFlags.NonPublic | BindingFlags.Instance, null, [typeof(int)], null);
+
+ // Act
+ var operationName = DataPortalOperationNameHelper.ComputeOperationName(method!);
+
+ // Assert
+ operationName.Should().Be("Fetch__Int32");
+ }
+
+ [TestMethod]
+ public void ComputeOperationName_SingleStringParameter_ReturnsCorrectName()
+ {
+ // Arrange
+ var method = typeof(TestRoot).GetMethod("DataPortal_Fetch", BindingFlags.NonPublic | BindingFlags.Instance, null, [typeof(string)], null);
+
+ // Act
+ var operationName = DataPortalOperationNameHelper.ComputeOperationName(method!);
+
+ // Assert
+ operationName.Should().Be("Fetch__String");
+ }
+
+ [TestMethod]
+ public void ComputeOperationName_MultipleParameters_ReturnsCorrectName()
+ {
+ // Arrange
+ var method = typeof(TestRoot).GetMethod("DataPortal_Fetch", BindingFlags.NonPublic | BindingFlags.Instance, null, [typeof(int), typeof(string)], null);
+
+ // Act
+ var operationName = DataPortalOperationNameHelper.ComputeOperationName(method!);
+
+ // Assert
+ operationName.Should().Be("Fetch__Int32_String");
+ }
+
+ [TestMethod]
+ public void ComputeOperationName_ArrayParameter_ReturnsCorrectName()
+ {
+ // Arrange
+ var method = typeof(TestRoot).GetMethod("DataPortal_Fetch", BindingFlags.NonPublic | BindingFlags.Instance, null, [typeof(int[])], null);
+
+ // Act
+ var operationName = DataPortalOperationNameHelper.ComputeOperationName(method!);
+
+ // Assert
+ operationName.Should().Be("Fetch__Int32Array");
+ }
+
+ [TestMethod]
+ public void ComputeOperationName_GenericParameter_ReturnsCorrectName()
+ {
+ // Arrange
+ var method = typeof(TestRoot).GetMethod("DataPortal_Fetch", BindingFlags.NonPublic | BindingFlags.Instance, null, [typeof(List)], null);
+
+ // Act
+ var operationName = DataPortalOperationNameHelper.ComputeOperationName(method!);
+
+ // Assert
+ operationName.Should().Be("Fetch__List_1_Int32");
+ }
+
+ [TestMethod]
+ public void ComputeOperationName_WithInjectAttribute_IgnoresInjectedParameter()
+ {
+ // Arrange
+ var method = typeof(TestRootWithDI).GetMethod("DataPortal_Fetch", BindingFlags.NonPublic | BindingFlags.Instance);
+
+ // Act
+ var operationName = DataPortalOperationNameHelper.ComputeOperationName(method!);
+
+ // Assert
+ operationName.Should().Be("Fetch__Int32");
+ }
+
+ [TestMethod]
+ public void ComputeOperationName_CreateOperation_ReturnsCorrectBaseName()
+ {
+ // Arrange
+ var method = typeof(TestRoot).GetMethod("DataPortal_Create", BindingFlags.NonPublic | BindingFlags.Instance, null, [typeof(string)], null);
+
+ // Act
+ var operationName = DataPortalOperationNameHelper.ComputeOperationName(method!);
+
+ // Assert
+ operationName.Should().Be("Create__String");
+ }
+
+ [TestMethod]
+ public void ComputeOperationName_DeleteOperation_ReturnsCorrectBaseName()
+ {
+ // Arrange
+ var method = typeof(TestRoot).GetMethod("DataPortal_Delete", BindingFlags.NonPublic | BindingFlags.Instance, null, [typeof(int)], null);
+
+ // Act
+ var operationName = DataPortalOperationNameHelper.ComputeOperationName(method!);
+
+ // Assert
+ operationName.Should().Be("Delete__Int32");
+ }
+
+ [TestMethod]
+ public void ComputeOperationName_ExecuteOperation_ReturnsCorrectBaseName()
+ {
+ // Arrange
+ var method = typeof(TestCommand).GetMethod("DataPortal_Execute", BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null);
+
+ // Act
+ var operationName = DataPortalOperationNameHelper.ComputeOperationName(method!);
+
+ // Assert
+ operationName.Should().Be("Execute");
+ }
+
+ #endregion
+
+ #region Integration Tests
+
+ [TestMethod]
+ public async Task DataPortal_Fetch_FlowsOperationNameToServer()
+ {
+ // Arrange & Act
+ var obj = await _diContext.CreateDataPortal().FetchAsync(123);
+
+ // Assert
+ obj.Should().NotBeNull();
+ obj.OperationNameWasCalled.Should().BeTrue();
+ }
+
+ [TestMethod]
+ public async Task DataPortal_Create_FlowsOperationNameToServer()
+ {
+ // Arrange & Act
+ var obj = await _diContext.CreateDataPortal().CreateAsync("test");
+
+ // Assert
+ obj.Should().NotBeNull();
+ obj.OperationNameWasCalled.Should().BeTrue();
+ }
+
+ [TestMethod]
+ public async Task DataPortal_Execute_FlowsOperationNameToServer()
+ {
+ // Arrange
+ var dp = _diContext.CreateDataPortal();
+ var cmd = await dp.CreateAsync();
+
+ // Act
+ cmd = await dp.ExecuteAsync(cmd);
+
+ // Assert
+ cmd.Should().NotBeNull();
+ cmd.OperationNameWasCalled.Should().BeTrue();
+ }
+
+ [TestMethod]
+ public async Task DataPortal_Update_FlowsInsertOperationName()
+ {
+ // Arrange
+ var obj = await _diContext.CreateDataPortal().CreateAsync();
+
+ // Act
+ obj = await _diContext.CreateDataPortal().UpdateAsync(obj);
+
+ // Assert
+ obj.Should().NotBeNull();
+ obj.OperationNameWasCalled.Should().BeTrue();
+ }
+
+ [TestMethod]
+ public async Task DataPortal_Update_FlowsUpdateOperationName()
+ {
+ // Arrange
+ var obj = await _diContext.CreateDataPortal().FetchAsync(123);
+
+ // Act
+ obj = await _diContext.CreateDataPortal().UpdateAsync(obj);
+
+ // Assert
+ obj.Should().NotBeNull();
+ obj.OperationNameWasCalled.Should().BeTrue();
+ }
+
+ [TestMethod]
+ public async Task DataPortal_Update_FlowsDeleteSelfOperationName()
+ {
+ // Arrange
+ var obj = await _diContext.CreateDataPortal().FetchAsync(123);
+ obj.Delete();
+
+ // Act
+ obj = await _diContext.CreateDataPortal().UpdateAsync(obj);
+
+ // Assert
+ obj.Should().NotBeNull();
+ obj.OperationNameWasCalled.Should().BeTrue();
+ }
+
+ #endregion
+
+ #region Test Classes
+
+ [Serializable]
+ public class TestRoot : BusinessBase
+ {
+ [Fetch]
+ private void DataPortal_Fetch()
+ {
+ }
+
+ [Fetch]
+ private void DataPortal_Fetch(int id)
+ {
+ }
+
+ [Fetch]
+ private void DataPortal_Fetch(string name)
+ {
+ }
+
+ [Fetch]
+ private void DataPortal_Fetch(int id, string name)
+ {
+ }
+
+ [Fetch]
+ private void DataPortal_Fetch(int[] ids)
+ {
+ }
+
+ [Fetch]
+ private void DataPortal_Fetch(List ids)
+ {
+ }
+
+ [Create]
+ private void DataPortal_Create(string name)
+ {
+ }
+
+ [Delete]
+ private void DataPortal_Delete(int id)
+ {
+ }
+ }
+
+ [Serializable]
+ public class TestRootWithDI : BusinessBase
+ {
+ [Fetch]
+ private void DataPortal_Fetch(int id, [Inject] IServiceProvider serviceProvider)
+ {
+ }
+ }
+
+ [Serializable]
+ public class TestCommand : CommandBase
+ {
+ [Execute]
+ private void DataPortal_Execute()
+ {
+ }
+ }
+
+ [Serializable]
+ public class TestRootForFlow : BusinessBase, IDataPortalOperationNamedMapping
+ {
+ public static readonly PropertyInfo OperationNameWasCalledProperty = RegisterProperty(nameof(OperationNameWasCalled));
+ public bool OperationNameWasCalled
+ {
+ get => GetProperty(OperationNameWasCalledProperty);
+ private set => LoadProperty(OperationNameWasCalledProperty, value);
+ }
+
+ public Task InvokeNamedOperationAsync(string operationName, bool isSync, object?[]? criteria, IServiceProvider serviceProvider)
+ {
+ OperationNameWasCalled = true;
+
+ // Dispatch based on operation name
+ switch (operationName)
+ {
+ case "Create":
+ DataPortal_Create();
+ break;
+ case "Create__String":
+ if (criteria is { Length: 1 } && criteria[0] is string name)
+ DataPortal_Create(name);
+ break;
+ case "Fetch__Int32":
+ if (criteria is { Length: 1 } && criteria[0] is int id)
+ DataPortal_Fetch(id);
+ break;
+ case "Insert":
+ DataPortal_Insert();
+ break;
+ case "Update":
+ DataPortal_Update();
+ break;
+ case "DeleteSelf":
+ DataPortal_DeleteSelf();
+ break;
+ default:
+ throw new DataPortalOperationNotSupportedException(operationName, criteria);
+ }
+
+ return Task.CompletedTask;
+ }
+
+ [Create]
+ private void DataPortal_Create()
+ {
+ }
+
+ [Create]
+ private void DataPortal_Create(string name)
+ {
+ }
+
+ [Fetch]
+ private void DataPortal_Fetch(int id)
+ {
+ MarkOld();
+ }
+
+ [Insert]
+ private void DataPortal_Insert()
+ {
+ MarkOld();
+ }
+
+ [Update]
+ private void DataPortal_Update()
+ {
+ }
+
+ [DeleteSelf]
+ private void DataPortal_DeleteSelf()
+ {
+ }
+ }
+
+ [Serializable]
+ public class TestCommandForFlow : CommandBase, IDataPortalOperationNamedMapping
+ {
+ public static readonly PropertyInfo OperationNameWasCalledProperty = RegisterProperty(nameof(OperationNameWasCalled));
+ public bool OperationNameWasCalled
+ {
+ get => ReadProperty(OperationNameWasCalledProperty);
+ private set => LoadProperty(OperationNameWasCalledProperty, value);
+ }
+
+ public Task InvokeNamedOperationAsync(string operationName, bool isSync, object?[]? criteria, IServiceProvider serviceProvider)
+ {
+ OperationNameWasCalled = true;
+
+ if (operationName == "Execute")
+ {
+ DataPortal_Execute();
+ return Task.CompletedTask;
+ }
+
+ throw new DataPortalOperationNotSupportedException(operationName, criteria);
+ }
+
+ [Create]
+ private void DataPortal_Create()
+ {
+ }
+
+ [Execute]
+ private void DataPortal_Execute()
+ {
+ }
+ }
+
+ #endregion
+ }
+}