mirror of
https://github.com/Govor-team/Govor.git
synced 2026-07-21 11:44:56 +00:00
AppTests
This commit is contained in:
@@ -0,0 +1,59 @@
|
|||||||
|
using Govor.ConsoleClient.Services.Interfaces;
|
||||||
|
using Moq;
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient.Tests;
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
public class AppTests
|
||||||
|
{
|
||||||
|
private Mock<IInputPipeline> _inputPipelineMock = null!;
|
||||||
|
private Mock<ILogger> _loggerMock = null!;
|
||||||
|
private App _app = null!;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
_inputPipelineMock = new Mock<IInputPipeline>();
|
||||||
|
_loggerMock = new Mock<ILogger>();
|
||||||
|
|
||||||
|
_inputPipelineMock.Setup(f => f.ProcessInputAsync(It.IsAny<string>())).Returns(Task.CompletedTask);
|
||||||
|
|
||||||
|
_app = new App(_inputPipelineMock.Object, _loggerMock.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task RunAsync_PrintsTitleOnce()
|
||||||
|
{
|
||||||
|
using var sr = new StringReader("exit");
|
||||||
|
Console.SetIn(sr);
|
||||||
|
|
||||||
|
await _app.RunAsync();
|
||||||
|
|
||||||
|
_loggerMock.Verify(l => l.Title(It.Is<string>(s => s.Contains("Говор"))), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task RunAsync_CallsInputPipeline_ForEachInput()
|
||||||
|
{
|
||||||
|
var inputText = "hello\n/command\nexit";
|
||||||
|
using var sr = new StringReader(inputText);
|
||||||
|
Console.SetIn(sr);
|
||||||
|
|
||||||
|
await _app.RunAsync();
|
||||||
|
|
||||||
|
_inputPipelineMock.Verify(p => p.ProcessInputAsync("hello"), Times.Once);
|
||||||
|
_inputPipelineMock.Verify(p => p.ProcessInputAsync("/command"), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task RunAsync_StopsOnExit()
|
||||||
|
{
|
||||||
|
using var sr = new StringReader("exit");
|
||||||
|
Console.SetIn(sr);
|
||||||
|
|
||||||
|
await _app.RunAsync();
|
||||||
|
|
||||||
|
// Убедимся, что ProcessInputAsync вообще не вызывался
|
||||||
|
_inputPipelineMock.Verify(p => p.ProcessInputAsync(It.IsAny<string>()), Times.Never);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<IsTestProject>true</IsTestProject>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
|
||||||
|
<PackageReference Include="Moq" Version="4.20.72" />
|
||||||
|
<PackageReference Include="NUnit" Version="4.3.2" />
|
||||||
|
<PackageReference Include="NUnit.Analyzers" Version="3.9.0" />
|
||||||
|
<PackageReference Include="NUnit3TestAdapter" Version="5.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="NUnit.Framework" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Govor.ConsoleClient\Govor.ConsoleClient.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
using Govor.ConsoleClient.Commands;
|
||||||
|
using Govor.ConsoleClient.Services.Implementations;
|
||||||
|
using Govor.ConsoleClient.Services.Interfaces;
|
||||||
|
using Moq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient.Tests.Services.Implementations;
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
public class InputPipelineTests
|
||||||
|
{
|
||||||
|
private Mock<ICommandDispatcher> _commandDispatcherMock = null!;
|
||||||
|
private Mock<ILogger> _loggerMock = null!;
|
||||||
|
private InputPipeline _inputPipeline = null!;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void SetUp()
|
||||||
|
{
|
||||||
|
_commandDispatcherMock = new Mock<ICommandDispatcher>();
|
||||||
|
_loggerMock = new Mock<ILogger>();
|
||||||
|
|
||||||
|
_inputPipeline = new InputPipeline(_commandDispatcherMock.Object, _loggerMock.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task ProcessInputAsync_EmptyOrWhitespaceInput_DoesNothing()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
await _inputPipeline.ProcessInputAsync(null!);
|
||||||
|
await _inputPipeline.ProcessInputAsync("");
|
||||||
|
await _inputPipeline.ProcessInputAsync(" ");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
_commandDispatcherMock.Verify(d => d.DispatchAsync(It.IsAny<string>()), Times.Never);
|
||||||
|
_loggerMock.Verify(l => l.Info(It.IsAny<string>()), Times.Never);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task ProcessInputAsync_CommandInput_DispatchesCommandAndResetsActiveCommand()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var commandMock = new Mock<ICommand>();
|
||||||
|
_commandDispatcherMock
|
||||||
|
.Setup(d => d.DispatchAsync("testcmd"))
|
||||||
|
.ReturnsAsync(commandMock.Object);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await _inputPipeline.ProcessInputAsync("/testcmd");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
_commandDispatcherMock.Verify(d => d.DispatchAsync("testcmd"), Times.Once);
|
||||||
|
_loggerMock.Verify(l => l.Info(It.IsAny<string>()), Times.Never);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task ProcessInputAsync_CommandInput_IfInteractiveCommand_SetsActiveCommand()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var interactiveCommandMock = new Mock<IInteractiveCommand>();
|
||||||
|
interactiveCommandMock.SetupGet(c => c.IsCompleted).Returns(false);
|
||||||
|
_commandDispatcherMock
|
||||||
|
.Setup(d => d.DispatchAsync("interactive"))
|
||||||
|
.ReturnsAsync(interactiveCommandMock.Object);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await _inputPipeline.ProcessInputAsync("/interactive");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var activeCommandField = typeof(InputPipeline).GetField("_activeCommand", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||||
|
var activeCommandValue = activeCommandField!.GetValue(_inputPipeline);
|
||||||
|
Assert.That(activeCommandValue, Is.SameAs(interactiveCommandMock.Object));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task ProcessInputAsync_NonCommandInput_WithActiveInteractiveCommand_CallsHandleInputAsync()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var interactiveCommandMock = new Mock<IInteractiveCommand>();
|
||||||
|
interactiveCommandMock.SetupGet(c => c.IsCompleted).Returns(false);
|
||||||
|
interactiveCommandMock.Setup(c => c.HandleInputAsync("user input")).Returns(Task.CompletedTask);
|
||||||
|
|
||||||
|
var activeCommandField = typeof(InputPipeline).GetField("_activeCommand", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||||
|
activeCommandField!.SetValue(_inputPipeline, interactiveCommandMock.Object);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await _inputPipeline.ProcessInputAsync("user input");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
interactiveCommandMock.Verify(c => c.HandleInputAsync("user input"), Times.Once);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task ProcessInputAsync_NonCommandInput_WithActiveInteractiveCommand_ResetsActiveCommand_WhenCompleted()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var interactiveCommandMock = new Mock<IInteractiveCommand>();
|
||||||
|
interactiveCommandMock.SetupSequence(c => c.IsCompleted)
|
||||||
|
.Returns(false)
|
||||||
|
.Returns(true);
|
||||||
|
interactiveCommandMock.Setup(c => c.HandleInputAsync(It.IsAny<string>())).Returns(Task.CompletedTask);
|
||||||
|
|
||||||
|
var activeCommandField = typeof(InputPipeline).GetField("_activeCommand", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
||||||
|
activeCommandField!.SetValue(_inputPipeline, interactiveCommandMock.Object);
|
||||||
|
|
||||||
|
// Act & Assert 1
|
||||||
|
await _inputPipeline.ProcessInputAsync("input1");
|
||||||
|
Assert.That(interactiveCommandMock.Object, Is.SameAs(activeCommandField.GetValue(_inputPipeline)));
|
||||||
|
|
||||||
|
// Act & Assert 2
|
||||||
|
await _inputPipeline.ProcessInputAsync("input2");
|
||||||
|
Assert.That(activeCommandField.GetValue(_inputPipeline), Is.Null);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task ProcessInputAsync_NonCommandInput_WithoutActiveCommand_LogsInfo()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
await _inputPipeline.ProcessInputAsync("just text");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
_loggerMock.Verify(l => l.Info("Введите /help, чтобы узнать доступные команды!"), Times.Once);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
using Govor.ConsoleClient.Services;
|
using Govor.ConsoleClient.Services;
|
||||||
|
using Govor.ConsoleClient.Services.Interfaces;
|
||||||
|
|
||||||
namespace Govor.ConsoleClient;
|
namespace Govor.ConsoleClient;
|
||||||
|
|
||||||
public class App
|
public class App
|
||||||
{
|
{
|
||||||
private readonly InputPipeline _inputPipeline;
|
private readonly IInputPipeline _inputPipeline;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
public App(InputPipeline inputPipeline, ILogger logger)
|
public App(IInputPipeline inputPipeline, ILogger logger)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_inputPipeline = inputPipeline;
|
_inputPipeline = inputPipeline;
|
||||||
|
|||||||
@@ -1,22 +1,58 @@
|
|||||||
|
using System.Reflection;
|
||||||
using Govor.ConsoleClient.Services;
|
using Govor.ConsoleClient.Services;
|
||||||
|
using Govor.ConsoleClient.Services.Interfaces;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace Govor.ConsoleClient.Commands;
|
namespace Govor.ConsoleClient.Commands;
|
||||||
|
|
||||||
public class HelpCommand : ICommand
|
public class HelpCommand : ICommand
|
||||||
{
|
{
|
||||||
|
private readonly IServiceProvider _serviceProvider;
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
|
public HelpCommand(IServiceProvider serviceProvider, ILogger logger)
|
||||||
|
{
|
||||||
|
_serviceProvider = serviceProvider;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
public Task ExecuteAsync(CommandContext context)
|
public Task ExecuteAsync(CommandContext context)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Commands:");
|
var dispatcher = _serviceProvider.GetRequiredService<ICommandDispatcher>();
|
||||||
|
var commands = dispatcher.GetAllCommands();
|
||||||
|
|
||||||
|
if (context.Arguments is not null)
|
||||||
|
{
|
||||||
|
var command = commands.FirstOrDefault(c =>
|
||||||
|
(c.GetType().GetCustomAttribute<CommandRouteAttribute>()?.Path.Replace("/", "").ToLower()
|
||||||
|
?? c.GetType().Name.Replace("Command", "").ToLower()) == context.Arguments.ToLower());
|
||||||
|
|
||||||
|
if (command != null)
|
||||||
|
{
|
||||||
|
_logger.Info($"{context.Arguments} - {command.LongHelp()}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.Warn("Unknown command");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.Info("Чтобы получить подробную информацию, напишите /help {command}");
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var command in commands)
|
||||||
|
{
|
||||||
|
var name = command.GetType().GetCustomAttribute<CommandRouteAttribute>()?.Path.Replace("/", "").ToLower()
|
||||||
|
?? command.GetType().Name.Replace("Command", "").ToLower();
|
||||||
|
|
||||||
|
_logger.Log($"{name} - {command.ShortHelp()}");
|
||||||
|
}
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string LongHelp()
|
public string LongHelp() => "Необходима для получения информации о доступных командах\nЧтобы получить подробную информацию о команде, напишите /help {command}";
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public string ShortHelp()
|
public string ShortHelp() => "Необходима для получения информации о доступных командах";
|
||||||
{
|
}
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -39,6 +39,6 @@ public class SendMessageCommand : IInteractiveCommand
|
|||||||
|
|
||||||
public string ShortHelp()
|
public string ShortHelp()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
return "Отпарвка тестовых сообщений не существующему юзеру";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Govor.ConsoleClient.Commands;
|
using Govor.ConsoleClient.Commands;
|
||||||
using Govor.ConsoleClient.Services;
|
using Govor.ConsoleClient.Services;
|
||||||
|
using Govor.ConsoleClient.Services.Extensions;
|
||||||
|
using Govor.ConsoleClient.Services.Interfaces;
|
||||||
using Govor.ConsoleClient.Services.Middleware;
|
using Govor.ConsoleClient.Services.Middleware;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
@@ -16,12 +18,9 @@ public static class DependencyInjection
|
|||||||
services.AddCommands();
|
services.AddCommands();
|
||||||
|
|
||||||
// Сервисы
|
// Сервисы
|
||||||
services.AddSingleton<CommandDispatcher>();
|
services.AddApplicationServices();
|
||||||
services.AddSingleton<InputPipeline>();
|
|
||||||
services.AddSingleton<ConsoleLogger>();
|
|
||||||
services.AddSingleton<ILogger>(sp => sp.GetRequiredService<ConsoleLogger>());
|
|
||||||
services.AddSingleton<CommandContext>();
|
services.AddSingleton<CommandContext>();
|
||||||
services.AddSingleton<MiddlewarePipeline>();
|
|
||||||
|
|
||||||
// Middleware
|
// Middleware
|
||||||
services.AddSingleton<ICommandMiddleware, ExceptionHandlingMiddleware>();
|
services.AddSingleton<ICommandMiddleware, ExceptionHandlingMiddleware>();
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using Govor.ConsoleClient.Services.Implementations;
|
||||||
|
using Govor.ConsoleClient.Services.Interfaces;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient.Services.Extensions;
|
||||||
|
|
||||||
|
public static class ServiceCollectionExtensions
|
||||||
|
{
|
||||||
|
public static IServiceCollection AddApplicationServices(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddSingleton<IInputPipeline, InputPipeline>();
|
||||||
|
services.AddSingleton<ICommandDispatcher, CommandDispatcher>();
|
||||||
|
services.AddSingleton<IMiddlewarePipeline, MiddlewarePipeline>();
|
||||||
|
services.AddSingleton<ConsoleLogger>();
|
||||||
|
services.AddSingleton<ILogger>(sp => sp.GetRequiredService<ConsoleLogger>());
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
-4
@@ -1,15 +1,16 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Govor.ConsoleClient.Commands;
|
using Govor.ConsoleClient.Commands;
|
||||||
|
using Govor.ConsoleClient.Services.Interfaces;
|
||||||
|
|
||||||
namespace Govor.ConsoleClient.Services;
|
namespace Govor.ConsoleClient.Services.Implementations;
|
||||||
|
|
||||||
public class CommandDispatcher
|
public class CommandDispatcher : ICommandDispatcher
|
||||||
{
|
{
|
||||||
private readonly Dictionary<string, ICommand> _commands = new();
|
private readonly Dictionary<string, ICommand> _commands = new();
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly MiddlewarePipeline _pipeline;
|
private readonly IMiddlewarePipeline _pipeline;
|
||||||
|
|
||||||
public CommandDispatcher(IEnumerable<ICommand> commands, ILogger logger, MiddlewarePipeline pipeline)
|
public CommandDispatcher(IEnumerable<ICommand> commands, ILogger logger, IMiddlewarePipeline pipeline)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_pipeline = pipeline;
|
_pipeline = pipeline;
|
||||||
@@ -38,4 +39,6 @@ public class CommandDispatcher
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerable<ICommand> GetAllCommands() => _commands.Values;
|
||||||
}
|
}
|
||||||
+3
-1
@@ -1,4 +1,6 @@
|
|||||||
namespace Govor.ConsoleClient.Services;
|
using Govor.ConsoleClient.Services.Interfaces;
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient.Services.Implementations;
|
||||||
|
|
||||||
public class ConsoleLogger : ILogger
|
public class ConsoleLogger : ILogger
|
||||||
{
|
{
|
||||||
+8
-7
@@ -1,14 +1,15 @@
|
|||||||
using Govor.ConsoleClient.Commands;
|
using Govor.ConsoleClient.Commands;
|
||||||
|
using Govor.ConsoleClient.Services.Interfaces;
|
||||||
|
|
||||||
namespace Govor.ConsoleClient.Services;
|
namespace Govor.ConsoleClient.Services.Implementations;
|
||||||
|
|
||||||
public class InputPipeline
|
public class InputPipeline : IInputPipeline
|
||||||
{
|
{
|
||||||
private readonly CommandDispatcher _dispatcher;
|
private readonly ICommandDispatcher _dispatcher;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private IInteractiveCommand? _activeCommand;
|
private IInteractiveCommand? _activeCommand;
|
||||||
|
|
||||||
public InputPipeline(CommandDispatcher dispatcher, ILogger logger)
|
public InputPipeline(ICommandDispatcher dispatcher, ILogger logger)
|
||||||
{
|
{
|
||||||
_dispatcher = dispatcher;
|
_dispatcher = dispatcher;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
@@ -20,12 +21,12 @@ public class InputPipeline
|
|||||||
|
|
||||||
if (input.StartsWith("/"))
|
if (input.StartsWith("/"))
|
||||||
{
|
{
|
||||||
_activeCommand = null; // Сброс активной команды
|
_activeCommand = null;
|
||||||
|
|
||||||
var commandInput = input[1..];
|
var commandInput = input[1..];
|
||||||
var result = await _dispatcher.DispatchAsync(commandInput);
|
var result = await _dispatcher.DispatchAsync(commandInput);
|
||||||
|
|
||||||
// Если команда поддерживает интерактивность, сохраняем как активную
|
// If the command supports interactivity, save it as active
|
||||||
if (result is IInteractiveCommand interactiveCommand && !interactiveCommand.IsCompleted)
|
if (result is IInteractiveCommand interactiveCommand && !interactiveCommand.IsCompleted)
|
||||||
{
|
{
|
||||||
_activeCommand = interactiveCommand;
|
_activeCommand = interactiveCommand;
|
||||||
@@ -42,7 +43,7 @@ public class InputPipeline
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.Info($"[Ввод пользователя]: {input}");
|
_logger.Info($"Введите /help, чтобы узнать доступные команды!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+3
-2
@@ -1,10 +1,11 @@
|
|||||||
|
using Govor.ConsoleClient.Services.Interfaces;
|
||||||
using Govor.ConsoleClient.Services.Middleware;
|
using Govor.ConsoleClient.Services.Middleware;
|
||||||
|
|
||||||
namespace Govor.ConsoleClient.Services;
|
namespace Govor.ConsoleClient.Services.Implementations;
|
||||||
|
|
||||||
public delegate Task CommandMiddleware(CommandContext context, Func<Task> next);
|
public delegate Task CommandMiddleware(CommandContext context, Func<Task> next);
|
||||||
|
|
||||||
public class MiddlewarePipeline
|
public class MiddlewarePipeline : IMiddlewarePipeline
|
||||||
{
|
{
|
||||||
private readonly IList<ICommandMiddleware> _middlewares;
|
private readonly IList<ICommandMiddleware> _middlewares;
|
||||||
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
using Govor.ConsoleClient.Commands;
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient.Services.Interfaces;
|
||||||
|
|
||||||
|
public interface ICommandDispatcher
|
||||||
|
{
|
||||||
|
Task<ICommand?> DispatchAsync(string input);
|
||||||
|
IEnumerable<ICommand> GetAllCommands();
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Govor.ConsoleClient.Services.Interfaces;
|
||||||
|
|
||||||
|
public interface IInputPipeline
|
||||||
|
{
|
||||||
|
Task ProcessInputAsync(string input);
|
||||||
|
}
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
namespace Govor.ConsoleClient.Services;
|
namespace Govor.ConsoleClient.Services.Interfaces;
|
||||||
|
|
||||||
public interface ILogger
|
public interface ILogger
|
||||||
{
|
{
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Govor.ConsoleClient.Services.Interfaces;
|
||||||
|
|
||||||
|
public interface IMiddlewarePipeline
|
||||||
|
{
|
||||||
|
Task ExecuteAsync(CommandContext context);
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using Govor.ConsoleClient.Services.Interfaces;
|
||||||
|
|
||||||
namespace Govor.ConsoleClient.Services.Middleware;
|
namespace Govor.ConsoleClient.Services.Middleware;
|
||||||
|
|
||||||
public class ExceptionHandlingMiddleware : ICommandMiddleware
|
public class ExceptionHandlingMiddleware : ICommandMiddleware
|
||||||
@@ -17,7 +19,7 @@ public class ExceptionHandlingMiddleware : ICommandMiddleware
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.Error($"Произошла ошибка при выполнении команды '{context.Route}': {ex.Message}");
|
_logger.Error($"Произошла ошибка при выполнении команды '{context?.Route}': {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"BaseUrl": "https://govor-team-govor-88b3.twc1.net"
|
||||||
|
}
|
||||||
@@ -25,6 +25,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Govor.Application.Tests", "
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Govor.Data.Tests", "Govor.Data.Tests\Govor.Data.Tests.csproj", "{CF6B23EC-932A-4998-BA95-C94CAB7B092C}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Govor.Data.Tests", "Govor.Data.Tests\Govor.Data.Tests.csproj", "{CF6B23EC-932A-4998-BA95-C94CAB7B092C}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Govor.ConsoleClient.Tests", "Govor.ConsoleClient.Tests\Govor.ConsoleClient.Tests.csproj", "{B1E79EB6-DBD3-4E82-AB6D-DCFCE6533965}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -67,6 +69,10 @@ Global
|
|||||||
{CF6B23EC-932A-4998-BA95-C94CAB7B092C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{CF6B23EC-932A-4998-BA95-C94CAB7B092C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{CF6B23EC-932A-4998-BA95-C94CAB7B092C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{CF6B23EC-932A-4998-BA95-C94CAB7B092C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{CF6B23EC-932A-4998-BA95-C94CAB7B092C}.Release|Any CPU.Build.0 = Release|Any CPU
|
{CF6B23EC-932A-4998-BA95-C94CAB7B092C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{B1E79EB6-DBD3-4E82-AB6D-DCFCE6533965}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{B1E79EB6-DBD3-4E82-AB6D-DCFCE6533965}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{B1E79EB6-DBD3-4E82-AB6D-DCFCE6533965}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{B1E79EB6-DBD3-4E82-AB6D-DCFCE6533965}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(NestedProjects) = preSolution
|
GlobalSection(NestedProjects) = preSolution
|
||||||
{15031CBD-F319-4755-BA91-B86F20BD8E37} = {4ED5259A-6FB4-4D89-8E6B-4778DC68F7D4}
|
{15031CBD-F319-4755-BA91-B86F20BD8E37} = {4ED5259A-6FB4-4D89-8E6B-4778DC68F7D4}
|
||||||
@@ -78,5 +84,6 @@ Global
|
|||||||
{FC5EDCA8-FD58-4078-8FB1-2BDBB2F6CA3E} = {114F53C1-B0AB-4BA0-9E36-0E811D1B3776}
|
{FC5EDCA8-FD58-4078-8FB1-2BDBB2F6CA3E} = {114F53C1-B0AB-4BA0-9E36-0E811D1B3776}
|
||||||
{F56A64DF-2938-4BE0-83F2-B86429F19259} = {4ED5259A-6FB4-4D89-8E6B-4778DC68F7D4}
|
{F56A64DF-2938-4BE0-83F2-B86429F19259} = {4ED5259A-6FB4-4D89-8E6B-4778DC68F7D4}
|
||||||
{CF6B23EC-932A-4998-BA95-C94CAB7B092C} = {4ED5259A-6FB4-4D89-8E6B-4778DC68F7D4}
|
{CF6B23EC-932A-4998-BA95-C94CAB7B092C} = {4ED5259A-6FB4-4D89-8E6B-4778DC68F7D4}
|
||||||
|
{B1E79EB6-DBD3-4E82-AB6D-DCFCE6533965} = {4ED5259A-6FB4-4D89-8E6B-4778DC68F7D4}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|||||||
Reference in New Issue
Block a user