From 1a400162ac265b9f86e528b661ac9fb3934578ad Mon Sep 17 00:00:00 2001 From: fboucher-os Date: Tue, 27 Oct 2026 07:15:29 -0400 Subject: [PATCH] feat(web-app): add News & Updates section to Blazor home page (#219) --- .../Tests/NewsFeedServiceTests.cs | 152 ++++++++++++++++++ .../Components/Pages/Home.razor | 19 ++- .../INewsFeedService.cs | 8 + src/NoteBookmark.BlazorApp/NewsFeedService.cs | 68 ++++++++ src/NoteBookmark.BlazorApp/Program.cs | 4 + .../Data/NewsFeedService.cs | 89 ++-------- .../NewsFeedMarkdownRenderer.cs | 114 +++++++++++++ 7 files changed, 375 insertions(+), 79 deletions(-) create mode 100644 src/NoteBookmark.BlazorApp.Tests/Tests/NewsFeedServiceTests.cs create mode 100644 src/NoteBookmark.BlazorApp/INewsFeedService.cs create mode 100644 src/NoteBookmark.BlazorApp/NewsFeedService.cs create mode 100644 src/NoteBookmark.SharedUI/NewsFeedMarkdownRenderer.cs diff --git a/src/NoteBookmark.BlazorApp.Tests/Tests/NewsFeedServiceTests.cs b/src/NoteBookmark.BlazorApp.Tests/Tests/NewsFeedServiceTests.cs new file mode 100644 index 0000000..7b7fbe5 --- /dev/null +++ b/src/NoteBookmark.BlazorApp.Tests/Tests/NewsFeedServiceTests.cs @@ -0,0 +1,152 @@ +using System.Net; +using System.Text; +using Bunit; +using FluentAssertions; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Moq; +using NoteBookmark.BlazorApp.Components.Pages; +using NoteBookmark.BlazorApp.Tests.Helpers; + +namespace NoteBookmark.BlazorApp.Tests.Tests; + +public sealed class NewsFeedServiceTests : BunitContext +{ + [Fact] + public async Task GetHtmlAsync_RendersMarkdownRewritesRelativeAssetsAndSanitizesUrls() + { + var requestedUrls = new List(); + var handler = new DelegateHttpMessageHandler(request => + { + requestedUrls.Add(request.RequestUri!.AbsoluteUri); + return new HttpResponseMessage(HttpStatusCode.OK) + { + Content = new StringContent( + "# Product Updates\n\n![Logo](assets/logo.png)\n\n![Chart](./assets/sub/chart(1).png)\n\n![External](https://example.com/banner.png)\n\n\n\n[Safe](https://example.com) [Email](mailto:test@example.com) [Unsafe](javascript:alert(1))", + Encoding.UTF8, + "text/plain") + }; + }); + var service = CreateService(handler); + + var html = await service.GetHtmlAsync(); + + requestedUrls.Should().Equal("https://raw.githubusercontent.com/fboucher/NoteBookmark/main/docs/news.md"); + html.Should().Contain("

Product Updates

"); + html.Should().Contain("src=\"https://raw.githubusercontent.com/fboucher/NoteBookmark/main/docs/assets/logo.png\" alt=\"Logo\""); + html.Should().Contain("src=\"https://raw.githubusercontent.com/fboucher/NoteBookmark/main/docs/assets/sub/chart%281%29.png\" alt=\"Chart\""); + html.Should().Contain("src=\"https://example.com/banner.png\" alt=\"External\""); + html.Should().NotContain("