From 4c355ae83d79692fe376609bf4f17f9ad132a5b4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=93=D0=B5=D1=80=D0=B0=D1=81=D0=B8=D0=BC=D0=BE=D0=B2=20?=
 =?UTF-8?q?=D0=A1=D0=B5=D1=80=D0=B3=D0=B5=D0=B9=20=D0=9F=D0=B0=D0=B2=D0=BB?=
 =?UTF-8?q?=D0=BE=D0=B2=D0=B8=D1=87?= <s.gerasimov.2023@stud.nstu.ru>
Date: Fri, 21 Feb 2025 15:21:12 +0700
Subject: [PATCH 1/2] Add initial project structure with Command pattern
 implementation and unit tests

---
 Lab1.sln                                | 13 +++++++
 Lab1/Lab1.csproj                        |  4 +++
 Lab1/MainActivity.cs                    |  1 +
 Lab1/Program.cs                         |  3 --
 UI.Tests/Domain/CommandTest.cs          | 47 +++++++++++++++++++++++++
 UI/Data/Service/HelloCommandExecutor.cs | 11 ++++++
 UI/Domain/Command.cs                    | 26 ++++++++++++++
 UI/Domain/ICommandExecutor.cs           |  6 ++++
 UI/UI.csproj                            | 10 ++++++
 9 files changed, 118 insertions(+), 3 deletions(-)
 create mode 100644 Lab1/MainActivity.cs
 delete mode 100644 Lab1/Program.cs
 create mode 100644 UI.Tests/Domain/CommandTest.cs
 create mode 100644 UI/Data/Service/HelloCommandExecutor.cs
 create mode 100644 UI/Domain/Command.cs
 create mode 100644 UI/Domain/ICommandExecutor.cs
 create mode 100644 UI/UI.csproj

diff --git a/Lab1.sln b/Lab1.sln
index f707e5c..f73fd1b 100644
--- a/Lab1.sln
+++ b/Lab1.sln
@@ -1,7 +1,12 @@
 п»ї
 Microsoft Visual Studio Solution File, Format Version 12.00
+#
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lab1", "Lab1\Lab1.csproj", "{2851C4FA-47FB-4B7B-A7F2-229EC08CA36C}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UI", "UI\UI.csproj", "{B0D69506-EF6C-4C37-B3E6-6D02EF1C8E14}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UI.Tests", "UI.Tests\UI.Tests.csproj", "{CFFBE5D7-BC91-4994-9BE4-0795E02E3EE7}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -12,5 +17,13 @@ Global
 		{2851C4FA-47FB-4B7B-A7F2-229EC08CA36C}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{2851C4FA-47FB-4B7B-A7F2-229EC08CA36C}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{2851C4FA-47FB-4B7B-A7F2-229EC08CA36C}.Release|Any CPU.Build.0 = Release|Any CPU
