mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-14 20:48:17 +08:00
116 lines
5.8 KiB
Lua
116 lines
5.8 KiB
Lua
-- AP selection through the real controller and the real bridge.
|
||
--
|
||
-- The policy and its pinned BSSID have to survive the trip from the dialog to
|
||
-- the daemon unchanged, the wired half has to be cleared rather than carried,
|
||
-- and a refusal has to reach the user instead of being swallowed into a save
|
||
-- that appears to have worked.
|
||
local repo = ... or "."
|
||
local harness = dofile(repo .. "/tests/lua/controller_harness.lua")(repo)
|
||
local controller = harness.controller
|
||
local schema = require "luci.smart_srun.schema"
|
||
|
||
assert(schema.normalize_ap_selection(nil, "02:11:22:33:44:55") == "fixed")
|
||
assert(schema.normalize_ap_selection("auto", "02:11:22:33:44:55") == "auto")
|
||
|
||
local CONFIG = {
|
||
revision = 3,
|
||
selection = { active_campus_id = "c1", default_campus_id = "c1" },
|
||
campus_accounts = { { id = "c1", label = "one", access_mode = "wifi", ssid = "Campus",
|
||
bssid = "02:11:22:33:44:55", ap_selection = "fixed", login = {} } },
|
||
hotspot_profiles = {},
|
||
}
|
||
|
||
harness.responses["config.get"] = CONFIG
|
||
harness.responses["campus.upsert"] = { config_revision = 4, id = "c1" }
|
||
|
||
for _, policy in ipairs({ "auto", "strongest", "fixed" }) do
|
||
harness.reset()
|
||
harness.form = { action = "edit_campus", id = "c1", expected_revision = "3", access_mode = "wifi",
|
||
ap_selection = policy, bssid = "02:11:22:33:44:55", ssid = "Campus" }
|
||
controller.action_enqueue()
|
||
local call = assert(harness.last_call("campus.upsert"), "the save must reach the daemon")
|
||
assert(call.started, "a save may start the service")
|
||
assert(call.params.expected_revision == 3, "the save carries the browser revision")
|
||
local account = call.params.account
|
||
assert(account.id == "c1", account.id)
|
||
assert(account.ap_selection == policy, account.ap_selection)
|
||
assert(account.bssid == "02:11:22:33:44:55", account.bssid)
|
||
assert(harness.output.ok == true, harness.output.message)
|
||
assert(harness.output.message == "已更新", harness.output.message)
|
||
assert(#harness.writes == 0, "the page must not write any file")
|
||
end
|
||
|
||
-- An unset policy with a pinned address still means "fixed": the frozen dialog
|
||
-- can submit an empty selector, and losing the pin would silently roam.
|
||
harness.reset()
|
||
harness.form = { action = "edit_campus", id = "c1", expected_revision = "3", access_mode = "wifi",
|
||
ap_selection = "", bssid = "02:11:22:33:44:55", ssid = "Campus" }
|
||
controller.action_enqueue()
|
||
assert(harness.last_call("campus.upsert").params.account.ap_selection == "fixed")
|
||
|
||
-- The wired half clears the wireless one, so a stored account never carries an
|
||
-- effective setting for the mode it is not in.
|
||
harness.reset()
|
||
harness.form = { action = "edit_campus", id = "c1", expected_revision = "3", access_mode = "wired",
|
||
wired_iface = "wan", ap_selection = "fixed", bssid = "02:11:22:33:44:55" }
|
||
controller.action_enqueue()
|
||
local wired = harness.last_call("campus.upsert").params.account
|
||
assert(wired.ssid == "" and wired.bssid == "" and wired.radio == "", "wireless half must be cleared")
|
||
assert(wired.ap_selection == "auto", wired.ap_selection)
|
||
assert(wired.wired_iface == "wan", wired.wired_iface)
|
||
|
||
-- Validation lives in the daemon now. What the page owes the user is the
|
||
-- refusal, in the daemon's own words, with nothing saved.
|
||
harness.reset()
|
||
harness.responses["campus.upsert"] = {
|
||
error = { code = "InvalidConfig", message = "不是有效的单播 BSSID(形如 aa:bb:cc:dd:ee:ff)",
|
||
field = "campus_accounts[0].bssid" },
|
||
}
|
||
harness.form = { action = "edit_campus", id = "c1", expected_revision = "3", access_mode = "wifi",
|
||
ap_selection = "fixed", bssid = "01:11:22:33:44:55", ssid = "Campus" }
|
||
controller.action_enqueue()
|
||
assert(harness.output.ok == false, "an invalid address must not report success")
|
||
assert(harness.output.message:find("单播 BSSID", 1, true), harness.output.message)
|
||
assert(#harness.writes == 0)
|
||
harness.responses["campus.upsert"] = { config_revision = 5, id = "c1" }
|
||
|
||
-- The status answer reports the wireless detail it actually has. The daemon's
|
||
-- projection does not carry SSID, BSSID, signal or channel yet (batch B), and
|
||
-- the page publishes them empty rather than repeating the configuration as if
|
||
-- it had been observed.
|
||
harness.reset()
|
||
harness.responses["status.get"] = {
|
||
service = "running", enabled = true, config_revision = 3,
|
||
written_at = "2026-09-18T12:00:00Z",
|
||
accounts = { { account_id = "c1", link = "Ready", auth = "VerifiedSelf",
|
||
connectivity = "InternetReachable", identity = "student" } },
|
||
actions = {},
|
||
wireless = { state = "associated", device = "phy1-sta0", ssid = "Campus",
|
||
bssid = "02:11:22:33:44:55", signal = -52, channel = 44, iface = "wwan" },
|
||
}
|
||
controller.action_status()
|
||
local status = harness.output
|
||
assert(status.current_ssid == "Campus", status.current_ssid)
|
||
assert(status.current_bssid == "02:11:22:33:44:55", status.current_bssid)
|
||
assert(status.current_signal == -52 and status.current_channel == 44)
|
||
assert(status.ap_selection_policy == "fixed" and status.ap_selection_reason == "已连接指定接入点")
|
||
assert(status.connectivity_level == "online", status.connectivity_level)
|
||
|
||
-- A line that is not ready claims nothing about the air.
|
||
harness.reset()
|
||
harness.responses["status.get"] = {
|
||
service = "running", enabled = true, written_at = "2026-09-18T12:00:00Z",
|
||
accounts = { { account_id = "c1", link = "LinkDown", auth = "Unknown", connectivity = "Offline" } },
|
||
actions = {},
|
||
}
|
||
controller.action_status()
|
||
assert(harness.output.current_ssid == "", harness.output.current_ssid)
|
||
assert(harness.output.campus_ssid == "Campus", "the configured SSID is still shown as configured")
|
||
|
||
for _, event in ipairs({ "ap_selection", "ap_association" }) do
|
||
local line = controller.friendly_line("[2026-06-01 22:00:00] INFO " .. event .. " | fixture")
|
||
assert(not line:find(event, 1, true), line)
|
||
end
|
||
|
||
print("ap selection probe: ok")
|