Files
EVEngine/test/editor_dialogue_graph.cpp
T

104 lines
4.4 KiB
C++

#include "dialogue_editing/DialogueGraph.h"
#include "dialogue/ConversationAuthoring.h"
#include "zeroerr/assert.h"
#include "zeroerr/unittest.h"
using namespace eve::dialogue_editing;
using namespace eve::editing;
namespace {
GraphDocumentData conversationGraph(DialogueGraphDomain& domain) {
auto line = domain.makeNode(GraphNodeId("greeting"), "line");
auto choice = domain.makeNode(GraphNodeId("answer"), "choice");
auto route = domain.makeRouteNode(GraphNodeId("answer.yes"), "Yes");
auto end = domain.makeNode(GraphNodeId("done"), "end");
REQUIRE(line.ok());
REQUIRE(choice.ok());
REQUIRE(route.ok());
REQUIRE(end.ok());
auto* lineProperties = line.value().properties.getIf<EditorValue::Object>();
REQUIRE(lineProperties);
(*lineProperties)["speaker"] = "guide";
(*lineProperties)["text"] = "Continue?";
(*lineProperties)["i18nKey"] = "dialogue.guide.continue";
(*lineProperties)["voice"] = "asset://voice/continue.ogg";
GraphDocument graph;
REQUIRE(graph.createNode(line.value()).ok());
REQUIRE(graph.createNode(choice.value()).ok());
REQUIRE(graph.createNode(route.value()).ok());
REQUIRE(graph.createNode(end.value()).ok());
const auto connect = [&](const char* edge, const char* from, const char* to) {
const auto* output = graph.findPin(GraphPinId(from));
const auto* input = graph.findPin(GraphPinId(to));
REQUIRE(output);
REQUIRE(input);
REQUIRE(graph.connect({StableId(edge), output->id, input->id},
domain.canConnect(*output, *input)).ok());
};
connect("line-choice", "greeting.out", "answer.in");
connect("choice-route", "answer.out", "answer.yes.in");
connect("route-end", "answer.yes.out", "done.in");
EditorValue::Array parameters{"has_met_guide"};
REQUIRE(graph.setParameters(EditorValue::Object{{"id", "intro"},
{"version", int64_t{2}},
{"entry", "greeting"},
{"parameters", std::move(parameters)}}).ok());
return graph.snapshot(domain.domain());
}
} // namespace
TEST_CASE("editor.dialogue.graph_compiles_nodes_routes_and_localization_metadata") {
DialogueGraphDomain domain;
const GraphDocumentData graph = conversationGraph(domain);
const DialogueGraphCompileResult compiled = domain.compile(graph);
CHECK_EQ(static_cast<int>(compiled.status), static_cast<int>(EditorStatus::Applied));
CHECK_EQ(compiled.documentRevision, graph.revision);
const auto* definition = compiled.definition.getIf<EditorValue::Object>();
REQUIRE(definition);
CHECK_EQ(*definition->at("id").getIf<std::string>(), "intro");
CHECK_EQ(*definition->at("version").getIf<int64_t>(), int64_t{2});
CHECK_EQ(definition->at("nodes").getIf<EditorValue::Array>()->size(), size_t{3});
}
TEST_CASE("editor.dialogue.graph_rejects_bypassed_or_incomplete_routes") {
DialogueGraphDomain domain;
GraphDocumentData graph = conversationGraph(domain);
graph.edges.erase(graph.edges.begin() + 1);
const auto incomplete = domain.compile(graph);
CHECK_EQ(static_cast<int>(incomplete.status), static_cast<int>(EditorStatus::Failed));
REQUIRE(!incomplete.diagnostics.empty());
graph = conversationGraph(domain);
graph.schemaVersion = 3;
CHECK_EQ(static_cast<int>(domain.compile(graph).status), static_cast<int>(EditorStatus::Unsupported));
graph = conversationGraph(domain);
auto* parameters = graph.parameters.getIf<EditorValue::Object>();
REQUIRE(parameters);
(*parameters)["entry"] = "answer.yes";
CHECK_EQ(static_cast<int>(domain.compile(graph).status), static_cast<int>(EditorStatus::Failed));
}
TEST_CASE("editor.dialogue.graph_builds_real_conversation_document") {
DialogueGraphDomain domain;
const GraphDocumentData graph = conversationGraph(domain);
DialogueGraphRuntimeBuilder builder;
auto built = builder.build(graph);
REQUIRE(built.ok());
auto* document = built.value();
REQUIRE(document);
CHECK_EQ(document->getId(), "intro");
CHECK_EQ(document->getEntry(), "greeting");
CHECK_EQ(document->getNodeCount(), 3);
CHECK_EQ(document->getField("greeting", "next"), "answer");
CHECK_EQ(document->getRouteLabel("answer", 0), "Yes");
CHECK_EQ(document->getRouteTarget("answer", 0), "done");
CHECK(document->validate());
delete document;
}