forked from qt-creator/qt-creator
UnitTests: Tests for headless QML theme generator
Task-number: QDS-11956 Change-Id: I5b76b62153436aa2ee3811702beca06af611308a Reviewed-by: Marco Bubke <marco.bubke@qt.io> Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
@@ -26,6 +26,8 @@
|
||||
|
||||
#include <utils/smallstringio.h>
|
||||
|
||||
#include <designsystem/dsconstants.h>
|
||||
|
||||
namespace std {
|
||||
template <typename T> ostream &operator<<(ostream &out, const QVector<T> &vector)
|
||||
{
|
||||
@@ -435,6 +437,30 @@ const char *sourceTypeToText(SourceType sourceType)
|
||||
|
||||
} // namespace
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const ThemeProperty &prop)
|
||||
{
|
||||
out << "{name: " << prop.name.toStdString() << ", value: " << prop.value
|
||||
<< ", isBinding: " << prop.isBinding << "}";
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void PrintTo(const ThemeProperty &prop, std::ostream *os)
|
||||
{
|
||||
*os << prop;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const GroupType &group)
|
||||
{
|
||||
out << "ThemeGroup{ " << static_cast<int>(group) << ", " << GroupId(group) << "}";
|
||||
return out;
|
||||
}
|
||||
|
||||
void PrintTo(const GroupType &group, std::ostream *os)
|
||||
{
|
||||
*os << group;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const FileStatus &fileStatus)
|
||||
{
|
||||
return out << "(" << fileStatus.sourceId << ", " << fileStatus.size << ", "
|
||||
|
@@ -133,11 +133,17 @@ class FileStatus;
|
||||
class Import;
|
||||
class NodeMetaInfo;
|
||||
class PropertyMetaInfo;
|
||||
class ThemeProperty;
|
||||
enum class GroupType;
|
||||
struct CompoundPropertyMetaInfo;
|
||||
enum class FlagIs : unsigned int;
|
||||
template<typename NameType>
|
||||
class BasicAuxiliaryDataKey;
|
||||
|
||||
void PrintTo(const ThemeProperty &prop, std::ostream *os);
|
||||
std::ostream &operator<<(std::ostream &out, const ThemeProperty &prop);
|
||||
void PrintTo(const GroupType &group, std::ostream *os);
|
||||
std::ostream &operator<<(std::ostream &out, const GroupType &group);
|
||||
std::ostream &operator<<(std::ostream &out, const ModelNode &node);
|
||||
std::ostream &operator<<(std::ostream &out, const VariantProperty &property);
|
||||
std::ostream &operator<<(std::ostream &out, const AbstractProperty &property);
|
||||
|
@@ -46,6 +46,7 @@ endfunction(unittest_copy_data_folder)
|
||||
|
||||
add_subdirectory(componentcore)
|
||||
add_subdirectory(designercoreutils)
|
||||
add_subdirectory(designsystem)
|
||||
add_subdirectory(listmodeleditor)
|
||||
add_subdirectory(imagecache)
|
||||
add_subdirectory(metainfo)
|
||||
|
8
tests/unit/tests/unittests/designsystem/CMakeLists.txt
Normal file
8
tests/unit/tests/unittests/designsystem/CMakeLists.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
extend_qtc_test(unittest
|
||||
DEPENDS
|
||||
QmlDesignerUtils DesignSystem
|
||||
SOURCES
|
||||
dsthemegroup-test.cpp
|
||||
dsthememgr-test.cpp
|
||||
dsthemeqml-test.cpp
|
||||
)
|
237
tests/unit/tests/unittests/designsystem/dsthemegroup-test.cpp
Normal file
237
tests/unit/tests/unittests/designsystem/dsthemegroup-test.cpp
Normal file
@@ -0,0 +1,237 @@
|
||||
// Copyright (C) 2024 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include "../utils/googletest.h"
|
||||
|
||||
#include <gtest-creator-printing.h>
|
||||
|
||||
#include <designsystem/dsconstants.h>
|
||||
#include <designsystem/dsthemegroup.h>
|
||||
|
||||
using QmlDesigner::DSThemeGroup;
|
||||
using QmlDesigner::ThemeProperty;
|
||||
|
||||
namespace {
|
||||
constexpr const char testPropertyNameFoo[] = "propFoo";
|
||||
constexpr const char testPropertyNameBar[] = "propBar";
|
||||
|
||||
constexpr QmlDesigner::ThemeId themeId1 = 0;
|
||||
constexpr QmlDesigner::ThemeId themeId2 = 1;
|
||||
|
||||
MATCHER_P3(HasPropertyCount, themeId, themePropCount, totalPropsCount, "")
|
||||
{
|
||||
const DSThemeGroup &group = arg;
|
||||
return group.count() == totalPropsCount && group.count(themeId) == themePropCount;
|
||||
}
|
||||
|
||||
MATCHER_P2(HasThemeProperty, themeId, themeProp, "")
|
||||
{
|
||||
const DSThemeGroup &group = arg;
|
||||
const std::optional<ThemeProperty> prop = group.propertyValue(themeId, themeProp.name);
|
||||
|
||||
return prop && themeProp.name == prop->name && themeProp.value == prop->value
|
||||
&& themeProp.isBinding == prop->isBinding;
|
||||
}
|
||||
|
||||
class DesignGroupTest : public testing::TestWithParam<QmlDesigner::GroupType>
|
||||
{
|
||||
protected:
|
||||
DesignGroupTest()
|
||||
: group(groupType)
|
||||
{
|
||||
}
|
||||
|
||||
QmlDesigner::GroupType groupType = GetParam();
|
||||
QmlDesigner::DSThemeGroup group;
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(DesignSystem,
|
||||
DesignGroupTest,
|
||||
testing::Values(QmlDesigner::GroupType::Colors,
|
||||
QmlDesigner::GroupType::Flags,
|
||||
QmlDesigner::GroupType::Numbers,
|
||||
QmlDesigner::GroupType::Strings));
|
||||
|
||||
TEST_P(DesignGroupTest, add_property)
|
||||
{
|
||||
// arrange
|
||||
ThemeProperty testProp{testPropertyNameFoo, "test", false};
|
||||
|
||||
// act
|
||||
group.addProperty(themeId1, testProp);
|
||||
|
||||
//assert
|
||||
ASSERT_THAT(group,
|
||||
AllOf(HasPropertyCount(themeId1, 1u, 1u), HasThemeProperty(themeId1, testProp)));
|
||||
}
|
||||
|
||||
TEST_P(DesignGroupTest, add_multiple_properties)
|
||||
{
|
||||
// arrange
|
||||
ThemeProperty testPropFoo{testPropertyNameFoo, "#aaccff", false};
|
||||
ThemeProperty testPropBar{testPropertyNameBar, "#bbddee", false};
|
||||
|
||||
// act
|
||||
group.addProperty(themeId1, testPropFoo);
|
||||
group.addProperty(themeId1, testPropBar);
|
||||
|
||||
//assert
|
||||
ASSERT_THAT(group,
|
||||
AllOf(HasPropertyCount(themeId1, 2u, 2u),
|
||||
HasThemeProperty(themeId1, testPropFoo),
|
||||
HasThemeProperty(themeId1, testPropBar)));
|
||||
}
|
||||
|
||||
TEST_P(DesignGroupTest, add_property_with_empty_property_name)
|
||||
{
|
||||
// arrange
|
||||
ThemeProperty testProp{"", "test", false};
|
||||
|
||||
// act
|
||||
group.addProperty(themeId1, testProp);
|
||||
|
||||
//assert
|
||||
ASSERT_THAT(group,
|
||||
AllOf(HasPropertyCount(themeId1, 0u, 0u), Not(HasThemeProperty(themeId1, testProp))));
|
||||
}
|
||||
|
||||
TEST_P(DesignGroupTest, add_binding_property)
|
||||
{
|
||||
// arrange
|
||||
ThemeProperty testProp{testPropertyNameFoo, "root.width", true};
|
||||
|
||||
// act
|
||||
group.addProperty(themeId1, testProp);
|
||||
|
||||
//assert
|
||||
ASSERT_THAT(group,
|
||||
AllOf(HasPropertyCount(themeId1, 1u, 1u), HasThemeProperty(themeId1, testProp)));
|
||||
}
|
||||
|
||||
TEST_P(DesignGroupTest, add_property_with_duplicate_name)
|
||||
{
|
||||
// arrange
|
||||
ThemeProperty testPropA{testPropertyNameFoo, "#aaccff", false};
|
||||
ThemeProperty testPropB{testPropertyNameFoo, "#bbddee", false};
|
||||
group.addProperty(themeId1, testPropA);
|
||||
|
||||
// act
|
||||
group.addProperty(themeId1, testPropB);
|
||||
|
||||
//assert
|
||||
ASSERT_THAT(group,
|
||||
AllOf(HasPropertyCount(themeId1, 1u, 1u),
|
||||
HasThemeProperty(themeId1, testPropA),
|
||||
Not(HasThemeProperty(themeId1, testPropB))));
|
||||
}
|
||||
|
||||
TEST_P(DesignGroupTest, remove_property)
|
||||
{
|
||||
// arrange
|
||||
ThemeProperty testProp{testPropertyNameFoo, "#aaccff", false};
|
||||
group.addProperty(themeId1, testProp);
|
||||
|
||||
// act
|
||||
group.removeProperty(testPropertyNameFoo);
|
||||
|
||||
//assert
|
||||
ASSERT_THAT(group,
|
||||
AllOf(HasPropertyCount(themeId1, 0u, 0u), Not(HasThemeProperty(themeId1, testProp))));
|
||||
}
|
||||
|
||||
TEST_P(DesignGroupTest, remove_nonexistent_property_have_no_side_effect)
|
||||
{
|
||||
// arrange
|
||||
ThemeProperty testPropFoo{testPropertyNameFoo, "#aaccff", false};
|
||||
group.addProperty(themeId1, testPropFoo);
|
||||
|
||||
// act
|
||||
group.removeProperty(testPropertyNameBar);
|
||||
|
||||
//assert
|
||||
ASSERT_THAT(group,
|
||||
AllOf(HasPropertyCount(themeId1, 1u, 1u), HasThemeProperty(themeId1, testPropFoo)));
|
||||
}
|
||||
|
||||
TEST_P(DesignGroupTest, remove_theme_with_multiple_properties)
|
||||
{
|
||||
// arrange
|
||||
ThemeProperty testPropFoo{testPropertyNameFoo, "#aaccff", false};
|
||||
group.addProperty(themeId1, testPropFoo);
|
||||
ThemeProperty testPropBar{testPropertyNameBar, "#bbddee", false};
|
||||
group.addProperty(themeId1, testPropBar);
|
||||
|
||||
// act
|
||||
group.removeTheme(themeId1);
|
||||
|
||||
//assert
|
||||
ASSERT_THAT(group,
|
||||
AllOf(HasPropertyCount(themeId1, 0u, 0u),
|
||||
Not(HasThemeProperty(themeId1, testPropFoo)),
|
||||
Not(HasThemeProperty(themeId1, testPropBar))));
|
||||
}
|
||||
|
||||
TEST_P(DesignGroupTest, remove_theme_from_group_having_multiple_themes)
|
||||
{
|
||||
// arrange
|
||||
ThemeProperty testPropFoo{testPropertyNameFoo, "#aaccff", false};
|
||||
group.addProperty(themeId1, testPropFoo);
|
||||
ThemeProperty testPropBar{testPropertyNameBar, "#bbddee", false};
|
||||
group.addProperty(themeId2, testPropBar);
|
||||
|
||||
// act
|
||||
group.removeTheme(themeId1);
|
||||
|
||||
//assert
|
||||
ASSERT_THAT(group,
|
||||
AllOf(HasPropertyCount(themeId1, 0u, 1u),
|
||||
Not(HasThemeProperty(themeId1, testPropFoo)),
|
||||
HasThemeProperty(themeId2, testPropBar)));
|
||||
}
|
||||
|
||||
TEST_P(DesignGroupTest, remove_nonexistent_theme_have_no_side_effect)
|
||||
{
|
||||
// arrange
|
||||
ThemeProperty testPropFoo{testPropertyNameFoo, "#aaccff", false};
|
||||
group.addProperty(themeId1, testPropFoo);
|
||||
|
||||
// act
|
||||
group.removeTheme(themeId2);
|
||||
|
||||
//assert
|
||||
ASSERT_THAT(group,
|
||||
AllOf(HasPropertyCount(themeId1, 1u, 1u), HasThemeProperty(themeId1, testPropFoo)));
|
||||
}
|
||||
|
||||
TEST_P(DesignGroupTest, duplicate_theme)
|
||||
{
|
||||
// arrange
|
||||
ThemeProperty testPropFoo{testPropertyNameFoo, "#aaccff", false};
|
||||
group.addProperty(themeId1, testPropFoo);
|
||||
ThemeProperty testPropBar{testPropertyNameBar, "#bbddee", false};
|
||||
group.addProperty(themeId1, testPropBar);
|
||||
|
||||
// act
|
||||
group.duplicateValues(themeId1, themeId2);
|
||||
|
||||
//assert
|
||||
ASSERT_THAT(group,
|
||||
AllOf(HasPropertyCount(themeId2, 2u, 2u),
|
||||
HasThemeProperty(themeId2, testPropFoo),
|
||||
HasThemeProperty(themeId2, testPropBar)));
|
||||
}
|
||||
|
||||
TEST_P(DesignGroupTest, duplicate_nonexistent_have_no_side_effect)
|
||||
{
|
||||
// arrange
|
||||
ThemeProperty testPropFoo{testPropertyNameFoo, "#aaccff", false};
|
||||
group.addProperty(themeId1, testPropFoo);
|
||||
|
||||
// act
|
||||
group.duplicateValues(themeId2, themeId1);
|
||||
|
||||
//assert
|
||||
ASSERT_THAT(group,
|
||||
AllOf(HasPropertyCount(themeId1, 1u, 1u), HasThemeProperty(themeId1, testPropFoo)));
|
||||
}
|
||||
} // namespace
|
266
tests/unit/tests/unittests/designsystem/dsthememgr-test.cpp
Normal file
266
tests/unit/tests/unittests/designsystem/dsthememgr-test.cpp
Normal file
@@ -0,0 +1,266 @@
|
||||
// Copyright (C) 2024 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include "../utils/googletest.h"
|
||||
|
||||
#include <bindingproperty.h>
|
||||
#include <model.h>
|
||||
#include <nodeproperty.h>
|
||||
#include <projectstoragemock.h>
|
||||
#include <sourcepathcachemock.h>
|
||||
|
||||
#include <designsystem/dsthememanager.h>
|
||||
|
||||
#include <format>
|
||||
|
||||
using QmlDesigner::DSThemeManager;
|
||||
using QmlDesigner::GroupType;
|
||||
using QmlDesigner::Import;
|
||||
using QmlDesigner::ModelNode;
|
||||
using QmlDesigner::ThemeProperty;
|
||||
|
||||
namespace {
|
||||
constexpr const char testPropNameFoo[] = "propFoo";
|
||||
constexpr const char testPropNameBar[] = "propBar";
|
||||
|
||||
constexpr const char darkThemeName[] = "dark";
|
||||
constexpr const char lightThemeName[] = "light";
|
||||
|
||||
MATCHER_P3(HasProperty,
|
||||
themeId,
|
||||
group,
|
||||
themeProp,
|
||||
std::format("Collection {} have a property {}",
|
||||
(negation ? "Does't " : "Does "),
|
||||
PrintToString(themeProp)))
|
||||
{
|
||||
const DSThemeManager &mgr = arg;
|
||||
const std::optional<ThemeProperty> prop = mgr.property(themeId, group, themeProp.name);
|
||||
|
||||
return prop && themeProp.name == prop->name && themeProp.value == prop->value
|
||||
&& themeProp.isBinding == prop->isBinding;
|
||||
}
|
||||
|
||||
class DesignSystemManagerTest : public testing::TestWithParam<QmlDesigner::GroupType>
|
||||
{
|
||||
protected:
|
||||
QmlDesigner::GroupType groupType = GetParam();
|
||||
DSThemeManager mgr;
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(DesignSystem,
|
||||
DesignSystemManagerTest,
|
||||
testing::Values(QmlDesigner::GroupType::Colors,
|
||||
QmlDesigner::GroupType::Flags,
|
||||
QmlDesigner::GroupType::Numbers,
|
||||
QmlDesigner::GroupType::Strings));
|
||||
|
||||
TEST(DesignSystemManagerTest, add_theme)
|
||||
{
|
||||
// arrange
|
||||
DSThemeManager mgr;
|
||||
|
||||
// act
|
||||
const auto themeId = mgr.addTheme(darkThemeName);
|
||||
|
||||
// assert
|
||||
ASSERT_THAT(themeId, Optional(A<QmlDesigner::ThemeId>()));
|
||||
}
|
||||
|
||||
TEST(DesignSystemManagerTest, add_theme_with_empty_name_fails)
|
||||
{
|
||||
// arrange
|
||||
DSThemeManager mgr;
|
||||
|
||||
// act
|
||||
const auto themeId = mgr.addTheme("");
|
||||
|
||||
// assert
|
||||
ASSERT_THAT(themeId, Eq(std::nullopt));
|
||||
}
|
||||
|
||||
TEST(DesignSystemManagerTest, add_theme_generates_valid_theme_id)
|
||||
{
|
||||
// arrange
|
||||
DSThemeManager mgr;
|
||||
|
||||
// act
|
||||
const auto themeId = mgr.addTheme(darkThemeName);
|
||||
|
||||
// assert
|
||||
ASSERT_THAT(mgr.themeId(darkThemeName), Optional(themeId));
|
||||
}
|
||||
|
||||
TEST(DesignSystemManagerTest, remove_theme)
|
||||
{
|
||||
// arrange
|
||||
DSThemeManager mgr;
|
||||
const auto themeId = mgr.addTheme(darkThemeName);
|
||||
|
||||
// act
|
||||
mgr.removeTheme(*themeId);
|
||||
|
||||
// assert
|
||||
ASSERT_THAT(mgr, Property(&DSThemeManager::themeCount, 0));
|
||||
}
|
||||
|
||||
TEST(DesignSystemManagerTest, remove_theme_with_properties)
|
||||
{
|
||||
// arrange
|
||||
DSThemeManager mgr;
|
||||
const auto themeId = mgr.addTheme(darkThemeName);
|
||||
ThemeProperty testProp{testPropNameFoo, "#aaccbb", false};
|
||||
mgr.addProperty(GroupType::Colors, testProp);
|
||||
|
||||
// act
|
||||
mgr.removeTheme(*themeId);
|
||||
|
||||
// assert
|
||||
ASSERT_THAT(mgr,
|
||||
AllOf(Property(&DSThemeManager::themeCount, 0),
|
||||
Not(HasProperty(*themeId, GroupType::Colors, testProp))));
|
||||
}
|
||||
|
||||
TEST_P(DesignSystemManagerTest, add_property_without_theme)
|
||||
{
|
||||
// arrange
|
||||
ThemeProperty testProp{testPropNameFoo, "test", false};
|
||||
|
||||
// act
|
||||
mgr.addProperty(groupType, testProp);
|
||||
|
||||
//assert
|
||||
ASSERT_THAT(mgr, Property(&DSThemeManager::themeCount, 0));
|
||||
}
|
||||
|
||||
TEST_P(DesignSystemManagerTest, add_property)
|
||||
{
|
||||
// arrange
|
||||
ThemeProperty testProp{testPropNameFoo, "test", false};
|
||||
const auto themeId = mgr.addTheme(darkThemeName);
|
||||
|
||||
// act
|
||||
mgr.addProperty(groupType, testProp);
|
||||
|
||||
// assert
|
||||
ASSERT_THAT(mgr,
|
||||
AllOf(Property(&DSThemeManager::themeCount, 1),
|
||||
HasProperty(*themeId, groupType, testProp)));
|
||||
}
|
||||
|
||||
TEST_P(DesignSystemManagerTest, adding_invalid_property_fails)
|
||||
{
|
||||
// arrange
|
||||
ThemeProperty testProp{testPropNameFoo, {}, false};
|
||||
const auto themeId = mgr.addTheme(darkThemeName);
|
||||
|
||||
// act
|
||||
const bool result = mgr.addProperty(groupType, testProp);
|
||||
|
||||
// assert
|
||||
ASSERT_FALSE(result);
|
||||
ASSERT_THAT(mgr,
|
||||
AllOf(Property(&DSThemeManager::themeCount, 1),
|
||||
Not(HasProperty(*themeId, groupType, testProp))));
|
||||
}
|
||||
|
||||
TEST_P(DesignSystemManagerTest, adding_property_adds_property_to_all_themes)
|
||||
{
|
||||
// arrange
|
||||
ThemeProperty testProp{testPropNameFoo, "test", false};
|
||||
const auto themeIdDark = mgr.addTheme(darkThemeName);
|
||||
const auto themeIdLight = mgr.addTheme(lightThemeName);
|
||||
|
||||
// act
|
||||
mgr.addProperty(groupType, testProp);
|
||||
|
||||
// assert
|
||||
ASSERT_THAT(mgr,
|
||||
AllOf(Property(&DSThemeManager::themeCount, 2),
|
||||
HasProperty(*themeIdDark, groupType, testProp),
|
||||
HasProperty(*themeIdLight, groupType, testProp)));
|
||||
}
|
||||
|
||||
TEST_P(DesignSystemManagerTest, update_property_value)
|
||||
{
|
||||
// arrange
|
||||
ThemeProperty testProp{testPropNameFoo, "test", false};
|
||||
ThemeProperty testPropUpdated{testPropNameFoo, "foo", false};
|
||||
const auto themeId = mgr.addTheme(darkThemeName);
|
||||
mgr.addProperty(groupType, testProp);
|
||||
|
||||
// act
|
||||
mgr.updateProperty(*themeId, groupType, testPropUpdated);
|
||||
|
||||
// assert
|
||||
ASSERT_THAT(mgr,
|
||||
AllOf(Property(&DSThemeManager::themeCount, 1),
|
||||
HasProperty(*themeId, groupType, testPropUpdated)));
|
||||
}
|
||||
|
||||
TEST_P(DesignSystemManagerTest, update_property_name)
|
||||
{
|
||||
// arrange
|
||||
ThemeProperty testProp{testPropNameFoo, "test", false};
|
||||
ThemeProperty testPropUpdated{testPropNameBar, "test", false};
|
||||
const auto themeId = mgr.addTheme(darkThemeName);
|
||||
mgr.addProperty(groupType, testProp);
|
||||
|
||||
// act
|
||||
mgr.updateProperty(*themeId, groupType, testProp, testPropUpdated.name);
|
||||
|
||||
// assert
|
||||
ASSERT_THAT(mgr,
|
||||
AllOf(Property(&DSThemeManager::themeCount, 1),
|
||||
HasProperty(*themeId, groupType, testPropUpdated)));
|
||||
}
|
||||
|
||||
TEST_P(DesignSystemManagerTest, updating_invalid_property_fails)
|
||||
{
|
||||
// arrange
|
||||
ThemeProperty testProp{testPropNameFoo, "test", false};
|
||||
ThemeProperty testPropUpdated{testPropNameFoo, {}, false};
|
||||
const auto themeId = mgr.addTheme(darkThemeName);
|
||||
mgr.addProperty(groupType, testProp);
|
||||
|
||||
// act
|
||||
mgr.updateProperty(*themeId, groupType, testProp, testPropUpdated.name);
|
||||
|
||||
// assert
|
||||
ASSERT_THAT(mgr,
|
||||
AllOf(Property(&DSThemeManager::themeCount, 1),
|
||||
HasProperty(*themeId, groupType, testProp)));
|
||||
}
|
||||
|
||||
TEST_P(DesignSystemManagerTest, remove_property)
|
||||
{
|
||||
// arrange
|
||||
ThemeProperty testProp{testPropNameFoo, "test", false};
|
||||
const auto themeId = mgr.addTheme(darkThemeName);
|
||||
mgr.addProperty(groupType, testProp);
|
||||
|
||||
// act
|
||||
mgr.removeProperty(groupType, testPropNameFoo);
|
||||
|
||||
// assert
|
||||
ASSERT_THAT(mgr,
|
||||
AllOf(Property(&DSThemeManager::themeCount, 1),
|
||||
Not(HasProperty(*themeId, groupType, testProp))));
|
||||
}
|
||||
|
||||
TEST_P(DesignSystemManagerTest, remove_absent_property_fails)
|
||||
{
|
||||
// arrange
|
||||
ThemeProperty testProp{testPropNameFoo, "test", false};
|
||||
const auto themeId = mgr.addTheme(darkThemeName);
|
||||
mgr.addProperty(groupType, testProp);
|
||||
|
||||
// act
|
||||
mgr.removeProperty(groupType, testPropNameBar);
|
||||
|
||||
// assert
|
||||
ASSERT_THAT(mgr,
|
||||
AllOf(Property(&DSThemeManager::themeCount, 1),
|
||||
HasProperty(*themeId, groupType, testProp)));
|
||||
}
|
||||
} // namespace
|
255
tests/unit/tests/unittests/designsystem/dsthemeqml-test.cpp
Normal file
255
tests/unit/tests/unittests/designsystem/dsthemeqml-test.cpp
Normal file
@@ -0,0 +1,255 @@
|
||||
// Copyright (C) 2024 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include "../utils/googletest.h"
|
||||
|
||||
#include <bindingproperty.h>
|
||||
#include <model.h>
|
||||
#include <nodeproperty.h>
|
||||
#include <projectstoragemock.h>
|
||||
#include <sourcepathcachemock.h>
|
||||
#include <variantproperty.h>
|
||||
|
||||
#include <designsystem/dsthemegroup.h>
|
||||
#include <designsystem/dsthememanager.h>
|
||||
|
||||
#include <format>
|
||||
#include <functional>
|
||||
|
||||
using QmlDesigner::DSThemeManager;
|
||||
using QmlDesigner::GroupType;
|
||||
using QmlDesigner::Import;
|
||||
using QmlDesigner::ModelNode;
|
||||
using QmlDesigner::ThemeProperty;
|
||||
|
||||
template<>
|
||||
struct std::formatter<QByteArray> : std::formatter<std::string>
|
||||
{
|
||||
template<typename FormatContext>
|
||||
auto format(const QByteArray &ba, FormatContext &ctx) const
|
||||
{
|
||||
return std::formatter<std::string>::format(ba.toStdString(), ctx);
|
||||
}
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
static std::string formatedPropStr(const char tag[], const char name[], const QVariant &v)
|
||||
{
|
||||
return std::format("{}Property({}, {})", tag, name, v.toString().toStdString());
|
||||
}
|
||||
|
||||
static auto bindingPropStr = std::bind(&formatedPropStr,
|
||||
"Binding",
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2);
|
||||
static auto variantPropStr = std::bind(&formatedPropStr,
|
||||
"Variant",
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2);
|
||||
|
||||
constexpr const char testPropertyName1[] = "prop1";
|
||||
constexpr const char darkThemeName[] = "dark";
|
||||
constexpr QmlDesigner::ThemeId testThemeId = 1;
|
||||
|
||||
MATCHER_P2(HasNodeProperty,
|
||||
name,
|
||||
typeName,
|
||||
std::format("{} have node {} with type {})", (negation ? "Does't " : "Does "), name, typeName))
|
||||
{
|
||||
ModelNode n = arg;
|
||||
return n.hasNodeProperty(name) && n.nodeProperty(name).modelNode().isValid()
|
||||
&& n.nodeProperty(name).modelNode().type() == typeName;
|
||||
}
|
||||
|
||||
MATCHER_P2(HasBindingProperty,
|
||||
name,
|
||||
value,
|
||||
std::format("{} have {})", (negation ? "Does't " : "Does "), bindingPropStr(name, value)))
|
||||
{
|
||||
ModelNode n = arg;
|
||||
return n.hasBindingProperty(name) && n.bindingProperty(name).expression() == value;
|
||||
}
|
||||
|
||||
MATCHER_P2(HasVariantProperty,
|
||||
name,
|
||||
value,
|
||||
std::format("{} have {})", (negation ? "Does't " : "Does "), variantPropStr(name, value)))
|
||||
{
|
||||
ModelNode n = arg;
|
||||
return n.hasVariantProperty(name) && n.variantProperty(name).value() == value;
|
||||
}
|
||||
|
||||
MATCHER_P2(HasGroupVariantProperty,
|
||||
groupName,
|
||||
themeProp,
|
||||
std::format("{} have node {} with {})",
|
||||
(negation ? "Does't " : "Does "),
|
||||
groupName.constData(),
|
||||
PrintToString(themeProp)))
|
||||
{
|
||||
ModelNode n = arg;
|
||||
|
||||
ModelNode groupNode = n.nodeProperty(groupName).modelNode();
|
||||
|
||||
return groupNode.isValid() && groupNode.hasVariantProperty(themeProp.name)
|
||||
&& groupNode.variantProperty(themeProp.name).value() == themeProp.value;
|
||||
}
|
||||
|
||||
MATCHER_P2(HasGroupBindingProperty,
|
||||
groupName,
|
||||
themeProp,
|
||||
std::format("{} have node {} with {})",
|
||||
(negation ? "Does't " : "Does "),
|
||||
groupName.constData(),
|
||||
PrintToString(themeProp)))
|
||||
{
|
||||
ModelNode n = arg;
|
||||
|
||||
ModelNode groupNode = n.nodeProperty(groupName).modelNode();
|
||||
|
||||
return groupNode.isValid() && groupNode.hasBindingProperty(themeProp.name)
|
||||
&& groupNode.bindingProperty(themeProp.name).expression() == themeProp.value.toString();
|
||||
}
|
||||
|
||||
class DesignSystemQmlTest : public testing::TestWithParam<QmlDesigner::GroupType>
|
||||
{
|
||||
protected:
|
||||
DesignSystemQmlTest()
|
||||
: group(groupType)
|
||||
{}
|
||||
|
||||
const QmlDesigner::GroupType groupType = GetParam();
|
||||
const QmlDesigner::PropertyName groupName = GroupId(groupType);
|
||||
QmlDesigner::DSThemeGroup group;
|
||||
NiceMock<SourcePathCacheMockWithPaths> pathCacheMock{"/path/model.qm"};
|
||||
NiceMock<ProjectStorageMockWithQtQuick> projectStorageMock{pathCacheMock.sourceId, "/path"};
|
||||
QmlDesigner::Model model{{projectStorageMock, pathCacheMock},
|
||||
"QtObject",
|
||||
{Import::createLibraryImport("QM"),
|
||||
Import::createLibraryImport("QtQuick")},
|
||||
QUrl::fromLocalFile(pathCacheMock.path.toQString())};
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(DesignSystem,
|
||||
DesignSystemQmlTest,
|
||||
testing::Values(QmlDesigner::GroupType::Colors,
|
||||
QmlDesigner::GroupType::Flags,
|
||||
QmlDesigner::GroupType::Numbers,
|
||||
QmlDesigner::GroupType::Strings));
|
||||
|
||||
TEST_P(DesignSystemQmlTest, group_aliase_properties_are_generated)
|
||||
{
|
||||
// arrange
|
||||
ThemeProperty testProp{testPropertyName1, "test", false};
|
||||
DSThemeManager mgr;
|
||||
mgr.addTheme(darkThemeName);
|
||||
mgr.addProperty(groupType, testProp);
|
||||
ModelNode rootNode = model.rootModelNode();
|
||||
QString binding = QString("currentTheme.%1").arg(QString::fromLatin1(groupName));
|
||||
|
||||
// act
|
||||
mgr.decorate(rootNode);
|
||||
|
||||
// assert
|
||||
ASSERT_THAT(rootNode,
|
||||
AllOf(Property(&ModelNode::type, Eq("QtObject")),
|
||||
HasBindingProperty(groupName, binding),
|
||||
HasBindingProperty("currentTheme", darkThemeName),
|
||||
HasNodeProperty(darkThemeName, "QtObject")));
|
||||
}
|
||||
|
||||
TEST_P(DesignSystemQmlTest, empty_groups_generate_no_group_aliase_properties)
|
||||
{
|
||||
// arrange
|
||||
DSThemeManager mgr;
|
||||
ModelNode rootNode = model.rootModelNode();
|
||||
QString binding = QString("currentTheme.%1").arg(QString::fromLatin1(groupName));
|
||||
|
||||
// act
|
||||
mgr.decorate(rootNode);
|
||||
|
||||
// assert
|
||||
ASSERT_THAT(rootNode,
|
||||
AllOf(Property(&ModelNode::type, Eq("QtObject")),
|
||||
Not(HasBindingProperty(groupName, binding)),
|
||||
Not(HasBindingProperty("currentTheme", darkThemeName)),
|
||||
Not(HasNodeProperty(darkThemeName, "QtObject"))));
|
||||
}
|
||||
|
||||
TEST_P(DesignSystemQmlTest, decorate_appends_binding_property_to_group_node)
|
||||
{
|
||||
// arrange
|
||||
ThemeProperty testProp{testPropertyName1, "width", true};
|
||||
group.addProperty(testThemeId, testProp);
|
||||
ModelNode rootNode = model.rootModelNode();
|
||||
|
||||
// act
|
||||
group.decorate(testThemeId, rootNode);
|
||||
|
||||
// assert
|
||||
ASSERT_THAT(rootNode,
|
||||
AllOf(HasNodeProperty(groupName, "QtObject"),
|
||||
HasGroupBindingProperty(groupName, testProp)));
|
||||
}
|
||||
|
||||
TEST_P(DesignSystemQmlTest, mcu_flag_decorate_appends_binding_property_to_root_node)
|
||||
{
|
||||
// arrange
|
||||
ThemeProperty testProp{testPropertyName1, "width", true};
|
||||
group.addProperty(testThemeId, testProp);
|
||||
ModelNode rootNode = model.rootModelNode();
|
||||
|
||||
// act
|
||||
group.decorate(testThemeId, rootNode, false);
|
||||
|
||||
// assert
|
||||
ASSERT_THAT(rootNode,
|
||||
AllOf(Not(HasNodeProperty(groupName, "QtObject")),
|
||||
HasBindingProperty(testProp.name, testProp.value)));
|
||||
}
|
||||
|
||||
TEST_P(DesignSystemQmlTest, decorate_appends_variant_property_to_group_node)
|
||||
{
|
||||
// arrange
|
||||
ThemeProperty testProp{testPropertyName1, 5, false};
|
||||
group.addProperty(testThemeId, testProp);
|
||||
ModelNode rootNode = model.rootModelNode();
|
||||
|
||||
// act
|
||||
group.decorate(testThemeId, rootNode);
|
||||
|
||||
// assert
|
||||
ASSERT_THAT(rootNode,
|
||||
AllOf(HasNodeProperty(groupName, "QtObject"),
|
||||
HasGroupVariantProperty(groupName, testProp)));
|
||||
}
|
||||
|
||||
TEST_P(DesignSystemQmlTest, mcu_flag_decorate_appends_variant_property_to_root_node)
|
||||
{
|
||||
// arrange
|
||||
ThemeProperty testProp{testPropertyName1, 5, false};
|
||||
group.addProperty(testThemeId, testProp);
|
||||
ModelNode rootNode = model.rootModelNode();
|
||||
|
||||
// act
|
||||
group.decorate(testThemeId, rootNode, false);
|
||||
|
||||
// assert
|
||||
ASSERT_THAT(rootNode,
|
||||
AllOf(Not(HasNodeProperty(groupName, "QtObject")),
|
||||
HasVariantProperty(testProp.name, testProp.value)));
|
||||
}
|
||||
|
||||
TEST_P(DesignSystemQmlTest, empty_group_decorate_adds_no_property)
|
||||
{
|
||||
// arrange
|
||||
ModelNode rootNode = model.rootModelNode();
|
||||
|
||||
// act
|
||||
group.decorate(testThemeId, rootNode);
|
||||
|
||||
// assert
|
||||
ASSERT_THAT(rootNode, Not(HasNodeProperty(groupName, "QtObject")));
|
||||
}
|
||||
} // namespace
|
Reference in New Issue
Block a user