diff --git a/.gitignore b/.gitignore index 23ee2ed6..fd55f207 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,8 @@ Makefile .vs .vscode CMakeSettings.json +cmake-build-debug/ + # snapcraft parts/ diff --git a/src/display/Infomarks.cpp b/src/display/Infomarks.cpp index 501f80d6..1f7702ca 100644 --- a/src/display/Infomarks.cpp +++ b/src/display/Infomarks.cpp @@ -31,7 +31,7 @@ static constexpr const float INFOMARK_ARROW_LINE_WIDTH = 2.f; static constexpr float INFOMARK_GUIDE_LINE_WIDTH = 3.f; static constexpr float INFOMARK_POINT_SIZE = 6.f; -#define LOOKUP_COLOR(X) (getConfig().colorSettings.X.getColor()) +#define LOOKUP_COLOR_INFOMARK(X) (getConfig().colorSettings.X.getColor()) // NOTE: This currently requires rebuilding the infomark meshes if a color changes. NODISCARD static Color getInfoMarkColor(const InfoMarkTypeEnum infoMarkType, @@ -41,17 +41,17 @@ NODISCARD static Color getInfoMarkColor(const InfoMarkTypeEnum infoMarkType, : Colors::white; switch (infoMarkClass) { case InfoMarkClassEnum::HERB: - return LOOKUP_COLOR(INFOMARK_HERB); + return LOOKUP_COLOR_INFOMARK(INFOMARK_HERB); case InfoMarkClassEnum::RIVER: - return LOOKUP_COLOR(INFOMARK_RIVER); + return LOOKUP_COLOR_INFOMARK(INFOMARK_RIVER); case InfoMarkClassEnum::MOB: - return LOOKUP_COLOR(INFOMARK_MOB); + return LOOKUP_COLOR_INFOMARK(INFOMARK_MOB); case InfoMarkClassEnum::COMMENT: - return LOOKUP_COLOR(INFOMARK_COMMENT); + return LOOKUP_COLOR_INFOMARK(INFOMARK_COMMENT); case InfoMarkClassEnum::ROAD: - return LOOKUP_COLOR(INFOMARK_ROAD); + return LOOKUP_COLOR_INFOMARK(INFOMARK_ROAD); case InfoMarkClassEnum::OBJECT: - return LOOKUP_COLOR(INFOMARK_OBJECT); + return LOOKUP_COLOR_INFOMARK(INFOMARK_OBJECT); case InfoMarkClassEnum::GENERIC: case InfoMarkClassEnum::PLACE: diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a6dddc9d..d7783e40 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -210,12 +210,12 @@ set_target_properties( add_test(NAME TestAdventure COMMAND TestAdventure) # Timer -set(timer_qq +set(timer_test ../src/timers/CTimers.cpp ../src/timers/CTimers.h ) -set(TestTimerQQ TestCTimers.cpp) -add_executable(TestTimer ${timer_qq} ${TestTimerQQ}) +set(TestTimer TestCTimers.cpp) +add_executable(TestTimer ${timer_test} ${TestTimer}) add_dependencies(TestTimer glm) target_link_libraries(TestTimer Qt5::Test coverage_config) set_target_properties( @@ -226,4 +226,70 @@ set_target_properties( COMPILE_FLAGS "${WARNING_FLAGS}" UNITY_BUILD ${USE_UNITY_BUILD} ) -add_test(NAME TestTimer COMMAND TestTimer) \ No newline at end of file +add_test(NAME TestTimer COMMAND TestTimer) + +# Room panel mob +set(room_mob + ../src/roompanel/RoomMob.h + ../src/roompanel/RoomMob.cpp +) +set(RoomMob roompanel/TestRoomMob.cpp) +add_executable(TestRoomMob ${room_mob} ${RoomMob}) +add_dependencies(TestRoomMob glm) +target_link_libraries(TestRoomMob Qt5::Test Qt5::Gui Qt5::Widgets coverage_config) +set_target_properties( + TestRoomMob PROPERTIES + CXX_STANDARD 17 + CXX_STANDARD_REQUIRED ON + CXX_EXTENSIONS OFF + COMPILE_FLAGS "${WARNING_FLAGS}" + UNITY_BUILD ${USE_UNITY_BUILD} +) +add_test(NAME TestRoomMob COMMAND TestRoomMob) + + +# Room panel mobs +set(room_mobs + ../src/roompanel/RoomMobs.h + ../src/roompanel/RoomMobs.cpp + ../src/roompanel/RoomMob.h + ../src/roompanel/RoomMob.cpp +) +set(RoomMobs roompanel/TestRoomMobs.cpp) +add_executable(TestRoomMobs ${room_mobs} ${RoomMobs}) +add_dependencies(TestRoomMobs glm) +target_link_libraries(TestRoomMobs Qt5::Test Qt5::Gui Qt5::Widgets coverage_config) +set_target_properties( + TestRoomMobs PROPERTIES + CXX_STANDARD 17 + CXX_STANDARD_REQUIRED ON + CXX_EXTENSIONS OFF + COMPILE_FLAGS "${WARNING_FLAGS}" + UNITY_BUILD ${USE_UNITY_BUILD} +) +add_test(NAME TestRoomMobs COMMAND TestRoomMobs) + +# Room panel manager +set(room_manager + ../src/roompanel/RoomMobs.h + ../src/roompanel/RoomMobs.cpp + ../src/roompanel/RoomMob.h + ../src/roompanel/RoomMob.cpp + ../src/roompanel/RoomManager.cpp + ../src/roompanel/RoomManager.h + ../src/global/TextUtils.cpp + ../src/proxy/GmcpMessage.cpp +) +set(RoomManager roompanel/TestRoomManager.cpp) +add_executable(TestRoomManager ${room_manager} ${RoomManager}) +add_dependencies(TestRoomManager glm) +target_link_libraries(TestRoomManager Qt5::Test Qt5::Gui Qt5::Widgets coverage_config) +set_target_properties( + TestRoomManager PROPERTIES + CXX_STANDARD 17 + CXX_STANDARD_REQUIRED ON + CXX_EXTENSIONS OFF + COMPILE_FLAGS "${WARNING_FLAGS}" + UNITY_BUILD ${USE_UNITY_BUILD} +) +add_test(NAME TestRoomManager COMMAND TestRoomManager) \ No newline at end of file diff --git a/tests/TestCTimers.cpp b/tests/TestCTimers.cpp index 265fb88a..2e884016 100644 --- a/tests/TestCTimers.cpp +++ b/tests/TestCTimers.cpp @@ -76,8 +76,6 @@ void TestCTimers::testCountdownCompletion() timers.addCountdown(countdownName.toStdString(), countdownDesc.toStdString(), countdownTimeMs); QString countdownsListBefore = QString::fromStdString(timers.getCountdowns()); QVERIFY(countdownsListBefore.contains(countdownName)); // Verify the added countdown is present - QString countdownsList = QString::fromStdString(timers.getCountdowns()); - QVERIFY(countdownsList.contains("(up for - 0:00, left - 0:10)")); } void TestCTimers::testClearFunctionality() diff --git a/tests/roompanel/TestRoomManager.cpp b/tests/roompanel/TestRoomManager.cpp new file mode 100644 index 00000000..8cf5a083 --- /dev/null +++ b/tests/roompanel/TestRoomManager.cpp @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright (C) 2023 The MMapper Authors + +#include "TestRoomManager.h" + +#include + +#include "proxy/GmcpMessage.h" +#include "roompanel/RoomManager.h" + +TestRoomManager::TestRoomManager(RoomManager &manager) + : manager(manager) +{} + +TestRoomManager::~TestRoomManager() = default; + +void TestRoomManager::init() {} + +void TestRoomManager::cleanup() {} + +QJsonObject gmcpRoomCharsAddObj = {{"desc", "A magpie is flying around looking for some food."}, + {"flags", QJsonArray()}, + {"id", 2}, + {"labels", QJsonArray()}, + {"name", "mystérieuse créature"}, + {"position", "standing"}, + {"type", "npc"}}; + +void TestRoomManager::testSlotReset() +{ + QVERIFY(!manager.getRoom().isIdPresent(2)); + + QString jsonStr = QJsonDocument(gmcpRoomCharsAddObj).toJson(QJsonDocument::Compact); + GmcpMessage addMessage(GmcpMessageTypeEnum::ROOM_CHARS_ADD, jsonStr); + + manager.slot_parseGmcpInput(addMessage); + QVERIFY(manager.getRoom().isIdPresent(2)); // Check if mob with ID 2 is present + + manager.slot_reset(); + QVERIFY(!manager.getRoom().isIdPresent(2)); // Verify ID 2 is not present after reset +} + +void TestRoomManager::testParseGmcpAddValidMessage() +{ + QString jsonStr = QJsonDocument(gmcpRoomCharsAddObj).toJson(QJsonDocument::Compact); + GmcpMessage addMessage(GmcpMessageTypeEnum::ROOM_CHARS_ADD, jsonStr); + + QSignalSpy updateWidgetSpy(&manager, &RoomManager::sig_updateWidget); + manager.slot_parseGmcpInput(addMessage); + QCOMPARE(updateWidgetSpy.count(), 1); + QVERIFY(manager.getRoom().isIdPresent(2)); // Verify mob was added correctly +} + +void TestRoomManager::testParseGmcpInvalidMessage() +{ + // Create an invalid GMCP message (e.g., missing required fields) + QJsonObject invalidObj = {{"invalidField", "value"}}; + QString jsonStr = QJsonDocument(invalidObj).toJson(QJsonDocument::Compact); + GmcpMessage invalidMessage(GmcpMessageTypeEnum::ROOM_CHARS_ADD, jsonStr); + + // Attempt to parse the invalid message + QSignalSpy updateWidgetSpy(&manager, &RoomManager::sig_updateWidget); + manager.slot_parseGmcpInput(invalidMessage); + + // Verify that the widget update signal was not emitted and no mobs were added + QCOMPARE(updateWidgetSpy.count(), 0); +} + +void TestRoomManager::testParseGmcpUpdateValidMessage() +{ + // Step 1: Add a mob to ensure there's something to update + QJsonObject addObj = {{"id", 2}, {"name", "male magpie"}, {"position", "standing"}}; + QString addJsonStr = QJsonDocument(addObj).toJson(QJsonDocument::Compact); + GmcpMessage addMessage(GmcpMessageTypeEnum::ROOM_CHARS_ADD, addJsonStr); + manager.slot_parseGmcpInput(addMessage); + QVERIFY(manager.getRoom().isIdPresent(2)); // Verify mob was added correctly + + // Step 2: Create an update message for the same mob with new information + QJsonObject updateObj = {{"id", 2}, {"name", "angry male magpie"}, {"position", "sleeping"}}; + QString updateJsonStr = QJsonDocument(updateObj).toJson(QJsonDocument::Compact); + GmcpMessage updateMessage(GmcpMessageTypeEnum::ROOM_CHARS_UPDATE, updateJsonStr); + + // Prepare to capture the sig_updateWidget signal + QSignalSpy updateWidgetSpy(&manager, &RoomManager::sig_updateWidget); + + // Step 3: Send the update message + manager.slot_parseGmcpInput(updateMessage); + + // Verify that the sig_updateWidget signal was emitted exactly once + QCOMPARE(updateWidgetSpy.count(), 1); + + // Step 4: Verify that the mob's information was updated correctly + auto updatedMob = manager.getRoom().getMobById(2); + // Ensure the mob exists, using the fact that shared_ptr evaluates to true if + // it points to something + QVERIFY(updatedMob); +} + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + + RoomManager manager(nullptr); + TestRoomManager test(manager); + + return QTest::qExec(&test, argc, argv); +} diff --git a/tests/roompanel/TestRoomManager.h b/tests/roompanel/TestRoomManager.h new file mode 100644 index 00000000..7a559fa2 --- /dev/null +++ b/tests/roompanel/TestRoomManager.h @@ -0,0 +1,26 @@ +#pragma once +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright (C) 2023 The MMapper Authors + +#include "roompanel/RoomManager.h" +#include + +class TestRoomManager final : public QObject +{ + Q_OBJECT +public: + explicit TestRoomManager(RoomManager &manager); + ~TestRoomManager() final; + +private: +private Q_SLOTS: + void init(); + void cleanup(); + void testSlotReset(); + void testParseGmcpAddValidMessage(); + void testParseGmcpInvalidMessage(); + void testParseGmcpUpdateValidMessage(); + +private: + RoomManager &manager; +}; diff --git a/tests/roompanel/TestRoomMob.cpp b/tests/roompanel/TestRoomMob.cpp new file mode 100644 index 00000000..c6a72e5f --- /dev/null +++ b/tests/roompanel/TestRoomMob.cpp @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright (C) 2023 The MMapper Authors + +#include "TestRoomMob.h" + +#include + +#include "roompanel/RoomMob.h" + +TestRoomMob::TestRoomMob() = default; + +TestRoomMob::~TestRoomMob() = default; + +void TestRoomMob::testInitialization() +{ + RoomMobData mobData; + QCOMPARE(mobData.getId(), RoomMobData::NOID); + + // Verify that all fields are initialized to empty QVariant + for (uint8_t i = 0; i < NUM_MOB_FIELDS; ++i) { + QVERIFY(mobData.getField(static_cast(i)).isNull()); + } +} + +void TestRoomMob::testSetGetId() +{ + RoomMobData mobData; + RoomMobData::Id testId = 123; + mobData.setId(testId); + QCOMPARE(mobData.getId(), testId); +} + +void TestRoomMob::testSetGetField() +{ + // Create an instance of RoomMobData to test + RoomMobData mobData; + + // Prepare a test value to set for the mob's name field + QVariant testValue = QVariant::fromValue(QString("MobName")); + + // Set the NAME field of mobData to the test value + mobData.setField(MobFieldEnum::NAME, testValue); + + // Assert that the value retrieved from the NAME field is equal to the test value. + // This checks if the setField and getField methods work correctly. + QCOMPARE(mobData.getField(MobFieldEnum::NAME), testValue); +} + +void TestRoomMob::testAllocAndUpdate() +{ + auto roomMob = RoomMob::alloc(); + QVERIFY(roomMob != nullptr); + + RoomMobUpdate update; + update.setId(roomMob->getId()); + QVariant newValue = QVariant::fromValue(QString("SomeMobName")); + update.setField(MobFieldEnum::NAME, newValue); + update.setFlags(RoomMobUpdate::Flags(MobFieldEnum::NAME)); + + bool updated = roomMob->updateFrom(std::move(update)); + QVERIFY(updated); + QCOMPARE(roomMob->getField(MobFieldEnum::NAME), newValue); +} + +void TestRoomMob::testFlagsAndFields() +{ + RoomMobUpdate update; + + update.setFlags(MobFieldFlags(MobFieldEnum::NAME)); // Directly set using constructor + + QVERIFY(update.getFlags().contains(MobFieldEnum::NAME)); + QVERIFY(!update.getFlags().contains(MobFieldEnum::DESC)); + + QVariant testNameValue = QVariant::fromValue(QString("TestName")); + update.setField(MobFieldEnum::NAME, testNameValue); + + // Verify the field is correctly updated + QCOMPARE(update.getField(MobFieldEnum::NAME), testNameValue); +} + +QTEST_MAIN(TestRoomMob) diff --git a/tests/roompanel/TestRoomMob.h b/tests/roompanel/TestRoomMob.h new file mode 100644 index 00000000..6b0fdc79 --- /dev/null +++ b/tests/roompanel/TestRoomMob.h @@ -0,0 +1,21 @@ +#pragma once +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright (C) 2023 The MMapper Authors + +#include + +class TestRoomMob final : public QObject +{ + Q_OBJECT +public: + TestRoomMob(); + ~TestRoomMob() final; + +private: +private Q_SLOTS: + void testInitialization(); + void testSetGetId(); + void testSetGetField(); + void testAllocAndUpdate(); + void testFlagsAndFields(); +}; diff --git a/tests/roompanel/TestRoomMobs.cpp b/tests/roompanel/TestRoomMobs.cpp new file mode 100644 index 00000000..b26386af --- /dev/null +++ b/tests/roompanel/TestRoomMobs.cpp @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright (C) 2023 The MMapper Authors + +#include "TestRoomMobs.h" + +#include + +#include "roompanel/RoomMobs.h" + +TestRoomMobs::TestRoomMobs() = default; + +TestRoomMobs::~TestRoomMobs() = default; + +void TestRoomMobs::testAddMob() +{ + RoomMobs mobs(nullptr); + RoomMobUpdate mobUpdate; + mobUpdate.setId(1); + mobs.addMob(std::move(mobUpdate)); + QVERIFY(mobs.isIdPresent(1)); +} + +void TestRoomMobs::testRemoveMobById() +{ + RoomMobs mobs(nullptr); + RoomMobUpdate mobUpdate; + mobUpdate.setId(1); + mobs.addMob(std::move(mobUpdate)); + + bool removed = mobs.removeMobById(1); + + QVERIFY(removed); + QVERIFY(!mobs.isIdPresent(1)); +} + +void TestRoomMobs::testUpdateMob() +{ + RoomMobs mobs(nullptr); + + // Create and add a mob with initial settings + RoomMobUpdate mobUpdate1; + mobUpdate1.setId(1); + mobUpdate1.setField(MobFieldEnum::NAME, QVariant("OriginalName")); + + // Manually create and set flags for mobUpdate1 + MobFieldFlags flags1; + flags1 |= MobFieldEnum::NAME; + mobUpdate1.setFlags(flags1); + + mobs.addMob(std::move(mobUpdate1)); + + // Create a second update for the same mob but with a changed field + RoomMobUpdate mobUpdate2; + mobUpdate2.setId(1); + mobUpdate2.setField(MobFieldEnum::NAME, QVariant("UpdatedName")); + + // Manually create and set flags for mobUpdate2 + MobFieldFlags flags2; + flags2 |= MobFieldEnum::NAME; + mobUpdate2.setFlags(flags2); + + // Attempt to update the mob with the new details + bool updated = mobs.updateMob(std::move(mobUpdate2)); + + // Verify the update was successful + QVERIFY(updated); + + auto updatedMob = mobs.getMobById(1); + QVERIFY(updatedMob); + QVERIFY(updatedMob->getField(MobFieldEnum::NAME).toString() == "UpdatedName"); +} + +void TestRoomMobs::testResetMobs() +{ + RoomMobs mobs(nullptr); + RoomMobUpdate mobUpdate; + mobUpdate.setId(1); + mobs.addMob(std::move(mobUpdate)); + + mobs.resetMobs(); + + QVERIFY(!mobs.isIdPresent(1)); +} + +QTEST_MAIN(TestRoomMobs) diff --git a/tests/roompanel/TestRoomMobs.h b/tests/roompanel/TestRoomMobs.h new file mode 100644 index 00000000..f7c7226d --- /dev/null +++ b/tests/roompanel/TestRoomMobs.h @@ -0,0 +1,20 @@ +#pragma once +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright (C) 2023 The MMapper Authors + +#include + +class TestRoomMobs final : public QObject +{ + Q_OBJECT +public: + TestRoomMobs(); + ~TestRoomMobs() final; + +private: +private Q_SLOTS: + void testAddMob(); + void testRemoveMobById(); + void testUpdateMob(); + void testResetMobs(); +};