Skip to content

Commit

Permalink
Return relevant items in STAC search (#267)
Browse files Browse the repository at this point in the history
  • Loading branch information
domi-b authored Aug 26, 2024
2 parents 5750a2c + 37fcf3b commit 7ddf1c0
Show file tree
Hide file tree
Showing 10 changed files with 260 additions and 7 deletions.
4 changes: 4 additions & 0 deletions src/Geopilot.Api/StacServices/HttpsStacApiContextFactory.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Stac;
using Stac.Api.Interfaces;
using Stac.Api.WebApi.Implementations.Default;

namespace Geopilot.Api.StacServices;

Expand All @@ -24,6 +25,9 @@ public HttpsStacApiContextFactory(IHttpContextAccessor httpContextAccessor, ISta
public IEnumerable<T> ApplyContextPostQueryFilters<T>(IStacApiContext stacApiContext, IDataProvider<T> dataProvider, IEnumerable<T> items)
where T : IStacObject
{
// Show the number of items in the search results
stacApiContext.Properties[DefaultConventions.MatchedCountPropertiesKey] = items.Count();

IEnumerable<T> filteredItems = items;
foreach (IStacApiContextFilter stacApiContextFilter in stacApiContextFilterProvider.GetFilters<T>())
{
Expand Down
19 changes: 12 additions & 7 deletions src/Geopilot.Api/StacServices/StacItemsProvider.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.EntityFrameworkCore;
using Geopilot.Api.Models;
using Microsoft.EntityFrameworkCore;
using Stac;
using Stac.Api.Interfaces;

Expand Down Expand Up @@ -72,20 +73,24 @@ public string GetItemEtag(string featureId, IStacApiContext stacApiContext)
}

/// <inheritdoc/>
public Task<IEnumerable<StacItem>> GetItemsAsync(IStacApiContext stacApiContext, CancellationToken cancellationToken)
public async Task<IEnumerable<StacItem>> GetItemsAsync(IStacApiContext stacApiContext, CancellationToken cancellationToken)
{
IEnumerable<StacItem> items = new List<StacItem>();
var items = new List<StacItem>();

var collectionIds = stacApiContext.Collections?.ToList();
using var db = contextFactory.CreateDbContext();
var mandates = db.MandatesWithIncludes.AsNoTracking().ToList();
IEnumerable<Mandate> mandates = await db.MandatesWithIncludes.AsNoTracking().ToListAsync(cancellationToken);

if (collectionIds?.Count > 0)
{
mandates = mandates.FindAll(m => collectionIds.Contains(stacConverter.GetCollectionId(m)));
mandates = mandates.Where(m => collectionIds.Contains(stacConverter.GetCollectionId(m)));
}

mandates.ToList().ForEach(m => items.Concat(m.Deliveries.Select(d => stacConverter.ToStacItem(d))));
return Task.FromResult(items);
foreach (var mandate in mandates)
{
items.AddRange(mandate.Deliveries.Select(stacConverter.ToStacItem));
}

return items;
}
}
1 change: 1 addition & 0 deletions tests/.editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
# Configure code analysis according to current standards by default.
[*.cs]
dotnet_diagnostic.CA1001.severity = none
dotnet_diagnostic.CA1861.severity = none
dotnet_diagnostic.SA0001.severity = none
dotnet_diagnostic.CS8604.severity = none
dotnet_diagnostic.CS8618.severity = none
2 changes: 2 additions & 0 deletions tests/Geopilot.Api.Test/Geopilot.Api.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsTestProject>true</IsTestProject>
<GenerateProgramFile>false</GenerateProgramFile>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.8" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
<PackageReference Include="Moq" Version="4.20.70" />
<PackageReference Include="MSTest.TestAdapter" Version="3.5.2" />
Expand Down
15 changes: 15 additions & 0 deletions tests/Geopilot.Api.Test/GeopilotApiApp.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;

namespace Geopilot.Api;

internal sealed class GeopilotApiApp : WebApplicationFactory<GeopilotApiApp>
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
base.ConfigureWebHost(builder);

builder.UseEnvironment("Development");
builder.UseContentRoot(Directory.GetCurrentDirectory());
}
}
42 changes: 42 additions & 0 deletions tests/Geopilot.Api.Test/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using Geopilot.Api;
using Geopilot.Api.StacServices;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Stac.Api.WebApi;

// This entry point is used by GeopilotApiApp for integration tests.
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddApiVersioning();
builder.Services.AddCors();

builder.Services
.AddControllers()
.ConfigureApplicationPartManager(options =>
{
options.ApplicationParts.Add(new AssemblyPart(typeof(Context).Assembly));
options.ApplicationParts.Add(new AssemblyPart(typeof(StacApiController).Assembly));
});

var contentTypeProvider = new FileExtensionContentTypeProvider();
contentTypeProvider.Mappings.TryAdd(".log", "text/plain");
contentTypeProvider.Mappings.TryAdd(".xtf", "application/interlis+xml");
builder.Services.AddSingleton<IContentTypeProvider>(contentTypeProvider);

var factory = new Mock<IDbContextFactory<Context>>();
factory.Setup(f => f.CreateDbContext()).Returns(AssemblyInitialize.DbFixture.GetTestContext);
builder.Services.AddSingleton(factory.Object);
builder.Services.AddTransient((provider) => provider.GetRequiredService<IDbContextFactory<Context>>().CreateDbContext());