+		{B0D69506-EF6C-4C37-B3E6-6D02EF1C8E14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{B0D69506-EF6C-4C37-B3E6-6D02EF1C8E14}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{B0D69506-EF6C-4C37-B3E6-6D02EF1C8E14}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{B0D69506-EF6C-4C37-B3E6-6D02EF1C8E14}.Release|Any CPU.Build.0 = Release|Any CPU
+		{CFFBE5D7-BC91-4994-9BE4-0795E02E3EE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CFFBE5D7-BC91-4994-9BE4-0795E02E3EE7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CFFBE5D7-BC91-4994-9BE4-0795E02E3EE7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CFFBE5D7-BC91-4994-9BE4-0795E02E3EE7}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 EndGlobal
diff --git a/Lab1/Lab1.csproj b/Lab1/Lab1.csproj
index 85b4959..ab750dc 100644
--- a/Lab1/Lab1.csproj
+++ b/Lab1/Lab1.csproj
@@ -1,5 +1,9 @@
 п»ї<Project Sdk="Microsoft.NET.Sdk">
 
+    <ItemGroup>
+      <ProjectReference Include="..\UI\UI.csproj" />
+    </ItemGroup>
+
     <PropertyGroup>
         <OutputType>Exe</OutputType>
         <TargetFramework>net9.0</TargetFramework>
diff --git a/Lab1/MainActivity.cs b/Lab1/MainActivity.cs
new file mode 100644
index 0000000..5f28270
--- /dev/null
+++ b/Lab1/MainActivity.cs
@@ -0,0 +1 @@
+п»ї
\ No newline at end of file
diff --git a/Lab1/Program.cs b/Lab1/Program.cs
deleted file mode 100644
index e5dff12..0000000
--- a/Lab1/Program.cs
+++ /dev/null
@@ -1,3 +0,0 @@
-п»ї// See https://aka.ms/new-console-template for more information
-
-Console.WriteLine("Hello, World!");
\ No newline at end of file
diff --git a/UI.Tests/Domain/CommandTest.cs b/UI.Tests/Domain/CommandTest.cs
new file mode 100644
index 0000000..d0f704c
--- /dev/null
+++ b/UI.Tests/Domain/CommandTest.cs
@@ -0,0 +1,47 @@
+using System.Collections.Generic;
+using JetBrains.Annotations;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using UI.Data.Service;
+using UI.Domain;
+using System;
+using Moq;
+
+namespace UI.Tests.Domain;
+
+[TestClass]
+[TestSubject(typeof(Command))]
+public class CommandTests
+{
+    [TestMethod]
+    public void Execute_CallsOnCommand_WhenNameMatches()
+    {
+        var mockExecutor = new Mock<ICommandExecutor>();
+        var command = new Command("test", mockExecutor.Object);
+        var args = new[] { "test", "arg1", "arg2" };
+
+        command.Execute(args);
+
+        mockExecutor.Verify(e => e.onCommand("test", new[] { "arg1", "arg2" }), Times.Once);
+    }
+
+    [TestMethod]
+    public void Execute_DoesNotCallOnCommand_WhenNameDoesNotMatch()
+    {
+        var mockExecutor = new Mock<ICommandExecutor>();
+        var command = new Command("test", mockExecutor.Object);
+        var args = new[] { "wrong", "arg1", "arg2" };
+
+        command.Execute(args);
+
+        mockExecutor.Verify(e => e.onCommand(It.IsAny<string>(), It.IsAny<string[]>()), Times.Never);
+    }
+
+    [TestMethod]
+    public void Execute_DoesNotThrow_WhenArgsIsEmpty()
+    {
+        var mockExecutor = new Mock<ICommandExecutor>();
+        var command = new Command("", mockExecutor.Object);
+        var args = Array.Empty<string>();
+        command.Execute(args);
+    }
+}
\ No newline at end of file
diff --git a/UI/Data/Service/HelloCommandExecutor.cs b/UI/Data/Service/HelloCommandExecutor.cs
new file mode 100644
index 0000000..6d3f32c
--- /dev/null
+++ b/UI/Data/Service/HelloCommandExecutor.cs
@@ -0,0 +1,11 @@
+using UI.Domain;
+
+namespace UI.Data.Service;
+
+public class HelloCommandExecutor : ICommandExecutor
+{
+    public void onCommand(string command, string[] args)
+    {
+        Console.WriteLine("Hello");
+    }
+}
\ No newline at end of file
diff --git a/UI/Domain/Command.cs b/UI/Domain/Command.cs
new file mode 100644
index 0000000..083cae2
--- /dev/null
+++ b/UI/Domain/Command.cs
@@ -0,0 +1,26 @@
+namespace UI.Domain;
+
+public class Command
+{
+    private readonly ICommandExecutor _commandExecutor;
+    private string _name;
+
+    public Command(string name, ICommandExecutor commandExecutor)
+    {
+        _commandExecutor = commandExecutor;
+        Name = name;
+    }
+
+    public string Name
+    {
+        get => _name;
+        set => _name = value;
+    }
+
+    public void Execute(string[] args)
+    {
+        if (!args[0].Equals(Name)) return;
+        var argsWithoutCommand = args.Skip(1).ToArray();
+        _commandExecutor.onCommand(Name, argsWithoutCommand);
+    }
+}
\ No newline at end of file
diff --git a/UI/Domain/ICommandExecutor.cs b/UI/Domain/ICommandExecutor.cs
new file mode 100644
index 0000000..76bb4e3
--- /dev/null
+++ b/UI/Domain/ICommandExecutor.cs
@@ -0,0 +1,6 @@
+namespace UI.Domain;
+
+public interface ICommandExecutor
+{
+    void onCommand(string command, string[] args);
+}
\ No newline at end of file
diff --git a/UI/UI.csproj b/UI/UI.csproj
new file mode 100644
index 0000000..29d8b08
--- /dev/null
+++ b/UI/UI.csproj
@@ -0,0 +1,10 @@
+п»ї<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net9.0</TargetFramework>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <Nullable>enable</Nullable>
+    <RootNamespace>UI</RootNamespace>
+  </PropertyGroup>
+
+</Project>
-- 
GitLab


From 591d29f83d47e26f7b9252d65fe51b6180e0d12d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=93=D0=B5=D1=80=D0=B0=D1=81=D0=B8=D0=BC=D0=BE=D0=B2=20?=
 =?UTF-8?q?=D0=A1=D0=B5=D1=80=D0=B3=D0=B5=D0=B9=20=D0=9F=D0=B0=D0=B2=D0=BB?=
 =?UTF-8?q?=D0=BE=D0=B2=D0=B8=D1=87?= <s.gerasimov.2023@stud.nstu.ru>
Date: Fri, 21 Feb 2025 15:21:12 +0700
Subject: [PATCH 2/2] Added UI.Tests.csproj

---
 Lab1.sln                                | 13 +++++++
 Lab1/Lab1.csproj                        |  4 +++
 Lab1/MainActivity.cs                    |  1 +
 Lab1/Program.cs                         |  3 --
 UI.Tests/Domain/CommandTest.cs          | 47 +++++++++++++++++++++++++
 UI.Tests/UI.Tests.csproj                | 21 +++++++++++
 UI/Data/Service/HelloCommandExecutor.cs | 11 ++++++
 UI/Domain/Command.cs                    | 26 ++++++++++++++
 UI/Domain/ICommandExecutor.cs           |  6 ++++
 UI/UI.csproj                            | 10 ++++++
 10 files changed, 139 insertions(+), 3 deletions(-)
 create mode 100644 Lab1/MainActivity.cs
 delete mode 100644 Lab1/Program.cs
 create mode 100644 UI.Tests/Domain/CommandTest.cs
 create mode 100644 UI.Tests/UI.Tests.csproj
 create mode 100644 UI/Data/Service/HelloCommandExecutor.cs
 create mode 100644 UI/Domain/Command.cs
 create mode 100644 UI/Domain/ICommandExecutor.cs
 create mode 100644 UI/UI.csproj

diff --git a/Lab1.sln b/Lab1.sln
index f707e5c..f73fd1b 100644
--- a/Lab1.sln
+++ b/Lab1.sln
@@ -1,7 +1,12 @@
 п»ї
 Microsoft Visual Studio Solution File, Format Version 12.00
+#
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lab1", "Lab1\Lab1.csproj", "{2851C4FA-47FB-4B7B-A7F2-229EC08CA36C}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UI", "UI\UI.csproj", "{B0D69506-EF6C-4C37-B3E6-6D02EF1C8E14}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UI.Tests", "UI.Tests\UI.Tests.csproj", "{CFFBE5D7-BC91-4994-9BE4-0795E02E3EE7}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -12,5 +17,13 @@ Global
 		{2851C4FA-47FB-4B7B-A7F2-229EC08CA36C}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{2851C4FA-47FB-4B7B-A7F2-229EC08CA36C}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{2851C4FA-47FB-4B7B-A7F2-229EC08CA36C}.Release|Any CPU.Build.0 = Release|Any CPU
+		{B0D69506-EF6C-4C37-B3E6-6D02EF1C8E14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{B0D69506-EF6C-4C37-B3E6-6D02EF1C8E14}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{B0D69506-EF6C-4C37-B3E6-6D02EF1C8E14}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{B0D69506-EF6C-4C37-B3E6-6D02EF1C8E14}.Release|Any CPU.Build.0 = Release|Any CPU
+		{CFFBE5D7-BC91-4994-9BE4-0795E02E3EE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CFFBE5D7-BC91-4994-9BE4-0795E02E3EE7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CFFBE5D7-BC91-4994-9BE4-0795E02E3EE7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CFFBE5D7-BC91-4994-9BE4-0795E02E3EE7}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 EndGlobal
diff --git a/Lab1/Lab1.csproj b/Lab1/Lab1.csproj
index 85b4959..ab750dc 100644
--- a/Lab1/Lab1.csproj
+++ b/Lab1/Lab1.csproj
@@ -1,5 +1,9 @@
 п»ї<Project Sdk="Microsoft.NET.Sdk">
 
+    <ItemGroup>
+      <ProjectReference Include="..\UI\UI.csproj" />
+    </ItemGroup>
+
     <PropertyGroup>
         <OutputType>Exe</OutputType>
         <TargetFramework>net9.0</TargetFramework>
diff --git a/Lab1/MainActivity.cs b/Lab1/MainActivity.cs
new file mode 100644
index 0000000..5f28270
--- /dev/null
+++ b/Lab1/MainActivity.cs
@@ -0,0 +1 @@
+п»ї
\ No newline at end of file
diff --git a/Lab1/Program.cs b/Lab1/Program.cs
deleted file mode 100644
index e5dff12..0000000
--- a/Lab1/Program.cs
+++ /dev/null
@@ -1,3 +0,0 @@
-п»ї// See https://aka.ms/new-console-template for more information
-
-Console.WriteLine("Hello, World!");
\ No newline at end of file
diff --git a/UI.Tests/Domain/CommandTest.cs b/UI.Tests/Domain/CommandTest.cs
new file mode 100644
index 0000000..d0f704c
--- /dev/null
+++ b/UI.Tests/Domain/CommandTest.cs
@@ -0,0 +1,47 @@
+using System.Collections.Generic;
+using JetBrains.Annotations;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using UI.Data.Service;
+using UI.Domain;
+using System;
+using Moq;
+
+namespace UI.Tests.Domain;
+
+[TestClass]
+[TestSubject(typeof(Command))]
+public class CommandTests
+{
+    [TestMethod]
+    public void Execute_CallsOnCommand_WhenNameMatches()
+    {
+        var mockExecutor = new Mock<ICommandExecutor>();
+        var command = new Command("test", mockExecutor.Object);
+        var args = new[] { "test", "arg1", "arg2" };
+
+        command.Execute(args);
+
+        mockExecutor.Verify(e => e.onCommand("test", new[] { "arg1", "arg2" }), Times.Once);
+    }
+
+    [TestMethod]
+    public void Execute_DoesNotCallOnCommand_WhenNameDoesNotMatch()
+    {
+        var mockExecutor = new Mock<ICommandExecutor>();
+        var command = new Command("test", mockExecutor.Object);
+        var args = new[] { "wrong", "arg1", "arg2" };
+
+        command.Execute(args);
+
+        mockExecutor.Verify(e => e.onCommand(It.IsAny<string>(), It.IsAny<string[]>()), Times.Never);
+    }
+
+    [TestMethod]
+    public void Execute_DoesNotThrow_WhenArgsIsEmpty()
+    {
+        var mockExecutor = new Mock<ICommandExecutor>();
+        var command = new Command("", mockExecutor.Object);
+        var args = Array.Empty<string>();
+        command.Execute(args);
+    }
+}
\ No newline at end of file
diff --git a/UI.Tests/UI.Tests.csproj b/UI.Tests/UI.Tests.csproj
new file mode 100644
index 0000000..923536d
--- /dev/null
+++ b/UI.Tests/UI.Tests.csproj
@@ -0,0 +1,21 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFrameworks>net9.0</TargetFrameworks>
+    
+    <IsPackable>false</IsPackable>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="JetBrains.Annotations" Version="2025.1.0-eap1" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
+    <PackageReference Include="Moq" Version="4.20.72" />
+    <PackageReference Include="MSTest.TestAdapter" Version="3.8.2" />
+    <PackageReference Include="MSTest.TestFramework" Version="3.8.2" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\UI\UI.csproj" />
+  </ItemGroup>
+  
+</Project>
\ No newline at end of file
diff --git a/UI/Data/Service/HelloCommandExecutor.cs b/UI/Data/Service/HelloCommandExecutor.cs
new file mode 100644
index 0000000..6d3f32c
--- /dev/null
+++ b/UI/Data/Service/HelloCommandExecutor.cs
@@ -0,0 +1,11 @@
+using UI.Domain;
+
+namespace UI.Data.Service;
+
+public class HelloCommandExecutor : ICommandExecutor
+{
+    public void onCommand(string command, string[] args)
+    {
+        Console.WriteLine("Hello");
+    }
+}
\ No newline at end of file
diff --git a/UI/Domain/Command.cs b/UI/Domain/Command.cs
new file mode 100644
index 0000000..083cae2
--- /dev/null
+++ b/UI/Domain/Command.cs
@@ -0,0 +1,26 @@
+namespace UI.Domain;
+
+public class Command
+{
+    private readonly ICommandExecutor _commandExecutor;
+    private string _name;
+
+    public Command(string name, ICommandExecutor commandExecutor)
+    {
+        _commandExecutor = commandExecutor;
+        Name = name;
+    }
+
+    public string Name
+    {
+        get => _name;
+        set => _name = value;
+    }
+
+    public void Execute(string[] args)
+    {
+        if (!args[0].Equals(Name)) return;
+        var argsWithoutCommand = args.Skip(1).ToArray();
+        _commandExecutor.onCommand(Name, argsWithoutCommand);
+    }
+}
\ No newline at end of file
diff --git a/UI/Domain/ICommandExecutor.cs b/UI/Domain/ICommandExecutor.cs
new file mode 100644
index 0000000..76bb4e3
--- /dev/null
+++ b/UI/Domain/ICommandExecutor.cs
@@ -0,0 +1,6 @@
+namespace UI.Domain;
+
+public interface ICommandExecutor
+{
+    void onCommand(string command, string[] args);
+}
\ No newline at end of file
diff --git a/UI/UI.csproj b/UI/UI.csproj
new file mode 100644
index 0000000..29d8b08
--- /dev/null
+++ b/UI/UI.csproj
@@ -0,0 +1,10 @@
+п»ї<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net9.0</TargetFramework>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <Nullable>enable</Nullable>
+    <RootNamespace>UI</RootNamespace>
+  </PropertyGroup>
+
+</Project>
-- 
GitLab