Skip to content

Commit

Permalink
Add GetCountryCode method and enhance API and docs
Browse files Browse the repository at this point in the history
- Added `GetCountryCode(string countryName)` to `CountryData.Standard` to return ISO 3166-1 alpha-2 codes.
- Updated `README.md` with documentation for `GetCountryCode`.
- Modified `Program.cs` in `CountryData.Sample.CountryConsoleProject` to call and print the result of `GetCountryCode`.
- Added `GetCountryCodeByName` API endpoint in `CountryController` within `CountryData.Sample.Web.API.Controllers`.
- Updated `CountryData.Sample.Web.API.csproj` to generate XML docs and suppress warning 1591.
- Enhanced Swagger configuration in `Program.cs` to include XML comments.
- Made `GetCountryData` method in `CountryHelper` virtual for potential overrides.
- Added `CountryExtensions` class in `CountryData.Standard` to manage `CountryHelper` and provide country-related methods.
- Implemented unit tests for `CountryExtensions` in `CountryExtensionsTests.cs`.
- Minor formatting changes in `Currency.cs` and `Regions.cs` to add missing braces.
- Changed `app.Run()` to `await app.RunAsync()` in `Program.cs` for async execution.
  • Loading branch information
Clifftech123 committed Sep 13, 2024
1 parent e8b183a commit 64f0d45
Show file tree
Hide file tree
Showing 11 changed files with 263 additions and 6 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ The CountryData.Standard library provides a set of methods that allow you to ret
| [`GetPhoneCodeByCountryShortCode(string shortCode)`](./docs/README.md) | Returns a single country's phone code by its short code. |
| [`GetCountryByPhoneCode(string phoneCode)`](./docs/README.md) | Returns country data for the country associated with the specified phone code. |
| [`GetCurrencyCodesByCountryCode(string shortCode)`](./docs/README.md) | Returns a list of currency codes for a specific country identified by its short code. |
| [`GetCountryByCurrencyCode(string currencyCode)`](./docs/README.md) | Returns a list of countries that use the specified currency code. |
| [`GetCountryByCurrencyCode(string currencyCode)`](./docs/README.md) | Returns a list of countries that use the specified currency code. |
| [`GetCountryCode(string countryName)`](./docs/README.md) | Returns the country code for a specific country name. |



### Initialize the Country data object
Expand Down
13 changes: 13 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,16 @@ Country GetCountryByCurrencyCode(string currencyCode);
This method is particularly useful when you have a currency code and need to retrieve the corresponding country's information. Simply pass the currency code as a string argument, and the method will return a `Country` object filled with relevant data.


### GetCountryCode(string countryName)

The `GetCountryCode()` method is designed to fetch the ISO 3166-1 alpha-2 code for a specific country using its name. This method returns a string containing the country's ISO code, making it easy to identify countries based on their names.

Here's the method signature in C#:

```csharp

string GetCountryCode(string countryName);
```



18 changes: 18 additions & 0 deletions sample/CountryData.Sample.Console/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public static void Main()
GetCountryByPhoneCode("+233");
GetCurrencyCodesByCountryCode("US");
GetCountryByCurrencyCode("GHS");
GetCountryCode("Ghana");
}

/// <summary>
Expand Down Expand Up @@ -145,5 +146,22 @@ private static void GetCountryByCurrencyCode(string currencyCode)
Console.WriteLine(country.CountryName);
}
}



/// <summary>
/// Retrieves the country code for a given country name and prints it to the console.
/// </summary>
/// <param name="countryName">The name of the country.</param>
private static void GetCountryCode(string countryName)
{
using var manager = new CountryExtensions();
var result = manager.GetCountryCode(countryName);
Console.WriteLine($"Country code for {countryName} is {result} ");
}




}
}
Original file line number Diff line number Diff line change
Expand Up @@ -186,5 +186,32 @@ public IActionResult GetCountryByCurrencyCode([FromQuery] string currencyCode)
return Ok(countryByCurrencyCode);
}



/// <summary>
/// Retrieves the country code for a given country name.
/// </summary>
/// <param name="countryName">The name of the country.</param>
/// <returns>The country code if found; otherwise, a NotFound result.</returns>
[HttpGet("countryCodeByName")]
[ProducesResponseType(typeof(string), 200)]
[ProducesResponseType(404)]
public IActionResult GetCountryCodeByName([FromQuery] string countryName)


{
using var manager = new CountryExtensions();
var countryCode = manager.GetCountryCode(countryName);
if (countryCode == null)
{
return NotFound();
}
return Ok(countryCode);
}


}
}



}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>

<ItemGroup>
Expand Down
22 changes: 20 additions & 2 deletions sample/CountryData.Sample.Web.API/Program.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,31 @@
using Microsoft.OpenApi.Models;
using System.Reflection;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo
{
Title = " CountryData.Stand",
Version = "v1",
Description = " Sample endpoint for CountryData.Standard "

});

// Set the comments path for the Swagger JSON and UI.
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
c.IncludeXmlComments(xmlPath);
});
// Register CountryHelper service
builder.Services.AddScoped<CountryData.Standard.CountryHelper>();

var app = builder.Build();

// Configure the HTTP request pipeline.
Expand All @@ -23,4 +41,4 @@

app.MapControllers();

