feat: complete legacy parity and modernize operator UI
This commit is contained in:
@@ -22,11 +22,11 @@ public sealed class LegacyOperatorSettingsTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SceneValidation_RequiresOnlyTheBaselineSceneAndReturnsAnAbbreviation()
|
||||
public void SceneValidation_RequiresEveryActiveSceneAndBuiltInAssetAndAllowsMissingExternalVideo()
|
||||
{
|
||||
using var directory = new TemporaryDirectory();
|
||||
var sceneDirectory = directory.CreateDirectory("Cuts");
|
||||
File.WriteAllText(Path.Combine(sceneDirectory, "5001.t2s"), "baseline");
|
||||
WriteValidSceneFiles(sceneDirectory);
|
||||
|
||||
var result = LegacyOperatorFolderValidator.Validate(
|
||||
LegacyOperatorSettingsFolderKind.Scene,
|
||||
@@ -34,7 +34,7 @@ public sealed class LegacyOperatorSettingsTests
|
||||
|
||||
Assert.True(result.IsValid);
|
||||
Assert.Equal(Path.GetFullPath(sceneDirectory), result.Folder!.CanonicalPath);
|
||||
Assert.Equal("baseline", File.ReadAllText(
|
||||
Assert.Equal("fixture-scene", File.ReadAllText(
|
||||
Path.Combine(result.Folder.CanonicalPath, "5001.t2s")));
|
||||
Assert.Contains("Cuts", result.Folder.AbbreviatedPath);
|
||||
Assert.InRange(
|
||||
@@ -42,9 +42,125 @@ public sealed class LegacyOperatorSettingsTests
|
||||
1,
|
||||
LegacyOperatorFolderValidator.DefaultDisplayCharacters);
|
||||
Assert.False(result.Folder.DatabaseIniDetected);
|
||||
Assert.Equal(
|
||||
LegacyOperatorFolderValidator.OptionalExternalAssetRelativePaths.Count,
|
||||
result.Folder.MissingOptionalExternalAssetCount);
|
||||
Assert.Null(result.WarningMessage);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SceneValidation_BaselineOnlyIsRejectedInsteadOfBreakingOtherScenesAfterRestart()
|
||||
{
|
||||
using var directory = new TemporaryDirectory();
|
||||
var sceneDirectory = directory.CreateDirectory("partial-Cuts");
|
||||
File.WriteAllText(Path.Combine(sceneDirectory, "5001.t2s"), "baseline");
|
||||
|
||||
var result = LegacyOperatorFolderValidator.Validate(
|
||||
LegacyOperatorSettingsFolderKind.Scene,
|
||||
sceneDirectory);
|
||||
|
||||
Assert.False(result.IsValid);
|
||||
Assert.Equal(
|
||||
LegacyOperatorFolderValidationFailure.RequiredFileMissing,
|
||||
result.Failure);
|
||||
Assert.Null(result.Folder);
|
||||
AssertPathFree(result.WarningMessage, sceneDirectory);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SceneValidation_MissingOneActiveSceneOrBuiltInAssetIsRejected()
|
||||
{
|
||||
using var directory = new TemporaryDirectory();
|
||||
var missingSceneDirectory = directory.CreateDirectory("missing-scene");
|
||||
WriteValidSceneFiles(missingSceneDirectory);
|
||||
File.Delete(Path.Combine(missingSceneDirectory, "5079.t2s"));
|
||||
var missingScene = LegacyOperatorFolderValidator.Validate(
|
||||
LegacyOperatorSettingsFolderKind.Scene,
|
||||
missingSceneDirectory);
|
||||
|
||||
var missingAssetDirectory = directory.CreateDirectory("missing-asset");
|
||||
WriteValidSceneFiles(missingAssetDirectory);
|
||||
File.Delete(Path.Combine(missingAssetDirectory, "Images", "KRX.png"));
|
||||
var missingAsset = LegacyOperatorFolderValidator.Validate(
|
||||
LegacyOperatorSettingsFolderKind.Scene,
|
||||
missingAssetDirectory);
|
||||
|
||||
Assert.False(missingScene.IsValid);
|
||||
Assert.Equal(LegacyOperatorFolderValidationFailure.RequiredFileMissing,
|
||||
missingScene.Failure);
|
||||
Assert.False(missingAsset.IsValid);
|
||||
Assert.Equal(LegacyOperatorFolderValidationFailure.RequiredFileMissing,
|
||||
missingAsset.Failure);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SceneValidation_RejectsEmptyRequiredOrPresentOptionalFiles()
|
||||
{
|
||||
using var directory = new TemporaryDirectory();
|
||||
var emptyRequiredDirectory = directory.CreateDirectory("empty-required");
|
||||
WriteValidSceneFiles(emptyRequiredDirectory);
|
||||
File.WriteAllBytes(Path.Combine(emptyRequiredDirectory, "5076.t2s"), []);
|
||||
var emptyRequired = LegacyOperatorFolderValidator.Validate(
|
||||
LegacyOperatorSettingsFolderKind.Scene,
|
||||
emptyRequiredDirectory);
|
||||
|
||||
var emptyOptionalDirectory = directory.CreateDirectory("empty-optional");
|
||||
WriteValidSceneFiles(emptyOptionalDirectory);
|
||||
var optionalPath = Path.Combine(emptyOptionalDirectory, "Video", "큐브배경.vrv");
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(optionalPath)!);
|
||||
File.WriteAllBytes(optionalPath, []);
|
||||
var emptyOptional = LegacyOperatorFolderValidator.Validate(
|
||||
LegacyOperatorSettingsFolderKind.Scene,
|
||||
emptyOptionalDirectory);
|
||||
|
||||
Assert.False(emptyRequired.IsValid);
|
||||
Assert.Equal(LegacyOperatorFolderValidationFailure.RequiredFileUnsafe,
|
||||
emptyRequired.Failure);
|
||||
Assert.False(emptyOptional.IsValid);
|
||||
Assert.Equal(LegacyOperatorFolderValidationFailure.RequiredFileUnsafe,
|
||||
emptyOptional.Failure);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SceneValidationContract_MatchesTheReachableCutRequirementManifest()
|
||||
{
|
||||
var manifestPath = Path.Combine(
|
||||
FindRepositoryRoot(),
|
||||
"scripts",
|
||||
"LegacyCutRequirements.json");
|
||||
using var document = JsonDocument.Parse(File.ReadAllBytes(manifestPath));
|
||||
var root = document.RootElement;
|
||||
var manifestScenes = root.GetProperty("activeAliases")
|
||||
.EnumerateArray()
|
||||
.Select(value => string.Concat(value.GetString(), ".t2s"))
|
||||
.ToArray();
|
||||
var manifestAssets = root.GetProperty("assets")
|
||||
.EnumerateArray()
|
||||
.Select(value => new
|
||||
{
|
||||
Kind = value.GetProperty("kind").GetString(),
|
||||
Path = value.GetProperty("path").GetString()!
|
||||
})
|
||||
.ToArray();
|
||||
|
||||
Assert.Equal(
|
||||
manifestScenes.OrderBy(value => value, StringComparer.Ordinal),
|
||||
LegacyOperatorFolderValidator.RequiredSceneFileNames
|
||||
.OrderBy(value => value, StringComparer.Ordinal));
|
||||
Assert.Equal(
|
||||
manifestAssets.Where(value => value.Kind != "Video")
|
||||
.Select(value => value.Path)
|
||||
.OrderBy(value => value, StringComparer.Ordinal),
|
||||
LegacyOperatorFolderValidator.RequiredBuiltInAssetRelativePaths
|
||||
.OrderBy(value => value, StringComparer.Ordinal));
|
||||
Assert.Equal(
|
||||
manifestAssets.Where(value => value.Kind == "Video")
|
||||
.Select(value => value.Path)
|
||||
.OrderBy(value => value, StringComparer.Ordinal),
|
||||
LegacyOperatorFolderValidator.OptionalExternalAssetRelativePaths
|
||||
.OrderBy(value => value, StringComparer.Ordinal));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SceneValidation_MissingBaselineFailsWithoutLeakingThePath()
|
||||
{
|
||||
@@ -229,7 +345,7 @@ public sealed class LegacyOperatorSettingsTests
|
||||
{
|
||||
using var directory = new TemporaryDirectory();
|
||||
var sceneDirectory = directory.CreateDirectory("Cuts");
|
||||
File.WriteAllText(Path.Combine(sceneDirectory, "5001.t2s"), "baseline");
|
||||
WriteValidSceneFiles(sceneDirectory);
|
||||
var resourceDirectory = directory.CreateDirectory("Res");
|
||||
WriteValidResourceFiles(resourceDirectory);
|
||||
var backgroundDirectory = directory.CreateDirectory("Background");
|
||||
@@ -395,6 +511,22 @@ public sealed class LegacyOperatorSettingsTests
|
||||
WriteComparisonFile(resourceDirectory);
|
||||
}
|
||||
|
||||
private static void WriteValidSceneFiles(string sceneDirectory)
|
||||
{
|
||||
foreach (var fileName in LegacyOperatorFolderValidator.RequiredSceneFileNames)
|
||||
{
|
||||
File.WriteAllText(Path.Combine(sceneDirectory, fileName), "fixture-scene");
|
||||
}
|
||||
|
||||
foreach (var relativePath in
|
||||
LegacyOperatorFolderValidator.RequiredBuiltInAssetRelativePaths)
|
||||
{
|
||||
var path = Path.Combine(sceneDirectory, relativePath);
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(path)!);
|
||||
File.WriteAllText(path, "fixture-asset");
|
||||
}
|
||||
}
|
||||
|
||||
private static void WriteFixedFile(
|
||||
string resourceDirectory,
|
||||
string fileName,
|
||||
@@ -463,6 +595,21 @@ public sealed class LegacyOperatorSettingsTests
|
||||
DecoderFallback.ExceptionFallback);
|
||||
}
|
||||
|
||||
private static string FindRepositoryRoot()
|
||||
{
|
||||
for (var current = new DirectoryInfo(AppContext.BaseDirectory);
|
||||
current is not null;
|
||||
current = current.Parent)
|
||||
{
|
||||
if (File.Exists(Path.Combine(current.FullName, "MBN_STOCK_WEBVIEW.sln")))
|
||||
{
|
||||
return current.FullName;
|
||||
}
|
||||
}
|
||||
|
||||
throw new DirectoryNotFoundException("Repository root was not found.");
|
||||
}
|
||||
|
||||
private sealed class TemporaryDirectory : IDisposable
|
||||
{
|
||||
public TemporaryDirectory()
|
||||
|
||||
Reference in New Issue
Block a user