All checks were successful
Publish NuGet Packages / build-and-publish (push) Successful in 29s
191 lines
5.8 KiB
C#
191 lines
5.8 KiB
C#
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Options;
|
|
using Svrnty.GeoManagement.Abstractions.Models;
|
|
using Svrnty.GeoManagement.Google;
|
|
using Svrnty.GeoManagement.Google.Configuration;
|
|
using Svrnty.GeoManagement.Tests.Configuration;
|
|
|
|
namespace Svrnty.GeoManagement.Tests;
|
|
|
|
public class GoogleProviderTests : IDisposable
|
|
{
|
|
private readonly GeoManagementGoogleProvider _provider;
|
|
private readonly IConfiguration _configuration;
|
|
private readonly ILogger<GeoManagementGoogleProvider> _logger;
|
|
private readonly TestDataConfiguration _testData;
|
|
|
|
public GoogleProviderTests()
|
|
{
|
|
// Build configuration from appsettings.Development.json
|
|
_configuration = new ConfigurationBuilder()
|
|
.SetBasePath(Directory.GetCurrentDirectory())
|
|
.AddJsonFile("appsettings.Development.json", optional: false, reloadOnChange: false)
|
|
.AddEnvironmentVariables()
|
|
.Build();
|
|
|
|
// Setup logger
|
|
var loggerFactory = LoggerFactory.Create(builder =>
|
|
{
|
|
builder.AddConsole();
|
|
builder.SetMinimumLevel(LogLevel.Debug);
|
|
});
|
|
_logger = loggerFactory.CreateLogger<GeoManagementGoogleProvider>();
|
|
|
|
// Get options from configuration
|
|
var options = _configuration.GetSection("GoogleGeoManagement").Get<GoogleGeoManagementOptions>();
|
|
if (options == null || string.IsNullOrWhiteSpace(options.ApiKey))
|
|
{
|
|
throw new InvalidOperationException(
|
|
"Google API key not configured. Please add your API key to appsettings.Development.json");
|
|
}
|
|
|
|
// Load test data from configuration
|
|
_testData = _configuration.GetSection("TestData").Get<TestDataConfiguration>()
|
|
?? throw new InvalidOperationException(
|
|
"Test data not configured. Please add TestData section to appsettings.Development.json");
|
|
|
|
_provider = new GeoManagementGoogleProvider(
|
|
Options.Create(options),
|
|
_logger);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetGeoPointAsync_WithValidAddress_ReturnsCoordinates()
|
|
{
|
|
// Arrange
|
|
var address = new Address
|
|
{
|
|
Line1 = _testData.ValidAddress.Line1,
|
|
Line2 = _testData.ValidAddress.Line2,
|
|
City = _testData.ValidAddress.City,
|
|
Subdivision = _testData.ValidAddress.Subdivision,
|
|
PostalCode = _testData.ValidAddress.PostalCode,
|
|
CountryCode = _testData.ValidAddress.Country,
|
|
Location = null,
|
|
Note = null
|
|
};
|
|
|
|
// Act
|
|
var result = await _provider.GetGeoPointAsync(address);
|
|
|
|
// Assert
|
|
Assert.NotNull(result);
|
|
Assert.InRange(result.Latitude, _testData.ExpectedLatRange.Min, _testData.ExpectedLatRange.Max);
|
|
Assert.InRange(result.Longitude, _testData.ExpectedLongRange.Min, _testData.ExpectedLongRange.Max);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ReverseGeocodeAsync_WithValidCoordinates_ReturnsAddress()
|
|
{
|
|
// Arrange
|
|
var geoPoint = new GeoPoint(
|
|
_testData.ValidGeoPoint.Latitude,
|
|
_testData.ValidGeoPoint.Longitude);
|
|
|
|
// Act
|
|
var result = await _provider.ReverseGeocodeAsync(geoPoint);
|
|
|
|
// Assert
|
|
Assert.NotNull(result);
|
|
Assert.NotNull(result.Line1);
|
|
Assert.NotNull(result.City);
|
|
Assert.NotNull(result.CountryCode);
|
|
Assert.True(result.IsNormalized());
|
|
Assert.NotNull(result.Location);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task NormalizeAddressAsync_WithAddressObject_ReturnsNormalizedAddress()
|
|
{
|
|
// Arrange
|
|
var address = new Address
|
|
{
|
|
Line1 = _testData.NormalizeTestAddress.Line1,
|
|
Line2 = _testData.NormalizeTestAddress.Line2,
|
|
City = _testData.NormalizeTestAddress.City,
|
|
Subdivision = _testData.NormalizeTestAddress.Subdivision,
|
|
PostalCode = _testData.NormalizeTestAddress.PostalCode,
|
|
CountryCode = _testData.NormalizeTestAddress.Country,
|
|
Location = null,
|
|
Note = null
|
|
};
|
|
|
|
// Act
|
|
var result = await _provider.NormalizeAddressAsync(address);
|
|
|
|
// Assert
|
|
Assert.NotNull(result);
|
|
Assert.True(result.IsNormalized());
|
|
Assert.NotNull(result.Location);
|
|
Assert.NotNull(result.Line1);
|
|
Assert.Contains("Amphitheatre", result.Line1, StringComparison.OrdinalIgnoreCase);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task NormalizeAddressAsync_WithAddressString_ReturnsNormalizedAddress()
|
|
{
|
|
// Arrange
|
|
var addressString = _testData.AddressString;
|
|
|
|
// Act
|
|
var result = await _provider.NormalizeAddressAsync(addressString);
|
|
|
|
// Assert
|
|
Assert.NotNull(result);
|
|
Assert.True(result.IsNormalized());
|
|
Assert.NotNull(result.Location);
|
|
Assert.NotNull(result.Line1);
|
|
Assert.Contains("Mountain View", result.City, StringComparison.OrdinalIgnoreCase);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetGeoPointAsync_WithInvalidAddress_ReturnsNull()
|
|
{
|
|
// Arrange
|
|
var address = new Address
|
|
{
|
|
Line1 = _testData.InvalidAddress.Line1,
|
|
Line2 = _testData.InvalidAddress.Line2,
|
|
City = _testData.InvalidAddress.City,
|
|
Subdivision = _testData.InvalidAddress.Subdivision,
|
|
PostalCode = _testData.InvalidAddress.PostalCode,
|
|
CountryCode = _testData.InvalidAddress.Country,
|
|
Location = null,
|
|
Note = null
|
|
};
|
|
|
|
// Act
|
|
var result = await _provider.GetGeoPointAsync(address);
|
|
|
|
// Assert - Google might still return something, so we just verify it doesn't crash
|
|
// In real scenarios, very invalid addresses should return null
|
|
Assert.True(result == null || result.Latitude != 0 || result.Longitude != 0);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ReverseGeocodeAsync_WithOceanCoordinates_ReturnsAddress()
|
|
{
|
|
// Arrange
|
|
var geoPoint = new GeoPoint(
|
|
_testData.OceanGeoPoint.Latitude,
|
|
_testData.OceanGeoPoint.Longitude);
|
|
|
|
// Act
|
|
var result = await _provider.ReverseGeocodeAsync(geoPoint);
|
|
|
|
// Assert - May return null or a very general location
|
|
// This test just verifies it doesn't crash
|
|
if (result != null)
|
|
{
|
|
Assert.True(result.IsNormalized());
|
|
}
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
// Cleanup if needed
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
}
|