Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
9547c47
philips-hue: fix process_rest_response mangling dkjson.decode's return
varzac Aug 12, 2026
6eedf8a
philips-hue: add capability command -> REST request integration tests
varzac Aug 12, 2026
f633227
philips-hue: add refresh -> attribute event integration tests
varzac Aug 13, 2026
a55ffd0
philips-hue: add bridge discovery & pairing integration tests
varzac Aug 13, 2026
d51eece
philips-hue: add child device stray-handling lifecycle test
varzac Aug 13, 2026
cdcc2d4
philips-hue: fix onmessage misreading json.decode's position as an error
varzac Aug 13, 2026
02a7b85
philips-hue: add SSE bridge event-stream integration tests
varzac Aug 13, 2026
9bef830
philips-hue: bound scan_groups and connectivity-poll retry loops
varzac Aug 13, 2026
4e6044f
philips-hue: suppress group scanning outside tests that exercise it
varzac Aug 13, 2026
1b1b27d
philips-hue: opt into cosock's test-coroutine-priority scheduling
varzac Aug 13, 2026
43b1425
philips-hue: restore full SSE reconnect test
varzac Aug 13, 2026
3dcec07
philips-hue: rename expect_http_request to assert_http_request_received
varzac Aug 14, 2026
ce36b9f
philips-hue: remove maximum retry limit for group membership scanning
varzac Aug 14, 2026
091dcd8
philips-hue: remove maximum retry limit for connectivity polling
varzac Aug 14, 2026
8dac59e
philips-hue: add color control command tests
varzac Aug 14, 2026
2076439
philips-hue: document profile compatibility in command tests
varzac Aug 14, 2026
3322a3a
philips-hue: add generic child device test fixture helper
varzac Aug 14, 2026
e8dde8c
philips-hue: add button device SSE integration tests
varzac Aug 14, 2026
7fa6287
philips-hue: add multi-button and motion sensor SSE tests
varzac Aug 14, 2026
beec44d
philips-hue: extract SSE test helpers and documentation
varzac Aug 14, 2026
882eff5
philips-hue: add contact sensor SSE integration tests
varzac Aug 14, 2026
896179a
philips-hue: add error handling integration tests
varzac Aug 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion drivers/SmartThings/philips-hue/src/hue/api.lua
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,11 @@ local function process_rest_response(response, err, partial, err_callback)
)
end

return table.unpack(json_result, 1, json_result.n)
-- json.decode (dkjson) returns (value, next_position, error_message) -- only the first of
-- those is the decoded value this function documents returning; propagating all of them
-- here means the *parse position* gets misinterpreted as this function's `err` return by
-- every caller, on every successful decode.
return json_result[1]
else
return nil, "no response or error received"
end
Expand Down
424 changes: 424 additions & 0 deletions drivers/SmartThings/philips-hue/src/test/hue_test_helpers.lua

Large diffs are not rendered by default.

122 changes: 122 additions & 0 deletions drivers/SmartThings/philips-hue/src/test/test_hue_bridge_discovery.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
local test = require "integration_test"
local lan_test_utils = require "integration_test.lan_test_utils"
local mock_mdns = require "integration_test.mock_mdns"
local mock_devices_api = require "integration_test.mock_devices_api"

local Discovery = require "disco"

local BRIDGE_IP = "192.168.1.20"
local BRIDGE_MAC = "aa-bb-cc-dd-ee-ff"
local BRIDGE_DNI = "AABBCCDDEEFF" -- BRIDGE_MAC with separators stripped, uppercased
local BRIDGE_NAME = "Living Room"

test.add_test_env_setup_func(function(driver)
-- disco is a module-level singleton that persists across tests within this file; a stale
-- discovery_active=true (e.g. left over from an interrupted prior run) would make
-- HueDiscovery.discover silently no-op.
Discovery.discovery_active = false
Discovery.api_keys = {}
Discovery.disco_api_instances = {}
end)

local function test_init()
-- No bridge device is pre-registered here -- discovering and creating it is exactly what
-- these tests exercise.
end

test.set_test_init_function(test_init)

--- Queue an mDNS response for the bridge and start discovery via the same "discovery" channel
--- message the real hub sends when a user initiates a scan (see
--- st.handlers.discovery_message_handlers), rather than invoking Discovery.discover directly:
--- that function makes real (mocked) blocking REST calls internally via cosock, which only
--- works correctly inside a real cosock-managed thread -- exactly what the framework's own
--- discovery dispatch spins up, and what the test coroutine itself is not.
local function start_discovery()
mock_mdns.__queue_response(Discovery.ServiceType, Discovery.Domain, {
found = {
mock_mdns.build_event({
name = "Hue Bridge",
service_type = Discovery.ServiceType,
domain = Discovery.Domain,
address = BRIDGE_IP,
port = 443,
}),
},
})
test.socket.discovery:__queue_receive({ "start", {} })
end

--- Discovery.discover loops "scan, sleep 1s" until told to stop; without this it would keep
--- retrying (and re-sending requests) forever.
local function stop_discovery()
test.socket.discovery:__queue_receive({ "stop" })
end

test.register_coroutine_test(
"mDNS discovery finds a bridge and requests an API key, but does not create a device if the Link Button hasn't been pressed",
function()
local bridge_server = lan_test_utils.build_mock_server(BRIDGE_IP, 443)
bridge_server:queue_http_response(200, {}, {
mac = BRIDGE_MAC,
swversion = "1968054000",
modelid = "BSB002",
name = BRIDGE_NAME,
})
bridge_server:queue_http_response(200, {}, {
{ error = { type = 101, address = "/", description = "link button not pressed" } },
})

start_discovery()
test.wait_for_events()
stop_discovery()
test.wait_for_events()

bridge_server:assert_http_request_received("GET", "/api/config")
bridge_server:assert_http_request_received(
"POST",
"/api",
{ body = { devicetype = "smartthings_edge_driver#" .. BRIDGE_IP, generateclientkey = true } }
)
end
)

test.register_coroutine_test(
"mDNS discovery creates a bridge device once an API key is obtained",
function()
local bridge_server = lan_test_utils.build_mock_server(BRIDGE_IP, 443)
bridge_server:queue_http_response(200, {}, {
mac = BRIDGE_MAC,
swversion = "1968054000",
modelid = "BSB002",
name = BRIDGE_NAME,
})
bridge_server:queue_http_response(200, {}, {
{ success = { username = "new-bridge-api-key", client_key = "some-client-key" } },
})

mock_devices_api.__expect_create_device({
deviceNetworkId = BRIDGE_DNI,
label = BRIDGE_NAME,
profileReference = "hue-bridge",
manufacturer = "Signify Netherlands B.V.",
model = "BSB002",
vendorProvidedLabel = BRIDGE_NAME,
type = "LAN",
})

start_discovery()
test.wait_for_events()
stop_discovery()
test.wait_for_events()

bridge_server:assert_http_request_received("GET", "/api/config")
bridge_server:assert_http_request_received(
"POST",
"/api",
{ body = { devicetype = "smartthings_edge_driver#" .. BRIDGE_IP, generateclientkey = true } }
)
end
)

test.run_registered_tests()
Loading
Loading