大更新
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
#include "adminive/adapters/boost_pfr.hpp"
|
||||
#include "adminive/adapters/nlohmann_json.hpp"
|
||||
#include "adminive/http.hpp"
|
||||
#include <cassert>
|
||||
#include "adminive_test.hpp"
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <variant>
|
||||
@@ -281,21 +281,21 @@ int main() {
|
||||
};
|
||||
adminive::Resource_Service<Runtime_Config, Json> service(runtime, "/config", std::move(transaction));
|
||||
const auto invalid = service.update_response(R"({"nested":{"count":0}})");
|
||||
assert(invalid.status == 422);
|
||||
assert(invalid.body.at("field_errors").contains("nested.count"));
|
||||
ADMINIVE_CHECK(invalid.status == 422);
|
||||
ADMINIVE_CHECK(invalid.body.at("field_errors").contains("nested.count"));
|
||||
const auto rejected_commit = service.update_response(R"({"name":"blocked"})");
|
||||
assert(rejected_commit.status == 422);
|
||||
assert(rejected_commit.body.at("field_errors").at("name") == "name is blocked");
|
||||
assert(runtime.name() == "default");
|
||||
ADMINIVE_CHECK(rejected_commit.status == 422);
|
||||
ADMINIVE_CHECK(rejected_commit.body.at("field_errors").at("name") == "name is blocked");
|
||||
ADMINIVE_CHECK(runtime.name() == "default");
|
||||
const auto valid = service.update_response(R"({"nested":{"count":8},"name":"updated"})");
|
||||
assert(valid.status == 200);
|
||||
assert(runtime.count() == 8);
|
||||
assert(runtime.name() == "updated");
|
||||
assert(runtime.apply_count() == 1);
|
||||
assert(transaction_count == 1);
|
||||
ADMINIVE_CHECK(valid.status == 200);
|
||||
ADMINIVE_CHECK(runtime.count() == 8);
|
||||
ADMINIVE_CHECK(runtime.name() == "updated");
|
||||
ADMINIVE_CHECK(runtime.apply_count() == 1);
|
||||
ADMINIVE_CHECK(transaction_count == 1);
|
||||
const auto inherited = adminive::to_descriptor_json<Json, Inherited_Config>();
|
||||
assert(inherited.at("fields").at(0).at("name") == "alpha");
|
||||
assert(inherited.at("fields").at(1).at("name") == "beta");
|
||||
ADMINIVE_CHECK(inherited.at("fields").at(0).at("name") == "alpha");
|
||||
ADMINIVE_CHECK(inherited.at("fields").at(1).at("name") == "beta");
|
||||
adminive::Managed_Value<Inherited_Config> managed_inherited;
|
||||
managed_inherited.field<0>().write([](int& value) {
|
||||
value = 12;
|
||||
@@ -303,47 +303,47 @@ int main() {
|
||||
managed_inherited.field<1>().write([](std::string& value) {
|
||||
value = "changed";
|
||||
});
|
||||
assert(managed_inherited.field<0>().snapshot() == 12);
|
||||
assert(managed_inherited.field<1>().snapshot() == "changed");
|
||||
ADMINIVE_CHECK(managed_inherited.field<0>().snapshot() == 12);
|
||||
ADMINIVE_CHECK(managed_inherited.field<1>().snapshot() == "changed");
|
||||
Control_Config controls;
|
||||
const auto control_form = adminive::to_amis_form_schema<Json>(controls, adminive::describe_edit_view<Control_Config>());
|
||||
assert(control_form.at("body").at(0).at("type") == "input-color");
|
||||
ADMINIVE_CHECK(control_form.at("body").at(0).at("type") == "input-color");
|
||||
Device_Config devices;
|
||||
const auto device_form = adminive::to_amis_form_schema<Json>(devices, adminive::describe_edit_view<Device_Config>());
|
||||
assert(device_form.at("body").at(0).at("type") == "fieldset");
|
||||
assert(device_form.at("body").at(0).at("body").at(0).at("type") == "select");
|
||||
assert(device_form.at("body").at(0).at("body").at(1).at("body").at(2).at("type") == "input-color");
|
||||
ADMINIVE_CHECK(device_form.at("body").at(0).at("type") == "fieldset");
|
||||
ADMINIVE_CHECK(device_form.at("body").at(0).at("body").at(0).at("type") == "select");
|
||||
ADMINIVE_CHECK(device_form.at("body").at(0).at("body").at(1).at("body").at(2).at("type") == "input-color");
|
||||
const auto polymorphic_patch = Json{{"device", Json{{"type", "network"}, {"host", "10.0.0.1"}, {"port", 7000}, {"baud_rate", 9600}}}};
|
||||
const auto polymorphic_update = adminive::apply_frontend_patch<Json>(devices, polymorphic_patch);
|
||||
assert(polymorphic_update.success);
|
||||
assert(std::holds_alternative<Network_Device>(devices.device));
|
||||
assert(std::get<Network_Device>(devices.device).host == "10.0.0.1");
|
||||
ADMINIVE_CHECK(polymorphic_update.success);
|
||||
ADMINIVE_CHECK(std::holds_alternative<Network_Device>(devices.device));
|
||||
ADMINIVE_CHECK(std::get<Network_Device>(devices.device).host == "10.0.0.1");
|
||||
const auto status_descriptor = adminive::to_status_descriptor_json<Json, Overview_Status>();
|
||||
const auto status_service = adminive::make_amis_status_service<Json>(status_descriptor, "/status", 1000);
|
||||
assert(status_service.at("body").at("title") == "运行状态");
|
||||
assert(status_service.at("body").at("body").at("body").size() == 2);
|
||||
ADMINIVE_CHECK(status_service.at("body").at("title") == "运行状态");
|
||||
ADMINIVE_CHECK(status_service.at("body").at("body").at("body").size() == 2);
|
||||
const auto descriptor_without_defaults = adminive::to_descriptor_json<Json, Secret_Config>();
|
||||
assert(!descriptor_without_defaults.at("fields").at(0).contains("default"));
|
||||
ADMINIVE_CHECK(!descriptor_without_defaults.at("fields").at(0).contains("default"));
|
||||
const auto descriptor_with_defaults = adminive::to_descriptor_json_with_defaults<Json, Secret_Config>();
|
||||
assert(!descriptor_with_defaults.at("fields").at(0).contains("default"));
|
||||
assert(descriptor_with_defaults.at("fields").at(1).at("default") == "public");
|
||||
ADMINIVE_CHECK(!descriptor_with_defaults.at("fields").at(0).contains("default"));
|
||||
ADMINIVE_CHECK(descriptor_with_defaults.at("fields").at(1).at("default") == "public");
|
||||
Secret_Config secret;
|
||||
const auto frontend_secret = adminive::to_frontend_json<Json>(secret);
|
||||
assert(!frontend_secret.contains("secret"));
|
||||
assert(frontend_secret.at("visible") == "public");
|
||||
ADMINIVE_CHECK(!frontend_secret.contains("secret"));
|
||||
ADMINIVE_CHECK(frontend_secret.at("visible") == "public");
|
||||
bool duplicate_rejected{};
|
||||
try {
|
||||
static_cast<void>(adminive::to_descriptor_json<Json, Duplicate_Config>());
|
||||
} catch(const std::invalid_argument&) {
|
||||
duplicate_rejected = true;
|
||||
}
|
||||
assert(duplicate_rejected);
|
||||
ADMINIVE_CHECK(duplicate_rejected);
|
||||
bool invalid_sort_rejected{};
|
||||
try {
|
||||
adminive::validate_table_view<Invalid_Sort_Config>(adminive::describe_table_view<Invalid_Sort_Config>());
|
||||
} catch(const std::invalid_argument&) {
|
||||
invalid_sort_rejected = true;
|
||||
}
|
||||
assert(invalid_sort_rejected);
|
||||
ADMINIVE_CHECK(invalid_sort_rejected);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "config_store.hpp"
|
||||
#include <cassert>
|
||||
#include "adminive_test.hpp"
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
int main() {
|
||||
@@ -9,18 +9,18 @@ int main() {
|
||||
std::filesystem::remove_all(test_directory);
|
||||
{
|
||||
Config_Store store(config_path);
|
||||
assert(std::filesystem::exists(config_path));
|
||||
assert(store.radio_service().snapshot().profile_name == "Primary Radio Profile");
|
||||
ADMINIVE_CHECK(std::filesystem::exists(config_path));
|
||||
ADMINIVE_CHECK(store.radio_service().snapshot().profile_name == "Primary Radio Profile");
|
||||
auto updated = store.radio_service().snapshot();
|
||||
updated.profile_name = "Persisted Profile";
|
||||
store.persist_radio_service(updated);
|
||||
assert(store.radio_service().snapshot().profile_name == "Persisted Profile");
|
||||
assert(!std::filesystem::exists(config_path.string() + ".tmp"));
|
||||
ADMINIVE_CHECK(store.radio_service().snapshot().profile_name == "Persisted Profile");
|
||||
ADMINIVE_CHECK(!std::filesystem::exists(config_path.string() + ".tmp"));
|
||||
}
|
||||
{
|
||||
Config_Store store(config_path);
|
||||
assert(store.radio_service().snapshot().profile_name == "Persisted Profile");
|
||||
assert(store.default_device_type() == Device_Table_Type::serial);
|
||||
ADMINIVE_CHECK(store.radio_service().snapshot().profile_name == "Persisted Profile");
|
||||
ADMINIVE_CHECK(store.default_device_type() == Device_Table_Type::serial);
|
||||
}
|
||||
std::filesystem::remove_all(test_directory);
|
||||
return 0;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "adminive/adapters/drogon.hpp"
|
||||
#include "adminive/adapters/nlohmann_json.hpp"
|
||||
#include <cassert>
|
||||
#include "adminive_test.hpp"
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
@@ -67,39 +67,39 @@ int main() {
|
||||
});
|
||||
status.bind(app, options);
|
||||
}
|
||||
assert(app.filters("/config/data", drogon::Post).size() == 2);
|
||||
assert(app.filters("/status/data", drogon::Get).size() == 2);
|
||||
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::HttpRequest>();
|
||||
drogon::HttpResponsePtr response;
|
||||
app.handle("/config/view", drogon::Get, request, [&response](const drogon::HttpResponsePtr& value) {
|
||||
response = value;
|
||||
});
|
||||
assert(response->status == drogon::k200OK);
|
||||
assert(Json::parse(response->body).at("data").at("kind") == "form");
|
||||
ADMINIVE_CHECK(response->status == drogon::k200OK);
|
||||
ADMINIVE_CHECK(Json::parse(response->body).at("data").at("kind") == "form");
|
||||
request->body = R"({"name":"updated"})";
|
||||
request->user = "wyc";
|
||||
response.reset();
|
||||
app.handle("/config/data", drogon::Post, request, [&response](const drogon::HttpResponsePtr& value) {
|
||||
response = value;
|
||||
});
|
||||
assert(!response);
|
||||
assert(tasks.size() == 1);
|
||||
ADMINIVE_CHECK(!response);
|
||||
ADMINIVE_CHECK(tasks.size() == 1);
|
||||
tasks.front()();
|
||||
tasks.erase(tasks.begin());
|
||||
assert(response);
|
||||
assert(response->status == drogon::k200OK);
|
||||
assert(config.name == "updated");
|
||||
assert(committed_user == "wyc");
|
||||
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;
|
||||
});
|
||||
assert(!response);
|
||||
assert(tasks.size() == 1);
|
||||
ADMINIVE_CHECK(!response);
|
||||
ADMINIVE_CHECK(tasks.size() == 1);
|
||||
tasks.front()();
|
||||
tasks.erase(tasks.begin());
|
||||
assert(response->status == drogon::k200OK);
|
||||
assert(Json::parse(response->body).at("data").at("user").at("value") == "wyc");
|
||||
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) {
|
||||
@@ -107,45 +107,45 @@ int main() {
|
||||
});
|
||||
tasks.front()();
|
||||
tasks.erase(tasks.begin());
|
||||
assert(response->status == drogon::k500InternalServerError);
|
||||
ADMINIVE_CHECK(response->status == drogon::k500InternalServerError);
|
||||
response.reset();
|
||||
app.handle("/status/descriptor", drogon::Get, request, [&response](const drogon::HttpResponsePtr& value) {
|
||||
response = value;
|
||||
});
|
||||
assert(response->status == drogon::k200OK);
|
||||
ADMINIVE_CHECK(response->status == drogon::k200OK);
|
||||
adminive::Drogon_Collection_Resource<drogon_test::Config, Json> collection("/configs", {drogon_test::Config{"first"}});
|
||||
collection.bind(app, options);
|
||||
response.reset();
|
||||
app.handle("/configs/view", drogon::Get, request, [&response](const drogon::HttpResponsePtr& value) {
|
||||
response = value;
|
||||
});
|
||||
assert(response->status == drogon::k200OK);
|
||||
assert(Json::parse(response->body).at("data").at("kind") == "table");
|
||||
assert(Json::parse(response->body).at("data").at("columns").at(0).at("searchable") == true);
|
||||
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;
|
||||
});
|
||||
assert(response->status == drogon::k200OK);
|
||||
assert(Json::parse(response->body).at("data").at("total") == 1);
|
||||
ADMINIVE_CHECK(response->status == drogon::k200OK);
|
||||
ADMINIVE_CHECK(Json::parse(response->body).at("data").at("total") == 1);
|
||||
response.reset();
|
||||
app.handle("/configs/1", drogon::Get, request, [&response](const drogon::HttpResponsePtr& value) {
|
||||
response = value;
|
||||
});
|
||||
assert(response->status == drogon::k200OK);
|
||||
assert(Json::parse(response->body).at("data").at("name") == "first");
|
||||
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;
|
||||
});
|
||||
assert(!response);
|
||||
assert(tasks.size() == 1);
|
||||
ADMINIVE_CHECK(!response);
|
||||
ADMINIVE_CHECK(tasks.size() == 1);
|
||||
tasks.front()();
|
||||
tasks.erase(tasks.begin());
|
||||
assert(response->status == drogon::k200OK);
|
||||
assert(collection.size() == 2);
|
||||
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) {
|
||||
@@ -153,16 +153,16 @@ int main() {
|
||||
});
|
||||
tasks.front()();
|
||||
tasks.erase(tasks.begin());
|
||||
assert(response->status == drogon::k200OK);
|
||||
assert(Json::parse(response->body).at("data").at("name") == "changed");
|
||||
ADMINIVE_CHECK(response->status == drogon::k200OK);
|
||||
ADMINIVE_CHECK(Json::parse(response->body).at("data").at("name") == "changed");
|
||||
response.reset();
|
||||
app.handle("/configs/1", drogon::Delete, request, [&response](const drogon::HttpResponsePtr& value) {
|
||||
response = value;
|
||||
});
|
||||
tasks.front()();
|
||||
tasks.erase(tasks.begin());
|
||||
assert(response->status == drogon::k200OK);
|
||||
assert(collection.size() == 1);
|
||||
assert(app.filters("/configs/{1:id}", drogon::Patch).size() == 2);
|
||||
ADMINIVE_CHECK(response->status == drogon::k200OK);
|
||||
ADMINIVE_CHECK(collection.size() == 1);
|
||||
ADMINIVE_CHECK(app.filters("/configs/{1:id}", drogon::Patch).size() == 2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
#include "gallery.hpp"
|
||||
#include "adminive_test.hpp"
|
||||
#include <string>
|
||||
#include <thread>
|
||||
namespace {
|
||||
using adminive::example::Json;
|
||||
Json body_json(const httplib::Result& result) {
|
||||
ADMINIVE_CHECK(result);
|
||||
return Json::parse(result->body);
|
||||
}
|
||||
void check_status(const httplib::Result& result, int status) {
|
||||
ADMINIVE_CHECK(result);
|
||||
ADMINIVE_CHECK(result->status == status);
|
||||
}
|
||||
}
|
||||
int main() {
|
||||
adminive::example::Component_Gallery gallery;
|
||||
httplib::Server server;
|
||||
gallery.bind(server);
|
||||
const int port = server.bind_to_any_port("127.0.0.1");
|
||||
ADMINIVE_CHECK(port > 0);
|
||||
std::thread thread([&] {
|
||||
ADMINIVE_CHECK(server.listen_after_bind());
|
||||
});
|
||||
httplib::Client client("127.0.0.1", port);
|
||||
const Json docs = body_json(client.Get("/admin/gallery/docs")).at("data");
|
||||
ADMINIVE_CHECK(docs.at("cases").size() == 14);
|
||||
ADMINIVE_CHECK(docs.at("capabilities").at("adapters").size() > 5);
|
||||
ADMINIVE_CHECK(docs.at("examples").at("form_create_view").at("mode") == "create");
|
||||
std::size_t creatable_fields = 0;
|
||||
for(const auto& field : docs.at("examples").at("descriptor").at("fields")) {
|
||||
if(field.at("creatable").get<bool>()) {
|
||||
++creatable_fields;
|
||||
}
|
||||
}
|
||||
ADMINIVE_CHECK(creatable_fields > 5);
|
||||
Json field_policies = Json::object();
|
||||
for(const auto& field : docs.at("examples").at("field_policies")) {
|
||||
field_policies[field.at("name").get<std::string>()] = field;
|
||||
}
|
||||
ADMINIVE_CHECK(field_policies.at("backend_only").at("writable") == true);
|
||||
ADMINIVE_CHECK(field_policies.at("backend_only").at("editable") == false);
|
||||
ADMINIVE_CHECK(field_policies.at("backend_only").at("creatable") == false);
|
||||
ADMINIVE_CHECK(field_policies.at("hidden_backend").at("writable") == true);
|
||||
ADMINIVE_CHECK(field_policies.at("hidden_backend").at("readable") == false);
|
||||
ADMINIVE_CHECK(field_policies.at("no_default_text").at("include_default") == false);
|
||||
ADMINIVE_CHECK(docs.at("examples").at("data").contains("backend_only"));
|
||||
ADMINIVE_CHECK(!docs.at("examples").at("data").contains("hidden_backend"));
|
||||
for(const auto& field : docs.at("examples").at("descriptor").at("fields")) {
|
||||
if(field.at("name") == "no_default_text") {
|
||||
ADMINIVE_CHECK(!field.contains("default"));
|
||||
}
|
||||
}
|
||||
ADMINIVE_CHECK(!docs.at("examples").at("adapter_data").contains("secret"));
|
||||
ADMINIVE_CHECK(docs.at("examples").at("reflection_descriptor").at("fields").size() == 2);
|
||||
ADMINIVE_CHECK(docs.at("examples").at("collection_list_view").at("mode") == "list");
|
||||
const Json manifest = body_json(client.Get("/admin/gallery/frontend/manifest")).at("data");
|
||||
ADMINIVE_CHECK(manifest.at("slots").size() == 3);
|
||||
ADMINIVE_CHECK(manifest.at("slots").at("alpha").at("component_kind") == "amis_schema");
|
||||
const Json managed = body_json(client.Get("/admin/gallery/managed")).at("data");
|
||||
ADMINIVE_CHECK(managed.at("lock_count").get<std::size_t>() > 0);
|
||||
const Json boundaries = body_json(client.Get("/admin/gallery/boundaries")).at("data");
|
||||
ADMINIVE_CHECK(boundaries.size() == 11);
|
||||
ADMINIVE_CHECK(boundaries.at(4).at("id") == "manifest-duplicate-slot");
|
||||
ADMINIVE_CHECK(boundaries.at(4).at("rejected") == true);
|
||||
check_status(client.Get("/admin/gallery/lab/invalid-filter"), 400);
|
||||
const Json item_status = body_json(client.Get("/admin/gallery/items/1/status")).at("data");
|
||||
ADMINIVE_CHECK(item_status.at("state").at("value") == "enabled");
|
||||
httplib::Headers headers{{"X-Adminive-User", "gallery-test"}, {"X-Request-Id", "request-1"}};
|
||||
const auto success = client.Post("/admin/gallery/transaction/success", headers, R"({"name":"success"})", "application/json");
|
||||
check_status(success, 200);
|
||||
ADMINIVE_CHECK(body_json(success).at("demo").at("events") == Json::array({"prepare", "commit"}));
|
||||
const auto prepare = client.Post("/admin/gallery/transaction/prepare-reject", headers, R"({"name":"prepare"})", "application/json");
|
||||
check_status(prepare, 500);
|
||||
ADMINIVE_CHECK(body_json(prepare).at("demo").at("events") == Json::array({"prepare", "rollback"}));
|
||||
const auto commit = client.Post("/admin/gallery/transaction/commit-fail", headers, R"({"name":"commit"})", "application/json");
|
||||
check_status(commit, 500);
|
||||
const Json commit_json = body_json(commit);
|
||||
ADMINIVE_CHECK(commit_json.at("demo").at("events") == Json::array({"prepare", "commit", "rollback"}));
|
||||
ADMINIVE_CHECK(commit_json.at("demo").at("context").at("user") == "gallery-test");
|
||||
const auto rollback = client.Post("/admin/gallery/transaction/rollback-fail", headers, R"({"name":"rollback"})", "application/json");
|
||||
check_status(rollback, 500);
|
||||
ADMINIVE_CHECK(body_json(rollback).at("msg").get<std::string>().find("rollback failed") != std::string::npos);
|
||||
server.stop();
|
||||
thread.join();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
#include "adminive/adapters/nlohmann_json.hpp"
|
||||
#include "adminive/adapters/httplib.hpp"
|
||||
#include "adminive_test.hpp"
|
||||
#include <atomic>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
namespace httplib_adapter_test {
|
||||
using Json = nlohmann::json;
|
||||
struct Config {
|
||||
std::string name{"initial"};
|
||||
int count{1};
|
||||
};
|
||||
struct Item_Status {
|
||||
std::string state{"ready"};
|
||||
};
|
||||
struct Row {
|
||||
std::string name;
|
||||
bool enabled{true};
|
||||
int score{};
|
||||
Item_Status status() {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
}
|
||||
namespace adminive {
|
||||
template <>
|
||||
struct Type_Descriptor<httplib_adapter_test::Config> {
|
||||
static auto get() {
|
||||
using T = httplib_adapter_test::Config;
|
||||
return object<T>("httplib_config", ADMINIVE_FIELD(T, name).editable(), ADMINIVE_FIELD(T, count).editable());
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct Type_Descriptor<httplib_adapter_test::Item_Status> {
|
||||
static auto get() {
|
||||
using T = httplib_adapter_test::Item_Status;
|
||||
return object<T>("httplib_item_status", ADMINIVE_FIELD(T, state));
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct Type_Descriptor<httplib_adapter_test::Row> {
|
||||
static auto get() {
|
||||
using T = httplib_adapter_test::Row;
|
||||
return object<T>("httplib_row", ADMINIVE_FIELD(T, name).creatable().editable(), ADMINIVE_FIELD(T, enabled).creatable().editable(), ADMINIVE_FIELD(T, score).creatable().editable());
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct Type_View_Descriptor<httplib_adapter_test::Row> {
|
||||
static Table_View table() {
|
||||
using T = httplib_adapter_test::Row;
|
||||
return table_view<T>(column<&T::name>("Name").sort().search(), column<&T::enabled>("Enabled").filter(), column<&T::score>("Score").sort()).reorderable();
|
||||
}
|
||||
};
|
||||
}
|
||||
namespace {
|
||||
using httplib_adapter_test::Json;
|
||||
Json body_json(const httplib::Result& result) {
|
||||
ADMINIVE_CHECK(result);
|
||||
return Json::parse(result->body);
|
||||
}
|
||||
void check_status(const httplib::Result& result, int status) {
|
||||
ADMINIVE_CHECK(result);
|
||||
ADMINIVE_CHECK(result->status == status);
|
||||
}
|
||||
}
|
||||
int main() {
|
||||
using namespace httplib_adapter_test;
|
||||
Config config;
|
||||
std::string committed_user;
|
||||
std::string committed_request_id;
|
||||
std::string committed_remote;
|
||||
adminive::Resource_Transaction<Config> transaction;
|
||||
transaction.commit = [&](const Config&, const adminive::Request_Context& context) {
|
||||
committed_user = context.user;
|
||||
committed_request_id = context.request_id;
|
||||
committed_remote = context.remote_address;
|
||||
};
|
||||
adminive::Http_Resource<Config, Json> resource(config, "/config", transaction);
|
||||
adminive::Http_Collection_Resource<Row, Json> collection("/rows", {Row{"alpha", true, 70}, Row{"beta", false, 90}, Row{"gamma", true, 50}});
|
||||
collection.register_status<&Row::status>(25);
|
||||
httplib::Server server;
|
||||
resource.bind(server, adminive::Httplib_Bind_Options{[](const httplib::Request& request) {
|
||||
adminive::Request_Context context;
|
||||
context.user = request.get_header_value("X-User");
|
||||
context.request_id = request.get_header_value("X-Request-Id");
|
||||
context.remote_address = request.remote_addr;
|
||||
context.attributes.emplace("transport", "httplib");
|
||||
return context;
|
||||
}});
|
||||
collection.bind(server);
|
||||
const int port = server.bind_to_any_port("127.0.0.1");
|
||||
ADMINIVE_CHECK(port > 0);
|
||||
std::thread thread([&] {
|
||||
ADMINIVE_CHECK(server.listen_after_bind());
|
||||
});
|
||||
httplib::Client client("127.0.0.1", port);
|
||||
check_status(client.Get("/config/descriptor"), 200);
|
||||
ADMINIVE_CHECK(body_json(client.Get("/config/view")).at("data").at("kind") == "form");
|
||||
ADMINIVE_CHECK(body_json(client.Get("/config/data")).at("data").at("name") == "initial");
|
||||
check_status(client.Get("/config/amis"), 200);
|
||||
httplib::Headers headers{{"X-User", "alice"}, {"X-Request-Id", "request-42"}};
|
||||
const auto update = client.Post("/config/data", headers, R"({"name":"updated","count":9})", "application/json");
|
||||
check_status(update, 200);
|
||||
ADMINIVE_CHECK(config.name == "updated");
|
||||
ADMINIVE_CHECK(config.count == 9);
|
||||
ADMINIVE_CHECK(committed_user == "alice");
|
||||
ADMINIVE_CHECK(committed_request_id == "request-42");
|
||||
ADMINIVE_CHECK(committed_remote == "127.0.0.1");
|
||||
ADMINIVE_CHECK(body_json(client.Get("/rows/descriptor")).at("data").at("name") == "httplib_row");
|
||||
ADMINIVE_CHECK(body_json(client.Get("/rows/view")).at("data").at("kind") == "table");
|
||||
ADMINIVE_CHECK(body_json(client.Get("/rows?perPage=2&page=1&orderBy=score&orderDir=desc")).at("data").at("items").at(0).at("name") == "beta");
|
||||
ADMINIVE_CHECK(body_json(client.Get("/rows?name=alp")).at("data").at("total") == 1);
|
||||
ADMINIVE_CHECK(body_json(client.Get("/rows?enabled=true")).at("data").at("total") == 2);
|
||||
check_status(client.Get("/rows?orderBy=enabled&orderDir=asc"), 400);
|
||||
check_status(client.Get("/rows?orderBy=score&orderDir=sideways"), 400);
|
||||
const auto created = body_json(client.Post("/rows", R"({"name":"delta","enabled":true,"score":80})", "application/json"));
|
||||
const auto created_id = created.at("data").at("id").get<std::uint64_t>();
|
||||
ADMINIVE_CHECK(created.at("data").at("name") == "delta");
|
||||
ADMINIVE_CHECK(body_json(client.Get(("/rows/" + std::to_string(created_id)).c_str())).at("data").at("score") == 80);
|
||||
check_status(client.Put(("/rows/" + std::to_string(created_id)).c_str(), R"({"score":81})", "application/json"), 200);
|
||||
ADMINIVE_CHECK(body_json(client.Get(("/rows/" + std::to_string(created_id)).c_str())).at("data").at("score") == 81);
|
||||
check_status(client.Patch(("/rows/" + std::to_string(created_id)).c_str(), R"({"name":"delta-patched"})", "application/json"), 200);
|
||||
ADMINIVE_CHECK(body_json(client.Get(("/rows/" + std::to_string(created_id) + "/status").c_str())).at("data").at("state").at("value") == "ready");
|
||||
check_status(client.Post("/rows/order", R"({"ids":[3,2,1]})", "application/json"), 200);
|
||||
ADMINIVE_CHECK(body_json(client.Get("/rows?orderBy=id&orderDir=asc")).at("data").at("total") == 4);
|
||||
check_status(client.Delete(("/rows/" + std::to_string(created_id)).c_str()), 200);
|
||||
ADMINIVE_CHECK(body_json(client.Get("/rows")).at("data").at("total") == 3);
|
||||
server.stop();
|
||||
thread.join();
|
||||
return 0;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "adminive/adapters/nlohmann_json.hpp"
|
||||
#include "adminive/http.hpp"
|
||||
#include <atomic>
|
||||
#include <cassert>
|
||||
#include "adminive_test.hpp"
|
||||
#include <string>
|
||||
#include <thread>
|
||||
namespace managed_test {
|
||||
@@ -87,72 +87,72 @@ int main() {
|
||||
static_assert(Writable_Field<decltype(unsynchronized)>);
|
||||
static_assert(!Reference_Escaping_Read<decltype(immutable)>);
|
||||
const auto resolved = guarded.resolved_synchronization();
|
||||
assert(resolved.lock_count == 2);
|
||||
assert(resolved.slot(0) != structive::Resolved_Synchronization_View::unsynchronized_slot);
|
||||
assert(resolved.slot(1) == structive::Resolved_Synchronization_View::unsynchronized_slot);
|
||||
assert(resolved.slot(2) != structive::Resolved_Synchronization_View::unsynchronized_slot);
|
||||
assert(resolved.slot(0) != resolved.slot(2));
|
||||
assert(resolved.slot(3) == structive::Resolved_Synchronization_View::unsynchronized_slot);
|
||||
ADMINIVE_CHECK(resolved.lock_count == 2);
|
||||
ADMINIVE_CHECK(resolved.slot(0) != structive::Resolved_Synchronization_View::unsynchronized_slot);
|
||||
ADMINIVE_CHECK(resolved.slot(1) == structive::Resolved_Synchronization_View::unsynchronized_slot);
|
||||
ADMINIVE_CHECK(resolved.slot(2) != structive::Resolved_Synchronization_View::unsynchronized_slot);
|
||||
ADMINIVE_CHECK(resolved.slot(0) != resolved.slot(2));
|
||||
ADMINIVE_CHECK(resolved.slot(3) == structive::Resolved_Synchronization_View::unsynchronized_slot);
|
||||
Probe_Lock::reset();
|
||||
assert(immutable.snapshot() == 2);
|
||||
assert(Probe_Lock::exclusive_locks.load(std::memory_order_relaxed) == 0);
|
||||
assert(Probe_Lock::shared_locks.load(std::memory_order_relaxed) == 0);
|
||||
ADMINIVE_CHECK(immutable.snapshot() == 2);
|
||||
ADMINIVE_CHECK(Probe_Lock::exclusive_locks.load(std::memory_order_relaxed) == 0);
|
||||
ADMINIVE_CHECK(Probe_Lock::shared_locks.load(std::memory_order_relaxed) == 0);
|
||||
Probe_Lock::reset();
|
||||
editable.write([](int& value) {
|
||||
value = 11;
|
||||
});
|
||||
assert(Probe_Lock::exclusive_locks.load(std::memory_order_relaxed) == 1);
|
||||
assert(Probe_Lock::shared_locks.load(std::memory_order_relaxed) == 0);
|
||||
ADMINIVE_CHECK(Probe_Lock::exclusive_locks.load(std::memory_order_relaxed) == 1);
|
||||
ADMINIVE_CHECK(Probe_Lock::shared_locks.load(std::memory_order_relaxed) == 0);
|
||||
Probe_Lock::reset();
|
||||
backend.write([](int& value) {
|
||||
value = 12;
|
||||
});
|
||||
assert(Probe_Lock::exclusive_locks.load(std::memory_order_relaxed) == 1);
|
||||
ADMINIVE_CHECK(Probe_Lock::exclusive_locks.load(std::memory_order_relaxed) == 1);
|
||||
Probe_Lock::reset();
|
||||
unsynchronized.write([](int& value) {
|
||||
value = 13;
|
||||
});
|
||||
assert(Probe_Lock::exclusive_locks.load(std::memory_order_relaxed) == 0);
|
||||
assert(Probe_Lock::shared_locks.load(std::memory_order_relaxed) == 0);
|
||||
ADMINIVE_CHECK(Probe_Lock::exclusive_locks.load(std::memory_order_relaxed) == 0);
|
||||
ADMINIVE_CHECK(Probe_Lock::shared_locks.load(std::memory_order_relaxed) == 0);
|
||||
const auto descriptor = adminive::to_descriptor_json<Json, Section_Config>();
|
||||
assert(descriptor.at("protocol_version") == 5);
|
||||
assert(!descriptor.at("fields").at(0).contains("lock_mode"));
|
||||
assert(descriptor.at("fields").at(0).at("writable") == true);
|
||||
assert(descriptor.at("fields").at(0).at("synchronized") == true);
|
||||
assert(descriptor.at("fields").at(1).at("writable") == false);
|
||||
assert(descriptor.at("fields").at(1).at("synchronized") == false);
|
||||
assert(descriptor.at("fields").at(2).at("writable") == true);
|
||||
assert(descriptor.at("fields").at(2).at("editable") == false);
|
||||
assert(descriptor.at("fields").at(2).at("synchronized") == true);
|
||||
assert(descriptor.at("fields").at(3).at("writable") == true);
|
||||
assert(descriptor.at("fields").at(3).at("synchronized") == false);
|
||||
ADMINIVE_CHECK(descriptor.at("protocol_version") == 5);
|
||||
ADMINIVE_CHECK(!descriptor.at("fields").at(0).contains("lock_mode"));
|
||||
ADMINIVE_CHECK(descriptor.at("fields").at(0).at("writable") == true);
|
||||
ADMINIVE_CHECK(descriptor.at("fields").at(0).at("synchronized") == true);
|
||||
ADMINIVE_CHECK(descriptor.at("fields").at(1).at("writable") == false);
|
||||
ADMINIVE_CHECK(descriptor.at("fields").at(1).at("synchronized") == false);
|
||||
ADMINIVE_CHECK(descriptor.at("fields").at(2).at("writable") == true);
|
||||
ADMINIVE_CHECK(descriptor.at("fields").at(2).at("editable") == false);
|
||||
ADMINIVE_CHECK(descriptor.at("fields").at(2).at("synchronized") == true);
|
||||
ADMINIVE_CHECK(descriptor.at("fields").at(3).at("writable") == true);
|
||||
ADMINIVE_CHECK(descriptor.at("fields").at(3).at("synchronized") == false);
|
||||
adminive::Managed_Value<Root_Config, adminive::Mutex_Policy<Probe_Lock>> nested;
|
||||
auto section = nested.member<&Root_Config::section>();
|
||||
static_assert(!Writable_Field<decltype(section)>);
|
||||
Probe_Lock::reset();
|
||||
assert(section.member<&Section_Config::immutable_value>().snapshot() == 2);
|
||||
assert(Probe_Lock::shared_locks.load(std::memory_order_relaxed) == 0);
|
||||
ADMINIVE_CHECK(section.member<&Section_Config::immutable_value>().snapshot() == 2);
|
||||
ADMINIVE_CHECK(Probe_Lock::shared_locks.load(std::memory_order_relaxed) == 0);
|
||||
Probe_Lock::reset();
|
||||
section.member<&Section_Config::editable_value>().write([](int& value) {
|
||||
value = 31;
|
||||
});
|
||||
assert(Probe_Lock::exclusive_locks.load(std::memory_order_relaxed) == 1);
|
||||
ADMINIVE_CHECK(Probe_Lock::exclusive_locks.load(std::memory_order_relaxed) == 1);
|
||||
Probe_Lock::reset();
|
||||
section.member<&Section_Config::unsynchronized_value>().write([](int& value) {
|
||||
value = 32;
|
||||
});
|
||||
assert(Probe_Lock::exclusive_locks.load(std::memory_order_relaxed) == 0);
|
||||
ADMINIVE_CHECK(Probe_Lock::exclusive_locks.load(std::memory_order_relaxed) == 0);
|
||||
adminive::Managed_Value<Section_Config, structive::No_Lock_Policy> no_lock;
|
||||
adminive::Resource_Service<Section_Config, Json> service(no_lock, "/section");
|
||||
const auto rejected = service.update_response(R"({"backend_value":99,"immutable_value":88})");
|
||||
assert(rejected.status == 422);
|
||||
ADMINIVE_CHECK(rejected.status == 422);
|
||||
const auto update = service.update_response(R"({"editable_value":21,"unsynchronized_value":22})");
|
||||
assert(update.status == 200);
|
||||
ADMINIVE_CHECK(update.status == 200);
|
||||
const auto no_lock_snapshot = no_lock.snapshot();
|
||||
assert(no_lock_snapshot.editable_value == 21);
|
||||
assert(no_lock_snapshot.backend_value == 3);
|
||||
assert(no_lock_snapshot.immutable_value == 2);
|
||||
assert(no_lock_snapshot.unsynchronized_value == 22);
|
||||
ADMINIVE_CHECK(no_lock_snapshot.editable_value == 21);
|
||||
ADMINIVE_CHECK(no_lock_snapshot.backend_value == 3);
|
||||
ADMINIVE_CHECK(no_lock_snapshot.immutable_value == 2);
|
||||
ADMINIVE_CHECK(no_lock_snapshot.unsynchronized_value == 22);
|
||||
adminive::Managed_Value<Concurrent_Config> concurrent;
|
||||
std::atomic<bool> start{};
|
||||
auto first_writer = std::thread([&] {
|
||||
@@ -175,7 +175,7 @@ int main() {
|
||||
while(!start.load(std::memory_order_acquire)) {}
|
||||
for(int index = 0; index < 1000; ++index) {
|
||||
const Json value = adminive::to_json<Json>(concurrent);
|
||||
assert(value.at("immutable_value") == 7);
|
||||
ADMINIVE_CHECK(value.at("immutable_value") == 7);
|
||||
}
|
||||
});
|
||||
start.store(true, std::memory_order_release);
|
||||
@@ -183,8 +183,8 @@ int main() {
|
||||
second_writer.join();
|
||||
serializer.join();
|
||||
const auto concurrent_snapshot = concurrent.snapshot();
|
||||
assert(concurrent_snapshot.first == 4999);
|
||||
assert(concurrent_snapshot.second == 4999);
|
||||
assert(concurrent_snapshot.immutable_value == 7);
|
||||
ADMINIVE_CHECK(concurrent_snapshot.first == 4999);
|
||||
ADMINIVE_CHECK(concurrent_snapshot.second == 4999);
|
||||
ADMINIVE_CHECK(concurrent_snapshot.immutable_value == 7);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "adminive/adapters/nlohmann_json.hpp"
|
||||
#include "adminive/http.hpp"
|
||||
#include <cassert>
|
||||
#include "adminive_test.hpp"
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <optional>
|
||||
@@ -265,39 +265,39 @@ int main() {
|
||||
using namespace safety_test;
|
||||
Root_Config root;
|
||||
auto update = adminive::apply_frontend_patch<Json>(root, Json{{"child", Json{{"editable_value", 8}}}});
|
||||
assert(update.success);
|
||||
assert(root.child.editable_value == 8);
|
||||
assert(root.child.required_value == 3);
|
||||
ADMINIVE_CHECK(update.success);
|
||||
ADMINIVE_CHECK(root.child.editable_value == 8);
|
||||
ADMINIVE_CHECK(root.child.required_value == 3);
|
||||
update = adminive::apply_frontend_patch<Json>(root, Json{{"child", Json{{"locked_value", 9}}}});
|
||||
assert(!update.success);
|
||||
assert(update.field_errors.contains("child.locked_value"));
|
||||
assert(root.child.locked_value == 2);
|
||||
ADMINIVE_CHECK(!update.success);
|
||||
ADMINIVE_CHECK(update.field_errors.contains("child.locked_value"));
|
||||
ADMINIVE_CHECK(root.child.locked_value == 2);
|
||||
Root_Config created;
|
||||
update = adminive::apply_frontend_create<Json>(created, Json{{"child", Json{{"editable_value", 5}}}});
|
||||
assert(!update.success);
|
||||
assert(update.field_errors.contains("child.required_value"));
|
||||
ADMINIVE_CHECK(!update.success);
|
||||
ADMINIVE_CHECK(update.field_errors.contains("child.required_value"));
|
||||
const auto root_form = adminive::to_amis_form_schema<Json>(root, adminive::describe_edit_view<Root_Config>());
|
||||
assert(root_form.at("body").at(0).at("body").at(2).at("visibleOn") == "${child.editable_value > 0}");
|
||||
ADMINIVE_CHECK(root_form.at("body").at(0).at("body").at(2).at("visibleOn") == "${child.editable_value > 0}");
|
||||
Numeric_Config numeric;
|
||||
update = adminive::apply_frontend_patch<Json>(numeric, Json{{"signed_value", 1.5}});
|
||||
assert(!update.success);
|
||||
ADMINIVE_CHECK(!update.success);
|
||||
update = adminive::apply_frontend_patch<Json>(numeric, Json{{"unsigned_value", -1}});
|
||||
assert(!update.success);
|
||||
ADMINIVE_CHECK(!update.success);
|
||||
update = adminive::apply_frontend_patch<Json>(numeric, Json{{"signed_value", std::numeric_limits<std::uint64_t>::max()}});
|
||||
assert(!update.success);
|
||||
ADMINIVE_CHECK(!update.success);
|
||||
Optional_Config optional;
|
||||
const auto optional_form = adminive::to_amis_form_schema<Json>(optional, adminive::describe_edit_view<Optional_Config>());
|
||||
assert(optional_form.at("body").at(0).at("clearable") == true);
|
||||
assert(optional_form.at("body").at(1).at("clearable") == true);
|
||||
ADMINIVE_CHECK(optional_form.at("body").at(0).at("clearable") == true);
|
||||
ADMINIVE_CHECK(optional_form.at("body").at(1).at("clearable") == true);
|
||||
update = adminive::apply_frontend_patch<Json>(optional, Json{{"count", nullptr}, {"note", nullptr}});
|
||||
assert(update.success);
|
||||
assert(!optional.count);
|
||||
assert(!optional.note);
|
||||
ADMINIVE_CHECK(update.success);
|
||||
ADMINIVE_CHECK(!optional.count);
|
||||
ADMINIVE_CHECK(!optional.note);
|
||||
Multi_Error_Config multi;
|
||||
update = adminive::apply_frontend_patch<Json>(multi, Json{{"first", -1}, {"second", -2}});
|
||||
assert(!update.success);
|
||||
assert(update.field_errors.contains("first"));
|
||||
assert(update.field_errors.contains("second"));
|
||||
ADMINIVE_CHECK(!update.success);
|
||||
ADMINIVE_CHECK(update.field_errors.contains("first"));
|
||||
ADMINIVE_CHECK(update.field_errors.contains("second"));
|
||||
Runtime_Config runtime;
|
||||
bool rollback_called{};
|
||||
adminive::Resource_Transaction<Runtime_Model> transaction;
|
||||
@@ -305,39 +305,39 @@ int main() {
|
||||
throw std::runtime_error("external commit failed");
|
||||
};
|
||||
transaction.rollback = [&rollback_called](const Runtime_Model& original, const adminive::Request_Context&) {
|
||||
assert(original.value == 1);
|
||||
ADMINIVE_CHECK(original.value == 1);
|
||||
rollback_called = true;
|
||||
};
|
||||
adminive::Resource_Service<Runtime_Config, Json> service(runtime, "/runtime", std::move(transaction));
|
||||
const auto response = service.update_response(R"({"value":7})");
|
||||
assert(response.status == 500);
|
||||
assert(runtime.value() == 1);
|
||||
assert(rollback_called);
|
||||
ADMINIVE_CHECK(response.status == 500);
|
||||
ADMINIVE_CHECK(runtime.value() == 1);
|
||||
ADMINIVE_CHECK(rollback_called);
|
||||
Device_Config devices;
|
||||
update = adminive::apply_frontend_patch<Json>(devices, Json{{"device", Json{{"type", "serial"}, {"baud_rate", 9600}}}});
|
||||
assert(update.success);
|
||||
assert(std::get<Serial_Device>(devices.device).port == "COM1");
|
||||
assert(std::get<Serial_Device>(devices.device).baud_rate == 9600);
|
||||
ADMINIVE_CHECK(update.success);
|
||||
ADMINIVE_CHECK(std::get<Serial_Device>(devices.device).port == "COM1");
|
||||
ADMINIVE_CHECK(std::get<Serial_Device>(devices.device).baud_rate == 9600);
|
||||
update = adminive::apply_frontend_patch<Json>(devices, Json{{"device", Json{{"type", "network"}, {"host", "10.0.0.1"}, {"port", 7000}}}});
|
||||
assert(update.success);
|
||||
assert(std::holds_alternative<Network_Device>(devices.device));
|
||||
ADMINIVE_CHECK(update.success);
|
||||
ADMINIVE_CHECK(std::holds_alternative<Network_Device>(devices.device));
|
||||
update = adminive::apply_frontend_patch<Json>(devices, Json{{"device", Json{{"type", "token"}, {"token", "abc"}}}});
|
||||
assert(update.success);
|
||||
assert(std::holds_alternative<Token_Device>(devices.device));
|
||||
assert(std::get<Token_Device>(devices.device).token == "abc");
|
||||
ADMINIVE_CHECK(update.success);
|
||||
ADMINIVE_CHECK(std::holds_alternative<Token_Device>(devices.device));
|
||||
ADMINIVE_CHECK(std::get<Token_Device>(devices.device).token == "abc");
|
||||
bool invalid_name_rejected{};
|
||||
try {
|
||||
static_cast<void>(adminive::to_descriptor_json<Json, Invalid_Name_Config>());
|
||||
} catch(const std::invalid_argument&) {
|
||||
invalid_name_rejected = true;
|
||||
}
|
||||
assert(invalid_name_rejected);
|
||||
ADMINIVE_CHECK(invalid_name_rejected);
|
||||
bool conflict_rejected{};
|
||||
try {
|
||||
static_cast<void>(adminive::to_descriptor_json<Json, Conflict_Config>());
|
||||
} catch(const std::invalid_argument&) {
|
||||
conflict_rejected = true;
|
||||
}
|
||||
assert(conflict_rejected);
|
||||
ADMINIVE_CHECK(conflict_rejected);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+137
-137
@@ -1,6 +1,6 @@
|
||||
#include "example_descriptors.hpp"
|
||||
#include "gallery.hpp"
|
||||
#include <cassert>
|
||||
#include "adminive_test.hpp"
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
@@ -29,10 +29,10 @@ const Json* find_named_node(const Json& value, std::string_view name) {
|
||||
void assert_flex_items_renderable(const Json& value) {
|
||||
if(value.is_object()) {
|
||||
if(value.contains("type") && value.at("type") == "flex") {
|
||||
assert(value.contains("items"));
|
||||
ADMINIVE_CHECK(value.contains("items"));
|
||||
for(const auto& item : value.at("items")) {
|
||||
assert(item.is_object());
|
||||
assert(item.contains("type"));
|
||||
ADMINIVE_CHECK(item.is_object());
|
||||
ADMINIVE_CHECK(item.contains("type"));
|
||||
}
|
||||
}
|
||||
for(const auto& [key, child] : value.items()) {
|
||||
@@ -96,172 +96,172 @@ int main() {
|
||||
using adminive::example::Radio_State;
|
||||
Radio_State state;
|
||||
const auto descriptor = adminive::to_descriptor_json<Json, Radio_State>();
|
||||
assert(descriptor.at("protocol") == "adminive.resource");
|
||||
assert(descriptor.at("protocol_version") == 5);
|
||||
assert(descriptor.at("name") == "radio_state");
|
||||
assert(descriptor.at("fields").size() == 5);
|
||||
ADMINIVE_CHECK(descriptor.at("protocol") == "adminive.resource");
|
||||
ADMINIVE_CHECK(descriptor.at("protocol_version") == 5);
|
||||
ADMINIVE_CHECK(descriptor.at("name") == "radio_state");
|
||||
ADMINIVE_CHECK(descriptor.at("fields").size() == 5);
|
||||
const auto& mode_field = descriptor.at("fields").at(0);
|
||||
assert(mode_field.at("name") == "mode");
|
||||
assert(mode_field.at("presentation").at("label") == "运行模式");
|
||||
assert(mode_field.at("value_type") == "enum");
|
||||
assert(mode_field.at("presentation").at("options").size() == 4);
|
||||
assert(mode_field.at("presentation").at("options").at(0).at("value") == "receive");
|
||||
assert(mode_field.at("presentation").at("options").at(2).at("value") == "duplex");
|
||||
ADMINIVE_CHECK(mode_field.at("name") == "mode");
|
||||
ADMINIVE_CHECK(mode_field.at("presentation").at("label") == "运行模式");
|
||||
ADMINIVE_CHECK(mode_field.at("value_type") == "enum");
|
||||
ADMINIVE_CHECK(mode_field.at("presentation").at("options").size() == 4);
|
||||
ADMINIVE_CHECK(mode_field.at("presentation").at("options").at(0).at("value") == "receive");
|
||||
ADMINIVE_CHECK(mode_field.at("presentation").at("options").at(2).at("value") == "duplex");
|
||||
const auto& port_field = descriptor.at("fields").at(1);
|
||||
assert(port_field.at("name") == "port");
|
||||
assert(port_field.at("presentation").at("label") == "监听端口");
|
||||
assert(port_field.at("minimum") == 1);
|
||||
assert(port_field.at("maximum") == 65535);
|
||||
assert(descriptor.at("fields").at(2).at("multiple_of") == 2);
|
||||
assert(!descriptor.contains("list"));
|
||||
ADMINIVE_CHECK(port_field.at("name") == "port");
|
||||
ADMINIVE_CHECK(port_field.at("presentation").at("label") == "监听端口");
|
||||
ADMINIVE_CHECK(port_field.at("minimum") == 1);
|
||||
ADMINIVE_CHECK(port_field.at("maximum") == 65535);
|
||||
ADMINIVE_CHECK(descriptor.at("fields").at(2).at("multiple_of") == 2);
|
||||
ADMINIVE_CHECK(!descriptor.contains("list"));
|
||||
const auto table_view = adminive::describe_table_view<Radio_State>();
|
||||
assert(table_view.columns.size() == 5);
|
||||
assert(table_view.columns.at(0).field == "mode");
|
||||
assert(table_view.columns.at(0).label == "模式");
|
||||
assert(table_view.columns.at(0).sortable);
|
||||
assert(table_view.columns.at(0).filterable);
|
||||
assert(table_view.columns.at(2).field == "port");
|
||||
assert(table_view.columns.at(2).searchable);
|
||||
assert(table_view.default_order_by == "buffer_count");
|
||||
ADMINIVE_CHECK(table_view.columns.size() == 5);
|
||||
ADMINIVE_CHECK(table_view.columns.at(0).field == "mode");
|
||||
ADMINIVE_CHECK(table_view.columns.at(0).label == "模式");
|
||||
ADMINIVE_CHECK(table_view.columns.at(0).sortable);
|
||||
ADMINIVE_CHECK(table_view.columns.at(0).filterable);
|
||||
ADMINIVE_CHECK(table_view.columns.at(2).field == "port");
|
||||
ADMINIVE_CHECK(table_view.columns.at(2).searchable);
|
||||
ADMINIVE_CHECK(table_view.default_order_by == "buffer_count");
|
||||
const auto table_view_json = adminive::to_view_json<Json, Radio_State>(table_view);
|
||||
assert(table_view_json.at("protocol") == "adminive.view");
|
||||
assert(table_view_json.at("kind") == "table");
|
||||
assert(table_view_json.at("columns").at(0).at("field") == "mode");
|
||||
assert(table_view_json.at("columns").at(0).at("filterable") == true);
|
||||
ADMINIVE_CHECK(table_view_json.at("protocol") == "adminive.view");
|
||||
ADMINIVE_CHECK(table_view_json.at("kind") == "table");
|
||||
ADMINIVE_CHECK(table_view_json.at("columns").at(0).at("field") == "mode");
|
||||
ADMINIVE_CHECK(table_view_json.at("columns").at(0).at("filterable") == true);
|
||||
const auto initial = adminive::to_json<Json>(state);
|
||||
assert(initial.at("mode") == "receive");
|
||||
assert(initial.at("port") == 9999);
|
||||
ADMINIVE_CHECK(initial.at("mode") == "receive");
|
||||
ADMINIVE_CHECK(initial.at("port") == 9999);
|
||||
Radio_State assigned;
|
||||
auto result = adminive::assign_json<Json>(assigned, Json{{"mode", "transmit"}, {"port", 7000}, {"buffer_count", 6}, {"low_watermark", 10}, {"high_watermark", 20}});
|
||||
assert(result.success);
|
||||
assert(assigned.mode == Radio_Mode::transmit);
|
||||
assert(assigned.port.value() == 7000);
|
||||
ADMINIVE_CHECK(result.success);
|
||||
ADMINIVE_CHECK(assigned.mode == Radio_Mode::transmit);
|
||||
ADMINIVE_CHECK(assigned.port.value() == 7000);
|
||||
result = adminive::apply_json_patch<Json>(assigned, Json{{"mode", "duplex"}, {"port", 7200}});
|
||||
assert(result.success);
|
||||
assert(assigned.mode == Radio_Mode::duplex);
|
||||
assert(assigned.port.value() == 7200);
|
||||
ADMINIVE_CHECK(result.success);
|
||||
ADMINIVE_CHECK(assigned.mode == Radio_Mode::duplex);
|
||||
ADMINIVE_CHECK(assigned.port.value() == 7200);
|
||||
result = adminive::apply_patch<Json>(state, Json{{"buffer_count", 3}});
|
||||
assert(!result.success);
|
||||
assert(state.buffer_count.value() == 2);
|
||||
ADMINIVE_CHECK(!result.success);
|
||||
ADMINIVE_CHECK(state.buffer_count.value() == 2);
|
||||
result = adminive::apply_patch<Json>(state, Json{{"low_watermark", 64}, {"high_watermark", 32}});
|
||||
assert(!result.success);
|
||||
assert(state.low_watermark == 0);
|
||||
ADMINIVE_CHECK(!result.success);
|
||||
ADMINIVE_CHECK(state.low_watermark == 0);
|
||||
result = adminive::apply_patch<Json>(state, Json{{"missing", 1}});
|
||||
assert(!result.success);
|
||||
assert(result.field_errors.contains("missing"));
|
||||
ADMINIVE_CHECK(!result.success);
|
||||
ADMINIVE_CHECK(result.field_errors.contains("missing"));
|
||||
Radio_State created;
|
||||
result = adminive::apply_frontend_create<Json>(created, Json{{"mode", "maintenance"}, {"port", 7300}, {"buffer_count", 10}, {"low_watermark", 12}, {"high_watermark", 24}});
|
||||
assert(result.success);
|
||||
assert(created.mode == Radio_Mode::maintenance);
|
||||
ADMINIVE_CHECK(result.success);
|
||||
ADMINIVE_CHECK(created.mode == Radio_Mode::maintenance);
|
||||
result = adminive::apply_frontend_create<Json>(created, Json{{"port", 7300}});
|
||||
assert(!result.success);
|
||||
assert(result.field_errors.contains("mode"));
|
||||
assert(result.field_errors.contains("buffer_count"));
|
||||
ADMINIVE_CHECK(!result.success);
|
||||
ADMINIVE_CHECK(result.field_errors.contains("mode"));
|
||||
ADMINIVE_CHECK(result.field_errors.contains("buffer_count"));
|
||||
const auto form_view = adminive::edit_form<Radio_State>().submit("Confirm Changes");
|
||||
const auto form = adminive::to_amis_form_schema<Json>(state, form_view, "/admin/radio_state");
|
||||
assert(form.at("type") == "form");
|
||||
assert(form.at("body").size() == 5);
|
||||
assert(form.at("body").at(0).at("type") == "select");
|
||||
assert(form.at("body").at(0).at("options").size() == 4);
|
||||
assert(form.at("body").at(1).at("type") == "input-number");
|
||||
assert(form.at("body").at(2).at("step") == 2);
|
||||
assert(form.at("actions").at(1).at("label") == "Confirm Changes");
|
||||
ADMINIVE_CHECK(form.at("type") == "form");
|
||||
ADMINIVE_CHECK(form.at("body").size() == 5);
|
||||
ADMINIVE_CHECK(form.at("body").at(0).at("type") == "select");
|
||||
ADMINIVE_CHECK(form.at("body").at(0).at("options").size() == 4);
|
||||
ADMINIVE_CHECK(form.at("body").at(1).at("type") == "input-number");
|
||||
ADMINIVE_CHECK(form.at("body").at(2).at("step") == 2);
|
||||
ADMINIVE_CHECK(form.at("actions").at(1).at("label") == "Confirm Changes");
|
||||
const auto crud = adminive::to_amis_table_schema<Json, Radio_State>("/admin/radio_states", table_view);
|
||||
assert(crud.at("type") == "page");
|
||||
ADMINIVE_CHECK(crud.at("type") == "page");
|
||||
const auto& crud_body = crud.at("body").at(0);
|
||||
assert(crud_body.at("type") == "crud");
|
||||
assert(crud_body.at("columns").size() == 7);
|
||||
assert(crud_body.at("columns").at(1).at("name") == "mode");
|
||||
assert(crud_body.at("columns").at(1).at("type") == "mapping");
|
||||
assert(crud_body.at("columns").at(1).at("map").at("duplex") == "双工");
|
||||
assert(crud_body.at("columns").at(1).at("filterable") == true);
|
||||
assert(crud_body.at("columns").at(3).at("name") == "port");
|
||||
assert(crud_body.at("columns").at(3).at("searchable") == true);
|
||||
ADMINIVE_CHECK(crud_body.at("type") == "crud");
|
||||
ADMINIVE_CHECK(crud_body.at("columns").size() == 7);
|
||||
ADMINIVE_CHECK(crud_body.at("columns").at(1).at("name") == "mode");
|
||||
ADMINIVE_CHECK(crud_body.at("columns").at(1).at("type") == "mapping");
|
||||
ADMINIVE_CHECK(crud_body.at("columns").at(1).at("map").at("duplex") == "双工");
|
||||
ADMINIVE_CHECK(crud_body.at("columns").at(1).at("filterable") == true);
|
||||
ADMINIVE_CHECK(crud_body.at("columns").at(3).at("name") == "port");
|
||||
ADMINIVE_CHECK(crud_body.at("columns").at(3).at("searchable") == true);
|
||||
const auto& create_form = crud_body.at("headerToolbar").at(2).at("dialog").at("body");
|
||||
assert(create_form.at("actions").at(1).at("label") == "新增");
|
||||
ADMINIVE_CHECK(create_form.at("actions").at(1).at("label") == "新增");
|
||||
const auto status_descriptor = adminive::to_status_descriptor_json<Json, Radio_Item_Status>();
|
||||
assert(status_descriptor.at("protocol") == "adminive.status");
|
||||
assert(status_descriptor.at("fields").size() == 3);
|
||||
assert(status_descriptor.at("fields").at(0).at("name") == "operating_state");
|
||||
assert(status_descriptor.at("fields").at(0).at("value_type") == "enum");
|
||||
assert(status_descriptor.at("fields").at(0).at("color") == true);
|
||||
ADMINIVE_CHECK(status_descriptor.at("protocol") == "adminive.status");
|
||||
ADMINIVE_CHECK(status_descriptor.at("fields").size() == 3);
|
||||
ADMINIVE_CHECK(status_descriptor.at("fields").at(0).at("name") == "operating_state");
|
||||
ADMINIVE_CHECK(status_descriptor.at("fields").at(0).at("value_type") == "enum");
|
||||
ADMINIVE_CHECK(status_descriptor.at("fields").at(0).at("color") == true);
|
||||
const auto first_status = adminive::to_status_json<Json>(state.status());
|
||||
const auto second_status = adminive::to_status_json<Json>(state.status());
|
||||
assert(first_status.at("operating_state").contains("color"));
|
||||
assert(!first_status.at("operating_state").at("color").get<std::string>().empty());
|
||||
assert(first_status.at("refresh_sequence").at("value") == 1);
|
||||
assert(second_status.at("refresh_sequence").at("value") == 2);
|
||||
ADMINIVE_CHECK(first_status.at("operating_state").contains("color"));
|
||||
ADMINIVE_CHECK(!first_status.at("operating_state").at("color").get<std::string>().empty());
|
||||
ADMINIVE_CHECK(first_status.at("refresh_sequence").at("value") == 1);
|
||||
ADMINIVE_CHECK(second_status.at("refresh_sequence").at("value") == 2);
|
||||
const auto overview_descriptor = adminive::to_status_descriptor_json<Json, adminive::example::Server_Status>();
|
||||
const auto status_crud = adminive::to_amis_table_schema<Json, Radio_State>("/admin/radio_states", table_view, &status_descriptor, 2000, &overview_descriptor, "/admin/status", 2000);
|
||||
assert(status_crud.at("body").is_array());
|
||||
assert(status_crud.at("body").at(0).at("type") == "service");
|
||||
assert(status_crud.at("body").at(1).at("columns").size() == 8);
|
||||
ADMINIVE_CHECK(status_crud.at("body").is_array());
|
||||
ADMINIVE_CHECK(status_crud.at("body").at(0).at("type") == "service");
|
||||
ADMINIVE_CHECK(status_crud.at("body").at(1).at("columns").size() == 8);
|
||||
const auto& status_column = status_crud.at("body").at(1).at("columns").at(6);
|
||||
assert(status_column.at("label") == "实时状态");
|
||||
assert(status_column.at("popOver").at("trigger") == "click");
|
||||
assert(status_column.at("popOver").at("body").at("api").at("url") == "/admin/radio_states/${id}/status");
|
||||
ADMINIVE_CHECK(status_column.at("label") == "实时状态");
|
||||
ADMINIVE_CHECK(status_column.at("popOver").at("trigger") == "click");
|
||||
ADMINIVE_CHECK(status_column.at("popOver").at("body").at("api").at("url") == "/admin/radio_states/${id}/status");
|
||||
adminive::example::Http_Collection_Resource<Radio_State> collection_resource("/admin/radio_states", std::vector<Radio_State>{state});
|
||||
collection_resource.register_overview_status<adminive::example::Server_Status>("/admin/status", 2000);
|
||||
collection_resource.register_status<&Radio_State::status>(3000);
|
||||
const auto registered_schema = collection_resource.amis_schema();
|
||||
const auto& registered_status_column = registered_schema.at("body").at(1).at("columns").at(6);
|
||||
assert(registered_status_column.at("popOver").at("body").at("interval") == 3000);
|
||||
ADMINIVE_CHECK(registered_status_column.at("popOver").at("body").at("interval") == 3000);
|
||||
Radio_Service_Config service_config;
|
||||
const auto service_descriptor = adminive::to_descriptor_json<Json, Radio_Service_Config>();
|
||||
assert(service_descriptor.at("fields").size() == 7);
|
||||
assert(service_descriptor.at("fields").at(0).at("value_type") == "string");
|
||||
assert(service_descriptor.at("fields").at(1).at("value_type") == "enum");
|
||||
assert(service_descriptor.at("fields").at(2).at("value_type") == "integer");
|
||||
assert(service_descriptor.at("fields").at(3).at("value_type") == "number");
|
||||
assert(service_descriptor.at("fields").at(4).at("value_type") == "object");
|
||||
assert(service_descriptor.at("fields").at(4).at("children").size() == 3);
|
||||
assert(service_descriptor.at("fields").at(5).at("presentation").at("visible_on") == "${$self.mode == 'duplex'}");
|
||||
assert(service_descriptor.at("fields").at(6).at("children").at(1).at("presentation").at("control") == "date");
|
||||
assert(service_descriptor.at("fields").at(6).at("children").at(2).at("presentation").at("control") == "color");
|
||||
ADMINIVE_CHECK(service_descriptor.at("fields").size() == 7);
|
||||
ADMINIVE_CHECK(service_descriptor.at("fields").at(0).at("value_type") == "string");
|
||||
ADMINIVE_CHECK(service_descriptor.at("fields").at(1).at("value_type") == "enum");
|
||||
ADMINIVE_CHECK(service_descriptor.at("fields").at(2).at("value_type") == "integer");
|
||||
ADMINIVE_CHECK(service_descriptor.at("fields").at(3).at("value_type") == "number");
|
||||
ADMINIVE_CHECK(service_descriptor.at("fields").at(4).at("value_type") == "object");
|
||||
ADMINIVE_CHECK(service_descriptor.at("fields").at(4).at("children").size() == 3);
|
||||
ADMINIVE_CHECK(service_descriptor.at("fields").at(5).at("presentation").at("visible_on") == "${$self.mode == 'duplex'}");
|
||||
ADMINIVE_CHECK(service_descriptor.at("fields").at(6).at("children").at(1).at("presentation").at("control") == "date");
|
||||
ADMINIVE_CHECK(service_descriptor.at("fields").at(6).at("children").at(2).at("presentation").at("control") == "color");
|
||||
const auto service_view = adminive::describe_edit_view<Radio_Service_Config>();
|
||||
const auto service_view_json = adminive::to_view_json<Json, Radio_Service_Config>(service_view);
|
||||
assert(service_view_json.at("body").at("kind") == "tabs");
|
||||
assert(service_view_json.at("body").at("children").size() == 3);
|
||||
ADMINIVE_CHECK(service_view_json.at("body").at("kind") == "tabs");
|
||||
ADMINIVE_CHECK(service_view_json.at("body").at("children").size() == 3);
|
||||
const auto service_form = adminive::to_amis_form_schema<Json>(service_config, service_view, "/admin/config/radio/data");
|
||||
assert(service_form.at("body").at(0).at("type") == "tabs");
|
||||
ADMINIVE_CHECK(service_form.at("body").at(0).at("type") == "tabs");
|
||||
const Json* profile_control = find_named_node(service_form, "profile_name");
|
||||
const Json* mode_control = find_named_node(service_form, "mode");
|
||||
const Json* worker_control = find_named_node(service_form, "worker_count");
|
||||
const Json* date_control = find_named_node(service_form, "appearance.effective_date");
|
||||
const Json* color_control = find_named_node(service_form, "appearance.accent_color");
|
||||
assert(profile_control && profile_control->at("type") == "input-text");
|
||||
assert(mode_control && mode_control->at("type") == "select");
|
||||
assert(worker_control && worker_control->at("type") == "input-number");
|
||||
assert(date_control && date_control->at("type") == "input-date");
|
||||
assert(color_control && color_control->at("type") == "input-color");
|
||||
assert(service_form.at("actions").at(1).at("label") == "确认修改");
|
||||
ADMINIVE_CHECK(profile_control && profile_control->at("type") == "input-text");
|
||||
ADMINIVE_CHECK(mode_control && mode_control->at("type") == "select");
|
||||
ADMINIVE_CHECK(worker_control && worker_control->at("type") == "input-number");
|
||||
ADMINIVE_CHECK(date_control && date_control->at("type") == "input-date");
|
||||
ADMINIVE_CHECK(color_control && color_control->at("type") == "input-color");
|
||||
ADMINIVE_CHECK(service_form.at("actions").at(1).at("label") == "确认修改");
|
||||
result = adminive::apply_frontend_patch<Json>(service_config, Json{{"profile_name", "Duplex Profile"}, {"mode", "duplex"}, {"worker_count", 8}, {"receive_gain", 2.5}, {"primary_endpoint", Json{{"enabled", true}, {"host", "10.0.0.1"}, {"port", 9200}}}, {"backup_endpoint", Json{{"enabled", true}, {"host", "10.0.0.2"}, {"port", 9201}}}, {"appearance", Json{{"panel_title", "Duplex Radio"}, {"effective_date", "2026-08-07"}, {"accent_color", "#16a34a"}}}});
|
||||
assert(result.success);
|
||||
assert(service_config.mode == Radio_Mode::duplex);
|
||||
assert(service_config.primary_endpoint.host == "10.0.0.1");
|
||||
assert(service_config.appearance.accent_color == "#16a34a");
|
||||
ADMINIVE_CHECK(result.success);
|
||||
ADMINIVE_CHECK(service_config.mode == Radio_Mode::duplex);
|
||||
ADMINIVE_CHECK(service_config.primary_endpoint.host == "10.0.0.1");
|
||||
ADMINIVE_CHECK(service_config.appearance.accent_color == "#16a34a");
|
||||
Alert_Config alert_config;
|
||||
const auto alert_view = adminive::describe_edit_view<Alert_Config>();
|
||||
const auto alert_view_json = adminive::to_view_json<Json, Alert_Config>(alert_view);
|
||||
assert(alert_view_json.at("body").at("kind") == "vertical");
|
||||
ADMINIVE_CHECK(alert_view_json.at("body").at("kind") == "vertical");
|
||||
const auto alert_form = adminive::to_amis_form_schema<Json>(alert_config, alert_view, "/admin/config/alerts/data");
|
||||
assert(find_named_node(alert_form, "rule_name"));
|
||||
assert(find_named_node(alert_form, "effective_date")->at("type") == "input-date");
|
||||
assert(find_named_node(alert_form, "highlight_color")->at("type") == "input-color");
|
||||
ADMINIVE_CHECK(find_named_node(alert_form, "rule_name"));
|
||||
ADMINIVE_CHECK(find_named_node(alert_form, "effective_date")->at("type") == "input-date");
|
||||
ADMINIVE_CHECK(find_named_node(alert_form, "highlight_color")->at("type") == "input-color");
|
||||
const Json* webhook_group = find_titled_node(alert_form, "Webhook 端点");
|
||||
assert(webhook_group);
|
||||
assert(webhook_group->at("visibleOn") == "${enabled && channel == 'webhook'}");
|
||||
ADMINIVE_CHECK(webhook_group);
|
||||
ADMINIVE_CHECK(webhook_group->at("visibleOn") == "${enabled && channel == 'webhook'}");
|
||||
adminive::example::Http_Resource<Radio_Service_Config> service_resource(service_config, "/admin/config/radio");
|
||||
const auto resource_view = service_resource.view_schema();
|
||||
assert(resource_view.at("protocol") == "adminive.view");
|
||||
assert(resource_view.at("kind") == "form");
|
||||
ADMINIVE_CHECK(resource_view.at("protocol") == "adminive.view");
|
||||
ADMINIVE_CHECK(resource_view.at("kind") == "form");
|
||||
const auto resource_form = service_resource.amis_schema();
|
||||
assert(resource_form.at("api").at("method") == "post");
|
||||
assert(resource_form.at("api").at("url") == "/admin/config/radio/data");
|
||||
assert(resource_form.at("actions").at(1).at("label") == "确认修改");
|
||||
ADMINIVE_CHECK(resource_form.at("api").at("method") == "post");
|
||||
ADMINIVE_CHECK(resource_form.at("api").at("url") == "/admin/config/radio/data");
|
||||
ADMINIVE_CHECK(resource_form.at("actions").at(1).at("label") == "确认修改");
|
||||
adminive::example::Component_Gallery gallery;
|
||||
const auto gallery_schema = gallery.amis_schema();
|
||||
assert(gallery_schema.at("type") == "panel");
|
||||
ADMINIVE_CHECK(gallery_schema.at("type") == "panel");
|
||||
assert_flex_items_renderable(gallery_schema);
|
||||
const Json* automatic_control = find_named_node(gallery_schema, "automatic_text");
|
||||
const Json* text_control = find_named_node(gallery_schema, "text_value");
|
||||
@@ -274,31 +274,31 @@ int main() {
|
||||
const Json* color_gallery_control = find_named_node(gallery_schema, "color_value");
|
||||
const Json* optional_control = find_named_node(gallery_schema, "optional_text");
|
||||
const Json* readonly_control = find_named_node(gallery_schema, "read_only_text");
|
||||
assert(automatic_control && automatic_control->at("type") == "input-text");
|
||||
assert(text_control && text_control->at("type") == "input-text");
|
||||
assert(multiline_control && multiline_control->at("type") == "textarea");
|
||||
assert(number_control && number_control->at("type") == "input-number");
|
||||
assert(number_control->at("min") == 0 && number_control->at("max") == 100);
|
||||
assert(even_control && even_control->at("type") == "input-number" && even_control->at("step") == 2);
|
||||
assert(boolean_control && boolean_control->at("type") == "switch");
|
||||
assert(select_control && select_control->at("type") == "select");
|
||||
assert(date_gallery_control && date_gallery_control->at("type") == "input-date");
|
||||
assert(color_gallery_control && color_gallery_control->at("type") == "input-color");
|
||||
assert(optional_control && optional_control->at("clearable") == true);
|
||||
assert(readonly_control && readonly_control->at("type") == "static");
|
||||
ADMINIVE_CHECK(automatic_control && automatic_control->at("type") == "input-text");
|
||||
ADMINIVE_CHECK(text_control && text_control->at("type") == "input-text");
|
||||
ADMINIVE_CHECK(multiline_control && multiline_control->at("type") == "textarea");
|
||||
ADMINIVE_CHECK(number_control && number_control->at("type") == "input-number");
|
||||
ADMINIVE_CHECK(number_control->at("min") == 0 && number_control->at("max") == 100);
|
||||
ADMINIVE_CHECK(even_control && even_control->at("type") == "input-number" && even_control->at("step") == 2);
|
||||
ADMINIVE_CHECK(boolean_control && boolean_control->at("type") == "switch");
|
||||
ADMINIVE_CHECK(select_control && select_control->at("type") == "select");
|
||||
ADMINIVE_CHECK(date_gallery_control && date_gallery_control->at("type") == "input-date");
|
||||
ADMINIVE_CHECK(color_gallery_control && color_gallery_control->at("type") == "input-color");
|
||||
ADMINIVE_CHECK(optional_control && optional_control->at("clearable") == true);
|
||||
ADMINIVE_CHECK(readonly_control && readonly_control->at("type") == "static");
|
||||
const Json* save_gallery_button = find_labeled_node(gallery_schema, "保存画廊数据");
|
||||
const Json* create_gallery_button = find_labeled_node(gallery_schema, "新增一行");
|
||||
const Json* edit_gallery_button = find_labeled_node(gallery_schema, "编辑");
|
||||
const Json* delete_gallery_button = find_labeled_node(gallery_schema, "删除");
|
||||
assert(save_gallery_button && save_gallery_button->at("type") == "submit");
|
||||
assert(create_gallery_button && create_gallery_button->at("type") == "button");
|
||||
assert(edit_gallery_button && edit_gallery_button->at("actionType") == "dialog");
|
||||
assert(delete_gallery_button && delete_gallery_button->at("actionType") == "ajax");
|
||||
ADMINIVE_CHECK(save_gallery_button && save_gallery_button->at("type") == "submit");
|
||||
ADMINIVE_CHECK(create_gallery_button && create_gallery_button->at("type") == "button");
|
||||
ADMINIVE_CHECK(edit_gallery_button && edit_gallery_button->at("actionType") == "dialog");
|
||||
ADMINIVE_CHECK(delete_gallery_button && delete_gallery_button->at("actionType") == "ajax");
|
||||
adminive::example::Server_Status server_status;
|
||||
server_status.server_time = "2026-08-06T00:00:00Z";
|
||||
server_status.poll_sequence = 7;
|
||||
const auto status_json = adminive::to_frontend_json<Json>(server_status);
|
||||
assert(status_json.at("service_state") == "running");
|
||||
assert(status_json.at("poll_sequence") == 7);
|
||||
ADMINIVE_CHECK(status_json.at("service_state") == "running");
|
||||
ADMINIVE_CHECK(status_json.at("poll_sequence") == 7);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "adminive/adminive.hpp"
|
||||
#include "adminive/adapters/nlohmann_json.hpp"
|
||||
#include <cassert>
|
||||
#include "adminive_test.hpp"
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
namespace view_test {
|
||||
@@ -43,211 +43,229 @@ int main() {
|
||||
using view_test::Config;
|
||||
using view_test::Json;
|
||||
const auto descriptor = adminive::to_descriptor_json<Json, Config>();
|
||||
assert(descriptor.at("fields").at(0).at("presentation").at("label") == "Name");
|
||||
assert(descriptor.at("fields").at(0).at("presentation").at("control") == "text");
|
||||
assert(!descriptor.at("fields").at(0).contains("sortable"));
|
||||
ADMINIVE_CHECK(descriptor.at("fields").at(0).at("presentation").at("label") == "Name");
|
||||
ADMINIVE_CHECK(descriptor.at("fields").at(0).at("presentation").at("control") == "text");
|
||||
ADMINIVE_CHECK(!descriptor.at("fields").at(0).contains("sortable"));
|
||||
const auto form_view = adminive::describe_edit_view<Config>();
|
||||
adminive::validate_form_view<Config>(form_view);
|
||||
const auto form_json = adminive::to_view_json<Json, Config>(form_view);
|
||||
assert(form_json.at("kind") == "form");
|
||||
assert(form_json.at("body").at("kind") == "vertical");
|
||||
assert(form_json.at("body").at("children").at(0).at("kind") == "group");
|
||||
assert(form_json.at("body").at("children").at(1).at("kind") == "grid");
|
||||
assert(form_json.at("body").at("children").at(2).at("kind") == "flow");
|
||||
assert(form_json.at("body").at("children").at(3).at("kind") == "tabs");
|
||||
ADMINIVE_CHECK(form_json.at("kind") == "form");
|
||||
ADMINIVE_CHECK(form_json.at("body").at("kind") == "vertical");
|
||||
ADMINIVE_CHECK(form_json.at("body").at("children").at(0).at("kind") == "group");
|
||||
ADMINIVE_CHECK(form_json.at("body").at("children").at(1).at("kind") == "grid");
|
||||
ADMINIVE_CHECK(form_json.at("body").at("children").at(2).at("kind") == "flow");
|
||||
ADMINIVE_CHECK(form_json.at("body").at("children").at(3).at("kind") == "tabs");
|
||||
Config config;
|
||||
const auto form_amis = adminive::to_amis_form_schema<Json>(config, form_view, "/config/data");
|
||||
assert(form_amis.at("type") == "form");
|
||||
assert(form_amis.at("actions").at(1).at("label") == "Save");
|
||||
assert(form_amis.at("body").at(0).at("type") == "fieldset");
|
||||
assert(form_amis.at("body").at(1).at("type") == "grid");
|
||||
assert(form_amis.at("body").at(2).at("type") == "flex");
|
||||
assert(form_amis.at("body").at(2).at("items").at(0).at("type") == "container");
|
||||
assert(form_amis.at("body").at(2).at("items").at(1).at("type") == "container");
|
||||
assert(form_amis.at("body").at(2).at("items").at(0).at("body").at(0).at("type") == "card");
|
||||
assert(form_amis.at("body").at(3).at("type") == "tabs");
|
||||
assert(form_amis.at("data").at("read_only") == "fixed");
|
||||
assert(form_amis.at("api").at("data").at("name") == "${name}");
|
||||
assert(form_amis.at("api").at("data").at("count") == "${count}");
|
||||
assert(form_amis.at("api").at("data").at("enabled") == "${enabled}");
|
||||
assert(form_amis.at("api").at("data").at("color") == "${color}");
|
||||
assert(!form_amis.at("api").at("data").contains("read_only"));
|
||||
ADMINIVE_CHECK(form_amis.at("type") == "form");
|
||||
ADMINIVE_CHECK(form_amis.at("actions").at(1).at("label") == "Save");
|
||||
ADMINIVE_CHECK(form_amis.at("body").at(0).at("type") == "fieldset");
|
||||
ADMINIVE_CHECK(form_amis.at("body").at(1).at("type") == "grid");
|
||||
ADMINIVE_CHECK(form_amis.at("body").at(2).at("type") == "flex");
|
||||
ADMINIVE_CHECK(form_amis.at("body").at(2).at("items").at(0).at("type") == "container");
|
||||
ADMINIVE_CHECK(form_amis.at("body").at(2).at("items").at(1).at("type") == "container");
|
||||
ADMINIVE_CHECK(form_amis.at("body").at(2).at("items").at(0).at("body").at(0).at("type") == "card");
|
||||
ADMINIVE_CHECK(form_amis.at("body").at(3).at("type") == "tabs");
|
||||
ADMINIVE_CHECK(form_amis.at("data").at("read_only") == "fixed");
|
||||
ADMINIVE_CHECK(form_amis.at("api").at("data").at("name") == "${name}");
|
||||
ADMINIVE_CHECK(form_amis.at("api").at("data").at("count") == "${count}");
|
||||
ADMINIVE_CHECK(form_amis.at("api").at("data").at("enabled") == "${enabled}");
|
||||
ADMINIVE_CHECK(form_amis.at("api").at("data").at("color") == "${color}");
|
||||
ADMINIVE_CHECK(!form_amis.at("api").at("data").contains("read_only"));
|
||||
const auto table_view = adminive::describe_table_view<Config>();
|
||||
adminive::validate_table_view<Config>(table_view);
|
||||
const auto table_json = adminive::to_view_json<Json, Config>(table_view);
|
||||
assert(table_json.at("kind") == "table");
|
||||
assert(table_json.at("columns").at(0).at("searchable") == true);
|
||||
assert(table_json.at("columns").at(0).at("fixed") == "left");
|
||||
assert(table_json.at("columns").at(1).at("sortable") == true);
|
||||
assert(table_json.at("columns").at(2).at("filterable") == true);
|
||||
assert(table_json.at("default_order_by") == "count");
|
||||
assert(table_json.at("default_order_dir") == "desc");
|
||||
ADMINIVE_CHECK(table_json.at("kind") == "table");
|
||||
ADMINIVE_CHECK(table_json.at("columns").at(0).at("searchable") == true);
|
||||
ADMINIVE_CHECK(table_json.at("columns").at(0).at("fixed") == "left");
|
||||
ADMINIVE_CHECK(table_json.at("columns").at(1).at("sortable") == true);
|
||||
ADMINIVE_CHECK(table_json.at("columns").at(2).at("filterable") == true);
|
||||
ADMINIVE_CHECK(table_json.at("default_order_by") == "count");
|
||||
ADMINIVE_CHECK(table_json.at("default_order_dir") == "desc");
|
||||
const auto composition = adminive::composition_view("config_page", adminive::compose::vertical(adminive::compose::heading("Config Page").accent("#123456"), adminive::compose::horizontal(adminive::compose::slot("form"), adminive::compose::slot("table"))));
|
||||
const auto composition_json = adminive::to_view_json<Json>(composition);
|
||||
assert(composition_json.at("kind") == "composition");
|
||||
assert(composition_json.at("body").at("children").at(0).at("kind") == "heading");
|
||||
ADMINIVE_CHECK(composition_json.at("kind") == "composition");
|
||||
ADMINIVE_CHECK(composition_json.at("body").at("children").at(0).at("kind") == "heading");
|
||||
const auto composition_amis = adminive::to_amis_composition_schema<Json>(composition, {{"form", form_amis}, {"table", Json{{"type", "tpl"}, {"tpl", "table"}}}});
|
||||
assert(composition_amis.at("body").at(0).at("type") == "tpl");
|
||||
assert(composition_amis.at("body").at(1).at("type") == "grid");
|
||||
ADMINIVE_CHECK(composition_amis.at("body").at(0).at("type") == "tpl");
|
||||
ADMINIVE_CHECK(composition_amis.at("body").at(1).at("type") == "grid");
|
||||
const auto five_columns = adminive::composition_view("five_columns", adminive::compose::horizontal(adminive::compose::slot("a"), adminive::compose::slot("b"), adminive::compose::slot("c"), adminive::compose::slot("d"), adminive::compose::slot("e")));
|
||||
const auto five_columns_amis = adminive::to_amis_composition_schema<Json>(five_columns, {{"a", Json{{"type", "tpl"}}}, {"b", Json{{"type", "tpl"}}}, {"c", Json{{"type", "tpl"}}}, {"d", Json{{"type", "tpl"}}}, {"e", Json{{"type", "tpl"}}}});
|
||||
const auto& five_widths = five_columns_amis.at("body").at(0).at("columns");
|
||||
assert(five_widths.at(0).at("md") == 3);
|
||||
assert(five_widths.at(1).at("md") == 3);
|
||||
assert(five_widths.at(2).at("md") == 2);
|
||||
assert(five_widths.at(3).at("md") == 2);
|
||||
assert(five_widths.at(4).at("md") == 2);
|
||||
ADMINIVE_CHECK(five_widths.at(0).at("md") == 3);
|
||||
ADMINIVE_CHECK(five_widths.at(1).at("md") == 3);
|
||||
ADMINIVE_CHECK(five_widths.at(2).at("md") == 2);
|
||||
ADMINIVE_CHECK(five_widths.at(3).at("md") == 2);
|
||||
ADMINIVE_CHECK(five_widths.at(4).at("md") == 2);
|
||||
const auto flow_composition = adminive::composition_view("flow_page", adminive::compose::flow(adminive::compose::slot("left"), adminive::compose::slot("right")));
|
||||
const auto flow_amis = adminive::to_amis_composition_schema<Json>(flow_composition, {{"left", Json{{"type", "tpl"}, {"tpl", "left"}}}, {"right", Json{{"type", "tpl"}, {"tpl", "right"}}}});
|
||||
assert(flow_amis.at("body").at(0).at("type") == "flex");
|
||||
assert(flow_amis.at("body").at(0).at("items").at(0).at("type") == "container");
|
||||
assert(flow_amis.at("body").at(0).at("items").at(1).at("type") == "container");
|
||||
ADMINIVE_CHECK(flow_amis.at("body").at(0).at("type") == "flex");
|
||||
ADMINIVE_CHECK(flow_amis.at("body").at(0).at("items").at(0).at("type") == "container");
|
||||
ADMINIVE_CHECK(flow_amis.at("body").at(0).at("items").at(1).at("type") == "container");
|
||||
const auto list_composition = adminive::composition_view("list_page", adminive::compose::list(adminive::compose::slot("left"), adminive::compose::slot("right")));
|
||||
const auto list_composition_json = adminive::to_view_json<Json>(list_composition);
|
||||
assert(list_composition_json.at("body").at("kind") == "list");
|
||||
ADMINIVE_CHECK(list_composition_json.at("body").at("kind") == "list");
|
||||
const auto list_composition_amis = adminive::to_amis_composition_schema<Json>(list_composition, {{"left", Json{{"type", "tpl"}, {"tpl", "left"}}}, {"right", Json{{"type", "tpl"}, {"tpl", "right"}}}});
|
||||
assert(list_composition_amis.at("body").at(0).at("type") == "container");
|
||||
assert(list_composition_amis.at("body").at(0).at("body").size() == 2);
|
||||
ADMINIVE_CHECK(list_composition_amis.at("body").at(0).at("type") == "container");
|
||||
ADMINIVE_CHECK(list_composition_amis.at("body").at(0).at("body").size() == 2);
|
||||
const auto frontend_composition = adminive::composition_view("frontend_page", adminive::compose::frontend(adminive::compose::slot("left"), adminive::compose::slot("right")));
|
||||
const auto frontend_composition_json = adminive::to_view_json<Json>(frontend_composition);
|
||||
assert(frontend_composition_json.at("body").at("kind") == "frontend");
|
||||
ADMINIVE_CHECK(frontend_composition_json.at("body").at("kind") == "frontend");
|
||||
const auto frontend_composition_amis = adminive::to_amis_composition_schema<Json>(frontend_composition, {{"left", Json{{"type", "tpl"}, {"tpl", "left"}}}, {"right", Json{{"type", "tpl"}, {"tpl", "right"}}}});
|
||||
assert(frontend_composition_amis.at("body").at(0).at("className") == "adminive-frontend-placement");
|
||||
ADMINIVE_CHECK(frontend_composition_amis.at("body").at(0).at("className") == "adminive-frontend-placement");
|
||||
const std::vector<adminive::Composition_Slot_Contract> slot_contracts{{"left", "amis_schema", "/left/descriptor", "/left/view", "/left/data", "/left/amis"}, {"right", "amis_schema", "/right/descriptor", "/right/view", "/right/data", "/right/amis"}};
|
||||
const auto manifest = adminive::to_composition_manifest_json<Json>(frontend_composition, slot_contracts, {{"left", Json{{"type", "tpl"}, {"tpl", "left"}}}, {"right", Json{{"type", "tpl"}, {"tpl", "right"}}}});
|
||||
assert(manifest.at("protocol") == "adminive.composition-manifest");
|
||||
assert(manifest.at("view").at("body").at("kind") == "frontend");
|
||||
assert(manifest.at("slots").at("left").at("view_api") == "/left/view");
|
||||
assert(manifest.at("slots").at("right").at("schema").at("tpl") == "right");
|
||||
ADMINIVE_CHECK(manifest.at("protocol") == "adminive.composition-manifest");
|
||||
ADMINIVE_CHECK(manifest.at("view").at("body").at("kind") == "frontend");
|
||||
ADMINIVE_CHECK(manifest.at("slots").at("left").at("view_api") == "/left/view");
|
||||
ADMINIVE_CHECK(manifest.at("slots").at("right").at("schema").at("tpl") == "right");
|
||||
const auto frontend_form = adminive::edit_form<Config>(adminive::frontend(adminive::list(adminive::use<&Config::name>(), adminive::use<&Config::count>())));
|
||||
const auto frontend_form_json = adminive::to_view_json<Json, Config>(frontend_form);
|
||||
assert(frontend_form_json.at("body").at("kind") == "frontend");
|
||||
assert(frontend_form_json.at("body").at("children").at(0).at("kind") == "list");
|
||||
ADMINIVE_CHECK(frontend_form_json.at("body").at("kind") == "frontend");
|
||||
ADMINIVE_CHECK(frontend_form_json.at("body").at("children").at(0).at("kind") == "list");
|
||||
const auto table_amis = adminive::to_amis_table_schema<Json, Config>("/configs", table_view);
|
||||
assert(table_amis.at("type") == "page");
|
||||
assert(table_amis.at("body").at(0).at("columns").at(1).at("searchable") == true);
|
||||
assert(table_amis.at("body").at(0).at("columns").at(2).at("sortable") == true);
|
||||
assert(table_amis.at("body").at(0).at("columns").at(3).at("filterable") == true);
|
||||
ADMINIVE_CHECK(table_amis.at("type") == "page");
|
||||
ADMINIVE_CHECK(table_amis.at("body").at(0).at("columns").at(1).at("searchable") == true);
|
||||
ADMINIVE_CHECK(table_amis.at("body").at(0).at("columns").at(2).at("sortable") == true);
|
||||
ADMINIVE_CHECK(table_amis.at("body").at(0).at("columns").at(3).at("filterable") == true);
|
||||
const auto& create_submit_data = table_amis.at("body").at(0).at("headerToolbar").at(2).at("dialog").at("body").at("api").at("data");
|
||||
assert(create_submit_data.at("name") == "${name}");
|
||||
assert(create_submit_data.at("count") == "${count}");
|
||||
assert(create_submit_data.at("enabled") == "${enabled}");
|
||||
assert(create_submit_data.at("color") == "${color}");
|
||||
assert(!create_submit_data.contains("read_only"));
|
||||
ADMINIVE_CHECK(create_submit_data.at("name") == "${name}");
|
||||
ADMINIVE_CHECK(create_submit_data.at("count") == "${count}");
|
||||
ADMINIVE_CHECK(create_submit_data.at("enabled") == "${enabled}");
|
||||
ADMINIVE_CHECK(create_submit_data.at("color") == "${color}");
|
||||
ADMINIVE_CHECK(!create_submit_data.contains("read_only"));
|
||||
const auto& edit_submit_data = table_amis.at("body").at(0).at("columns").back().at("buttons").at(0).at("dialog").at("body").at("api").at("data");
|
||||
assert(edit_submit_data.at("name") == "${name}");
|
||||
assert(edit_submit_data.at("count") == "${count}");
|
||||
assert(edit_submit_data.at("enabled") == "${enabled}");
|
||||
assert(edit_submit_data.at("color") == "${color}");
|
||||
assert(!edit_submit_data.contains("read_only"));
|
||||
ADMINIVE_CHECK(edit_submit_data.at("name") == "${name}");
|
||||
ADMINIVE_CHECK(edit_submit_data.at("count") == "${count}");
|
||||
ADMINIVE_CHECK(edit_submit_data.at("enabled") == "${enabled}");
|
||||
ADMINIVE_CHECK(edit_submit_data.at("color") == "${color}");
|
||||
ADMINIVE_CHECK(!edit_submit_data.contains("read_only"));
|
||||
const auto list_amis = adminive::to_amis_list_schema<Json, Config>("/configs", table_view, Json{{"title", "${name}"}});
|
||||
assert(list_amis.at("body").at(0).at("mode") == "list");
|
||||
assert(list_amis.at("body").at(0).at("id") == "view_config_table_crud_list");
|
||||
assert(!list_amis.at("body").at(0).contains("columns"));
|
||||
assert(list_amis.at("body").at(0).at("listItem").at("actions").size() == 2);
|
||||
assert(list_amis.at("body").at(0).at("listItem").at("actions").at(0).at("dialog").at("body").at("reload") == "view_config_table_crud_list");
|
||||
assert(list_amis.at("body").at(0).at("listItem").at("actions").at(1).at("reload") == "view_config_table_crud_list");
|
||||
assert(list_amis.at("body").at(0).at("headerToolbar").size() == 2);
|
||||
assert(list_amis.at("body").at(0).at("headerToolbar").at(1).at("dialog").at("body").at("reload") == "view_config_table_crud_list");
|
||||
ADMINIVE_CHECK(list_amis.at("body").at(0).at("mode") == "list");
|
||||
ADMINIVE_CHECK(list_amis.at("body").at(0).at("id") == "view_config_table_crud_list");
|
||||
ADMINIVE_CHECK(!list_amis.at("body").at(0).contains("columns"));
|
||||
ADMINIVE_CHECK(list_amis.at("body").at(0).at("listItem").at("actions").size() == 2);
|
||||
ADMINIVE_CHECK(list_amis.at("body").at(0).at("listItem").at("actions").at(0).at("dialog").at("body").at("reload") == "view_config_table_crud_list");
|
||||
ADMINIVE_CHECK(list_amis.at("body").at(0).at("listItem").at("actions").at(1).at("reload") == "view_config_table_crud_list");
|
||||
ADMINIVE_CHECK(list_amis.at("body").at(0).at("headerToolbar").size() == 2);
|
||||
ADMINIVE_CHECK(list_amis.at("body").at(0).at("headerToolbar").at(1).at("dialog").at("body").at("reload") == "view_config_table_crud_list");
|
||||
const auto cards_amis = adminive::to_amis_cards_schema<Json, Config>("/configs", table_view, Json{{"header", Json{{"title", "${name}"}}}}, 2);
|
||||
assert(cards_amis.at("body").at(0).at("mode") == "cards");
|
||||
assert(cards_amis.at("body").at(0).at("id") == "view_config_table_crud_cards");
|
||||
assert(cards_amis.at("body").at(0).at("columnsCount") == 2);
|
||||
assert(cards_amis.at("body").at(0).at("card").at("actions").size() == 2);
|
||||
assert(cards_amis.at("body").at(0).at("card").at("actions").at(1).at("reload") == "view_config_table_crud_cards");
|
||||
ADMINIVE_CHECK(cards_amis.at("body").at(0).at("mode") == "cards");
|
||||
ADMINIVE_CHECK(cards_amis.at("body").at(0).at("id") == "view_config_table_crud_cards");
|
||||
ADMINIVE_CHECK(cards_amis.at("body").at(0).at("columnsCount") == 2);
|
||||
ADMINIVE_CHECK(cards_amis.at("body").at(0).at("card").at("actions").size() == 2);
|
||||
ADMINIVE_CHECK(cards_amis.at("body").at(0).at("card").at("actions").at(1).at("reload") == "view_config_table_crud_cards");
|
||||
const auto item_view = adminive::collection_item<&Config::name>().subtitle<&Config::color>().accent<&Config::color>().body<&Config::count, &Config::enabled>();
|
||||
const auto collection_view = adminive::describe_collection_view<Config>();
|
||||
const auto labeled_collection = collection_view.id_title("Record").create_title("Add").edit_title("Change").delete_title("Remove").actions_title("Operations").confirm_title("Apply").delete_confirmation("Remove record?").status_title("Status");
|
||||
assert(labeled_collection.table.id_label == "Record");
|
||||
assert(labeled_collection.table.create_label == "Add");
|
||||
assert(labeled_collection.table.edit_label == "Change");
|
||||
assert(labeled_collection.table.delete_label == "Remove");
|
||||
assert(labeled_collection.table.actions_label == "Operations");
|
||||
assert(labeled_collection.table.confirm_label == "Apply");
|
||||
assert(labeled_collection.table.delete_confirm == "Remove record?");
|
||||
assert(labeled_collection.table.view_status_label == "Status");
|
||||
ADMINIVE_CHECK(labeled_collection.table.id_label == "Record");
|
||||
ADMINIVE_CHECK(labeled_collection.table.create_label == "Add");
|
||||
ADMINIVE_CHECK(labeled_collection.table.edit_label == "Change");
|
||||
ADMINIVE_CHECK(labeled_collection.table.delete_label == "Remove");
|
||||
ADMINIVE_CHECK(labeled_collection.table.actions_label == "Operations");
|
||||
ADMINIVE_CHECK(labeled_collection.table.confirm_label == "Apply");
|
||||
ADMINIVE_CHECK(labeled_collection.table.delete_confirm == "Remove record?");
|
||||
ADMINIVE_CHECK(labeled_collection.table.view_status_label == "Status");
|
||||
const auto semantic_list_view = collection_view.as_list(item_view);
|
||||
const auto semantic_list_json = adminive::to_view_json<Json, Config>(semantic_list_view);
|
||||
assert(semantic_list_json.at("kind") == "collection");
|
||||
assert(semantic_list_json.at("mode") == "list");
|
||||
assert(semantic_list_json.at("item").at("title_field") == "name");
|
||||
assert(semantic_list_json.at("item").at("fields").at(0) == "count");
|
||||
ADMINIVE_CHECK(semantic_list_json.at("kind") == "collection");
|
||||
ADMINIVE_CHECK(semantic_list_json.at("mode") == "list");
|
||||
ADMINIVE_CHECK(semantic_list_json.at("item").at("title_field") == "name");
|
||||
ADMINIVE_CHECK(semantic_list_json.at("item").at("fields").at(0) == "count");
|
||||
const auto semantic_list_amis = adminive::to_amis_collection_schema<Json, Config>("/configs", semantic_list_view);
|
||||
assert(semantic_list_amis.at("body").at(0).at("id") == "view_config_collection_crud_list");
|
||||
assert(semantic_list_amis.at("body").at(0).at("listItem").at("title") == "${name}");
|
||||
assert(semantic_list_amis.at("body").at(0).at("listItem").at("actions").at(1).at("reload") == "view_config_collection_crud_list");
|
||||
ADMINIVE_CHECK(semantic_list_amis.at("body").at(0).at("id") == "view_config_collection_crud_list");
|
||||
ADMINIVE_CHECK(semantic_list_amis.at("body").at(0).at("listItem").at("title") == "${name}");
|
||||
ADMINIVE_CHECK(semantic_list_amis.at("body").at(0).at("listItem").at("actions").at(1).at("reload") == "view_config_collection_crud_list");
|
||||
const auto semantic_cards_view = collection_view.as_cards(item_view, 4);
|
||||
const auto semantic_cards_json = adminive::to_view_json<Json, Config>(semantic_cards_view);
|
||||
assert(semantic_cards_json.at("mode") == "cards");
|
||||
assert(semantic_cards_json.at("cards_columns") == 4);
|
||||
ADMINIVE_CHECK(semantic_cards_json.at("mode") == "cards");
|
||||
ADMINIVE_CHECK(semantic_cards_json.at("cards_columns") == 4);
|
||||
const auto semantic_cards_amis = adminive::to_amis_collection_schema<Json, Config>("/configs", semantic_cards_view);
|
||||
assert(semantic_cards_amis.at("body").at(0).at("id") == "view_config_collection_crud_cards");
|
||||
assert(semantic_cards_amis.at("body").at(0).at("columnsCount") == 4);
|
||||
ADMINIVE_CHECK(semantic_cards_amis.at("body").at(0).at("id") == "view_config_collection_crud_cards");
|
||||
ADMINIVE_CHECK(semantic_cards_amis.at("body").at(0).at("columnsCount") == 4);
|
||||
const auto semantic_table_json = adminive::to_view_json<Json, Config>(collection_view.as_table());
|
||||
assert(semantic_table_json.at("mode") == "table");
|
||||
ADMINIVE_CHECK(semantic_table_json.at("mode") == "table");
|
||||
adminive::Collection_Service<Config, Json, adminive::No_Lock> collection("/configs", {Config{"Alpha", 3, true, "#111111"}, Config{"Beta", 7, false, "#222222"}, Config{"Alphabet", 5, true, "#333333"}});
|
||||
adminive::Collection_Query query;
|
||||
query.fields["name"] = "alpha";
|
||||
auto response = collection.list_response(query);
|
||||
assert(response.status == 200);
|
||||
assert(response.body.at("data").at("total") == 2);
|
||||
assert(response.body.at("data").at("items").at(0).at("count") == 5);
|
||||
ADMINIVE_CHECK(response.status == 200);
|
||||
ADMINIVE_CHECK(response.body.at("data").at("total") == 2);
|
||||
ADMINIVE_CHECK(response.body.at("data").at("items").at(0).at("count") == 5);
|
||||
query = {};
|
||||
query.fields["enabled"] = "true";
|
||||
response = collection.list_response(query);
|
||||
assert(response.status == 200);
|
||||
assert(response.body.at("data").at("total") == 2);
|
||||
ADMINIVE_CHECK(response.status == 200);
|
||||
ADMINIVE_CHECK(response.body.at("data").at("total") == 2);
|
||||
query = {};
|
||||
query.order_by = "count";
|
||||
query.order_dir = "asc";
|
||||
response = collection.list_response(query);
|
||||
assert(response.status == 200);
|
||||
assert(response.body.at("data").at("items").at(0).at("count") == 3);
|
||||
ADMINIVE_CHECK(response.status == 200);
|
||||
ADMINIVE_CHECK(response.body.at("data").at("items").at(0).at("count") == 3);
|
||||
query = {};
|
||||
query.fields["color"] = "#111111";
|
||||
response = collection.list_response(query);
|
||||
assert(response.status == 400);
|
||||
ADMINIVE_CHECK(response.status == 400);
|
||||
query = {};
|
||||
query.order_by = "enabled";
|
||||
query.order_dir = "asc";
|
||||
response = collection.list_response(query);
|
||||
ADMINIVE_CHECK(response.status == 400);
|
||||
query = {};
|
||||
query.order_by = "count";
|
||||
query.order_dir = "sideways";
|
||||
response = collection.list_response(query);
|
||||
ADMINIVE_CHECK(response.status == 400);
|
||||
bool invalid_manifest{};
|
||||
try {
|
||||
adminive::to_composition_manifest_json<Json>(frontend_composition, {adminive::Composition_Slot_Contract{"left", "amis_schema", {}, {}, {}, {}}}, {{"left", Json{{"type", "tpl"}}}});
|
||||
} catch(const std::invalid_argument&) {
|
||||
invalid_manifest = true;
|
||||
}
|
||||
assert(invalid_manifest);
|
||||
ADMINIVE_CHECK(invalid_manifest);
|
||||
bool duplicate_manifest_slot{};
|
||||
try {
|
||||
const auto duplicate_frontend_composition = adminive::composition_view("duplicate", adminive::compose::frontend(adminive::compose::slot("left"), adminive::compose::slot("left")));
|
||||
adminive::to_composition_manifest_json<Json>(duplicate_frontend_composition, {slot_contracts.front()}, {{"left", Json{{"type", "tpl"}}}});
|
||||
} catch(const std::invalid_argument&) {
|
||||
duplicate_manifest_slot = true;
|
||||
}
|
||||
ADMINIVE_CHECK(duplicate_manifest_slot);
|
||||
bool invalid_grid{};
|
||||
try {
|
||||
adminive::validate_form_view<Config>(adminive::edit_form<Config>(adminive::grid(0, adminive::use<&Config::name>())));
|
||||
} catch(const std::invalid_argument&) {
|
||||
invalid_grid = true;
|
||||
}
|
||||
assert(invalid_grid);
|
||||
ADMINIVE_CHECK(invalid_grid);
|
||||
bool invalid_tabs{};
|
||||
try {
|
||||
adminive::validate_form_view<Config>(adminive::edit_form<Config>(adminive::tabs(adminive::use<&Config::name>())));
|
||||
} catch(const std::invalid_argument&) {
|
||||
invalid_tabs = true;
|
||||
}
|
||||
assert(invalid_tabs);
|
||||
ADMINIVE_CHECK(invalid_tabs);
|
||||
bool invalid_tab_position{};
|
||||
try {
|
||||
adminive::validate_form_view<Config>(adminive::edit_form<Config>(adminive::tab("Invalid", adminive::use<&Config::name>())));
|
||||
} catch(const std::invalid_argument&) {
|
||||
invalid_tab_position = true;
|
||||
}
|
||||
assert(invalid_tab_position);
|
||||
ADMINIVE_CHECK(invalid_tab_position);
|
||||
bool invalid_composition_tab_position{};
|
||||
try {
|
||||
adminive::validate_composition_view(adminive::composition_view("invalid", adminive::compose::tab("Invalid", adminive::compose::slot("x"))));
|
||||
} catch(const std::invalid_argument&) {
|
||||
invalid_composition_tab_position = true;
|
||||
}
|
||||
assert(invalid_composition_tab_position);
|
||||
ADMINIVE_CHECK(invalid_composition_tab_position);
|
||||
bool invalid_sort{};
|
||||
try {
|
||||
adminive::validate_table_view<Config>(adminive::table_view<Config>(adminive::column<&Config::name>()).default_sort("name"));
|
||||
} catch(const std::invalid_argument&) {
|
||||
invalid_sort = true;
|
||||
}
|
||||
assert(invalid_sort);
|
||||
ADMINIVE_CHECK(invalid_sort);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user