app.Run();
await app.RunAsync();
77 changes: 77 additions & 0 deletions src/CountryData.Standard/CountryExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using System;
using System.Linq;

namespace CountryData.Standard
{
/// <summary>
/// Manages the CountryHelper instance and provides methods for retrieving country-related information.
/// </summary>
public class CountryExtensions : IDisposable
{
private CountryHelper _countryHelper;
private bool _disposed = false;

/// <summary>
/// Constructor to initialize the CountryHelper instance.
/// </summary>
public CountryExtensions()
{
_countryHelper = new CountryHelper();
}

/// <summary>
/// Gets the country code for the specified country name.
/// </summary>
/// <param name="countryName">The name of the country.</param>
/// <returns>The country code if found; otherwise, null.</returns>
public string GetCountryCode(string countryName)
{
if (countryName == null)
{
throw new ArgumentNullException(nameof(countryName));
}

var country = _countryHelper.GetCountryData()
.FirstOrDefault(c => c.CountryName.Equals(countryName, StringComparison.OrdinalIgnoreCase));

return country?.CountryShortCode;
}

/// <summary>
/// Dispose method to clean up resources.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

/// <summary>
/// Protected method to dispose resources.
/// </summary>
/// <param name="disposing">Indicates whether the method is called from Dispose or finalizer.</param>
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing && _countryHelper != null)
{
// Dispose managed resources.
_countryHelper = null;
}

// Dispose unmanaged resources.

_disposed = true;
}
}

/// <summary>
/// Finalizer to ensure resources are cleaned up.
/// </summary>
~CountryExtensions()
{
Dispose(false);
}
}
}
4 changes: 2 additions & 2 deletions src/CountryData.Standard/CountryHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public CountryHelper()


/// <summary>
///
/// Read
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
Expand All @@ -47,7 +47,7 @@ private string GetJsonData(string path)
/// that can be querried by Lambda Expressions
/// </summary>
/// <returns>IEnumerable<Country></returns>
public IEnumerable<Country> GetCountryData()
public virtual IEnumerable<Country> GetCountryData()
{
return _Countries;
}
Expand Down
1 change: 1 addition & 0 deletions src/CountryData.Standard/Currency.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ public class Currency
{
public string Code { get; set; }
public string Name { get; set; }

}
}
2 changes: 2 additions & 0 deletions src/CountryData.Standard/Regions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@ public class Regions
{
public String Name { get; set; }
public String ShortCode { get; set; }


}
}
97 changes: 97 additions & 0 deletions test/CountryData.UnitTests/CountryExtensionsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
using CountryData.Standard;
using FluentAssertions;
using System;
using Xunit;

namespace CountryData.UnitTests
{
public class CountryHelperManagerTests
{
/// <summary>
/// Tests that GetCountryCode returns the correct country code for a valid country name.
/// </summary>
[Fact]
public void GetCountryCode_ValidCountryName_ReturnsCountryCode()
{
// Arrange
using var manager = new CountryExtensions();
var countryName = "United States";

// Act
var result = manager.GetCountryCode(countryName);

// Assert
result.Should().Be("US");
}

/// <summary>
/// Tests that GetCountryCode returns null for an invalid country name.
/// </summary>
[Fact]
public void GetCountryCode_InvalidCountryName_ReturnsNull()
{
// Arrange
using var manager = new CountryExtensions();
var countryName = "Invalid Country";

// Act
var result = manager.GetCountryCode(countryName);

// Assert
result.Should().BeNull();
}

/// <summary>
/// Tests that GetCountryCode throws an ArgumentNullException for a null country name.
/// </summary>
[Fact]
public void GetCountryCode_NullCountryName_ThrowsArgumentNullException()
{
// Arrange
using var manager = new CountryExtensions();
string? countryName = null;

// Act
Action act = () => manager.GetCountryCode(countryName!);

// Assert
act.Should().Throw<ArgumentNullException>();
}

/// <summary>
/// Tests that Dispose method sets the _disposed flag to true.
/// </summary>
[Fact]
public void Dispose_SetsDisposedFlagToTrue()
{
// Arrange
var manager = new CountryExtensions();

// Act
manager.Dispose();

// Assert
var disposedField = typeof(CountryExtensions).GetField("_disposed", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
var disposedValue = (bool)disposedField.GetValue(manager);

Check warning on line 75 in test/CountryData.UnitTests/CountryExtensionsTests.cs

View workflow job for this annotation

GitHub Actions / build

Dereference of a possibly null reference.

Check warning on line 75 in test/CountryData.UnitTests/CountryExtensionsTests.cs

View workflow job for this annotation

GitHub Actions / build

Unboxing a possibly null value.
disposedValue.Should().BeTrue();
}

/// <summary>
/// Tests that Dispose method sets the _countryHelper to null.
/// </summary>
[Fact]
public void Dispose_SetsCountryHelperToNull()
{
// Arrange
var manager = new CountryExtensions();

// Act
manager.Dispose();

// Assert
var countryHelperField = typeof(CountryExtensions).GetField("_countryHelper", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
var countryHelperValue = countryHelperField.GetValue(manager);

Check warning on line 93 in test/CountryData.UnitTests/CountryExtensionsTests.cs

View workflow job for this annotation

GitHub Actions / build

Dereference of a possibly null reference.
countryHelperValue.Should().BeNull();
}
}
}

0 comments on commit 64f0d45

Please sign in to comment.