builder.Services.AddStacData(builder => { });

var app = builder.Build();

app.UseCors();
app.MapControllers();

app.Run();
41 changes: 41 additions & 0 deletions tests/Geopilot.Api.Test/StacApi/CatalogTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using Newtonsoft.Json.Schema;
using Stac;
using Stac.Schemas;

namespace Geopilot.Api.StacApi;

[TestClass]
public class CatalogTest
{
private GeopilotApiApp app;
private HttpClient httpClient;

[TestInitialize]
public void Initialize()
{
app = new GeopilotApiApp();
httpClient = app.CreateClient();
}

[TestCleanup]
public void Cleanup()
{
app.Dispose();
httpClient.Dispose();
}

[TestMethod]
public async Task ValidateCatalogAsync()
{
var stacValidator = new StacValidator(new JSchemaUrlResolver());
const string catalogUri = "/";

var json = await httpClient.GetStringAsync(catalogUri);

Assert.IsTrue(stacValidator.ValidateJson(json));

var catalog = StacConvert.Deserialize<StacCatalog>(json);
Assert.AreEqual("geopilot", catalog.Id);
Assert.AreEqual("1.0.0", catalog.StacVersion);
}
}
42 changes: 42 additions & 0 deletions tests/Geopilot.Api.Test/StacApi/CollectionsTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using Stac.Api.Clients.Collections;

namespace Geopilot.Api.StacApi;

[TestClass]
public class CollectionsTest
{
private GeopilotApiApp app;
private HttpClient httpClient;
private CollectionsClient collectionsClient;

[TestInitialize]
public void Initialize()
{
app = new GeopilotApiApp();
httpClient = app.CreateClient();
collectionsClient = new CollectionsClient(httpClient);
}

[TestCleanup]
public void Cleanup()
{
app.Dispose();
httpClient.Dispose();
}

[TestMethod]
public async Task GetCollectionsAsync()
{
var collections = await collectionsClient.GetCollectionsAsync();

Assert.AreEqual(10, collections.Collections.Count);
}

[TestMethod]
public async Task DescribeCollectionAsync()
{
var collection = await collectionsClient.DescribeCollectionAsync("coll_1");

Assert.AreEqual("Handmade Soft Cheese", collection.Title);
}
}
44 changes: 44 additions & 0 deletions tests/Geopilot.Api.Test/StacApi/FeaturesTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using Stac.Api.Clients.Features;

namespace Geopilot.Api.StacApi;

[TestClass]
public class FeaturesTest
{
private GeopilotApiApp app;
private HttpClient httpClient;
private FeaturesClient featuresClient;

[TestInitialize]
public void Initialize()
{
app = new GeopilotApiApp();
httpClient = app.CreateClient();
featuresClient = new FeaturesClient(httpClient);
}

[TestCleanup]
public void Cleanup()
{
app.Dispose();
httpClient.Dispose();
}

[TestMethod]
public async Task GetFeaturesAsync()
{
var featureCollection = await featuresClient.GetFeaturesAsync("coll_1", null, null, null);

Assert.AreEqual(2, featureCollection.NumberMatched);
CollectionAssert.AreEqual(new[] { "item_6", "item_14" }, featureCollection.Features.Select(f => f.Id).ToList());
}

[TestMethod]
public async Task GetFeatureByIdAsync()
{
var feature = await featuresClient.GetFeatureAsync("coll_1", "item_14");

StringAssert.StartsWith(feature.Title, "Datenlieferung_2023-07");
Assert.AreEqual(3, feature.Assets.Count);
}
}
57 changes: 57 additions & 0 deletions tests/Geopilot.Api.Test/StacApi/SearchTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using Stac.Api.Clients.ItemSearch;

namespace Geopilot.Api.StacApi;

[TestClass]
public class SearchTest
{
private GeopilotApiApp app;
private HttpClient httpClient;
private ItemSearchClient searchClient;

[TestInitialize]
public void Initialize()
{
app = new GeopilotApiApp();
httpClient = app.CreateClient();
searchClient = new ItemSearchClient(httpClient);
}

[TestCleanup]
public void Cleanup()
{
app.Dispose();
httpClient.Dispose();
}

[TestMethod]
public async Task SearchCollection1()
{
var result = await searchClient.PostItemSearchAsync(new SearchBody
{
Collections = new[] { "coll_1" },
Limit = 12,
});

Assert.AreEqual(2, result.Items.Count());
Assert.AreEqual(2, result.NumberMatched);
Assert.AreEqual(2, result.NumberReturned);

CollectionAssert.AreEqual(new[] { "item_6", "item_14" }, result.Items.Select(i => i.Id).ToList());
}

[TestMethod]
public async Task SearchLimit()
{
const int limit = 8;
var result = await searchClient.PostItemSearchAsync(new SearchBody
{
Collections = Array.Empty<string>(),
Limit = limit,
});

Assert.AreEqual(limit, result.Items.Count());
Assert.AreEqual(20, result.NumberMatched);
Assert.AreEqual(limit, result.NumberReturned);
}
}

0 comments on commit 7ddf1c0

Please sign in to comment.