Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding tests #5

Merged
merged 4 commits into from
Apr 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Joba.IBM.RPA.Cli/Joba.IBM.RPA.Cli.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
</PropertyGroup>
<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
<_Parameter1>$(AssemblyName).Tests</_Parameter1>
<_Parameter1>Joba.IBM.RPA.Cli.Tests</_Parameter1>
</AssemblyAttribute>
</ItemGroup>

Expand Down
22 changes: 20 additions & 2 deletions src/Joba.IBM.RPA.Cli/Package/PackageCommand.Install.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,29 @@ public InstallPackageCommand() : base(CommandName, "Installs packages")
private async Task HandleAsync(string name, int? version, string? sourceAlias, ILogger<InstallPackageCommand> logger,
IPackageManagerFactory packageManagerFactory, IProject project, InvocationContext context)
{
var cancellation = context.GetCancellationToken();
var handler = new InstallPackageHandler(logger, project, packageManagerFactory);
await handler.HandleAsync(name, version, sourceAlias, context.GetCancellationToken());
}
}

internal class InstallPackageHandler
{
private readonly ILogger logger;
private readonly IProject project;
private readonly IPackageManagerFactory packageManagerFactory;

public InstallPackageHandler(ILogger logger, IProject project, IPackageManagerFactory packageManagerFactory)
{
this.logger = logger;
this.project = project;
this.packageManagerFactory = packageManagerFactory;
}

internal async Task HandleAsync(string name, int? version, string? sourceAlias, CancellationToken cancellation)
{
var pattern = new NamePattern(name);
if (pattern.HasWildcard && version.HasValue)
throw new Exception($"You cannot specify the version if you're using '*' in the package name.");
throw new PackageException(pattern.ToString(), $"You cannot specify the version if you're using '*' in the package name.");

var manager = packageManagerFactory.Create(project, sourceAlias);
if (version.HasValue)
Expand Down
28 changes: 25 additions & 3 deletions src/Joba.IBM.RPA.Cli/Package/PackageCommand.Source.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.Extensions.Logging;
using Polly;

namespace Joba.IBM.RPA.Cli
{
Expand Down Expand Up @@ -33,14 +34,35 @@ public PackageSourceCommand() : base(CommandName, "Adds a package source")

private async Task HandleAsync(RemoteOptions options, ILogger<PackageSourceCommand> logger, IRpaClientFactory clientFactory,
IProject project, InvocationContext context)
{
var handler = new AddPackageSourceHandler(logger, project, context.Console, clientFactory);
await handler.HandleAsync(options, context.GetCancellationToken());
}
}

internal class AddPackageSourceHandler
{
private readonly ILogger logger;
private readonly IConsole console;
private readonly IProject project;
private readonly IRpaClientFactory clientFactory;

public AddPackageSourceHandler(ILogger logger, IProject project, IConsole console, IRpaClientFactory clientFactory)
{
this.logger = logger;
this.console = console;
this.project = project;
this.clientFactory = clientFactory;
}

internal async Task HandleAsync(RemoteOptions options, CancellationToken cancellation)
{
project.EnsureCanConfigure(options.Alias);
var cancellation = context.GetCancellationToken();
var regionSelector = new RegionSelector(context.Console, clientFactory, project);
var regionSelector = new RegionSelector(console, clientFactory, project);
var region = await regionSelector.SelectAsync(options.Address, options.RegionName, cancellation);

using var client = clientFactory.CreateFromRegion(region);
var accountSelector = new AccountSelector(context.Console, client.Account);
var accountSelector = new AccountSelector(console, client.Account);
var credentials = await accountSelector.SelectAsync(options.UserName, options.TenantCode, options.Password, cancellation);

var package = await project.PackageSources.AddAsync(client.Account, options.Alias, region, credentials, cancellation);
Expand Down
35 changes: 27 additions & 8 deletions src/Joba.IBM.RPA.Cli/Robot/RobotCommand.New.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.Extensions.Logging;
using System.Reflection;
using static Joba.IBM.RPA.Cli.ProjectCommand;

namespace Joba.IBM.RPA.Cli
{
Expand Down Expand Up @@ -27,16 +28,34 @@ private async Task HandleAsync(WalFileName name, string templateName, ILogger<Ro
{
var cancellation = context.GetCancellationToken();

if (project.Robots.Exists(name))
throw new InvalidOperationException($"Bot named '{name}' already exists.");
var handler = new NewRobotHandler(logger, project);
await handler.HandleAsync(name, templateName, context.GetCancellationToken());
}

internal class NewRobotHandler
{
private readonly ILogger logger;
private readonly IProject project;

public NewRobotHandler(ILogger logger, IProject project)
{
this.logger = logger;
this.project = project;
}

internal async Task HandleAsync(WalFileName name, string templateName, CancellationToken cancellation)
{
if (project.Robots.Exists(name.WithoutExtension))
throw new ProjectException($"Robot named '{name}' already exists.");

var template = new TemplateFactory(project.WorkingDirectory, Assembly.GetExecutingAssembly());
_ = await template.CreateAsync(name, templateName, cancellation);
var settings = RobotSettingsFactory.Create(templateName);
project.Robots.Add(name.WithoutExtension, settings);
var template = new TemplateFactory(project.WorkingDirectory, Assembly.GetExecutingAssembly());
_ = await template.CreateAsync(name, templateName, cancellation);
var settings = RobotSettingsFactory.Create(templateName, name.WithoutExtension);
project.Robots.Add(name.WithoutExtension, settings);

await project.SaveAsync(cancellation);
logger.LogInformation("Bot '{Bot}' created successfully based on '{Template}' template", name, templateName);
await project.SaveAsync(cancellation);
logger.LogInformation("Bot '{Bot}' created successfully based on '{Template}' template", name, templateName);
}
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions src/Joba.IBM.RPA.sln
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Joba.IBM.RPA.Tests", "Tests
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{165BDDAD-6020-41E0-98BF-219C9B05187E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Joba.IBM.RPA.Cli.Tests", "Tests\Joba.IBM.RPA.Cli.Tests\Joba.IBM.RPA.Cli.Tests.csproj", "{049D591E-71D2-4042-B73A-F929E067CAD5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -29,12 +31,17 @@ Global
{3BC3EC59-576D-4926-B38C-028A02283282}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3BC3EC59-576D-4926-B38C-028A02283282}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3BC3EC59-576D-4926-B38C-028A02283282}.Release|Any CPU.Build.0 = Release|Any CPU
{049D591E-71D2-4042-B73A-F929E067CAD5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{049D591E-71D2-4042-B73A-F929E067CAD5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{049D591E-71D2-4042-B73A-F929E067CAD5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{049D591E-71D2-4042-B73A-F929E067CAD5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{3BC3EC59-576D-4926-B38C-028A02283282} = {165BDDAD-6020-41E0-98BF-219C9B05187E}
{049D591E-71D2-4042-B73A-F929E067CAD5} = {165BDDAD-6020-41E0-98BF-219C9B05187E}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {21E0AAC9-AF2C-4B31-BEA6-F4208399F573}
Expand Down
4 changes: 4 additions & 0 deletions src/Joba.IBM.RPA/Environment/ParameterRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,9 @@ void ILocalRepository<Parameter>.Update(Parameter parameter)

public IEnumerator<Parameter> GetEnumerator() => mappings.Values.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
int ICollection.Count => mappings.Count;
bool ICollection.IsSynchronized => false;
object ICollection.SyncRoot => this;
void ICollection.CopyTo(Array array, int index) => mappings.CopyTo((KeyValuePair<string, Parameter>[])array, index);
}
}
2 changes: 1 addition & 1 deletion src/Joba.IBM.RPA/ILocalRepository.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace Joba.IBM.RPA
{
public interface ILocalRepository<T> : IEnumerable<T> where T : class
public interface ILocalRepository<T> : IEnumerable<T>, ICollection where T : class
{
void AddOrUpdate(params T[] items);
void Update(T item);
Expand Down
5 changes: 4 additions & 1 deletion src/Joba.IBM.RPA/Joba.IBM.RPA.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@
<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
<_Parameter1>$(AssemblyName).Tests</_Parameter1>
</AssemblyAttribute>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
<_Parameter1>DynamicProxyGenAssembly2</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Snippets\InjectDependencies.definitions.snippet" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Reflection;
using System.Text.Json.Serialization.Metadata;
using System.Linq;

namespace Joba.IBM.RPA
{
Expand All @@ -14,10 +15,18 @@ public override JsonTypeInfo GetTypeInfo(Type type, JsonSerializerOptions option
ConfigureConstructor(info);
ConfigureProperties(info, options);
}

SkipEmptyCollections(info);
return info;
}

protected virtual void ConfigureConstructor(JsonTypeInfo info)
private static void SkipEmptyCollections(JsonTypeInfo info)
{
foreach (var property in info.Properties.Where(property => typeof(ICollection).IsAssignableFrom(property.PropertyType)))
property.ShouldSerialize = (_, value) => value is ICollection collection && collection.Count > 0;
}

private static void ConfigureConstructor(JsonTypeInfo info)
{
var ctor = info.Type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, Type.EmptyTypes);
if (ctor != null)
Expand Down
1 change: 1 addition & 0 deletions src/Joba.IBM.RPA/Json/JsonSerializerOptionsFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ internal static JsonSerializerOptions CreateDefault()
{
WriteIndented = true,
PropertyNameCaseInsensitive = true,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
PropertyNamingPolicy = new JsonKebabCaseNamingPolicy(),
TypeInfoResolver = new IncludeInternalMembersJsonTypeInfoResolver(),
};
Expand Down
9 changes: 9 additions & 0 deletions src/Joba.IBM.RPA/Package/PackageExceptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ public class PackageException : Exception
public string PackageName { get; }
}

public class PackageNotFoundException : PackageException
{
public PackageNotFoundException(string packageName)
: this(packageName, $"Could not find '{packageName}' package.") { }
public PackageNotFoundException(string packageName, WalVersion version)
: this(packageName, $"Could not find package '{packageName}' with version '{version}'.") { }
public PackageNotFoundException(string packageName, string message) : base(packageName, message) { }
}

public class PackageAlreadyInstalledException : PackageException
{
public PackageAlreadyInstalledException(string packageName, WalVersion version)
Expand Down
6 changes: 5 additions & 1 deletion src/Joba.IBM.RPA/Package/PackageReferences.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,13 @@ private void EnsureDirectory()

public IEnumerator<PackageMetadata> GetEnumerator() => references.Values.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
int ICollection.Count => references.Count;
bool ICollection.IsSynchronized => false;
object ICollection.SyncRoot => this;
void ICollection.CopyTo(Array array, int index) => references.CopyTo((KeyValuePair<string, PackageMetadata>[])array, index);
}

public interface IPackages : IEnumerable<PackageMetadata>
public interface IPackages : IEnumerable<PackageMetadata>, ICollection
{
PackageMetadata? Get(string name);
WalFile? Get(PackageMetadata metadata);
Expand Down
9 changes: 0 additions & 9 deletions src/Joba.IBM.RPA/Package/PackageSourceException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,6 @@ public class PackageSourceException : Exception
public PackageSourceException(string message) : base(message) { }
}

public class PackageNotFoundException : PackageException
{
public PackageNotFoundException(string packageName)
: this(packageName, $"Could not find '{packageName}' package.") { }
public PackageNotFoundException(string packageName, WalVersion version)
: this(packageName, $"Could not find package '{packageName}' with version '{version}'.") { }
public PackageNotFoundException(string packageName, string message) : base(packageName, message) { }
}

public class PackageSourceNotFoundException : PackageSourceException
{
public PackageSourceNotFoundException(string alias)
Expand Down
6 changes: 5 additions & 1 deletion src/Joba.IBM.RPA/Project/PackageSourcesFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,13 @@ async Task<PackageSource> IPackageSources.AddAsync(IAccountResource resource, st

IEnumerator<PackageSource> IEnumerable<PackageSource>.GetEnumerator() => sources.Values.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => sources.Values.GetEnumerator();
int ICollection.Count => sources.Count;
bool ICollection.IsSynchronized => false;
object ICollection.SyncRoot => this;
void ICollection.CopyTo(Array array, int index) => sources.CopyTo((KeyValuePair<string, PackageSource>[])array, index);
}

public interface IPackageSources : IEnumerable<PackageSource>
public interface IPackageSources : IEnumerable<PackageSource>, ICollection
{
PackageSource this[string alias] { get; }
PackageSource? Get(string alias);
Expand Down
2 changes: 1 addition & 1 deletion src/Joba.IBM.RPA/Project/Project.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ internal Project(ProjectFile projectFile, ProjectSettings projectSettings, UserS
public DirectoryInfo RpaDirectory => projectFile.RpaDirectory;
public DirectoryInfo WorkingDirectory => projectFile.WorkingDirectory;
public string Name => projectFile.ProjectName;
public string Description => string.IsNullOrEmpty(projectSettings.Description) ? projectFile.ProjectName : projectSettings.Description;
public string Description => projectSettings.Description;
public IPackageSources PackageSources => packageSources ??= new PackageSources(projectSettings, userFile, userSettings);
public IPackages Packages => projectSettings.Packages;
public IRobots Robots => projectSettings.Robots;
Expand Down
10 changes: 4 additions & 6 deletions src/Joba.IBM.RPA/Project/ProjectFactory.cs
Original file line number Diff line number Diff line change
@@ -1,25 +1,23 @@
using Microsoft.Extensions.Logging;

namespace Joba.IBM.RPA
namespace Joba.IBM.RPA
{
public static class ProjectFactory
{
public static IProject Create(DirectoryInfo workingDir, string name)
{
var projectFile = new ProjectFile(workingDir, name);
if (projectFile.RpaDirectory.Exists)
throw new Exception($"A project is already configured in the '{workingDir.FullName}' directory");
throw new ProjectException($"A project is already configured in the '{workingDir.FullName}' directory");
projectFile.RpaDirectory.CreateHidden();

var userFile = new UserSettingsFile(projectFile.ProjectName);
var packageSourcesFile = new PackageSourcesFile(workingDir, projectFile.ProjectName);
var projectSettings = new ProjectSettings(workingDir);
var projectSettings = new ProjectSettings(workingDir) { Description = name };

return new Project(projectFile, projectSettings, userFile, new UserSettings(), packageSourcesFile);
}

public static IProject CreateFromCurrentDirectory(string name)
=> Create( new DirectoryInfo(System.Environment.CurrentDirectory), name);
=> Create(new DirectoryInfo(System.Environment.CurrentDirectory), name);

public static async Task<IProject?> TryLoadAsync(DirectoryInfo workingDir, CancellationToken cancellation)
{
Expand Down
2 changes: 1 addition & 1 deletion src/Joba.IBM.RPA/Project/ProjectFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ internal async Task SaveAsync(ProjectSettings projectSettings, CancellationToken
var file = Find(workingDir);
if (file == null)
return (null, null);
if (!file.Value.Exists || !file.Value.RpaDirectory.Exists)
if (!file.Value.Exists)
return (file, null);

var serializer = JsonSerializerOptionsFactory.CreateForProject(workingDir);
Expand Down
18 changes: 11 additions & 7 deletions src/Joba.IBM.RPA/Project/Robots.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Diagnostics.CodeAnalysis;
using System.Xml.Linq;

namespace Joba.IBM.RPA
{
Expand All @@ -20,9 +19,14 @@ internal Robots(IDictionary<string, RobotSettings> bots)
void IRobots.Add(string name, RobotSettings settings) => bots.Add(name, settings);
public IEnumerator<Robot> GetEnumerator() => bots.Select(b => new Robot(b.Key, b.Value)).GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

int ICollection.Count => bots.Count;
bool ICollection.IsSynchronized => false;
object ICollection.SyncRoot => this;
void ICollection.CopyTo(Array array, int index) => bots.CopyTo((KeyValuePair<string, RobotSettings>[])array, index);
}

public interface IRobots : IEnumerable<Robot>
public interface IRobots : IEnumerable<Robot>, ICollection
{
bool Exists(string name);
void Add(string name, RobotSettings settings);
Expand All @@ -31,14 +35,14 @@ public interface IRobots : IEnumerable<Robot>

public static class RobotSettingsFactory
{
public static RobotSettings Create(string type)
public static RobotSettings Create(string type, string description)
{
return type switch
{
ChatbotSettings.TypeName => new ChatbotSettings(),
AttendedSettings.TypeName => new AttendedSettings(),
UnattendedSettings.TypeName => new UnattendedSettings(),
_ => new UnattendedSettings()
ChatbotSettings.TypeName => new ChatbotSettings { Description = description },
AttendedSettings.TypeName => new AttendedSettings { Description = description },
UnattendedSettings.TypeName => new UnattendedSettings { Description = description },
_ => new UnattendedSettings { Description = description }
};
}
}
Expand Down
Loading