Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 6 additions & 2 deletions Source/Convenience/Services.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,12 @@ public struct HAServiceDefinition {
var descriptionValue: String? = try? data.decode("description")

// Treat empty strings as nil
if nameValue?.isEmpty == true { nameValue = nil }
if descriptionValue?.isEmpty == true { descriptionValue = nil }
if nameValue?.isEmpty == true {
nameValue = nil
}
if descriptionValue?.isEmpty == true {
descriptionValue = nil
}

try self.init(
domain: domain,
Expand Down
14 changes: 13 additions & 1 deletion Source/Data/HAEntity.swift
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,19 @@ public struct HAEntityAttributes {
/// This contains all keys and values received, including those not parsed or handled otherwise
public var dictionary: [String: Any]

/// The display name for the entity, from the `friendly_name` attribute
/// The value of the entity's legacy `friendly_name` state attribute.
///
/// - Warning: The `friendly_name` state attribute should no longer be used to display an
/// entity's name. It does not reflect the canonical display name, which is derived from the
/// entity and device registries together with any user customizations. Resolve the display
/// name from the entity registry display data provided by the `list_for_display` endpoint
/// instead. That endpoint is not currently mapped in HAKit; refer to its definition and usage
/// in `home-assistant/core` and `home-assistant/frontend`.
@available(
*,
deprecated,
message: "friendly_name should no longer be used to display an entity's name; it doesn't reflect the entity/device registry name or user customizations. Resolve the display name from the entity registry `list_for_display` endpoint instead (not yet mapped in HAKit — see home-assistant/core and home-assistant/frontend)."
)
public var friendlyName: String? {
self["friendly_name"] as? String
}
Expand Down
52 changes: 45 additions & 7 deletions Tests/HAURLSessionWebSocketEngine.test.swift
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,27 @@ internal class HAURLSessionWebSocketEngineTests: XCTestCase {
engine.urlSession(session, webSocketTask: task, didCloseWith: .goingAway, reason: Data("bye".utf8))
engine.urlSession(session, task: task, didCompleteWithError: URLError(.timedOut))

XCTAssertTrue(delegate.events.contains { if case .connected = $0 { return true } else { return false } })
XCTAssertTrue(delegate.events.contains { if case .disconnected = $0 { return true } else { return false } })
XCTAssertTrue(delegate.events.contains { if case .error = $0 { return true } else { return false } })
XCTAssertTrue(delegate.events.contains {
if case .connected = $0 {
return true
} else {
return false
}
})
XCTAssertTrue(delegate.events.contains {
if case .disconnected = $0 {
return true
} else {
return false
}
})
XCTAssertTrue(delegate.events.contains {
if case .error = $0 {
return true
} else {
return false
}
})
}

func testStartWritesAndStop() throws {
Expand All @@ -138,7 +156,9 @@ internal class HAURLSessionWebSocketEngineTests: XCTestCase {
let errored = expectation(description: "read fails once the socket is cancelled")
errored.assertForOverFulfill = false
delegate.onEvent = { event in
if case .error = event { errored.fulfill() }
if case .error = event {
errored.fulfill()
}
}

let request = try URLRequest(url: XCTUnwrap(URL(string: "wss://127.0.0.1:1/api/websocket")))
Expand Down Expand Up @@ -173,9 +193,27 @@ internal class HAURLSessionWebSocketEngineTests: XCTestCase {
engine.handleReceiveResult(.success(.data(Data("bytes".utf8))))
engine.handleReceiveResult(.failure(URLError(.badServerResponse)))

XCTAssertTrue(delegate.events.contains { if case .text("hello") = $0 { return true } else { return false } })
XCTAssertTrue(delegate.events.contains { if case .binary = $0 { return true } else { return false } })
XCTAssertTrue(delegate.events.contains { if case .error = $0 { return true } else { return false } })
XCTAssertTrue(delegate.events.contains {
if case .text("hello") = $0 {
return true
} else {
return false
}
})
XCTAssertTrue(delegate.events.contains {
if case .binary = $0 {
return true
} else {
return false
}
})
XCTAssertTrue(delegate.events.contains {
if case .error = $0 {
return true
} else {
return false
}
})
}

// MARK: - Helpers
Expand Down
12 changes: 11 additions & 1 deletion Tests/Services.test.swift
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,11 @@ internal class CallServiceTests: XCTestCase {
"description": "Only Description",
"fields": {}
},
"with_empty_description": {
"name": "Has Name",
"description": "",
"fields": {}
},
"with_neither": {
"fields": {}
}
Expand All @@ -279,7 +284,7 @@ internal class CallServiceTests: XCTestCase {
""")
let response = try HAResponseServices(data: data)
let domain = try XCTUnwrap(response.allByDomain["test_domain"])
XCTAssertEqual(domain.count, 4)
XCTAssertEqual(domain.count, 5)

var service: HAServiceDefinition!

Expand All @@ -298,6 +303,11 @@ internal class CallServiceTests: XCTestCase {
XCTAssertEqual(service.name, "Only Description")
XCTAssertEqual(service.description, "Only Description")

// Test with an empty description (treated as nil)
service = try XCTUnwrap(domain["with_empty_description"])
XCTAssertEqual(service.name, "Has Name")
XCTAssertNil(service.description, "empty description should be treated as nil")

// Test with neither (name falls back to domain.service pair)
service = try XCTUnwrap(domain["with_neither"])
XCTAssertEqual(service.name, "test_domain.with_neither")
Expand Down
Loading