v0.12.0
This commit is contained in:
@@ -8,6 +8,6 @@ bb7cd2c5b27c9dceec1d1d2846fbad9600df9c08e0ad07d13fcde97af533091c ./install.sh
|
||||
e00d211e3885e30d7fed1e43b44e6fdad40a67019060156c0641816a93e3365f ./network-debug.sh
|
||||
01952aa92b217f8eae2493b88870e2dec595100cd15c4d561ff11ae2b936c46f ./regenerate-sha.sh
|
||||
81345b6a0b51736bdbc98fd23199b62e4c721b4e7437e02dab7ea79b97dff29a ./service.sh
|
||||
c714e3cf2fba84ded718d102bd620cf879c1a8f3a5ae8f435be7863d8a0cd8e0 ./smoke.sh
|
||||
7e8f558b284362f55f50bd7223a89754a2a4960e746a27035cc61180f4a2da6f ./smoke.sh
|
||||
b50782b3742dfbf8a319c60571c968e93fdf8547db747c759edcffae68cb98bf ./update.sh
|
||||
4877f9e8217b6a77fb416722c3778373edac874ed3a583bb016ea76d4ffee7d4 ./verify_flow_logic.py
|
||||
0790b7b388467d9e75b621188cca473e22d73e01bcfa74e92fa23f92b0695855 ./verify_flow_logic.py
|
||||
|
||||
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
+7
-7
@@ -102,32 +102,32 @@ STALE_STATUS="$(curl -sS -o /dev/null -w '%{http_code}' -X PUT -H 'Content-Type:
|
||||
[[ "$STALE_STATUS" == "409" ]]
|
||||
|
||||
# Shared Flow inputs are source-only; comparisons belong exclusively to Flow references.
|
||||
curl -fsS "http://127.0.0.1:$PORT/api/settings" >"$TMP/settings-shared-input.json"
|
||||
curl -fsS "http://127.0.0.1:$PORT/api/settings/home-assistant" >"$TMP/settings-shared-input.json"
|
||||
python3 - "$TMP/settings-shared-input.json" "$TMP/settings-shared-input-put.json" <<'PYFLOW'
|
||||
import json,sys
|
||||
settings=json.load(open(sys.argv[1]))
|
||||
items=settings.setdefault("home_assistant",{}).setdefault("flow_inputs",[])
|
||||
items=settings.setdefault("flow_inputs",[])
|
||||
items=[item for item in items if item.get("id") != "smoke-shared-outdoor"]
|
||||
items.append({"id":"smoke-shared-outdoor","name":"Smoke outdoor value","kind":"outdoor_temperature","config":{}})
|
||||
settings["home_assistant"]["flow_inputs"]=items
|
||||
settings["flow_inputs"]=items
|
||||
json.dump(settings,open(sys.argv[2],"w"))
|
||||
PYFLOW
|
||||
curl -fsS -X PUT -H 'Content-Type: application/json' --data-binary @"$TMP/settings-shared-input-put.json" \
|
||||
"http://127.0.0.1:$PORT/api/settings" >"$TMP/settings-shared-input-result.json"
|
||||
"http://127.0.0.1:$PORT/api/settings/home-assistant" >"$TMP/settings-shared-input-result.json"
|
||||
python3 - "$TMP/settings-shared-input-result.json" <<'PYFLOW'
|
||||
import json,sys
|
||||
settings=json.load(open(sys.argv[1]))
|
||||
item=next(item for item in settings["home_assistant"]["flow_inputs"] if item["id"] == "smoke-shared-outdoor")
|
||||
item=next(item for item in settings["flow_inputs"] if item["id"] == "smoke-shared-outdoor")
|
||||
assert item["config"] == {}, item
|
||||
PYFLOW
|
||||
python3 - "$TMP/settings-shared-input-put.json" "$TMP/settings-shared-input-invalid.json" <<'PYFLOW'
|
||||
import json,sys
|
||||
settings=json.load(open(sys.argv[1]))
|
||||
item=next(item for item in settings["home_assistant"]["flow_inputs"] if item["id"] == "smoke-shared-outdoor")
|
||||
item=next(item for item in settings["flow_inputs"] if item["id"] == "smoke-shared-outdoor")
|
||||
item["config"]={"operator":"lt","value":20}
|
||||
json.dump(settings,open(sys.argv[2],"w"))
|
||||
PYFLOW
|
||||
INVALID_SHARED_STATUS="$(curl -sS -o /dev/null -w '%{http_code}' -X PUT -H 'Content-Type: application/json' --data-binary @"$TMP/settings-shared-input-invalid.json" "http://127.0.0.1:$PORT/api/settings")"
|
||||
INVALID_SHARED_STATUS="$(curl -sS -o /dev/null -w '%{http_code}' -X PUT -H 'Content-Type: application/json' --data-binary @"$TMP/settings-shared-input-invalid.json" "http://127.0.0.1:$PORT/api/settings/home-assistant")"
|
||||
[[ "$INVALID_SHARED_STATUS" == "400" ]]
|
||||
cat >"$TMP/flow-shared-value.json" <<EOF
|
||||
{"flow":{"name":"Shared value comparisons","enabled":true,"nodes":[{"id":"low","kind":"shared_input","x":20,"y":20,"config":{"input_id":"smoke-shared-outdoor","operator":"lt","value":20}},{"id":"high","kind":"shared_input","x":20,"y":140,"config":{"input_id":"smoke-shared-outdoor","operator":"gt","value":30}},{"id":"either","kind":"logic_or","x":220,"y":80,"config":{}},{"id":"action","kind":"zone_thermostat","x":420,"y":80,"config":{"zone_id":"$ZONE_ID","preset":"comfort","mode":"auto","cooldown_seconds":60}}],"edges":[{"id":"e1","from":"low","to":"either"},{"id":"e2","from":"high","to":"either"},{"id":"e3","from":"either","to":"action"}]},"overrides":{"low":15,"high":15},"log":false}
|
||||
|
||||
Regular → Executable
Regular → Executable
+2
-2
@@ -423,7 +423,7 @@ def main():
|
||||
check('on-change value mode needs one direct source/condition input' in api, 'on-change value-source guard missing')
|
||||
models=(ROOT/'src/models/flow.rs').read_text()
|
||||
core=(ROOT/'web/js/core.js').read_text()
|
||||
settings_api=(ROOT/'src/api/settings.rs').read_text()
|
||||
configuration_api=(ROOT/'src/api/configuration.rs').read_text()
|
||||
check('pub draft: bool' in models and '#[serde(default)]' in models, 'Flow draft persistence field missing')
|
||||
check('fn validate_flow_draft_graph' in api, 'draft structural validator missing')
|
||||
check(api.count('if input.draft { validate_flow_draft_graph(&input)?; } else { validate_flow_graph(&input)?; }') >= 3, 'draft create/update/import validation split missing')
|
||||
@@ -431,7 +431,7 @@ def main():
|
||||
check(api.count('(prepare_draft_flow(flow), vec![], vec![])') >= 3, 'draft save/import may compile executable outputs')
|
||||
check('flow.compiled_schedule_ids.clear()' in api and 'flow.compiled_automation_ids.clear()' in api, 'draft output clearing missing')
|
||||
check('"draft": flow.draft' in api, 'draft state missing from Flow export')
|
||||
check('import contains an executable Flow draft' in settings_api, 'configuration import does not enforce draft safety invariant')
|
||||
check('import contains an executable Flow draft' in configuration_api, 'configuration import does not enforce draft safety invariant')
|
||||
check('error.status = response.status' in core, 'frontend API errors do not expose HTTP validation status')
|
||||
check("error.status !== 400" in js and "draft:true" in js and "enabled:false" in js, 'save-as-draft retry flow missing')
|
||||
check("if (flow.draft) return toast(tr('flow.draftCannotEnable')" in js, 'draft quick-enable guard missing')
|
||||
|
||||
Reference in New Issue
Block a user