Files
MBN_STOCK_WEBVIEW/tests/MBN_STOCK_WEBVIEW.LegacyWeb.Tests/LegacyFsellPackageInputContractTests.cs

129 lines
5.0 KiB
C#

namespace MBN_STOCK_WEBVIEW.LegacyWeb.Tests;
public sealed class LegacyFsellPackageInputContractTests
{
private static readonly string Harness = File.ReadAllText(Path.Combine(
FindRepositoryRoot(),
"scripts",
"Test-LegacyPackageInput.mjs"));
[Fact]
public void FsellCellEditUsesPackagedPointerTextAndFocusChangeBeforeNativeDraftCheck()
{
var helper = Slice(
Harness,
"async function replaceManualNetSellCell",
"async function confirmManualNetSellAndVerifyReadback");
AssertInOrder(
helper,
"await replaceText(expression, value, label);",
"await pressKey(\"Tab\"",
"snapshot.state.revision > before.state.revision",
"snapshot.state.manualLists?.netRowsAreFresh === false",
"snapshot.state.manualLists?.writesQuarantined !== true",
"JSON.stringify(netSellProjection(snapshot)) === JSON.stringify(expectedRows)");
Assert.DoesNotContain("Runtime.evaluate", helper, StringComparison.Ordinal);
Assert.DoesNotContain(".value =", helper, StringComparison.Ordinal);
}
[Fact]
public void FsellSaveIsIssuedOnceAndRequiresCorrelatedFreshReadBeforeContinuing()
{
var helper = Slice(
Harness,
"async function confirmManualNetSellAndVerifyReadback",
"function viProjection");
Assert.Equal(
1,
helper.Split(
"await pointerClick(modalButtonByTextExpression(\"확인\"), label);",
StringSplitOptions.None).Length - 1);
AssertInOrder(
helper,
"before.state.manualLists?.canSave !== true",
"await pointerClick(modalButtonByTextExpression(\"확인\"), label);",
"snapshot.state.manualLists?.isOpen === false",
"snapshot.state.manualLists?.netRowsAreFresh === true",
"snapshot.state.manualLists?.writesQuarantined !== true",
"JSON.stringify(netSellProjection(snapshot)) === JSON.stringify(expectedRows)",
"snapshot.state.playlist.length === before.state.playlist.length + 1");
}
[Fact]
public void FsellRoundTripPersistsUniqueTemporaryValueThenRestoresExactBaseline()
{
var sequence = Slice(
Harness,
"\"fixed-245\", \"net-sell\", \"individual\", \"FSell save reopen\"");
Assert.Contains("randomBytes(3).readUIntBE(0, 3)", sequence,
StringComparison.Ordinal);
Assert.Equal(
2,
sequence.Split("await replaceManualNetSellCell(",
StringSplitOptions.None).Length - 1);
Assert.Equal(
2,
sequence.Split("await confirmManualNetSellAndVerifyReadback(",
StringSplitOptions.None).Length - 1);
AssertInOrder(
sequence,
"temporaryRows[0].leftAmount = temporaryLeftAmount;",
"\"FSell row 1 left amount temporary input\"",
"\"FSell temporary value confirm save\"",
"fsellRoundTrip.mutationSaveVerified = true;",
"\"FSell temporary value fresh read\"",
"fsellRoundTrip.mutationFreshReadVerified = true;",
"individualBaseline[0].leftAmount, individualBaseline",
"\"FSell original value confirm restore\"",
"fsellRoundTrip.restoreSaveVerified = true;",
"\"FSell restored fresh read\"",
"JSON.stringify(netSellProjection(current)) !== JSON.stringify(individualBaseline)",
"fsellRoundTrip.restoreFreshReadVerified = true;");
Assert.Contains("restored: true", sequence, StringComparison.Ordinal);
}
private static string Slice(string source, string start, string? end = null)
{
var startIndex = source.IndexOf(start, StringComparison.Ordinal);
Assert.True(startIndex >= 0, $"Start marker was not found: {start}");
if (end is null)
{
return source[startIndex..];
}
var endIndex = source.IndexOf(end, startIndex, StringComparison.Ordinal);
Assert.True(endIndex > startIndex, $"End marker was not found: {end}");
return source[startIndex..endIndex];
}
private static void AssertInOrder(string source, params string[] markers)
{
var cursor = 0;
foreach (var marker in markers)
{
var index = source.IndexOf(marker, cursor, StringComparison.Ordinal);
Assert.True(index >= cursor, $"Marker was missing or out of order: {marker}");
cursor = index + marker.Length;
}
}
private static string FindRepositoryRoot()
{
var directory = new DirectoryInfo(AppContext.BaseDirectory);
while (directory is not null)
{
if (File.Exists(Path.Combine(directory.FullName, "MBN_STOCK_WEBVIEW.sln")))
{
return directory.FullName;
}
directory = directory.Parent;
}
throw new DirectoryNotFoundException("Repository root was not found.");
}
}