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."); } }