#include "adminive/adapters/drogon.hpp" #include "adminive/adapters/nlohmann_json.hpp" #include "adminive_test.hpp" #include #include #include #include namespace drogon_test { struct Status { std::string user; }; struct Config { std::string name{"default"}; Status status() { if(name == "status-error") { throw std::runtime_error("item status failed"); } return Status{name}; } }; } namespace adminive { template <> struct Type_Descriptor { static auto get() { using T = drogon_test::Config; return object("config", "Config", ADMINIVE_FIELD(T, name).editable().creatable()); } }; template <> struct Type_View_Descriptor { static Table_View table() { using T = drogon_test::Config; return table_view(column<&T::name>("Name").sort().search()); } }; template <> struct Type_Descriptor { static auto get() { using T = drogon_test::Status; return object("status", "Status", ADMINIVE_FIELD(T, user).label("User")); } }; } int main() { using Json = nlohmann::json; drogon_test::Config config; drogon::HttpAppFramework app; std::vector> tasks; std::string committed_user; adminive::Resource_Transaction transaction; transaction.commit = [&committed_user](const drogon_test::Config&, const adminive::Request_Context& context) { committed_user = context.user; }; adminive::Drogon_Bind_Options options; options.executor = [&tasks](std::function task) { tasks.push_back(std::move(task)); }; options.filters = {"LoginFilter", "AdminFilter"}; options.context_factory = [](const drogon::HttpRequestPtr& request) { adminive::Request_Context context; context.user = request->user; return context; }; { adminive::Drogon_Resource resource(config, "/config", std::move(transaction)); resource.bind(app, options); adminive::Drogon_Status_Resource status("/status", [](const adminive::Request_Context& context) { if(context.user == "error") { throw std::runtime_error("status failed"); } return drogon_test::Status{context.user}; }); status.bind(app, options); } ADMINIVE_CHECK(app.filters("/config/data", drogon::Post).size() == 2); ADMINIVE_CHECK(app.filters("/status/data", drogon::Get).size() == 2); auto request = std::make_shared(); drogon::HttpResponsePtr response; app.handle("/config/view", drogon::Get, request, [&response](const drogon::HttpResponsePtr& value) { response = value; }); ADMINIVE_CHECK(response->status == drogon::k200OK); ADMINIVE_CHECK(Json::parse(response->body).at("data").at("kind") == "form"); adminive::Drogon_Bind_Options nonstd_options = options; nonstd_options.context_factory = [](const drogon::HttpRequestPtr&) -> adminive::Request_Context { throw 7; }; adminive::Drogon_Resource nonstd_resource(config, "/context-error"); nonstd_resource.bind(app, nonstd_options); adminive::Drogon_Status_Resource nonstd_status("/status-context-error", [](const adminive::Request_Context&) { return drogon_test::Status{}; }); nonstd_status.bind(app, nonstd_options); response.reset(); app.handle("/context-error/data", drogon::Post, request, [&response](const drogon::HttpResponsePtr& value) { response = value; }); ADMINIVE_CHECK(response->status == drogon::k500InternalServerError); response.reset(); app.handle("/status-context-error/data", drogon::Get, request, [&response](const drogon::HttpResponsePtr& value) { response = value; }); ADMINIVE_CHECK(response->status == drogon::k500InternalServerError); ADMINIVE_CHECK(tasks.empty()); request->body = R"({"name":"updated"})"; request->user = "wyc"; response.reset(); app.handle("/config/data", drogon::Post, request, [&response](const drogon::HttpResponsePtr& value) { response = value; }); ADMINIVE_CHECK(!response); ADMINIVE_CHECK(tasks.size() == 1); tasks.front()(); tasks.erase(tasks.begin()); ADMINIVE_CHECK(response); ADMINIVE_CHECK(response->status == drogon::k200OK); ADMINIVE_CHECK(config.name == "updated"); ADMINIVE_CHECK(committed_user == "wyc"); response.reset(); app.handle("/status/data", drogon::Get, request, [&response](const drogon::HttpResponsePtr& value) { response = value; }); ADMINIVE_CHECK(!response); ADMINIVE_CHECK(tasks.size() == 1); tasks.front()(); tasks.erase(tasks.begin()); ADMINIVE_CHECK(response->status == drogon::k200OK); ADMINIVE_CHECK(Json::parse(response->body).at("data").at("user").at("value") == "wyc"); request->user = "error"; response.reset(); app.handle("/status/data", drogon::Get, request, [&response](const drogon::HttpResponsePtr& value) { response = value; }); tasks.front()(); tasks.erase(tasks.begin()); ADMINIVE_CHECK(response->status == drogon::k500InternalServerError); response.reset(); app.handle("/status/descriptor", drogon::Get, request, [&response](const drogon::HttpResponsePtr& value) { response = value; }); ADMINIVE_CHECK(response->status == drogon::k200OK); adminive::Drogon_Collection_Resource collection("/configs", {drogon_test::Config{"first"}}); collection.register_status<&drogon_test::Config::status>(25); collection.bind(app, options); response.reset(); app.handle("/configs/view", drogon::Get, request, [&response](const drogon::HttpResponsePtr& value) { response = value; }); ADMINIVE_CHECK(response->status == drogon::k200OK); ADMINIVE_CHECK(Json::parse(response->body).at("data").at("kind") == "table"); ADMINIVE_CHECK(Json::parse(response->body).at("data").at("columns").at(0).at("searchable") == true); request->parameters = {{"page", "1"}, {"perPage", "10"}, {"name", "fir"}}; response.reset(); app.handle("/configs", drogon::Get, request, [&response](const drogon::HttpResponsePtr& value) { response = value; }); ADMINIVE_CHECK(response->status == drogon::k200OK); ADMINIVE_CHECK(Json::parse(response->body).at("data").at("total") == 1); request->parameters = {{"unknown", "value"}}; response.reset(); app.handle("/configs", drogon::Get, request, [&response](const drogon::HttpResponsePtr& value) { response = value; }); ADMINIVE_CHECK(response->status == drogon::k400BadRequest); request->parameters = {{"orderBy", "unknown"}, {"orderDir", "asc"}}; response.reset(); app.handle("/configs", drogon::Get, request, [&response](const drogon::HttpResponsePtr& value) { response = value; }); ADMINIVE_CHECK(response->status == drogon::k400BadRequest); request->parameters = {{"orderBy", "name"}, {"orderDir", "sideways"}}; response.reset(); app.handle("/configs", drogon::Get, request, [&response](const drogon::HttpResponsePtr& value) { response = value; }); ADMINIVE_CHECK(response->status == drogon::k400BadRequest); request->parameters.clear(); response.reset(); app.handle("/configs/1", drogon::Get, request, [&response](const drogon::HttpResponsePtr& value) { response = value; }); ADMINIVE_CHECK(response->status == drogon::k200OK); ADMINIVE_CHECK(Json::parse(response->body).at("data").at("name") == "first"); request->body = R"({"name":"second"})"; response.reset(); app.handle("/configs", drogon::Post, request, [&response](const drogon::HttpResponsePtr& value) { response = value; }); ADMINIVE_CHECK(!response); ADMINIVE_CHECK(tasks.size() == 1); tasks.front()(); tasks.erase(tasks.begin()); ADMINIVE_CHECK(response->status == drogon::k200OK); ADMINIVE_CHECK(collection.size() == 2); request->body = R"({"name":"changed"})"; response.reset(); app.handle("/configs/2", drogon::Patch, request, [&response](const drogon::HttpResponsePtr& value) { response = value; }); tasks.front()(); tasks.erase(tasks.begin()); ADMINIVE_CHECK(response->status == drogon::k200OK); ADMINIVE_CHECK(Json::parse(response->body).at("data").at("name") == "changed"); request->body = R"({"name":"status-error"})"; response.reset(); app.handle("/configs/2", drogon::Patch, request, [&response](const drogon::HttpResponsePtr& value) { response = value; }); tasks.front()(); tasks.erase(tasks.begin()); ADMINIVE_CHECK(response->status == drogon::k200OK); response.reset(); app.handle("/configs/2/status", drogon::Get, request, [&response](const drogon::HttpResponsePtr& value) { response = value; }); ADMINIVE_CHECK(!response); tasks.front()(); tasks.erase(tasks.begin()); ADMINIVE_CHECK(response->status == drogon::k500InternalServerError); response.reset(); app.handle("/configs/1", drogon::Delete, request, [&response](const drogon::HttpResponsePtr& value) { response = value; }); tasks.front()(); tasks.erase(tasks.begin()); ADMINIVE_CHECK(response->status == drogon::k200OK); ADMINIVE_CHECK(collection.size() == 1); ADMINIVE_CHECK(app.filters("/configs/{1:id}", drogon::Patch).size() == 2); return 0; }