Add XCUI schema document regression coverage
This commit is contained in:
153
tests/Resources/UI/test_ui_schema_document.cpp
Normal file
153
tests/Resources/UI/test_ui_schema_document.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <XCEngine/Resources/UI/UIDocumentCompiler.h>
|
||||
#include <XCEngine/Resources/UI/UIDocumentLoaders.h>
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
|
||||
using namespace XCEngine::Resources;
|
||||
|
||||
namespace {
|
||||
|
||||
void WriteTextFile(const std::filesystem::path& path, const std::string& contents) {
|
||||
std::filesystem::create_directories(path.parent_path());
|
||||
std::ofstream output(path, std::ios::binary | std::ios::trunc);
|
||||
ASSERT_TRUE(output.is_open());
|
||||
output << contents;
|
||||
ASSERT_TRUE(static_cast<bool>(output));
|
||||
}
|
||||
|
||||
TEST(UISchemaDocument, CompileAndArtifactLoadPopulateSchemaDefinition) {
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
const fs::path root = fs::temp_directory_path() / "xc_ui_schema_compile_test";
|
||||
const fs::path schemaPath = root / "markup.xcschema";
|
||||
const fs::path artifactPath = root / "markup.xcschemaasset";
|
||||
fs::remove_all(root);
|
||||
|
||||
WriteTextFile(
|
||||
schemaPath,
|
||||
"<Schema name=\"EditorMarkup\">\n"
|
||||
" <Element tag=\"View\" allowUnknownChildren=\"true\">\n"
|
||||
" <Attribute name=\"theme\" type=\"document\" kind=\"theme\" />\n"
|
||||
" <Attribute name=\"mode\" type=\"enum\" values=\"compact, cozy\" />\n"
|
||||
" <Element tag=\"Column\">\n"
|
||||
" <Attribute name=\"gap\" type=\"number\" />\n"
|
||||
" </Element>\n"
|
||||
" </Element>\n"
|
||||
"</Schema>\n");
|
||||
|
||||
UISchemaLoader loader;
|
||||
UIDocumentCompileResult compileResult = {};
|
||||
ASSERT_TRUE(loader.CompileDocument(schemaPath.string().c_str(), compileResult));
|
||||
ASSERT_TRUE(compileResult.succeeded);
|
||||
ASSERT_TRUE(compileResult.document.valid);
|
||||
ASSERT_TRUE(compileResult.document.schemaDefinition.valid);
|
||||
EXPECT_EQ(compileResult.document.schemaDefinition.name, "EditorMarkup");
|
||||
|
||||
const UISchemaElementDefinition* viewElement =
|
||||
compileResult.document.schemaDefinition.FindElement("View");
|
||||
ASSERT_NE(viewElement, nullptr);
|
||||
EXPECT_TRUE(viewElement->allowUnknownChildren);
|
||||
|
||||
const UISchemaAttributeDefinition* themeAttribute = viewElement->FindAttribute("theme");
|
||||
ASSERT_NE(themeAttribute, nullptr);
|
||||
EXPECT_EQ(themeAttribute->valueType, UISchemaValueType::Document);
|
||||
EXPECT_TRUE(themeAttribute->restrictDocumentKind);
|
||||
EXPECT_EQ(themeAttribute->documentKind, UIDocumentKind::Theme);
|
||||
|
||||
const UISchemaAttributeDefinition* modeAttribute = viewElement->FindAttribute("mode");
|
||||
ASSERT_NE(modeAttribute, nullptr);
|
||||
EXPECT_EQ(modeAttribute->valueType, UISchemaValueType::Enum);
|
||||
ASSERT_EQ(modeAttribute->allowedValues.Size(), 2u);
|
||||
EXPECT_EQ(modeAttribute->allowedValues[0], "compact");
|
||||
EXPECT_EQ(modeAttribute->allowedValues[1], "cozy");
|
||||
|
||||
LoadResult loadResult = loader.Load(schemaPath.string().c_str());
|
||||
ASSERT_TRUE(loadResult);
|
||||
ASSERT_NE(loadResult.resource, nullptr);
|
||||
auto* schemaResource = static_cast<UISchema*>(loadResult.resource);
|
||||
ASSERT_NE(schemaResource, nullptr);
|
||||
ASSERT_TRUE(schemaResource->GetSchemaDefinition().valid);
|
||||
ASSERT_NE(schemaResource->GetSchemaDefinition().FindElement("View"), nullptr);
|
||||
delete schemaResource;
|
||||
|
||||
XCEngine::Containers::String artifactWriteError;
|
||||
ASSERT_TRUE(
|
||||
WriteUIDocumentArtifact(artifactPath.string().c_str(), compileResult, &artifactWriteError))
|
||||
<< artifactWriteError.CStr();
|
||||
|
||||
UIDocumentCompileResult artifactResult = {};
|
||||
ASSERT_TRUE(LoadUIDocumentArtifact(
|
||||
artifactPath.string().c_str(),
|
||||
UIDocumentKind::Schema,
|
||||
artifactResult));
|
||||
ASSERT_TRUE(artifactResult.succeeded);
|
||||
ASSERT_TRUE(artifactResult.document.valid);
|
||||
ASSERT_TRUE(artifactResult.document.schemaDefinition.valid);
|
||||
|
||||
const UISchemaElementDefinition* artifactViewElement =
|
||||
artifactResult.document.schemaDefinition.FindElement("View");
|
||||
ASSERT_NE(artifactViewElement, nullptr);
|
||||
ASSERT_NE(artifactViewElement->FindChild("Column"), nullptr);
|
||||
|
||||
fs::remove_all(root);
|
||||
}
|
||||
|
||||
TEST(UISchemaDocument, CompileRejectsInvalidSchemaFlags) {
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
const fs::path root = fs::temp_directory_path() / "xc_ui_schema_invalid_flag_test";
|
||||
const fs::path schemaPath = root / "broken.xcschema";
|
||||
fs::remove_all(root);
|
||||
|
||||
WriteTextFile(
|
||||
schemaPath,
|
||||
"<Schema>\n"
|
||||
" <Element tag=\"View\" allowUnknownChildren=\"sometimes\" />\n"
|
||||
"</Schema>\n");
|
||||
|
||||
UISchemaLoader loader;
|
||||
UIDocumentCompileResult compileResult = {};
|
||||
EXPECT_FALSE(loader.CompileDocument(schemaPath.string().c_str(), compileResult));
|
||||
EXPECT_FALSE(compileResult.succeeded);
|
||||
EXPECT_FALSE(compileResult.errorMessage.Empty());
|
||||
ASSERT_FALSE(compileResult.document.diagnostics.Empty());
|
||||
|
||||
const std::string errorMessage = compileResult.errorMessage.CStr();
|
||||
EXPECT_NE(errorMessage.find("allowUnknownChildren"), std::string::npos);
|
||||
|
||||
fs::remove_all(root);
|
||||
}
|
||||
|
||||
TEST(UISchemaDocument, CompileRejectsDuplicateAttributeDefinitions) {
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
const fs::path root = fs::temp_directory_path() / "xc_ui_schema_duplicate_attribute_test";
|
||||
const fs::path schemaPath = root / "duplicate.xcschema";
|
||||
fs::remove_all(root);
|
||||
|
||||
WriteTextFile(
|
||||
schemaPath,
|
||||
"<Schema>\n"
|
||||
" <Element tag=\"View\">\n"
|
||||
" <Attribute name=\"id\" type=\"string\" />\n"
|
||||
" <Attribute name=\"id\" type=\"string\" />\n"
|
||||
" </Element>\n"
|
||||
"</Schema>\n");
|
||||
|
||||
UISchemaLoader loader;
|
||||
UIDocumentCompileResult compileResult = {};
|
||||
EXPECT_FALSE(loader.CompileDocument(schemaPath.string().c_str(), compileResult));
|
||||
EXPECT_FALSE(compileResult.succeeded);
|
||||
EXPECT_FALSE(compileResult.errorMessage.Empty());
|
||||
ASSERT_FALSE(compileResult.document.diagnostics.Empty());
|
||||
|
||||
const std::string errorMessage = compileResult.errorMessage.CStr();
|
||||
EXPECT_NE(errorMessage.find("Duplicate schema attribute definition"), std::string::npos);
|
||||
|
||||
fs::remove_all(root);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
Reference in New Issue
Block a user