110 lines
5.3 KiB
JavaScript
110 lines
5.3 KiB
JavaScript
const assert = require("node:assert/strict");
|
|
const fs = require("node:fs");
|
|
const path = require("node:path");
|
|
const test = require("node:test");
|
|
|
|
const root = path.resolve(__dirname, "..", "..");
|
|
const harness = fs.readFileSync(path.join(
|
|
root, "scripts", "Test-LegacyPackageLocalStateSmoke.mjs"), "utf8");
|
|
const wrapper = fs.readFileSync(path.join(
|
|
root, "scripts", "Invoke-LegacyPackageLocalStateSmoke.ps1"), "utf8");
|
|
const shared = fs.readFileSync(path.join(
|
|
root, "scripts", "Invoke-LegacyPackageInputSmoke.ps1"), "utf8");
|
|
|
|
test("local-state package smoke is a closed thirteen-step physical-input plan", () => {
|
|
assert.match(harness, /nextInputSequence !== 14/u);
|
|
assert.match(harness, /evidence\.exchanges\.length !== 13/u);
|
|
assert.match(wrapper, /exchangeCount = \$ExpectedExchangePlan\.Count/u);
|
|
assert.match(wrapper, /physicalClickCount/u);
|
|
assert.match(wrapper, /folderPickerCancelCount/u);
|
|
assert.match(wrapper, /\[string\]\$LegacyDataDirectory/u);
|
|
assert.match(wrapper,
|
|
/'\.\.\\MBN_STOCK_N\\MBN_STOCK_N\\bin\\Debug\\Data'/u);
|
|
assert.doesNotMatch(wrapper, /C:\\Users\\[^\\]+/iu);
|
|
assert.match(wrapper, /fileObservationCount/u);
|
|
assert.match(wrapper, /inputRetryCount = 0/u);
|
|
assert.match(wrapper, /function Read-LocalHarnessEvidenceFile/u);
|
|
assert.match(wrapper, /item\.Length -gt 128KB/u);
|
|
assert.doesNotMatch(wrapper,
|
|
/Read-SmallJsonEvidenceFile \$EvidencePath 'Local-state harness evidence'/u);
|
|
});
|
|
|
|
test("three app-owned folder pickers are clicked once and Escape-cancelled", () => {
|
|
for (const [target, kind] of [
|
|
["design-folder-picker", "design"],
|
|
["resource-folder-picker", "resource"],
|
|
["background-folder-picker", "background"]
|
|
]) {
|
|
assert.ok(harness.includes(`[\"${target}\", \"${kind}\"]`));
|
|
}
|
|
assert.match(wrapper, /Wait-UniqueOwnedFolderPicker/u);
|
|
assert.match(wrapper, /OwnerChainContains/u);
|
|
assert.match(wrapper, /VisibleTopLevelWindows/u);
|
|
assert.match(wrapper, /EnumWindows\(callback, IntPtr\.Zero\)/u);
|
|
assert.match(wrapper, /AutomationElement\]::FromHandle\(\$handle\)/u);
|
|
assert.match(wrapper, /\$windowClass -cne '#32770'/u);
|
|
assert.match(wrapper, /\$revalidated\[0\]\.Handle -ne \$picker\.Handle/u);
|
|
assert.match(wrapper, /ControlType\]::Button/u);
|
|
assert.match(wrapper, /Current\.ClassName -ceq 'Button'/u);
|
|
assert.match(wrapper, /\$automationId -ceq '1'/u);
|
|
assert.match(wrapper, /\$automationId -ceq '2'/u);
|
|
assert.match(wrapper, /WindowPattern\]::Pattern/u);
|
|
assert.match(wrapper, /\$windowPattern\.Current\.IsModal/u);
|
|
assert.match(wrapper, /AcquireOwnedForeground/u);
|
|
assert.match(wrapper, /OwnerChainContains\(window, expectedOwner\)/u);
|
|
assert.match(wrapper, /SendEscapeToForegroundWindow/u);
|
|
assert.match(harness, /waitForTrustedPointerClick/u);
|
|
assert.match(harness, /isTrusted: event\.isTrusted === true/u);
|
|
assert.match(wrapper, /closedAfterEscape = \$true/u);
|
|
assert.match(wrapper, /not destroyed after the one Escape input/u);
|
|
assert.match(wrapper, /settings file changed during a cancel-only smoke/u);
|
|
});
|
|
|
|
test("comparison import preflight and idempotence are exact", () => {
|
|
for (const hash of [
|
|
"1EE76BC464FB1C44C8B6546E99CDC21C726C0E2C24AD344F5C19AE41BFC0D2F2",
|
|
"13C07BA64587549EDA9C1A694F3DFA19875CB1F888F02C9E071F17C47739E087"
|
|
]) {
|
|
assert.ok(harness.includes(hash));
|
|
assert.ok(wrapper.includes(hash));
|
|
}
|
|
assert.match(harness, /receipt\?\.addedPairCount === 8/u);
|
|
assert.match(harness, /receipt\?\.addedPairCount === 0/u);
|
|
assert.match(harness, /receipt\?\.skippedDuplicateCount === 8/u);
|
|
assert.equal((harness.match(
|
|
/allowBusy: true, allowDialog: true, timeoutMilliseconds: 90_000/g) || []).length, 2);
|
|
assert.match(harness, /secondImportIdempotent = true/u);
|
|
assert.match(harness, /rowId: pair\.rowId/u);
|
|
assert.match(harness, /displayLabel: pair\.displayLabel/u);
|
|
assert.match(harness, /initialPair\.displayLabel !== "KRX100지수 ↔ 코스피 지수"/u);
|
|
assert.doesNotMatch(harness, /pair\.first\?\.displayName|pair\.second\?\.displayName/u);
|
|
assert.match(wrapper, /second import changed the comparison file/u);
|
|
});
|
|
|
|
test("tracked harness cannot synthesize WebView clicks or close the app", () => {
|
|
assert.match(harness, /"Input\.dispatchMouseEvent"/u);
|
|
assert.doesNotMatch(harness, /rpc\("Input\.dispatchMouseEvent"/u);
|
|
assert.doesNotMatch(harness, /rpc\("Input\.dispatchKeyEvent"/u);
|
|
assert.doesNotMatch(harness, /rpc\("(?:Browser|Page)\.close"/u);
|
|
assert.match(shared, /\[switch\]\$DefinitionsOnly/u);
|
|
assert.match(shared, /public static void SendApplicationClick\(/u);
|
|
assert.match(shared, /public static void SendEscapeToForegroundWindow\(/u);
|
|
assert.match(shared, /Key-up only releases the/u);
|
|
assert.match(shared, /caller separately proves that this exact/u);
|
|
assert.doesNotMatch(shared, /lost foreground before Escape was released/u);
|
|
});
|
|
|
|
test("initial native-state race is input-free and stdin cannot hold the helper open", () => {
|
|
assert.match(harness, /process\.stdin\.unref/u);
|
|
assert.match(harness,
|
|
/label !== "DryRun IDLE preflight"[\s\S]*Only the input-free initial preflight/u);
|
|
assert.match(harness,
|
|
/\{ allowBusy: false, allowMissingState: true \}/u);
|
|
assert.match(harness,
|
|
/last\.safety\.outboundMessages\.map\(row => row\.type\)/u);
|
|
assert.match(harness,
|
|
/last\.safety\.blockedOutboundMessages\.length/u);
|
|
assert.match(harness,
|
|
/last\.dom\.connectionText !== "DRY RUN"/u);
|
|
});
|