Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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 display name for the entity, from the `friendly_name` attribute.
Comment thread
bgoncal marked this conversation as resolved.
Outdated
///
/// - 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