Unify K1 discovery ownership and verification across enrollment paths
This commit is contained in:
@@ -16,6 +16,7 @@ let K1ConnectionPipelines;
|
||||
let physicalRecoveryConnectionDetail;
|
||||
let shouldRenderK1OperationalPanels;
|
||||
let K1ProvisioningPipeline;
|
||||
let K1WifiPasswordField;
|
||||
let RuntimeActionFenceTestContext;
|
||||
let LOCAL_OPERATION_PROGRESS_DELAY_MILLISECONDS;
|
||||
let emptySearchPresentation;
|
||||
@@ -102,6 +103,9 @@ before(async () => {
|
||||
logLevel: "silent",
|
||||
server: { middlewareMode: true },
|
||||
});
|
||||
({K1WifiPasswordField} = await server.ssrLoadModule(
|
||||
"@xgrids-k1/frontend/components/K1WifiPasswordField.tsx",
|
||||
));
|
||||
({ normalizeXgridsK1MissionState } = await server.ssrLoadModule(
|
||||
"@xgrids-k1/frontend/runtimeContext.tsx",
|
||||
));
|
||||
@@ -277,7 +281,7 @@ test("K1 one-intent source contract makes mode reset explicit and keeps device I
|
||||
assert.match(resultRows, /onSelect=\{\(\) => selectCandidate\(device\)\}/);
|
||||
assert.doesNotMatch(resultRows, /Переподключиться|reopen|verifyConnection/);
|
||||
assert.match(source, /onChange=\{\(event\) => setSsid\(event\.target\.value\)\}/);
|
||||
assert.match(source, /onChange=\{\(event\) => setPassword\(event\.target\.value\)\}/);
|
||||
assert.match(source, /<K1WifiPasswordField[\s\S]*?onChange=\{setPassword\}/);
|
||||
|
||||
assert.equal((apply.match(/await connect\(/g) ?? []).length, 1);
|
||||
assert.doesNotMatch(
|
||||
@@ -290,9 +294,13 @@ test("K1 one-intent source contract makes mode reset explicit and keeps device I
|
||||
source,
|
||||
/(?:color|background(?:-color)?):\s*(?:#[0-9a-f]{3,8}|rgba?\()/i,
|
||||
);
|
||||
const passwordSource = readFileSync(new URL(
|
||||
"../../../plugins/xgrids-k1/frontend/src/components/K1WifiPasswordField.tsx", import.meta.url,
|
||||
), "utf8");
|
||||
for (const sharedControl of ["Button", "IconButton", "TextField", "ActivityIndicator", "StatusBadge"]) {
|
||||
assert.match(source, new RegExp(`<${sharedControl}\\b`), sharedControl);
|
||||
assert.match(source + passwordSource, new RegExp(`<${sharedControl}\\b`), sharedControl);
|
||||
}
|
||||
assert.doesNotMatch(passwordSource, /<(?:button|input)\b/);
|
||||
assert.equal((source.match(/buttonLabel:\s*"Применить"/g) ?? []).length, 3);
|
||||
assert.match(source, /устарел|stale/i);
|
||||
assert.match(source, /network_outcome_unknown|safe_to_retry/i);
|
||||
@@ -1181,7 +1189,7 @@ function elementByProp(node, propName, expectedValue) {
|
||||
return elementByProp(node.props.children, propName, expectedValue);
|
||||
}
|
||||
|
||||
function createStatefulProvisioningHarness(initialProps) {
|
||||
function createStatefulProvisioningHarness(initialProps, Component = K1ProvisioningPipeline) {
|
||||
const hookSlots = [];
|
||||
let currentProps = initialProps;
|
||||
let capturedTree = null;
|
||||
@@ -1296,7 +1304,7 @@ function createStatefulProvisioningHarness(initialProps) {
|
||||
};
|
||||
|
||||
try {
|
||||
capturedTree = K1ProvisioningPipeline(currentProps);
|
||||
capturedTree = Component(currentProps);
|
||||
} finally {
|
||||
dispatcher.useState = originals.useState;
|
||||
dispatcher.useRef = originals.useRef;
|
||||
@@ -4669,23 +4677,11 @@ test("post-reset Scan selects the exact prior UUID locally and opens network fie
|
||||
"local selection must not manufacture a backend Apply attempt",
|
||||
);
|
||||
|
||||
const passwordField = elementByProp(tree, "label", "Пароль Wi‑Fi");
|
||||
const passwordField = elementByProp(tree, "placeholder", "Введите пароль");
|
||||
assert.ok(passwordField);
|
||||
assert.equal(passwordField.props.type, "password");
|
||||
passwordField.props.onChange({ target: { value: "test-only-password" } });
|
||||
passwordField.props.onChange("test-only-password");
|
||||
tree = harness.render(props());
|
||||
harness.flushEffects();
|
||||
const showPassword = elementByProp(tree, "label", "Показать пароль");
|
||||
assert.ok(showPassword);
|
||||
assert.equal(showPassword.props.disabled, false);
|
||||
showPassword.props.onClick();
|
||||
tree = harness.render(props());
|
||||
harness.flushEffects();
|
||||
assert.equal(
|
||||
elementByProp(tree, "label", "Пароль Wi‑Fi").props.type,
|
||||
"text",
|
||||
);
|
||||
assert.ok(elementByProp(tree, "label", "Скрыть пароль"));
|
||||
|
||||
const chooseAnother = actionByLabel(tree, "Выбрать другое");
|
||||
assert.ok(chooseAnother);
|
||||
@@ -7333,7 +7329,7 @@ test("Step-2 credentials and Apply share one canonical field stack", () => {
|
||||
|
||||
assert.match(
|
||||
form,
|
||||
/:\s*\(\s*<div className="field-stack"[\s\S]*?label="Пароль Wi‑Fi"[\s\S]*?\{applyAction\}\s*<\/div>/,
|
||||
/:\s*\(\s*<div className="field-stack"[\s\S]*?<K1WifiPasswordField[\s\S]*?\{applyAction\}\s*<\/div>/,
|
||||
);
|
||||
assert.match(form, /disabled=\{provisioningFieldsDisabled\}/);
|
||||
assert.match(form, /value=\{connectionAttemptOwnsDraft \? "" : password\}/);
|
||||
@@ -7769,3 +7765,26 @@ test("a failed Connect after completed Bluetooth search exposes recovery instead
|
||||
assert.match(markup, /K1 ответил ошибкой Bluetooth/);
|
||||
assert.doesNotMatch(markup, /Подключение не выполнено|дождитесь, пока система|private transport exception|Пароль передан/);
|
||||
});
|
||||
|
||||
|
||||
test("shared K1 password field reveals on demand and hides after clearing", () => {
|
||||
let value = "";
|
||||
const props = () => ({value, onChange:next=>{value=next;}, disabled:false});
|
||||
const harness = createStatefulProvisioningHarness(props(), K1WifiPasswordField);
|
||||
try {
|
||||
let tree = harness.render(props());
|
||||
assert.equal(elementByProp(tree, "label", "Показать пароль").props.disabled, true);
|
||||
elementByProp(tree, "label", "Пароль Wi‑Fi").props.onChange({target:{value:"test-only-value"}});
|
||||
tree = harness.render(props()); harness.flushEffects();
|
||||
elementByProp(tree, "label", "Показать пароль").props.onClick();
|
||||
tree = harness.render(props());
|
||||
assert.equal(elementByProp(tree, "label", "Пароль Wi‑Fi").props.type, "text");
|
||||
assert.equal(elementByProp(tree, "label", "Скрыть пароль").props['aria-pressed'], true);
|
||||
value = "";
|
||||
tree = harness.render(props()); harness.flushEffects();
|
||||
tree = harness.render(props());
|
||||
assert.equal(elementByProp(tree, "label", "Пароль Wi‑Fi").props.type, "password");
|
||||
assert.equal(elementByProp(tree, "label", "Показать пароль").props.disabled, true);
|
||||
assert.equal(elementByProp(tree, "label", "Пароль Wi‑Fi").props.autoComplete, "off");
|
||||
} finally { harness.dispose(); }
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user