using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using FluentAssertions;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Moq;
using NexusReader.Data.Persistence;
using NexusReader.Domain.Entities;
using NexusReader.Application.Queries.Reader;
using NexusReader.Infrastructure.Services;
using Xunit;
namespace NexusReader.Application.Tests.Services;
public class EpubReaderServiceTests : IDisposable
{
private readonly SqliteConnection _connection;
private readonly DbContextOptions";
// Act
var result = (string)method.Invoke(null, new object[] { input });
// Assert
result.Should().NotContain("onerror");
result.Should().NotContain("onload");
result.Should().NotContain("style");
result.Should().NotContain("class");
result.Should().Contain("src=\"images/cover.jpg\"");
result.Should().Contain("alt=\"Cover Image\"");
}
[Fact]
public void RewriteImageUrls_BlocksJavaScriptScheme()
{
// Arrange
var method = typeof(EpubReaderService).GetMethod("RewriteImageUrls", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
method.Should().NotBeNull();
var input = "
";
var ebookId = Guid.NewGuid();
// Act
var result = (string)method.Invoke(null, new object[] { input, ebookId, "OEBPS/chapter1.xhtml" });
// Assert
result.Should().NotContain("javascript:alert(1)");
}
[Fact]
public async Task GetEpubResourceAsync_RejectsInvalidResourcePaths()
{
// Arrange
var ebookId = Guid.NewGuid();
var userId = "test-user-id";
using (var context = new AppDbContext(_contextOptions))
{
var user = new NexusUser
{
Id = userId,
UserName = "testuser",
Email = "test@nexus.com",
TenantId = "tenant-123",
SubscriptionPlanId = 1
};
context.Users.Add(user);
var author = new Author { Id = 10, Name = "Giorgio Vasari" };
context.Authors.Add(author);
var ebook = new Ebook
{
Id = ebookId,
UserId = userId,
Title = "Test Book",
AuthorId = author.Id,
FilePath = "assets/book.epub",
AddedDate = DateTime.UtcNow,
LastReadDate = DateTime.UtcNow,
Progress = 0,
LastChapter = "Introduction"
};
context.Ebooks.Add(ebook);
await context.SaveChangesAsync();
}
var service = new EpubReaderService(_dbContextFactoryMock.Object, _loggerMock.Object);
// Act
var traversalResult = await service.GetEpubResourceAsync(ebookId, "../../appsettings.json", userId);
var colonResult = await service.GetEpubResourceAsync(ebookId, "C:\\windows\\win.ini", userId);
// Assert
traversalResult.IsSuccess.Should().BeFalse();
traversalResult.Errors.First().Message.Should().Contain("Invalid resource path");
colonResult.IsSuccess.Should().BeFalse();
colonResult.Errors.First().Message.Should().Contain("Invalid resource path");
}
[Fact]
public void RewriteImageUrls_PreservesImgPrefix()
{
// Arrange
var method = typeof(EpubReaderService).GetMethod("RewriteImageUrls", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
method.Should().NotBeNull();
var input = "
";
var ebookId = Guid.NewGuid();
// Act
var result = (string)method.Invoke(null, new object[] { input, ebookId, "OEBPS/cover-page.xhtml" });
// Assert
result.Should().StartWith("";
var inputHref = "
")] [InlineData("