#include #include "renderive/renderable/Inheritance.hpp" #include #include namespace { namespace renderable_chain = renderive::renderable_inheritance; enum class Visit { parent, child }; struct Event {}; struct Impl_Base : renderive::inheritance::Type_Root { explicit Impl_Base(std::vector& visits) : visits(&visits) {} std::vector* visits; }; struct Parent_Impl : renderable_chain::Impl_Root { using Impl_Root::Impl_Root; struct Observer : renderable_chain::Observer_Root { static void handle(Parent_Impl& impl, const Event&) { impl.visits->push_back(Visit::parent); } }; }; struct Child_Impl : renderable_chain::Impl_Node { using Impl_Node::Impl_Node; struct Observer : renderable_chain::Observer_Node { static void handle(Child_Impl& impl, const Event&) { impl.visits->push_back(Visit::child); } }; }; struct Parent_State : renderable_chain::State_Root {}; struct Child_State : renderable_chain::State_Node {}; struct Parent_Builder_Layer : renderable_chain::Builder_Root {}; struct Child_Builder_Layer : renderable_chain::Builder_Node {}; struct Business_Builder { explicit Business_Builder(bool& initialized) : initialized(&initialized) {} void build() const { *initialized = true; } bool* initialized; }; struct Final_Builder : renderable_chain::Builder { using Builder::Builder; }; struct Root_Base { public: explicit Root_Base(bool& constructed) : constructed(&constructed) { constructed = true; } bool* constructed; }; struct Renderable_Root : renderive::renderable::render_base { using render_base::render_base; struct Impl {}; }; struct Product_Properties { bool enabled{}; }; template struct Product_Business_Builder { using Product = Product_Type; using Properties = Properties_Type; explicit Product_Business_Builder(bool& initialized) : initialized(&initialized) {} void build() const { *initialized = true; } bool* initialized; }; struct Visual_Control : renderive::renderable::render_base { using State = Product_Properties; template using Business_Builder = Product_Business_Builder; using render_base::render_base; protected: template void set_state(Value&& value) { state.*Member = std::forward(value); } template auto get_state() const { return state.*Member; } private: State state; }; using Renderable_Product = renderive::renderable::attach; TEST(renderable_inheritance_test, dispatches_nested_observers_parent_first) { std::vector visits; Child_Impl impl(visits); impl.dispatch(Event{}); EXPECT_EQ(visits, (std::vector{Visit::parent, Visit::child})); } TEST(renderable_inheritance_test, preserves_business_builder_capabilities) { bool initialized{}; Final_Builder builder(initialized); builder.build(); EXPECT_TRUE(initialized); static_assert(std::same_as< renderive::inheritance::Type_At_Position_T< typename Final_Builder::Inheritance_Registry, renderable_chain::Builder_Chain, Final_Builder::Inheritance_Position>, Final_Builder>); static_assert(std::same_as< renderive::inheritance::Type_At_Position_T< typename Child_State::Inheritance_Registry, renderable_chain::State_Chain, Child_State::Inheritance_Position>, Child_State>); } TEST(renderable_inheritance_test, composes_root_control_and_product_without_business_boilerplate) { bool constructed{}; Renderable_Product product(constructed); EXPECT_TRUE(constructed); bool initialized{}; Renderable_Product::Builder builder(initialized); builder.build(); EXPECT_TRUE(initialized); static_assert(std::same_as); static_assert(std::same_as< typename Renderable_Product::Builder::Product, Renderable_Product>); } } // namespace