From 373e34f0f979c78eeb90b7c40063fd77e95dcb98 Mon Sep 17 00:00:00 2001
From: ChevCellios <171721150+ChevCellios@users.noreply.github.com>
Date: Sun, 16 Aug 2026 05:35:32 +0200
Subject: [PATCH 1/7] Complete ISS localization and mobile consent
---
Petabit.Tests/ApplicationTests.cs | 34 ++++++++++++++++++++++
Petabit/Resources/Views.Home.Index.de.resx | 10 +++++++
Petabit/Resources/Views.Home.Index.en.resx | 10 +++++++
Petabit/Resources/Views.Home.Index.hr.resx | 10 +++++++
Petabit/Views/Home/Index.cshtml | 30 ++++++++++++++-----
Petabit/Views/Shared/_Layout.cshtml.css | 2 ++
6 files changed, 88 insertions(+), 8 deletions(-)
diff --git a/Petabit.Tests/ApplicationTests.cs b/Petabit.Tests/ApplicationTests.cs
index 01adca6..17565c5 100644
--- a/Petabit.Tests/ApplicationTests.cs
+++ b/Petabit.Tests/ApplicationTests.cs
@@ -253,6 +253,40 @@ public async Task HomePageLocalizesLedDisplay(
Assert.Contains($"data-unavailable=\"{unavailableText}\"", body);
}
+ [Theory]
+ [InlineData("en", "Earth hologram", "United States", "Crew spacecraft")]
+ [InlineData("hr", "Hologram Zemlje", "SAD", "Posadna letjelica")]
+ [InlineData("de", "Erde-Hologramm", "USA", "Bemannte Raumfähre")]
+ public async Task HomePageLocalizesHologramAndStationDetails(
+ string culture,
+ string hologramTitle,
+ string countryText,
+ string purposeText)
+ {
+ using var request = new HttpRequestMessage(HttpMethod.Get, "/");
+ request.Headers.AcceptLanguage.ParseAdd(culture);
+
+ var response = await _client.SendAsync(request);
+ var body = await response.Content.ReadAsStringAsync();
+
+ Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+ Assert.Contains($">{hologramTitle}", body);
+ Assert.Contains($"data-country-usa=\"{countryText}\"", body);
+ Assert.Contains($"data-purpose-crewed=\"{purposeText}\"", body);
+ }
+
+ [Fact]
+ public async Task MobileAnalyticsConsentStylesProvideBottomSheetBehavior()
+ {
+ var styles = await _client.GetStringAsync("/Petabit.styles.css");
+
+ Assert.Contains("max-height: min(45vh, 18rem)", styles);
+ Assert.Contains("overscroll-behavior: contain", styles);
+ Assert.Contains("touch-action: pan-y", styles);
+ Assert.Contains("min-height: 44px", styles);
+ Assert.Contains("safe-area-inset-bottom", styles);
+ }
+
[Fact]
public async Task IssDataReturnsJsonWhenUpstreamSucceeds()
{
diff --git a/Petabit/Resources/Views.Home.Index.de.resx b/Petabit/Resources/Views.Home.Index.de.resx
index 53d9f01..0a578ea 100644
--- a/Petabit/Resources/Views.Home.Index.de.resx
+++ b/Petabit/Resources/Views.Home.Index.de.resx
@@ -139,4 +139,14 @@
ORBITAL VIEW
-@Localizer["HologramKicker"]
+Trenutna oznaka koristi podatke primljene nakon pinga. Linija prikazuje projekciju ISS orbite.
+@Localizer["HologramNote"]
Departure is planned.
]]>NASA changed its layout
"; + await service.RefreshAsync(CancellationToken.None); + Assert.True(service.RefreshFailed); + Assert.Same(previous, service.Current); + } + + [Fact] + public async Task InvalidSavedFileFallsBackToClearlyUnverifiedBootstrap() + { + Directory.CreateDirectory(directory); + await File.WriteAllTextAsync(Path.Combine(directory, "status.json"), "{broken"); + using var service = Create(new Handler(Feed, Overview)); + await service.RestoreAsync(CancellationToken.None); + Assert.Null(service.Current.CheckedAt); + Assert.Equal(11, service.Current.Crew.Length); + } + + [Fact] + public async Task StorageFailureIsReportedWithoutDiscardingSuccessfulNasaUpdate() + { + Directory.CreateDirectory(directory); + var blocked = Path.Combine(directory, "blocked"); + await File.WriteAllTextAsync(blocked, "file occupying directory path"); + using var service = Create(new Handler(Feed, Overview), Path.Combine(blocked, "status.json")); + await service.RefreshAsync(CancellationToken.None); + Assert.True(service.PersistenceFailed); + Assert.False(service.RefreshFailed); + Assert.Equal(7, service.Current.Crew.Length); + } + + [Fact] + public async Task ConditionalRequestsReuseUnchangedNasaDocuments() + { + var handler = new Handler(Feed, Overview) { Conditional = true }; + using var service = Create(handler); + await service.RefreshAsync(CancellationToken.None); + var first = service.Current; + await service.RefreshAsync(CancellationToken.None); + Assert.False(service.RefreshFailed); + Assert.Equal(2, handler.NotModifiedCount); + Assert.Equal(first.Crew, service.Current.Crew); + Assert.Single(service.Current.Events); + } + + public void Dispose() + { + if (Directory.Exists(directory)) Directory.Delete(directory, recursive: true); + } + + private class Factory(Handler handler) : IHttpClientFactory + { + public HttpClient CreateClient(string name) => new(handler, disposeHandler: false); + } + private class Handler(string feed, string overview) : HttpMessageHandler + { + public bool Unavailable { get; set; } + public bool Conditional { get; set; } + public int NotModifiedCount; + public string Overview { get; set; } = overview; + protected override Task@Localizer["WelcomeText"]
-@Localizer["VideoNote"]
+ + + @Localizer["VideoSource"] +STARLINK · ORBITAL NETWORK
@Localizer["StarlinkNote"]
+ + CelesTrak · @Localizer["StarlinkSource"] +@Localizer["Loading"]
+ +@Localizer["EventsNote"]