diff --git a/CHANGELOG.md b/CHANGELOG.md index 6cc774a..ece73a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## [0.6.3](https://github.com/rdkcentral/firebolt-cpp-client/compare/0.6.2...v0.6.3) + +### Fixed +- `Actions.intent` and `Actions.onIntent` now correctly handle a JSON object payload (`{"intent":"...","intentId":N}`) sent by the Firebolt backend. Previously the client failed to parse the response because it expected a plain string. + ## [0.6.2](https://github.com/rdkcentral/firebolt-cpp-client/compare/v0.6.1...v0.6.2) ### Fixed diff --git a/docs/openrpc/the-spec/firebolt-open-rpc.json b/docs/openrpc/the-spec/firebolt-open-rpc.json index da2da05..321cbe3 100644 --- a/docs/openrpc/the-spec/firebolt-open-rpc.json +++ b/docs/openrpc/the-spec/firebolt-open-rpc.json @@ -66,9 +66,14 @@ "params": [], "result": { "name": "intent", - "summary": "The current intent.", + "summary": "The current intent as a JSON document.", "schema": { - "type": "string" + "type": "object", + "required": ["intent", "intentId"], + "properties": { + "intent": { "type": "string" }, + "intentId": { "type": "integer" } + } } }, "examples": [ @@ -76,7 +81,7 @@ "name": "Get the current intent", "result": { "name": "Default Result", - "value": "launch" + "value": { "intent": "launch", "intentId": 1 } } } ] @@ -107,9 +112,14 @@ ], "result": { "name": "intent", - "summary": "The current intent.", + "summary": "The current intent as a JSON document.", "schema": { - "type": "string" + "type": "object", + "required": ["intent", "intentId"], + "properties": { + "intent": { "type": "string" }, + "intentId": { "type": "integer" } + } } }, "examples": [ @@ -123,7 +133,7 @@ ], "result": { "name": "Default Result", - "value": "launch" + "value": { "intent": "launch", "intentId": 1 } } } ] diff --git a/src/actions_impl.cpp b/src/actions_impl.cpp index b699bca..e65fc4e 100644 --- a/src/actions_impl.cpp +++ b/src/actions_impl.cpp @@ -34,12 +34,12 @@ ActionsImpl::ActionsImpl(Firebolt::Helpers::IHelper& helper) Result ActionsImpl::intent() const { - return helper_.get("Actions.intent"); + return helper_.get("Actions.intent"); } Result ActionsImpl::subscribeOnIntent(std::function&& notification) { - return subscriptionManager_.subscribe("Actions.onIntent", std::move(notification)); + return subscriptionManager_.subscribe("Actions.onIntent", std::move(notification)); } Result ActionsImpl::unsubscribe(SubscriptionId id) diff --git a/src/json_types/actions.h b/src/json_types/actions.h index 60c76ce..732775c 100644 --- a/src/json_types/actions.h +++ b/src/json_types/actions.h @@ -34,6 +34,20 @@ namespace Firebolt::Actions namespace JsonData { +// Serialises any JSON value (object, string, …) to its compact JSON text +// representation. Used for Actions.intent / Actions.onIntent whose wire format +// is the object {"intent":"...","intentId":N} but whose public C++ API surface +// exposes the whole document as a std::string, per the Firebolt 9 spec. +class JsonString : public Firebolt::JSON::NL_Json_Basic +{ +public: + void fromJson(const nlohmann::json& json) override { value_ = json.dump(); } + std::string value() const override { return value_; } + +private: + std::string value_; +}; + } // namespace JsonData } // namespace Firebolt::Actions diff --git a/test/component/actionsGeneratedTest.cpp b/test/component/actionsGeneratedTest.cpp index 38a5356..a8105c0 100644 --- a/test/component/actionsGeneratedTest.cpp +++ b/test/component/actionsGeneratedTest.cpp @@ -36,7 +36,9 @@ TEST_F(ActionsGeneratedCTest, Intent) { auto result = Firebolt::IFireboltAccessor::Instance().ActionsInterface().intent(); ASSERT_TRUE(result) << toError(result); - EXPECT_EQ(*result, "launch"); + auto parsed = nlohmann::json::parse(*result); + EXPECT_EQ(parsed.at("intent").get(), "launch"); + EXPECT_EQ(parsed.at("intentId").get(), 1); } TEST_F(ActionsGeneratedCTest, SubscribeOnIntent) @@ -44,7 +46,9 @@ TEST_F(ActionsGeneratedCTest, SubscribeOnIntent) auto id = Firebolt::IFireboltAccessor::Instance().ActionsInterface().subscribeOnIntent( [&](const std::string& intent) { - EXPECT_EQ(intent, "launch"); + auto parsed = nlohmann::json::parse(intent); + EXPECT_EQ(parsed.at("intent").get(), "launch"); + EXPECT_EQ(parsed.at("intentId").get(), 1); { std::lock_guard lock(mtx); eventReceived = true; @@ -55,7 +59,7 @@ TEST_F(ActionsGeneratedCTest, SubscribeOnIntent) ASSERT_TRUE(id) << toError(id); verifyEventSubscription(id); - triggerEvent("Actions.onIntent", R"("launch")"); + triggerEvent("Actions.onIntent", R"({"intent":"launch","intentId":1})"); verifyEventReceived(mtx, cv, eventReceived); auto result = Firebolt::IFireboltAccessor::Instance().ActionsInterface().unsubscribe(id.value()); diff --git a/test/unit/actionsTest.cpp b/test/unit/actionsTest.cpp index 1b87480..feec5ed 100644 --- a/test/unit/actionsTest.cpp +++ b/test/unit/actionsTest.cpp @@ -28,11 +28,13 @@ class ActionsUTest : public ::testing::Test, protected MockBase TEST_F(ActionsUTest, Start) { - mock_with_response("Actions.intent", "launch"); + mock_with_response("Actions.intent", nlohmann::json({{"intent", "launch"}, {"intentId", 1}})); auto result = actionsImpl_.intent(); ASSERT_TRUE(result) << "ActionsImpl::intent() returned an error"; - EXPECT_EQ(*result, "launch"); + auto parsed = nlohmann::json::parse(*result); + EXPECT_EQ(parsed.at("intent").get(), "launch"); + EXPECT_EQ(parsed.at("intentId").get(), 1); } TEST_F(ActionsUTest, SubscribeOnIntent)