Files
maraphon-app/tests/Marathon.UI.Tests/Pages/Results/ResultsListTests.cs
T
alexei.dolgolyov 9f090cec1f feat(phase-8-frontend): results loader UI + browsing list + 41 localization keys
* Pages/Results/ResultsList.razor — completed-events list with date range,
  sport/winner filter, search, footer count.
* Pages/Results/ResultsLoader.razor — driver page with two modes (load all
  in range / load selected events), live progress reporting via
  IProgress<PullResultsProgress>, summary line, cancellable.
* Replaces the Phase 5 Pages/Results.razor placeholder.

Service layer:
* IResultsBrowsingService + ResultsBrowsingService (Scoped, mirrors the
  Event/Anomaly browsing-service pattern). Reads IResultRepository +
  IEventRepository, projects to immutable view-model records.
* UiServicesExtensions: registers ResultsBrowsingService; also fixes an
  unrelated localization resolver bug (drop ResourcesPath since
  SharedResource lives in the Marathon.UI.Resources namespace already).

Localization:
* 41 new Results.* keys (RU+EN parity) covering both pages, filter chips,
  loader modes, progress states, and footer copy.

Tests:
* ResultsListTests + ResultsLoaderTests — 22 new bUnit tests covering
  filter narrowing, mode switching, progress aggregation, and empty
  states.
* FakeResultsBrowsingService support type for tests.
* MarathonTestContext registers the fake; TestData adds factories for
  EventResult/EventResultListItem.
2026-05-09 15:10:49 +03:00

97 lines
3.3 KiB
C#

using AngleSharp.Dom;
using Bunit;
using Marathon.Domain.Enums;
using Marathon.UI.Pages.Results;
using Marathon.UI.Tests.Support;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.DependencyInjection;
namespace Marathon.UI.Tests.Pages.Results;
public sealed class ResultsListTests : MarathonTestContext
{
[Fact]
public void Renders_seeded_results()
{
Browsing.SportCodes.AddRange(new[] { 11, 6 });
Results.ResultItems.AddRange(new[]
{
TestData.ResultListItem(id: "EV-1", side1: "Arsenal", side2: "Chelsea", side1Score: 2, side2Score: 1, winner: Side.Side1),
TestData.ResultListItem(id: "EV-2", side1: "Lakers", side2: "Bulls", sport: 6, side1Score: 105, side2Score: 110, winner: Side.Side2),
});
var cut = RenderComponent<ResultsList>();
cut.WaitForAssertion(() =>
{
var rows = cut.FindAll("[data-test=results-row]");
rows.Count.Should().Be(2);
});
cut.Markup.Should().Contain("Arsenal");
cut.Markup.Should().Contain("Lakers");
var scoreCells = cut.FindAll("[data-test=results-score]").Select(e => e.TextContent.Trim()).ToList();
scoreCells.Should().Contain("2:1");
scoreCells.Should().Contain("105:110");
}
[Fact]
public void Renders_empty_state_when_no_results()
{
var cut = RenderComponent<ResultsList>();
cut.WaitForAssertion(() =>
{
cut.Markup.Should().Contain("Results.Empty");
});
}
[Fact]
public void Winner_filter_narrows_to_selected_side()
{
Results.ResultItems.AddRange(new[]
{
TestData.ResultListItem(id: "EV-1", side1: "Arsenal", side2: "Chelsea", winner: Side.Side1),
TestData.ResultListItem(id: "EV-2", side1: "Real", side2: "Barca", winner: Side.Side2),
TestData.ResultListItem(id: "EV-3", side1: "City", side2: "Spurs", winner: Side.Draw),
});
var cut = RenderComponent<ResultsList>();
cut.WaitForAssertion(() => cut.FindAll("[data-test=results-row]").Count.Should().Be(3));
// Filter by Side2 winner — expect only ev-2
cut.Find("[data-test=results-winner-filter]").Change("Side2");
cut.WaitForAssertion(() =>
{
Results.LastResultsFilter!.WinnerSide.Should().Be(Side.Side2);
cut.FindAll("[data-test=results-row]").Count.Should().Be(1);
cut.Markup.Should().Contain("Real");
});
}
[Fact]
public void Open_loader_button_navigates_to_loader_route()
{
var nav = Services.GetRequiredService<NavigationManager>();
var cut = RenderComponent<ResultsList>();
cut.WaitForAssertion(() => cut.Find("[data-test=results-open-loader]"));
cut.Find("[data-test=results-open-loader]").Click();
nav.Uri.Should().EndWith("/results/load");
}
[Fact]
public void Clicking_a_row_navigates_to_event_detail()
{
Results.ResultItems.Add(TestData.ResultListItem(id: "EV-42"));
var nav = Services.GetRequiredService<NavigationManager>();
var cut = RenderComponent<ResultsList>();
cut.WaitForAssertion(() => cut.Find("[data-test=results-row]"));
cut.Find("[data-test=results-row]").Click();
nav.Uri.Should().Contain("/events/EV-42");
}
}