JR-023: correct the missing-dependency logs, and test them
Both failure paths still told admins the overlay was "falling back to patching index.html on disk". JR-021 deleted that fallback, so the message was false -- and it was false in the worst place, since an admin reads it precisely when debugging a missing overlay and would go hunting for a patch that no longer exists. They now name the install URL and say the overlay is disabled while every other feature is unaffected. The not-found case is a Warning, not Information: a headline feature being off should not sit among startup chatter. UT-012..015 cover the branch. The File Transformation assembly is genuinely absent from the test host, so TryRegister exercises its real not-found path rather than a seam invented for the test. UT-015 pins that a null payload returns empty rather than throwing -- this callback runs inside another plugin's request path on every page served, so throwing would break the web client itself, not just JRay's overlay. Making those runnable needed the test project to reference Jellyfin.Controller and Jellyfin.Model without the plugin's ExcludeAssets=runtime. My earlier claim that DisableTransitiveFrameworkReferences alone sufficed was too narrow: it drops the demand for the web *framework*, but ILogger and MediaBrowser.Common live in the excluded assets, so anything past dependency-free logic failed at run time with FileNotFoundException. Both settings are needed, and the register now says so. Second mutation check: downgrading the warning to Information fails UT-013 and nothing else. Source restored and re-verified. JR-023 reaches Done for the detection half. The config-page banner stays T4 -- verifiable only against a live server. TRACES: UT-012, UT-013, UT-014, UT-015 | JR-023 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Jellyfin.Plugin.JRay.Models;
|
||||
using Jellyfin.Plugin.JRay.Services;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Xunit;
|
||||
|
||||
namespace Jellyfin.Plugin.JRay.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// JR-023 — absent the File Transformation plugin, disable *only* the overlay
|
||||
/// and say so. There is no on-disk fallback (JR-021), so the failure path is
|
||||
/// the one an admin will actually meet, and it has to be legible: silently
|
||||
/// serving no overlay is indistinguishable from a broken install.
|
||||
///
|
||||
/// The File Transformation assembly is not loaded in the test host, so
|
||||
/// TryRegister exercises its not-found branch for real rather than through a
|
||||
/// seam invented for the test.
|
||||
///
|
||||
/// TRACES: UT-012, UT-013, UT-014, UT-015 | JR-023
|
||||
/// </summary>
|
||||
public class FileTransformationRegistrationTests
|
||||
{
|
||||
// UT-012
|
||||
[Fact]
|
||||
public void TryRegister_WithPluginAbsent_ReturnsFalse()
|
||||
{
|
||||
Assert.False(FileTransformationRegistration.TryRegister(new CapturingLogger()));
|
||||
}
|
||||
|
||||
// UT-013
|
||||
[Fact]
|
||||
public void TryRegister_WithPluginAbsent_WarnsNamingThePluginAndHowToInstallIt()
|
||||
{
|
||||
var logger = new CapturingLogger();
|
||||
|
||||
FileTransformationRegistration.TryRegister(logger);
|
||||
|
||||
var entry = Assert.Single(logger.Entries);
|
||||
|
||||
// Warning, not Information: the overlay is a headline feature and it is
|
||||
// off. Logging this at Information buries it among startup chatter.
|
||||
Assert.Equal(LogLevel.Warning, entry.Level);
|
||||
|
||||
// The message has to carry the install URL, and must not promise the
|
||||
// on-disk fallback that JR-021 removed.
|
||||
Assert.Contains(FileTransformationRegistration.ManifestUrl, entry.Message, StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("falling back", entry.Message, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
// UT-014
|
||||
[Fact]
|
||||
public void TransformIndexHtml_WithOverlayDisabled_ReturnsContentsUnchanged()
|
||||
{
|
||||
// No Plugin instance exists in the test host, so OverlayEnabled is
|
||||
// false — the same branch taken when an admin switches the overlay off.
|
||||
var html = "<html><body><div>x</div>\n</body></html>";
|
||||
|
||||
var result = FileTransformationRegistration.TransformIndexHtml(
|
||||
new TransformationPayload { Contents = html });
|
||||
|
||||
Assert.Equal(html, result);
|
||||
}
|
||||
|
||||
// UT-015
|
||||
[Fact]
|
||||
public void TransformIndexHtml_WithNullContents_ReturnsEmptyRatherThanThrowing()
|
||||
{
|
||||
// This callback is invoked by another plugin's code on every page
|
||||
// served. Throwing here would break the web client itself, not just
|
||||
// JRay's overlay.
|
||||
var result = FileTransformationRegistration.TransformIndexHtml(new TransformationPayload());
|
||||
|
||||
Assert.Equal(string.Empty, result);
|
||||
}
|
||||
|
||||
private sealed class CapturingLogger : ILogger
|
||||
{
|
||||
public List<(LogLevel Level, string Message)> Entries { get; } = new();
|
||||
|
||||
public IDisposable? BeginScope<TState>(TState state)
|
||||
where TState : notnull => null;
|
||||
|
||||
public bool IsEnabled(LogLevel logLevel) => true;
|
||||
|
||||
public void Log<TState>(
|
||||
LogLevel logLevel,
|
||||
EventId eventId,
|
||||
TState state,
|
||||
Exception? exception,
|
||||
Func<TState, Exception?, string> formatter)
|
||||
{
|
||||
Entries.Add((logLevel, formatter(state, exception)));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user