diff --git a/src/NoteBookmark.BlazorApp.Tests/Tests/PostReaderTests.cs b/src/NoteBookmark.BlazorApp.Tests/Tests/PostReaderTests.cs new file mode 100644 index 0000000..b480ab3 --- /dev/null +++ b/src/NoteBookmark.BlazorApp.Tests/Tests/PostReaderTests.cs @@ -0,0 +1,66 @@ +using Bunit; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.FluentUI.AspNetCore.Components; +using Moq; +using NoteBookmark.BlazorApp.Tests.Helpers; +using NoteBookmark.Domain; +using NoteBookmark.SharedUI; +using NoteBookmark.SharedUI.Components.Pages; +using Xunit; + +namespace NoteBookmark.BlazorApp.Tests.Tests; + +public sealed class PostReaderTests : BunitContext +{ + private readonly Mock _dataServiceMock; + + public PostReaderTests() + { + this.AddFluentUI(); + this.AddAuthorization().SetAuthorized("testuser"); + + _dataServiceMock = new Mock(); + _dataServiceMock.Setup(s => s.GetPost("p1")).ReturnsAsync(new Post + { + PartitionKey = "p", + RowKey = "p1", + Title = "Test Offline Article Title", + Author = "Frank Boucher", + Date_published = "2026-01-01T00:00:00" + }); + _dataServiceMock.Setup(s => s.GetPostHtmlAsync("p1")).ReturnsAsync("

Hello offline reader world

"); + + Services.AddSingleton(_dataServiceMock.Object); + } + + [Fact] + public void PostReader_RendersTitleAndContentAndSlider() + { + var cut = Render(ps => ps.Add(p => p.PostId, "p1")); + + cut.Markup.Should().Contain("Test Offline Article Title"); + cut.Markup.Should().Contain("Frank Boucher"); + cut.Markup.Should().Contain("Hello offline reader world"); + cut.Markup.Should().Contain("reader-content"); + cut.Markup.Should().Contain("Text size:"); + + var slider = cut.FindComponent>(); + slider.Instance.Min.Should().Be(8); + slider.Instance.Max.Should().Be(56); + } + + [Fact] + public void PostReader_SliderValueChange_UpdatesContentFontSize() + { + var cut = Render(ps => ps.Add(p => p.PostId, "p1")); + + var contentDivBefore = cut.Find("div.reader-content"); + contentDivBefore.GetAttribute("style").Should().Contain("font-size: 16px;"); + + var slider = cut.FindComponent>(); + cut.InvokeAsync(() => slider.Instance.ValueChanged.InvokeAsync(24)); + + var contentDivAfter = cut.Find("div.reader-content"); + contentDivAfter.GetAttribute("style").Should().Contain("font-size: 24px;"); + } +} diff --git a/src/NoteBookmark.SharedUI/Components/Pages/PostReader.razor b/src/NoteBookmark.SharedUI/Components/Pages/PostReader.razor index 9c086e5..57af22a 100644 --- a/src/NoteBookmark.SharedUI/Components/Pages/PostReader.razor +++ b/src/NoteBookmark.SharedUI/Components/Pages/PostReader.razor @@ -8,7 +8,7 @@ @(post?.Title ?? "Reading...") - + @post.Title +

@post.Title

@if (!string.IsNullOrEmpty(post.Author)) { @@ -38,7 +38,7 @@ @if (htmlContent != null) { -
+
@((MarkupString)htmlContent)
} @@ -46,6 +46,16 @@ {

Content not available.

} + + + + + + Text size: + @(textSize)px + + + } @@ -56,6 +66,7 @@ private Post? post; private string? htmlContent; private bool isLoading = true; + private int textSize = 16; protected override async Task OnInitializedAsync() { diff --git a/src/NoteBookmark.SharedUI/Components/Pages/PostReader.razor.css b/src/NoteBookmark.SharedUI/Components/Pages/PostReader.razor.css new file mode 100644 index 0000000..e80f390 --- /dev/null +++ b/src/NoteBookmark.SharedUI/Components/Pages/PostReader.razor.css @@ -0,0 +1,30 @@ +.reader-content { + width: 100%; + max-width: 100%; + overflow-wrap: anywhere; + word-break: break-word; + box-sizing: border-box; +} + +.reader-content ::deep * { + max-width: 100%; + box-sizing: border-box; +} + +.reader-content ::deep img { + max-width: 100%; + height: auto; +} + +.reader-content ::deep pre, +.reader-content ::deep code { + white-space: pre-wrap; + word-break: break-word; + overflow-x: auto; +} + +.reader-content ::deep table { + display: block; + max-width: 100%; + overflow-x: auto; +}