diff --git a/docs/TAG_ITEMS.md b/docs/TAG_ITEMS.md index e99f7cc92..c9f9ba5a7 100644 --- a/docs/TAG_ITEMS.md +++ b/docs/TAG_ITEMS.md @@ -32,3 +32,4 @@ 130 - Missed Approach Indicator 131 - Relevant ECFMP Flow Measures 132 - Glideslope Deviation +133 - Stand Assignment Source diff --git a/src/plugin/CMakeLists.txt b/src/plugin/CMakeLists.txt index e33f908c0..dd818321f 100644 --- a/src/plugin/CMakeLists.txt +++ b/src/plugin/CMakeLists.txt @@ -906,6 +906,9 @@ set(src__stands "stands/CompareStands.cpp" "stands/CompareStands.h" "stands/Stand.h" + "stands/StandAssignmentSource.h" + "stands/StandColourConfiguration.cpp" + "stands/StandColourConfiguration.h" "stands/StandEventHandler.cpp" "stands/StandEventHandler.h" "stands/StandModule.cpp" diff --git a/src/plugin/stands/StandAssignmentSource.h b/src/plugin/stands/StandAssignmentSource.h new file mode 100644 index 000000000..b6c8f2196 --- /dev/null +++ b/src/plugin/stands/StandAssignmentSource.h @@ -0,0 +1,66 @@ +#pragma once +#include +#include + +namespace UKControllerPlugin::Stands { + /* + Represents a stand assignment with its source (how it was assigned). + */ + struct StandAssignment + { + enum class Source + { + Unknown, + User, + ReservationAllocator, + VaaAllocator, + SystemAuto, + }; + + int standId; + + // The source of the assignment (user, reservation_allocator, vaa_allocator, system_auto) + Source source; + + [[nodiscard]] static constexpr auto ToString(Source source) -> std::string_view + { + using enum Source; + + switch (source) { + case Unknown: + return "unknown"; + case User: + return "user"; + case ReservationAllocator: + return "reservation_allocator"; + case VaaAllocator: + return "vaa_allocator"; + case SystemAuto: + return "system_auto"; + default: + return "unknown"; + } + } + + [[nodiscard]] static constexpr auto FromString(std::string_view source) -> Source + { + using enum Source; + + if (source == "user") { + return User; + } + if (source == "reservation_allocator") { + return ReservationAllocator; + } + if (source == "vaa_allocator") { + return VaaAllocator; + } + + if (source == "system_auto") { + return SystemAuto; + } + + return Unknown; + } + }; +} // namespace UKControllerPlugin::Stands diff --git a/src/plugin/stands/StandColourConfiguration.cpp b/src/plugin/stands/StandColourConfiguration.cpp new file mode 100644 index 000000000..e70a58ff8 --- /dev/null +++ b/src/plugin/stands/StandColourConfiguration.cpp @@ -0,0 +1,59 @@ +#include "StandColourConfiguration.h" +#include "StandAssignmentSource.h" +#include "euroscope/UserSetting.h" +#include "helper/HelperFunctions.h" +#include "log/LoggerFunctions.h" +#include + +namespace UKControllerPlugin::Stands { + + StandColourConfiguration::StandColourConfiguration(UKControllerPlugin::Euroscope::UserSetting& setting) + : StandColourConfiguration(&setting) + { + } + + StandColourConfiguration::StandColourConfiguration() : StandColourConfiguration(nullptr) + { + } + + StandColourConfiguration::StandColourConfiguration(UKControllerPlugin::Euroscope::UserSetting* userSetting) + : userSetting(userSetting), sourceColours( + {{StandAssignment::Source::User, DEFAULT_USER_COLOUR}, + {StandAssignment::Source::ReservationAllocator, DEFAULT_RESERVATION_COLOUR}, + {StandAssignment::Source::VaaAllocator, DEFAULT_VAA_COLOUR}, + {StandAssignment::Source::SystemAuto, DEFAULT_SYSTEM_COLOUR}}) + { + LoadFromUserSettings(); + } + + auto StandColourConfiguration::GetColourForSource(StandAssignment::Source source) const -> COLORREF + { + if (auto it = sourceColours.find(source); it != sourceColours.cend()) { + return it->second; + } + + return DEFAULT_COLOUR; + } + + void StandColourConfiguration::LoadFromUserSettings() + { + if (!this->userSetting) { + return; + } + + using enum UKControllerPlugin::Stands::StandAssignment::Source; + + constexpr std::array sourceColourDefaults = { + {Unknown, User, ReservationAllocator, VaaAllocator, SystemAuto}}; + + for (const auto source : sourceColourDefaults) { + const std::string key = std::string(SETTING_PREFIX) + std::string(StandAssignment::ToString(source)); + if (this->userSetting->HasEntry(key)) { + this->sourceColours[source] = this->userSetting->GetColourEntry(key); + } + } + + LogInfo("Loaded stand assignment source colours from UserSettings"); + } + +} // namespace UKControllerPlugin::Stands diff --git a/src/plugin/stands/StandColourConfiguration.h b/src/plugin/stands/StandColourConfiguration.h new file mode 100644 index 000000000..4a8030b8b --- /dev/null +++ b/src/plugin/stands/StandColourConfiguration.h @@ -0,0 +1,55 @@ +#pragma once +#include "StandAssignmentSource.h" +#include +#include +#include +#include + +namespace UKControllerPlugin::Euroscope { + class UserSetting; +} + +namespace UKControllerPlugin::Stands { + /* + Manages colour configuration for stand assignments based on their source. + Colours are persisted to EuroScope UserSettings and can be customized without recompilation. + */ + class StandColourConfiguration + { + public: + explicit StandColourConfiguration(UKControllerPlugin::Euroscope::UserSetting& userSetting); + explicit StandColourConfiguration(); + + /* + Get the colour for a given assignment source. + Returns a default grey if source is not found or not set. + */ + [[nodiscard]] auto GetColourForSource(StandAssignment::Source source) const -> COLORREF; + + /* + Load colours from UserSettings, with fallback to defaults. + */ + void LoadFromUserSettings(); + + private: + explicit StandColourConfiguration(UKControllerPlugin::Euroscope::UserSetting* userSetting); + + // Reference to user settings for persistence (null if not available) + UKControllerPlugin::Euroscope::UserSetting* userSetting; + + // Map of source to RGB colour + std::map sourceColours; + + // Default colour (grey) for unknown sources + static constexpr COLORREF DEFAULT_COLOUR = RGB(204, 204, 204); + + // Default colours if not configured + static constexpr COLORREF DEFAULT_USER_COLOUR = RGB(255, 149, 41); // orange + static constexpr COLORREF DEFAULT_RESERVATION_COLOUR = RGB(255, 216, 0); // yellow + static constexpr COLORREF DEFAULT_VAA_COLOUR = RGB(255, 216, 0); // yellow + static constexpr COLORREF DEFAULT_SYSTEM_COLOUR = RGB(255, 255, 255); // white + + // UserSetting key prefix for colours + static constexpr std::string_view SETTING_PREFIX = "stand_colour_"; + }; +} // namespace UKControllerPlugin::Stands diff --git a/src/plugin/stands/StandEventHandler.cpp b/src/plugin/stands/StandEventHandler.cpp index b74df94c1..de81f6a30 100644 --- a/src/plugin/stands/StandEventHandler.cpp +++ b/src/plugin/stands/StandEventHandler.cpp @@ -1,6 +1,8 @@ #include "StandAssignedMessage.h" +#include "StandColourConfiguration.h" #include "StandEventHandler.h" #include "StandUnassignedMessage.h" +#include #include "api/ApiException.h" #include "api/ApiInterface.h" #include "api/ApiRequestFactory.h" @@ -29,11 +31,15 @@ namespace UKControllerPlugin::Stands { const ApiInterface& api, TaskRunnerInterface& taskRunner, EuroscopePluginLoopbackInterface& plugin, + UKControllerPlugin::Euroscope::UserSetting* userSetting, Integration::OutboundIntegrationEventHandler& integrationEventHandler, std::shared_ptr ownership, std::set stands, int standSelectedCallbackId) : api(api), taskRunner(taskRunner), plugin(plugin), stands(std::move(stands)), + colourConfiguration( + userSetting ? std::make_shared(*userSetting) + : std::make_shared()), integrationEventHandler(integrationEventHandler), ownership(ownership), standSelectedCallbackId(standSelectedCallbackId) { @@ -103,6 +109,8 @@ namespace UKControllerPlugin::Stands { auto StandEventHandler::AssignStandInApi( const std::string& callsign, const std::string& airfield, const std::string& identifier) -> std::string { + using Source = StandAssignment::Source; + // Find the requested stand auto stand = std::find_if( this->stands.cbegin(), this->stands.cend(), [airfield, identifier](const Stand& stand) -> bool { @@ -115,7 +123,7 @@ namespace UKControllerPlugin::Stands { } // Assign that stand - this->AssignStandToAircraft(callsign, *stand); + this->AssignStandToAircraft(callsign, *stand, Source::User); int standId = stand->id; auto callsignForRequest = callsign; @@ -192,7 +200,7 @@ namespace UKControllerPlugin::Stands { auto StandEventHandler::GetAssignedStandForCallsign(const std::string& callsign) const -> int { auto assignment = this->standAssignments.find(callsign); - return assignment == this->standAssignments.cend() ? noStandAssigned : assignment->second; + return assignment == this->standAssignments.cend() ? noStandAssigned : assignment->second.standId; } auto StandEventHandler::GetLastAirfield() const -> std::string @@ -217,7 +225,17 @@ namespace UKControllerPlugin::Stands { void StandEventHandler::SetAssignedStand(const std::string& callsign, int standId) { - this->standAssignments[callsign] = standId; + this->SetAssignedStand(callsign, standId, StandAssignment::Source::SystemAuto); + } + + void StandEventHandler::SetAssignedStand(const std::string& callsign, int standId, const std::string& source) + { + this->SetAssignedStand(callsign, standId, StandAssignment::FromString(source)); + } + + void StandEventHandler::SetAssignedStand(const std::string& callsign, int standId, StandAssignment::Source source) + { + this->standAssignments[callsign] = {standId, source}; } void StandEventHandler::StandSelected(int functionId, std::string context, RECT mousePosition) @@ -254,8 +272,8 @@ namespace UKControllerPlugin::Stands { auto mapLock = this->LockStandMap(); auto assignedStand = this->standAssignments.find(flightplan.GetCallsign()); if (assignedStand != this->standAssignments.cend() && - this->stands.find(assignedStand->second) != this->stands.cend()) { - startingText = this->stands.find(assignedStand->second)->identifier; + this->stands.find(assignedStand->second.standId) != this->stands.cend()) { + startingText = this->stands.find(assignedStand->second.standId)->identifier; } // Display the popup @@ -277,7 +295,13 @@ namespace UKControllerPlugin::Stands { auto StandEventHandler::GetTagItemDescription(int tagItemId) const -> std::string { - return "Assigned Stand"; + if (tagItemId == assignedStandTagItemId) { + return "Assigned Stand"; + } + if (tagItemId == standAssignmentSourceTagItemId) { + return "Stand Assignment Source"; + } + return ""; } /* @@ -286,14 +310,24 @@ namespace UKControllerPlugin::Stands { void StandEventHandler::SetTagItemData(UKControllerPlugin::Tag::TagData& tagData) { auto mapLock = this->LockStandMap(); - if (this->standAssignments.count(tagData.GetFlightplan().GetCallsign()) != 0) { - auto stand = this->stands.find(this->standAssignments.at(tagData.GetFlightplan().GetCallsign())); - if (stand == this->stands.cend()) { - return; - } + const auto& callsign = tagData.GetFlightplan().GetCallsign(); + if (!this->standAssignments.contains(callsign)) { + return; + } + const auto& assignment = this->standAssignments.at(callsign); + auto stand = this->stands.find(assignment.standId); + if (stand == this->stands.cend()) { + return; + } + + if (tagData.GetItemCode() == assignedStandTagItemId) { tagData.SetItemString(stand->identifier); + } else if (tagData.GetItemCode() == standAssignmentSourceTagItemId) { + tagData.SetItemString(GetAssignmentSourceShorthand(assignment.source)); } + + tagData.SetTagColour(this->colourConfiguration->GetColourForSource(assignment.source)); } auto StandEventHandler::AssignmentMessageValid(const nlohmann::json& message) const -> bool @@ -303,6 +337,37 @@ namespace UKControllerPlugin::Stands { this->stands.find(message.at("stand_id").get()) != this->stands.cend(); } + auto StandEventHandler::GetAssignmentSourceFromMessage(const nlohmann::json& message) -> StandAssignment::Source + { + using Source = StandAssignment::Source; + + if (message.contains("assignment_source") && message.at("assignment_source").is_string()) { + return StandAssignment::FromString(message.at("assignment_source").get()); + } + + return Source::Unknown; + } + + auto StandEventHandler::GetAssignmentSourceShorthand(StandAssignment::Source source) -> std::string + { + using enum UKControllerPlugin::Stands::StandAssignment::Source; + + switch (source) { + case Unknown: + return "UNK"; + case User: + return "USER"; + case ReservationAllocator: + return "RES"; + case VaaAllocator: + return "VAA"; + case SystemAuto: + return "AUTO"; + default: + return "UNK"; + } + } + auto StandEventHandler::UnassignmentMessageValid(const nlohmann::json& message) -> bool { return message.is_object() && message.contains("callsign") && message.at("callsign").is_string(); @@ -354,17 +419,23 @@ namespace UKControllerPlugin::Stands { EuroScopeCFlightPlanInterface& flightPlan, EuroScopeCRadarTargetInterface& radarTarget) { auto mapLock = this->LockStandMap(); - if (this->standAssignments.count(flightPlan.GetCallsign()) == 0) { + if (!this->standAssignments.contains(flightPlan.GetCallsign())) { + return; + } + + const auto& assignment = this->standAssignments.at(flightPlan.GetCallsign()); + const auto& stand = this->stands.find(assignment.standId); + if (stand == this->stands.cend()) { + LogWarning( + std::format("Assigned stand id {} not found for {}", assignment.standId, flightPlan.GetCallsign())); return; } - if (this->stands.find(this->standAssignments.at(flightPlan.GetCallsign()))->identifier == - flightPlan.GetAnnotation(this->annotationIndex)) { + if (stand->identifier == flightPlan.GetAnnotation(this->annotationIndex)) { return; } - flightPlan.AnnotateFlightStrip( - this->annotationIndex, this->stands.find(this->standAssignments.at(flightPlan.GetCallsign()))->identifier); + flightPlan.AnnotateFlightStrip(this->annotationIndex, stand->identifier); } void StandEventHandler::FlightPlanDisconnectEvent(EuroScopeCFlightPlanInterface& flightPlan) @@ -400,7 +471,8 @@ namespace UKControllerPlugin::Stands { this->AssignStandToAircraft( assignment->at("callsign").get(), - *this->stands.find(assignment->at("stand_id").get())); + *this->stands.find(assignment->at("stand_id").get()), + GetAssignmentSourceFromMessage(*assignment)); } LogInfo("Loaded " + std::to_string(this->standAssignments.size()) + " stand assignments"); } catch (ApiException&) { @@ -424,7 +496,8 @@ namespace UKControllerPlugin::Stands { this->AssignStandToAircraft( message.data.at("callsign").get(), - *this->stands.find(message.data.at("stand_id").get())); + *this->stands.find(message.data.at("stand_id").get()), + GetAssignmentSourceFromMessage(message.data)); } else if (message.event == "App\\Events\\StandUnassignedEvent") { // If a stand has been unassigned, unassign it here if (!UnassignmentMessageValid(message.data)) { @@ -455,16 +528,27 @@ namespace UKControllerPlugin::Stands { } void StandEventHandler::AssignStandToAircraft(const std::string& callsign, const Stand& stand) + { + using Source = StandAssignment::Source; + + this->AssignStandToAircraft(callsign, stand, Source::SystemAuto); + } + + void StandEventHandler::AssignStandToAircraft( + const std::string& callsign, const Stand& stand, StandAssignment::Source source) { this->AnnotateFlightStrip(callsign, stand.id); - this->standAssignments[callsign] = stand.id; + this->SetAssignedStand(callsign, stand.id, source); this->integrationEventHandler.SendEvent( std::make_shared(callsign, stand.airfieldCode, stand.identifier)); - LogInfo( - "Stand id " + std::to_string(stand.id) + "(" + stand.airfieldCode + "/" + stand.identifier + - ") " - "assigned to " + - callsign); + const auto logMessage = std::format( + "Stand id {} ({}/{}) assigned to {} (source: {})", + stand.id, + stand.airfieldCode, + stand.identifier, + callsign, + StandAssignment::ToString(source)); + LogInfo(logMessage); } auto StandEventHandler::ActionsToProcess() const -> std::vector { diff --git a/src/plugin/stands/StandEventHandler.h b/src/plugin/stands/StandEventHandler.h index 0c4981986..5b9523940 100644 --- a/src/plugin/stands/StandEventHandler.h +++ b/src/plugin/stands/StandEventHandler.h @@ -1,6 +1,7 @@ #pragma once #include "CompareStands.h" #include "Stand.h" +#include "StandAssignmentSource.h" #include "flightplan/FlightPlanEventHandlerInterface.h" #include "integration/ExternalMessageHandlerInterface.h" #include "integration/IntegrationActionProcessor.h" @@ -14,6 +15,7 @@ namespace UKControllerPlugin { } // namespace Api namespace Euroscope { class EuroscopePluginLoopbackInterface; + class UserSetting; } // namespace Euroscope namespace Ownership { class AirfieldServiceProviderCollection; @@ -24,6 +26,8 @@ namespace UKControllerPlugin { } // namespace UKControllerPlugin namespace UKControllerPlugin::Stands { + class StandColourConfiguration; + /* Handles events related to stands. */ @@ -38,6 +42,7 @@ namespace UKControllerPlugin::Stands { const UKControllerPlugin::Api::ApiInterface& api, TaskManager::TaskRunnerInterface& taskRunner, Euroscope::EuroscopePluginLoopbackInterface& plugin, + UKControllerPlugin::Euroscope::UserSetting* userSetting, Integration::OutboundIntegrationEventHandler& integrationEventHandler, std::shared_ptr ownership, std::set stands, @@ -64,6 +69,8 @@ namespace UKControllerPlugin::Stands { [[nodiscard]] auto GetLastAirfield() const -> std::string; void RemoveFlightStripAnnotation(const std::string& callsign) const; void SetAssignedStand(const std::string& callsign, int standId); + void SetAssignedStand(const std::string& callsign, int standId, const std::string& source); + void SetAssignedStand(const std::string& callsign, int standId, StandAssignment::Source source); void StandSelected(int functionId, std::string context, RECT); void DisplayStandAssignmentEditBox( UKControllerPlugin::Euroscope::EuroScopeCFlightPlanInterface& flightplan, @@ -93,8 +100,13 @@ namespace UKControllerPlugin::Stands { // No stand has been assigned to the aircraft inline static const int noStandAssigned = -1; + // Tag item IDs for stand display and source indication + inline static const int assignedStandTagItemId = 110; + inline static const int standAssignmentSourceTagItemId = 133; + private: void AssignStandToAircraft(const std::string& callsign, const Stand& stand); + void AssignStandToAircraft(const std::string& callsign, const Stand& stand, StandAssignment::Source source); [[nodiscard]] auto AssignStandInApi(const std::string& callsign, const std::string& airfield, const std::string& identifier) -> std::string; @@ -104,6 +116,9 @@ namespace UKControllerPlugin::Stands { void DoApiStandRequest(const std::string& callsign, const nlohmann::json data); void UnassignStandForAircraft(const std::string& callsign); [[nodiscard]] auto AssignmentMessageValid(const nlohmann::json& message) const -> bool; + [[nodiscard]] static auto GetAssignmentSourceFromMessage(const nlohmann::json& message) + -> StandAssignment::Source; + [[nodiscard]] static auto GetAssignmentSourceShorthand(StandAssignment::Source source) -> std::string; auto CanAssignStand(UKControllerPlugin::Euroscope::EuroScopeCFlightPlanInterface& flightplan) const -> bool; static auto UnassignmentMessageValid(const nlohmann::json& message) -> bool; auto @@ -126,8 +141,11 @@ namespace UKControllerPlugin::Stands { // All the stands we have std::set stands; - // The currently assigned stands and who they are assigned to - std::map standAssignments; + // The currently assigned stands and who they are assigned to, with source information + std::map> standAssignments; + + // Colour configuration for stand assignment sources + std::shared_ptr colourConfiguration; // Locks the stand assignments map to prevent concurrent edits std::recursive_mutex mapMutex; diff --git a/src/plugin/stands/StandModule.cpp b/src/plugin/stands/StandModule.cpp index d42f41c7f..2ae48fece 100644 --- a/src/plugin/stands/StandModule.cpp +++ b/src/plugin/stands/StandModule.cpp @@ -23,7 +23,7 @@ using UKControllerPlugin::Tag::TagFunction; namespace UKControllerPlugin::Stands { // The tag item id for assigned stand - const int assignedStandTagItemId = 110; + // Tag item IDs are defined in StandEventHandler const int openStandAssignmentPopupTagFunctionId = 9007; const int openStandAssignmentEditBoxTagFunctionId = 9008; @@ -39,6 +39,7 @@ namespace UKControllerPlugin::Stands { *container.api, *container.taskRunner, *container.plugin, + container.pluginUserSettingHandler.get(), *container.integrationModuleContainer->outboundMessageHandler, container.airfieldOwnership, stands, @@ -83,7 +84,8 @@ namespace UKControllerPlugin::Stands { // Assign to handlers container.flightplanHandler->RegisterHandler(eventHandler); - container.tagHandler->RegisterTagItem(assignedStandTagItemId, eventHandler); + container.tagHandler->RegisterTagItem(StandEventHandler::assignedStandTagItemId, eventHandler); + container.tagHandler->RegisterTagItem(StandEventHandler::standAssignmentSourceTagItemId, eventHandler); container.pushEventProcessors->AddProcessor(eventHandler); container.externalEventHandler->AddHandler(eventHandler); container.integrationModuleContainer->inboundMessageHandler->AddProcessor(eventHandler); diff --git a/test/plugin/ecfmp/AircraftFlowMeasureMapTest.cpp b/test/plugin/ecfmp/AircraftFlowMeasureMapTest.cpp index cfab2c51c..84748b5b0 100644 --- a/test/plugin/ecfmp/AircraftFlowMeasureMapTest.cpp +++ b/test/plugin/ecfmp/AircraftFlowMeasureMapTest.cpp @@ -435,4 +435,4 @@ namespace UKControllerPluginTest::ECFMP { EXPECT_EQ(1, map.GetFlowMeasuresForCallsign("BAW456").size()); EXPECT_EQ(mockFlowMeasure2, *map.GetFlowMeasuresForCallsign("BAW456").begin()); } -} // namespace UKControllerPluginTest::ECFMP +} // namespace UKControllerPluginTest::ECFMP \ No newline at end of file diff --git a/test/plugin/stands/StandEventHandlerTest.cpp b/test/plugin/stands/StandEventHandlerTest.cpp index 2bdf46e72..6e17a7c6e 100644 --- a/test/plugin/stands/StandEventHandlerTest.cpp +++ b/test/plugin/stands/StandEventHandlerTest.cpp @@ -1,8 +1,13 @@ #include "stands/StandEventHandler.h" +#include "stands/StandColourConfiguration.h" +#include "stands/StandAssignmentSource.h" +#include +#include #include "tag/TagData.h" #include "api/ApiException.h" #include "controller/ActiveCallsign.h" #include "controller/ControllerPosition.h" +#include "euroscope/UserSetting.h" #include "ownership/AirfieldServiceProviderCollection.h" #include "ownership/ServiceProvision.h" #include "stands/StandUnassignedMessage.h" @@ -15,6 +20,7 @@ using ::testing::Return; using ::testing::Test; using ::testing::Throw; using UKControllerPlugin::Api::ApiException; +using UKControllerPlugin::Euroscope::UserSetting; using UKControllerPlugin::Integration::InboundMessage; using UKControllerPlugin::Integration::MessageType; using UKControllerPlugin::Plugin::PopupMenuItem; @@ -23,6 +29,8 @@ using UKControllerPlugin::Push::PushEventSubscription; using UKControllerPlugin::Stands::CompareStands; using UKControllerPlugin::Stands::Stand; using UKControllerPlugin::Stands::StandAssignedMessage; +using UKControllerPlugin::Stands::StandAssignment; +using UKControllerPlugin::Stands::StandColourConfiguration; using UKControllerPlugin::Stands::StandEventHandler; using UKControllerPlugin::Stands::StandUnassignedMessage; using UKControllerPlugin::Tag::TagData; @@ -31,6 +39,7 @@ using UKControllerPluginTest::Euroscope::MockEuroScopeCControllerInterface; using UKControllerPluginTest::Euroscope::MockEuroScopeCFlightPlanInterface; using UKControllerPluginTest::Euroscope::MockEuroScopeCRadarTargetInterface; using UKControllerPluginTest::Euroscope::MockEuroscopePluginLoopbackInterface; +using UKControllerPluginTest::Euroscope::MockUserSettingProviderInterface; using UKControllerPluginTest::Integration::MockOutboundIntegrationEventHandler; using UKControllerPluginTest::TaskManager::MockTaskRunnerInterface; @@ -40,18 +49,27 @@ namespace UKControllerPluginTest { class StandEventHandlerTest : public ApiTestCase { public: + [[nodiscard]] static auto + MakeActiveCallsign(const UKControllerPlugin::Controller::ControllerPosition& controller, bool isUser) + -> std::shared_ptr + { + return std::make_shared( + "LON_S_CTR", "Test", controller, isUser); + } + StandEventHandlerTest() : controller(2, "LON_S_CTR", 129.420, std::vector{"EGKK"}, true, false, true), - userCallsign(std::make_shared( - "LON_S_CTR", "Test", controller, true)), - notUserCallsign(std::make_shared( - "LON_S_CTR", "Test", controller, false)), + userCallsign(MakeActiveCallsign(controller, true)), + notUserCallsign(MakeActiveCallsign(controller, false)), airfieldOwnership( std::make_shared()), + userSetting(mockUserSettingProvider), + colourConfiguration(std::make_shared(userSetting)), tagData(flightplan, radarTarget, 110, 1, itemString, &euroscopeColourCode, &tagColour, &fontSize), - handler(api, taskRunner, plugin, mockIntegration, airfieldOwnership, GetStands(), 1) + handler(api, taskRunner, plugin, &userSetting, mockIntegration, airfieldOwnership, GetStands(), 1) { ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); + ON_CALL(this->mockUserSettingProvider, KeyExists(_)).WillByDefault(Return(false)); this->mockController = std::make_shared>(); } @@ -65,6 +83,203 @@ namespace UKControllerPluginTest { return stands; } + void SetAssignedStandWithSource(int standId, StandAssignment::Source source) + { + this->handler.SetAssignedStand("BAW123", standId, source); + } + + auto CreateSourceTagData() -> TagData + { + return TagData( + this->flightplan, + this->radarTarget, + StandEventHandler::standAssignmentSourceTagItemId, + 1, + this->itemString, + &this->euroscopeColourCode, + &this->tagColour, + &this->fontSize); + } + + void ExpectSourceTagItemShorthand(StandAssignment::Source source, const std::string& expectedShorthand) + { + this->SetAssignedStandWithSource(1, source); + auto sourceTagData = this->CreateSourceTagData(); + this->handler.SetTagItemData(sourceTagData); + EXPECT_EQ(expectedShorthand, sourceTagData.GetItemString()); + } + + void ExpectTagItem110ColourForSource(StandAssignment::Source source) + { + this->SetAssignedStandWithSource(3, source); + COLORREF expectedColour = this->colourConfiguration->GetColourForSource(source); + this->handler.SetTagItemData(this->tagData); + EXPECT_EQ(expectedColour, this->tagData.GetTagColour()); + } + + void ExpectSourceTagItemColourForSource(StandAssignment::Source source) + { + this->SetAssignedStandWithSource(3, source); + COLORREF expectedColour = this->colourConfiguration->GetColourForSource(source); + auto sourceTagData = this->CreateSourceTagData(); + this->handler.SetTagItemData(sourceTagData); + EXPECT_EQ(expectedColour, sourceTagData.GetTagColour()); + } + + // Sets IsTracked, IsTrackedByUser, IsVatsimRecognisedController, + // GetOrigin("EGKK") and GetDistanceFromOrigin on the fixture flightplan. + void SetupFlightplan(bool tracked, bool trackedByUser, bool vatsim = true, double distance = 4) + { + ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(tracked)); + ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(trackedByUser)); + ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); + ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(vatsim)); + ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); + ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(distance)); + } + + // Creates a NiceMock flightplan wired up as plugin.GetSelectedFlightplan(). + [[nodiscard]] auto MakeSelectedFlightplan(bool tracked = false, bool trackedByUser = false) + -> std::shared_ptr> + { + auto fp = std::make_shared>(); + ON_CALL(*fp, IsTracked()).WillByDefault(Return(tracked)); + ON_CALL(*fp, IsTrackedByUser()).WillByDefault(Return(trackedByUser)); + ON_CALL(*fp, GetCallsign()).WillByDefault(Return("BAW123")); + ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(fp)); + return fp; + } + + // Calls handler.ProcessAction capturing success/failure into the provided refs. + void CallProcessAction( + std::shared_ptr message, + bool& successCalled, + std::vector& failureMessages) + { + this->handler.ProcessAction( + message, + [&successCalled]() { successCalled = true; }, + [&failureMessages](std::vector msgs) { failureMessages = std::move(msgs); }); + } + + // Creates a mock flightplan registered for "BAW123", sets up the + // AnnotateFlightStrip(3,"1L") expectation, and expects the integration event. + [[nodiscard]] auto MakeSyncFlightplanForBaw123Stand1() + -> std::shared_ptr> + { + auto fp = std::make_shared>(); + ON_CALL(this->plugin, GetFlightplanForCallsign("BAW123")).WillByDefault(Return(fp)); + EXPECT_CALL(*fp, AnnotateFlightStrip(3, "1L")).Times(1); + auto expectedMsg = std::make_shared("BAW123", "EGKK", "1L"); + EXPECT_CALL(this->mockIntegration, SendEvent(MatchMessageInterface(expectedMsg))).Times(1); + return fp; + } + + [[nodiscard]] static auto AllSources() -> std::array + { + using enum UKControllerPlugin::Stands::StandAssignment::Source; + + return {User, ReservationAllocator, VaaAllocator, SystemAuto}; + } + + [[nodiscard]] static auto MakeInboundMessage(const std::string& type, const nlohmann::json& data) + { + return InboundMessage::FromJson( + nlohmann::json{{"type", type}, {"version", 1}, {"id", "foo"}, {"data", data}}); + } + + void SetProviderForAirfield( + const std::string& airfield, + UKControllerPlugin::Ownership::ServiceType serviceType = + UKControllerPlugin::Ownership::ServiceType::Delivery) + { + std::vector> provisions; + provisions.push_back( + std::make_shared(serviceType, userCallsign)); + airfieldOwnership->SetProvidersForAirfield(airfield, provisions); + } + + void SetupAutoStandSelectionMenu(const std::string& destination = "EGGW", double distance = 1.0) + { + SetupFlightplan(false, false, true, distance); + ON_CALL(this->flightplan, GetDestination()).WillByDefault(Return(destination)); + this->handler.DisplayStandSelectionMenu(this->flightplan, this->radarTarget, "", {0, 0}); + } + + [[nodiscard]] auto MakeSelectedFlightplanForAutoRequest( + const std::string& destination, double distanceFromOrigin, const std::string& aircraftType = "") + -> std::shared_ptr> + { + auto pluginReturnedFp = std::make_shared>(); + + ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(true)); + ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(true)); + ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); + ON_CALL(*pluginReturnedFp, GetOrigin()).WillByDefault(Return("EGKK")); + ON_CALL(*pluginReturnedFp, GetDestination()).WillByDefault(Return(destination)); + ON_CALL(*pluginReturnedFp, GetDistanceFromOrigin()).WillByDefault(Return(distanceFromOrigin)); + + if (!aircraftType.empty()) { + ON_CALL(*pluginReturnedFp, GetAircraftType()).WillByDefault(Return(aircraftType)); + } + + ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); + return pluginReturnedFp; + } + + void SetupRadarTargetForCallsign(const std::string& callsign, double latitude = 123, double longitude = 456) + { + auto pluginReturnedRt = std::make_shared>(); + + EuroScopePlugIn::CPosition position; + position.m_Latitude = latitude; + position.m_Longitude = longitude; + ON_CALL(*pluginReturnedRt, GetPosition()).WillByDefault(Return(position)); + + ON_CALL(this->plugin, GetRadarTargetForCallsign(callsign)).WillByDefault(Return(pluginReturnedRt)); + } + + void SelectAutoAndExpectNoStandAssigned() + { + this->handler.StandSelected(1, "AUTO", {}); + this->AwaitApiCallCompletion(); + EXPECT_EQ(this->handler.noStandAssigned, this->handler.GetAssignedStandForCallsign("BAW123")); + } + + void ExpectProcessActionFailureNoAssignment( + const std::shared_ptr& message) + { + bool successCalled = false; + std::vector failureMessages; + CallProcessAction(message, successCalled, failureMessages); + + EXPECT_FALSE(successCalled); + EXPECT_FALSE(failureMessages.empty()); + EXPECT_EQ(this->handler.noStandAssigned, this->handler.GetAssignedStandForCallsign("BAW123")); + } + + [[nodiscard]] static auto DepartureStandRequestBody() -> nlohmann::json + { + return nlohmann::json{ + {"callsign", "BAW123"}, + {"departure_airfield", "EGKK"}, + {"assignment_type", "departure"}, + {"latitude", 123}, + {"longitude", 456}, + }; + } + + [[nodiscard]] static auto ArrivalStandRequestBody() -> nlohmann::json + { + return nlohmann::json{ + {"callsign", "BAW123"}, + {"departure_airfield", "EGKK"}, + {"arrival_airfield", "EGGW"}, + {"assignment_type", "arrival"}, + {"aircraft_type", "B738"}, + }; + } + double fontSize = 24.1; COLORREF tagColour = RGB(255, 255, 255); int euroscopeColourCode = EuroScopePlugIn::TAG_COLOR_ASSUMED; @@ -76,10 +291,13 @@ namespace UKControllerPluginTest { NiceMock flightplan; NiceMock radarTarget; std::shared_ptr> mockController; + NiceMock mockUserSettingProvider; UKControllerPlugin::Controller::ControllerPosition controller; std::shared_ptr userCallsign; std::shared_ptr notUserCallsign; std::shared_ptr airfieldOwnership; + UserSetting userSetting; + std::shared_ptr colourConfiguration; TagData tagData; StandEventHandler handler; }; @@ -107,6 +325,48 @@ namespace UKControllerPluginTest { EXPECT_EQ("Foooooo", this->tagData.GetItemString()); } + TEST_F(StandEventHandlerTest, ItReturnsDescriptionForSourceTagItem) + { + EXPECT_EQ( + "Stand Assignment Source", + this->handler.GetTagItemDescription(StandEventHandler::standAssignmentSourceTagItemId)); + } + + TEST_F(StandEventHandlerTest, ItReturnsSourceShorthandForSourceTagItem) + { + const auto sources = AllSources(); + const std::array expectedShorthand = {"USER", "RES", "VAA", "AUTO"}; + + for (size_t i = 0; i < std::size(sources); ++i) { + this->ExpectSourceTagItemShorthand(sources[i], expectedShorthand[i]); + } + } + + TEST_F(StandEventHandlerTest, ItReturnsNothingForSourceTagItemIfStandNotAssigned) + { + auto sourceTagData = this->CreateSourceTagData(); + this->handler.SetTagItemData(sourceTagData); + EXPECT_EQ("Foooooo", sourceTagData.GetItemString()); + } + + TEST_F(StandEventHandlerTest, TagItem110UsesSourceColours) + { + const auto sources = AllSources(); + + for (const auto& source : sources) { + this->ExpectTagItem110ColourForSource(source); + } + } + + TEST_F(StandEventHandlerTest, SourceTagItemUsesSourceColours) + { + const auto sources = AllSources(); + + for (const auto& source : sources) { + this->ExpectSourceTagItemColourForSource(source); + } + } + TEST_F(StandEventHandlerTest, ItSubscribesToChannels) { std::set expectedSubscriptions; @@ -124,15 +384,7 @@ namespace UKControllerPluginTest { {"stand_id", 1}, }}; - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(this->plugin, GetFlightplanForCallsign("BAW123")).WillByDefault(Return(pluginReturnedFp)); - - EXPECT_CALL(*pluginReturnedFp, AnnotateFlightStrip(3, "1L")).Times(1); - - auto expectedMessage = std::make_shared("BAW123", "EGKK", "1L"); - EXPECT_CALL(this->mockIntegration, SendEvent(MatchMessageInterface(expectedMessage))).Times(1); + auto pluginReturnedFp = MakeSyncFlightplanForBaw123Stand1(); this->handler.ProcessPushEvent(message); ASSERT_EQ(1, this->handler.GetAssignedStandForCallsign("BAW123")); @@ -365,15 +617,7 @@ namespace UKControllerPluginTest { }); assignments.push_back(nlohmann::json::object()); - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(this->plugin, GetFlightplanForCallsign("BAW123")).WillByDefault(Return(pluginReturnedFp)); - - EXPECT_CALL(*pluginReturnedFp, AnnotateFlightStrip(3, "1L")).Times(1); - - auto expectedMessage = std::make_shared("BAW123", "EGKK", "1L"); - EXPECT_CALL(this->mockIntegration, SendEvent(MatchMessageInterface(expectedMessage))).Times(1); + auto pluginReturnedFp = MakeSyncFlightplanForBaw123Stand1(); EXPECT_CALL(this->api, GetAssignedStands()).Times(1).WillOnce(Return(assignments)); @@ -393,15 +637,7 @@ namespace UKControllerPluginTest { {"stand_id", 2}, }); - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(this->plugin, GetFlightplanForCallsign("BAW123")).WillByDefault(Return(pluginReturnedFp)); - - EXPECT_CALL(*pluginReturnedFp, AnnotateFlightStrip(3, "1L")).Times(1); - - auto expectedMessage = std::make_shared("BAW123", "EGKK", "1L"); - EXPECT_CALL(this->mockIntegration, SendEvent(MatchMessageInterface(expectedMessage))).Times(1); + auto pluginReturnedFp = MakeSyncFlightplanForBaw123Stand1(); EXPECT_CALL(this->api, GetAssignedStands()).Times(1).WillOnce(Return(assignments)); @@ -422,15 +658,7 @@ namespace UKControllerPluginTest { {"stand_id", 2}, }); - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(this->plugin, GetFlightplanForCallsign("BAW123")).WillByDefault(Return(pluginReturnedFp)); - - EXPECT_CALL(*pluginReturnedFp, AnnotateFlightStrip(3, "1L")).Times(1); - - auto expectedMessage = std::make_shared("BAW123", "EGKK", "1L"); - EXPECT_CALL(this->mockIntegration, SendEvent(MatchMessageInterface(expectedMessage))).Times(1); + auto pluginReturnedFp = MakeSyncFlightplanForBaw123Stand1(); EXPECT_CALL(this->api, GetAssignedStands()).Times(1).WillOnce(Return(assignments)); @@ -450,15 +678,7 @@ namespace UKControllerPluginTest { {"callsign", "VIR245"}, }); - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(this->plugin, GetFlightplanForCallsign("BAW123")).WillByDefault(Return(pluginReturnedFp)); - - EXPECT_CALL(*pluginReturnedFp, AnnotateFlightStrip(3, "1L")).Times(1); - - auto expectedMessage = std::make_shared("BAW123", "EGKK", "1L"); - EXPECT_CALL(this->mockIntegration, SendEvent(MatchMessageInterface(expectedMessage))).Times(1); + auto pluginReturnedFp = MakeSyncFlightplanForBaw123Stand1(); EXPECT_CALL(this->api, GetAssignedStands()).Times(1).WillOnce(Return(assignments)); @@ -479,15 +699,7 @@ namespace UKControllerPluginTest { {"stand_id", "2"}, }); - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(this->plugin, GetFlightplanForCallsign("BAW123")).WillByDefault(Return(pluginReturnedFp)); - - EXPECT_CALL(*pluginReturnedFp, AnnotateFlightStrip(3, "1L")).Times(1); - - auto expectedMessage = std::make_shared("BAW123", "EGKK", "1L"); - EXPECT_CALL(this->mockIntegration, SendEvent(MatchMessageInterface(expectedMessage))).Times(1); + auto pluginReturnedFp = MakeSyncFlightplanForBaw123Stand1(); EXPECT_CALL(this->api, GetAssignedStands()).Times(1).WillOnce(Return(assignments)); @@ -508,15 +720,7 @@ namespace UKControllerPluginTest { {"stand_id", -55}, }); - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(this->plugin, GetFlightplanForCallsign("BAW123")).WillByDefault(Return(pluginReturnedFp)); - - EXPECT_CALL(*pluginReturnedFp, AnnotateFlightStrip(3, "1L")).Times(1); - - auto expectedMessage = std::make_shared("BAW123", "EGKK", "1L"); - EXPECT_CALL(this->mockIntegration, SendEvent(MatchMessageInterface(expectedMessage))).Times(1); + auto pluginReturnedFp = MakeSyncFlightplanForBaw123Stand1(); EXPECT_CALL(this->api, GetAssignedStands()).Times(1).WillOnce(Return(assignments)); @@ -569,19 +773,7 @@ namespace UKControllerPluginTest { menuItemStandNone.fixedPosition = true; // Tracked by user - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(true)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(4)); + SetupFlightplan(true, true); RECT expectedArea = {0, 0, 400, 600}; EXPECT_CALL(this->plugin, TriggerPopupList(RectEq(expectedArea), "Assign Stand", 2)).Times(1); @@ -624,22 +816,9 @@ namespace UKControllerPluginTest { menuItemStandNone.fixedPosition = true; // Not tracked by anyone - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - + SetupFlightplan(false, false, true, 8); ON_CALL(this->flightplan, GetDestination()).WillByDefault(Return("EGLL")); - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(8)); - RECT expectedArea = {0, 0, 400, 600}; EXPECT_CALL(this->plugin, TriggerPopupList(RectEq(expectedArea), "Assign Stand", 2)).Times(1); @@ -655,19 +834,7 @@ namespace UKControllerPluginTest { TEST_F(StandEventHandlerTest, ItDoesntTriggerTheSelectionMenuIfFlightplanTrackedBySomeoneElse) { // Not tracked by user - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(4)); + SetupFlightplan(true, false); RECT expectedArea = {0, 0, 400, 600}; EXPECT_CALL(this->plugin, TriggerPopupList(RectEq(expectedArea), "Assign Stand", 2)).Times(0); @@ -680,19 +847,7 @@ namespace UKControllerPluginTest { TEST_F(StandEventHandlerTest, ItDoesntTriggerTheSelectionMenuIfNotVatsimRecognisedController) { // Not tracked by user - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(false)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(4)); + SetupFlightplan(false, false, false); RECT expectedArea = {0, 0, 400, 600}; EXPECT_CALL(this->plugin, TriggerPopupList(RectEq(expectedArea), "Assign Stand", 2)).Times(0); @@ -705,19 +860,7 @@ namespace UKControllerPluginTest { TEST_F(StandEventHandlerTest, ItTriggersTheStandEditBoxWithDepartureAirportIfWithinLimit) { // Tracked by user - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(true)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(4)); + SetupFlightplan(true, true); RECT expectedArea = {0, 0, 80, 25}; EXPECT_CALL(this->plugin, ShowTextEditPopup(RectEq(expectedArea), 1, "")).Times(1); @@ -729,22 +872,9 @@ namespace UKControllerPluginTest { TEST_F(StandEventHandlerTest, ItTriggersTheStandEditBoxWithArrivalAirportIfNotCloseToDeparture) { // Not tracked by anyone - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - + SetupFlightplan(false, false, true, 8); ON_CALL(this->flightplan, GetDestination()).WillByDefault(Return("EGLL")); - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(8)); - RECT expectedArea = {0, 0, 80, 25}; EXPECT_CALL(this->plugin, ShowTextEditPopup(RectEq(expectedArea), 1, "")).Times(1); @@ -755,19 +885,7 @@ namespace UKControllerPluginTest { TEST_F(StandEventHandlerTest, ItDoesntTriggerTheEditBoxIfFlightplanTrackedBySomeoneElse) { // Not tracked by user - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(4)); + SetupFlightplan(true, false); EXPECT_CALL(this->plugin, ShowTextEditPopup(_, _, _)).Times(0); @@ -778,19 +896,7 @@ namespace UKControllerPluginTest { TEST_F(StandEventHandlerTest, ItDoesntTriggerTheEditBoxIfNotVatsimRecognisedController) { // Not tracked by user - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(false)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(4)); + SetupFlightplan(true, false, false); EXPECT_CALL(this->plugin, ShowTextEditPopup(_, _, _)).Times(0); @@ -803,22 +909,9 @@ namespace UKControllerPluginTest { this->handler.SetAssignedStand("BAW123", 1); // Not tracked by anyone - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - + SetupFlightplan(false, false, true, 8); ON_CALL(this->flightplan, GetDestination()).WillByDefault(Return("EGLL")); - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(8)); - RECT expectedArea = {0, 0, 80, 25}; EXPECT_CALL(this->plugin, ShowTextEditPopup(RectEq(expectedArea), 1, "1L")).Times(1); @@ -828,68 +921,26 @@ namespace UKControllerPluginTest { TEST_F(StandEventHandlerTest, ItDoesntMakeAStandAssignmentRequestIfFlightplanTrackedBySomeoneElse) { // Trigger the menu first to set the last airport - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(true)); + SetupFlightplan(true, false); - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); + this->handler.DisplayStandSelectionMenu(this->flightplan, this->radarTarget, "", {0, 0}); - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); + auto pluginReturnedFp = MakeSelectedFlightplan(true, false); - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); + EXPECT_CALL(this->api, AssignStandToAircraft("BAW123", _)).Times(0); - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); + this->handler.StandSelected(1, "55", {}); + EXPECT_EQ(this->handler.noStandAssigned, this->handler.GetAssignedStandForCallsign("BAW123")); + } - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(4)); + TEST_F(StandEventHandlerTest, ItDoesntMakeAStandAssignmentRequestIfNotVatsimRecognisedController) + { + // Trigger the menu first to set the last airport + SetupFlightplan(false, false, false); this->handler.DisplayStandSelectionMenu(this->flightplan, this->radarTarget, "", {0, 0}); - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(true)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); - - EXPECT_CALL(this->api, AssignStandToAircraft("BAW123", _)).Times(0); - - this->handler.StandSelected(1, "55", {}); - EXPECT_EQ(this->handler.noStandAssigned, this->handler.GetAssignedStandForCallsign("BAW123")); - } - - TEST_F(StandEventHandlerTest, ItDoesntMakeAStandAssignmentRequestIfNotVatsimRecognisedController) - { - // Trigger the menu first to set the last airport - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(false)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(4)); - - this->handler.DisplayStandSelectionMenu(this->flightplan, this->radarTarget, "", {0, 0}); - - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(true)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); + auto pluginReturnedFp = MakeSelectedFlightplan(true, false); EXPECT_CALL(this->api, AssignStandToAircraft("BAW123", _)).Times(0); @@ -903,16 +954,7 @@ namespace UKControllerPluginTest { ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); + auto pluginReturnedFp = MakeSelectedFlightplan(); EXPECT_CALL(this->api, AssignStandToAircraft("BAW123", 2)).Times(0); @@ -923,32 +965,11 @@ namespace UKControllerPluginTest { TEST_F(StandEventHandlerTest, ItMakesAStandAssignmentRequestWhenStandSelected) { // Trigger the menu first to set the last airport - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(4)); + SetupFlightplan(false, false); this->handler.DisplayStandSelectionMenu(this->flightplan, this->radarTarget, "", {0, 0}); - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); + auto pluginReturnedFp = MakeSelectedFlightplan(); ON_CALL(this->plugin, GetFlightplanForCallsign("BAW123")).WillByDefault(Return(pluginReturnedFp)); @@ -966,32 +987,11 @@ namespace UKControllerPluginTest { TEST_F(StandEventHandlerTest, StandAssignmentsAreCaseInsensitive) { // Trigger the menu first to set the last airport - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(4)); + SetupFlightplan(false, false); this->handler.DisplayStandSelectionMenu(this->flightplan, this->radarTarget, "", {0, 0}); - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); + auto pluginReturnedFp = MakeSelectedFlightplan(); ON_CALL(this->plugin, GetFlightplanForCallsign("BAW123")).WillByDefault(Return(pluginReturnedFp)); @@ -1009,32 +1009,11 @@ namespace UKControllerPluginTest { TEST_F(StandEventHandlerTest, ItHandlesApiExceptionOnStandAssignment) { // Trigger the menu first to set the last airport - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(4)); + SetupFlightplan(false, false); this->handler.DisplayStandSelectionMenu(this->flightplan, this->radarTarget, "", {0, 0}); - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); + auto pluginReturnedFp = MakeSelectedFlightplan(); ON_CALL(this->plugin, GetFlightplanForCallsign("BAW123")).WillByDefault(Return(pluginReturnedFp)); @@ -1052,32 +1031,11 @@ namespace UKControllerPluginTest { TEST_F(StandEventHandlerTest, ItDoesntAssignStandFromTheWrongAirfield) { // Trigger the menu first to set the last airport - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(4)); + SetupFlightplan(false, false); this->handler.DisplayStandSelectionMenu(this->flightplan, this->radarTarget, "", {0, 0}); - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); + auto pluginReturnedFp = MakeSelectedFlightplan(); EXPECT_CALL(this->api, AssignStandToAircraft("BAW123", _)).Times(0); @@ -1090,32 +1048,11 @@ namespace UKControllerPluginTest { this->handler.SetAssignedStand("BAW123", 2); // Trigger the menu first to set the last airport - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(4)); + SetupFlightplan(false, false); this->handler.DisplayStandSelectionMenu(this->flightplan, this->radarTarget, "", {0, 0}); - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); + auto pluginReturnedFp = MakeSelectedFlightplan(); ON_CALL(this->plugin, GetFlightplanForCallsign("BAW123")).WillByDefault(Return(pluginReturnedFp)); @@ -1135,32 +1072,11 @@ namespace UKControllerPluginTest { this->handler.SetAssignedStand("BAW123", 2); // Trigger the menu first to set the last airport - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(4)); + SetupFlightplan(false, false); this->handler.DisplayStandSelectionMenu(this->flightplan, this->radarTarget, "", {0, 0}); - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); + auto pluginReturnedFp = MakeSelectedFlightplan(); ON_CALL(this->plugin, GetFlightplanForCallsign("BAW123")).WillByDefault(Return(pluginReturnedFp)); @@ -1180,32 +1096,11 @@ namespace UKControllerPluginTest { this->handler.SetAssignedStand("BAW123", 2); // Trigger the menu first to set the last airport - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(4)); + SetupFlightplan(false, false); this->handler.DisplayStandSelectionMenu(this->flightplan, this->radarTarget, "", {0, 0}); - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); + auto pluginReturnedFp = MakeSelectedFlightplan(); EXPECT_CALL(this->api, DeleteStandAssignmentForAircraft("BAW123")) .Times(1) @@ -1223,16 +1118,7 @@ namespace UKControllerPluginTest { ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); + auto pluginReturnedFp = MakeSelectedFlightplan(); EXPECT_CALL(this->api, DeleteStandAssignmentForAircraft("BAW123")).Times(0); @@ -1243,32 +1129,11 @@ namespace UKControllerPluginTest { TEST_F(StandEventHandlerTest, ItDoesntMakeDeletionRequestIfNoStandAssigned) { // Trigger the menu first to set the last airport - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(4)); + SetupFlightplan(false, false); this->handler.DisplayStandSelectionMenu(this->flightplan, this->radarTarget, "", {0, 0}); - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); + auto pluginReturnedFp = MakeSelectedFlightplan(); EXPECT_CALL(this->api, DeleteStandAssignmentForAircraft(_)).Times(0); @@ -1281,32 +1146,11 @@ namespace UKControllerPluginTest { this->handler.SetAssignedStand("BAW123", 2); // Trigger the menu first to set the last airport - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(4)); + SetupFlightplan(false, false); this->handler.DisplayStandSelectionMenu(this->flightplan, this->radarTarget, "", {0, 0}); - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(true)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); + auto pluginReturnedFp = MakeSelectedFlightplan(true, false); EXPECT_CALL(this->api, DeleteStandAssignmentForAircraft(_)).Times(0); @@ -1319,32 +1163,11 @@ namespace UKControllerPluginTest { this->handler.SetAssignedStand("BAW123", 2); // Trigger the menu first to set the last airport - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(false)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(4)); + SetupFlightplan(false, false, false); this->handler.DisplayStandSelectionMenu(this->flightplan, this->radarTarget, "", {0, 0}); - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); + auto pluginReturnedFp = MakeSelectedFlightplan(); EXPECT_CALL(this->api, DeleteStandAssignmentForAircraft(_)).Times(0); @@ -1410,16 +1233,7 @@ namespace UKControllerPluginTest { ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); + auto pluginReturnedFp = MakeSelectedFlightplan(); ON_CALL(this->plugin, GetFlightplanForCallsign("BAW123")).WillByDefault(Return(pluginReturnedFp)); @@ -1439,16 +1253,7 @@ namespace UKControllerPluginTest { ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); + auto pluginReturnedFp = MakeSelectedFlightplan(); ON_CALL(this->plugin, GetFlightplanForCallsign("BAW123")).WillByDefault(Return(pluginReturnedFp)); @@ -1477,16 +1282,7 @@ namespace UKControllerPluginTest { ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); + auto pluginReturnedFp = MakeSelectedFlightplan(); ON_CALL(this->plugin, GetFlightplanForCallsign("BAW123")).WillByDefault(Return(pluginReturnedFp)); @@ -1506,17 +1302,13 @@ namespace UKControllerPluginTest { TEST_F(StandEventHandlerTest, ItUnassignsStandFromIntegrationMessage) { this->handler.SetAssignedStand("BAW123", 3); - auto message = InboundMessage::FromJson(nlohmann::json{ - {"type", "unassign_stand"}, {"version", 1}, {"id", "foo"}, {"data", {{"callsign", "BAW123"}}}}); + auto message = MakeInboundMessage("unassign_stand", {{"callsign", "BAW123"}}); EXPECT_CALL(this->api, DeleteStandAssignmentForAircraft("BAW123")).Times(1); bool successCalled = false; std::vector failureMessages; - this->handler.ProcessAction( - message, - [&successCalled]() { successCalled = true; }, - [&failureMessages](std::vector messages) { failureMessages = std::move(messages); }); + CallProcessAction(message, successCalled, failureMessages); EXPECT_TRUE(successCalled); EXPECT_TRUE(failureMessages.empty()); @@ -1525,17 +1317,13 @@ namespace UKControllerPluginTest { TEST_F(StandEventHandlerTest, ItDoesntUnassignStandFromAircraftFromMessageIfNothingToDo) { - auto message = InboundMessage::FromJson(nlohmann::json{ - {"type", "unassign_stand"}, {"version", 1}, {"id", "foo"}, {"data", {{"callsign", "BAW123"}}}}); + auto message = MakeInboundMessage("unassign_stand", {{"callsign", "BAW123"}}); EXPECT_CALL(this->api, DeleteStandAssignmentForAircraft("BAW123")).Times(0); bool successCalled = false; std::vector failureMessages; - this->handler.ProcessAction( - message, - [&successCalled]() { successCalled = true; }, - [&failureMessages](std::vector messages) { failureMessages = std::move(messages); }); + CallProcessAction(message, successCalled, failureMessages); EXPECT_TRUE(successCalled); EXPECT_TRUE(failureMessages.empty()); @@ -1545,15 +1333,11 @@ namespace UKControllerPluginTest { TEST_F(StandEventHandlerTest, ItDoesntUnassignStandFromAircraftIfBadCallsign) { this->handler.SetAssignedStand("BAW123", 3); - auto message = InboundMessage::FromJson(nlohmann::json{ - {"type", "unassign_stand"}, {"version", 1}, {"id", "foo"}, {"data", {{"callsign", 123}}}}); + auto message = MakeInboundMessage("unassign_stand", {{"callsign", 123}}); bool successCalled = false; std::vector failureMessages; - this->handler.ProcessAction( - message, - [&successCalled]() { successCalled = true; }, - [&failureMessages](std::vector messages) { failureMessages = std::move(messages); }); + CallProcessAction(message, successCalled, failureMessages); EXPECT_FALSE(successCalled); EXPECT_FALSE(failureMessages.empty()); @@ -1563,15 +1347,11 @@ namespace UKControllerPluginTest { TEST_F(StandEventHandlerTest, ItDoesntUnassignStandFromAircraftIfNoCallsign) { this->handler.SetAssignedStand("BAW123", 3); - auto message = InboundMessage::FromJson(nlohmann::json{ - {"type", "unassign_stand"}, {"version", 1}, {"id", "foo"}, {"data", nlohmann::json::object()}}); + auto message = MakeInboundMessage("unassign_stand", nlohmann::json::object()); bool successCalled = false; std::vector failureMessages; - this->handler.ProcessAction( - message, - [&successCalled]() { successCalled = true; }, - [&failureMessages](std::vector messages) { failureMessages = std::move(messages); }); + CallProcessAction(message, successCalled, failureMessages); EXPECT_FALSE(successCalled); EXPECT_FALSE(failureMessages.empty()); @@ -1584,16 +1364,7 @@ namespace UKControllerPluginTest { ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); + auto pluginReturnedFp = MakeSelectedFlightplan(); ON_CALL(this->plugin, GetFlightplanForCallsign("BAW123")).WillByDefault(Return(pluginReturnedFp)); @@ -1604,18 +1375,12 @@ namespace UKControllerPluginTest { EXPECT_CALL(this->api, AssignStandToAircraft("BAW123", 2)).Times(1); - auto message = InboundMessage::FromJson(nlohmann::json{ - {"type", "assign_stand"}, - {"version", 1}, - {"id", "foo"}, - {"data", {{"callsign", "BAW123"}, {"airfield", "EGKK"}, {"stand", "55"}}}}); + auto message = + MakeInboundMessage("assign_stand", {{"callsign", "BAW123"}, {"airfield", "EGKK"}, {"stand", "55"}}); bool successCalled = false; std::vector failureMessages; - this->handler.ProcessAction( - message, - [&successCalled]() { successCalled = true; }, - [&failureMessages](std::vector messages) { failureMessages = std::move(messages); }); + CallProcessAction(message, successCalled, failureMessages); EXPECT_TRUE(successCalled); EXPECT_TRUE(failureMessages.empty()); @@ -1626,212 +1391,63 @@ namespace UKControllerPluginTest { { ON_CALL(this->plugin, GetFlightplanForCallsign("BAW123")).WillByDefault(Return(nullptr)); - auto message = InboundMessage::FromJson(nlohmann::json{ - {"type", "assign_stand"}, - {"version", 1}, - {"id", "foo"}, - {"data", {{"callsign", "BAW123"}, {"airfield", "EGKK"}, {"stand", "55"}}}}); - - bool successCalled = false; - std::vector failureMessages; - this->handler.ProcessAction( - message, - [&successCalled]() { successCalled = true; }, - [&failureMessages](std::vector messages) { failureMessages = std::move(messages); }); - - EXPECT_FALSE(successCalled); - EXPECT_FALSE(failureMessages.empty()); - EXPECT_EQ(this->handler.noStandAssigned, this->handler.GetAssignedStandForCallsign("BAW123")); + auto message = + MakeInboundMessage("assign_stand", {{"callsign", "BAW123"}, {"airfield", "EGKK"}, {"stand", "55"}}); + ExpectProcessActionFailureNoAssignment(message); } TEST_F(StandEventHandlerTest, ItFailsAssignmentFromMessageIfCallsignMissing) { - auto message = InboundMessage::FromJson(nlohmann::json{ - {"type", "assign_stand"}, - {"version", 1}, - {"id", "foo"}, - {"data", {{"airfield", "EGKK"}, {"stand", "55"}}}}); - - bool successCalled = false; - std::vector failureMessages; - this->handler.ProcessAction( - message, - [&successCalled]() { successCalled = true; }, - [&failureMessages](std::vector messages) { failureMessages = std::move(messages); }); - - EXPECT_FALSE(successCalled); - EXPECT_FALSE(failureMessages.empty()); - EXPECT_EQ(this->handler.noStandAssigned, this->handler.GetAssignedStandForCallsign("BAW123")); + auto message = MakeInboundMessage("assign_stand", {{"airfield", "EGKK"}, {"stand", "55"}}); + ExpectProcessActionFailureNoAssignment(message); } TEST_F(StandEventHandlerTest, ItFailsAssignmentFromMessageIfCallsignNotString) { - auto message = InboundMessage::FromJson(nlohmann::json{ - {"type", "assign_stand"}, - {"version", 1}, - {"id", "foo"}, - {"data", {{"callsign", 123}, {"airfield", "EGKK"}, {"stand", "55"}}}}); - - bool successCalled = false; - std::vector failureMessages; - this->handler.ProcessAction( - message, - [&successCalled]() { successCalled = true; }, - [&failureMessages](std::vector messages) { failureMessages = std::move(messages); }); - - EXPECT_FALSE(successCalled); - EXPECT_FALSE(failureMessages.empty()); - EXPECT_EQ(this->handler.noStandAssigned, this->handler.GetAssignedStandForCallsign("BAW123")); + auto message = + MakeInboundMessage("assign_stand", {{"callsign", 123}, {"airfield", "EGKK"}, {"stand", "55"}}); + ExpectProcessActionFailureNoAssignment(message); } TEST_F(StandEventHandlerTest, ItFailsAssignmentFromMessageIfAirfieldMissing) { - auto message = InboundMessage::FromJson(nlohmann::json{ - {"type", "assign_stand"}, - {"version", 1}, - {"id", "foo"}, - {"data", {{"callsign", "BAW123"}, {"stand", "55"}}}}); - - bool successCalled = false; - std::vector failureMessages; - this->handler.ProcessAction( - message, - [&successCalled]() { successCalled = true; }, - [&failureMessages](std::vector messages) { failureMessages = std::move(messages); }); - - EXPECT_FALSE(successCalled); - EXPECT_FALSE(failureMessages.empty()); - EXPECT_EQ(this->handler.noStandAssigned, this->handler.GetAssignedStandForCallsign("BAW123")); + auto message = MakeInboundMessage("assign_stand", {{"callsign", "BAW123"}, {"stand", "55"}}); + ExpectProcessActionFailureNoAssignment(message); } TEST_F(StandEventHandlerTest, ItFailsAssignmentFromMessageIfAirfieldNotString) { - auto message = InboundMessage::FromJson(nlohmann::json{ - {"type", "assign_stand"}, - {"version", 1}, - {"id", "foo"}, - {"data", {{"callsign", "BAW123"}, {"airfield", 123}, {"stand", "55"}}}}); - - bool successCalled = false; - std::vector failureMessages; - this->handler.ProcessAction( - message, - [&successCalled]() { successCalled = true; }, - [&failureMessages](std::vector messages) { failureMessages = std::move(messages); }); - - EXPECT_FALSE(successCalled); - EXPECT_FALSE(failureMessages.empty()); - EXPECT_EQ(this->handler.noStandAssigned, this->handler.GetAssignedStandForCallsign("BAW123")); + auto message = + MakeInboundMessage("assign_stand", {{"callsign", "BAW123"}, {"airfield", 123}, {"stand", "55"}}); + ExpectProcessActionFailureNoAssignment(message); } TEST_F(StandEventHandlerTest, ItFailsAssignmentFromMessageIfStandMissing) { - auto message = InboundMessage::FromJson(nlohmann::json{ - {"type", "assign_stand"}, - {"version", 1}, - {"id", "foo"}, - {"data", - { - {"callsign", "BAW123"}, - {"airfield", "EGKK"}, - }}}); - - bool successCalled = false; - std::vector failureMessages; - this->handler.ProcessAction( - message, - [&successCalled]() { successCalled = true; }, - [&failureMessages](std::vector messages) { failureMessages = std::move(messages); }); - - EXPECT_FALSE(successCalled); - EXPECT_FALSE(failureMessages.empty()); - EXPECT_EQ(this->handler.noStandAssigned, this->handler.GetAssignedStandForCallsign("BAW123")); - } + auto message = MakeInboundMessage("assign_stand", {{"callsign", "BAW123"}, {"airfield", "EGKK"}}); + ExpectProcessActionFailureNoAssignment(message); + } TEST_F(StandEventHandlerTest, ItFailsAssignmentFromMessageIfStandNotString) { - auto message = InboundMessage::FromJson(nlohmann::json{ - {"type", "assign_stand"}, - {"version", 1}, - {"id", "foo"}, - {"data", {{"callsign", "BAW123"}, {"airfield", "EGKK"}, {"stand", 55}}}}); - - bool successCalled = false; - std::vector failureMessages; - this->handler.ProcessAction( - message, - [&successCalled]() { successCalled = true; }, - [&failureMessages](std::vector messages) { failureMessages = std::move(messages); }); - - EXPECT_FALSE(successCalled); - EXPECT_FALSE(failureMessages.empty()); - EXPECT_EQ(this->handler.noStandAssigned, this->handler.GetAssignedStandForCallsign("BAW123")); + auto message = + MakeInboundMessage("assign_stand", {{"callsign", "BAW123"}, {"airfield", "EGKK"}, {"stand", 55}}); + ExpectProcessActionFailureNoAssignment(message); } TEST_F(StandEventHandlerTest, ItRequestsADepartureStandFromApi) { // Make "us" the delivery controller - std::vector> provisions; - provisions.push_back(std::make_shared( - UKControllerPlugin::Ownership::ServiceType::Delivery, userCallsign)); - airfieldOwnership->SetProvidersForAirfield("EGKK", provisions); - - // Trigger the menu first to set the last airport - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDestination()).WillByDefault(Return("EGGW")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(1)); - - this->handler.DisplayStandSelectionMenu(this->flightplan, this->radarTarget, "", {0, 0}); - - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(true)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(true)); - - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); + SetProviderForAirfield("EGKK"); - ON_CALL(*pluginReturnedFp, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(*pluginReturnedFp, GetDestination()).WillByDefault(Return("EGGW")); - - ON_CALL(*pluginReturnedFp, GetDistanceFromOrigin()).WillByDefault(Return(1)); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); - - std::shared_ptr> pluginReturnedRt = - std::make_shared>(); - - EuroScopePlugIn::CPosition position; - position.m_Latitude = 123; - position.m_Longitude = 456; - ON_CALL(*pluginReturnedRt, GetPosition()).WillByDefault(Return(position)); - - ON_CALL(this->plugin, GetRadarTargetForCallsign("BAW123")).WillByDefault(Return(pluginReturnedRt)); + SetupAutoStandSelectionMenu("EGGW", 1); + [[maybe_unused]] const auto selectedFlightplan = MakeSelectedFlightplanForAutoRequest("EGGW", 1); + SetupRadarTargetForCallsign("BAW123"); this->ExpectApiRequest() ->Post() .To("stand/assignment/requestauto") - .WithBody(nlohmann::json{ - {"callsign", "BAW123"}, - {"departure_airfield", "EGKK"}, - {"assignment_type", "departure"}, - {"latitude", 123}, - {"longitude", 456}, - }) + .WithBody(DepartureStandRequestBody()) .WillReturnCreated() .WithResponseBody(nlohmann::json{{"stand_id", 3}}); @@ -1844,527 +1460,133 @@ namespace UKControllerPluginTest { TEST_F(StandEventHandlerTest, DepartureStandRequestsHandlesNonCreatedCode) { // Make "us" the delivery controller - std::vector> provisions; - provisions.push_back(std::make_shared( - UKControllerPlugin::Ownership::ServiceType::Delivery, userCallsign)); - airfieldOwnership->SetProvidersForAirfield("EGKK", provisions); - - // Trigger the menu first to set the last airport - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDestination()).WillByDefault(Return("EGGW")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(1)); - - this->handler.DisplayStandSelectionMenu(this->flightplan, this->radarTarget, "", {0, 0}); - - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(true)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(true)); + SetProviderForAirfield("EGKK"); - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(*pluginReturnedFp, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(*pluginReturnedFp, GetDestination()).WillByDefault(Return("EGGW")); - - ON_CALL(*pluginReturnedFp, GetDistanceFromOrigin()).WillByDefault(Return(1)); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); - - std::shared_ptr> pluginReturnedRt = - std::make_shared>(); - - EuroScopePlugIn::CPosition position; - position.m_Latitude = 123; - position.m_Longitude = 456; - ON_CALL(*pluginReturnedRt, GetPosition()).WillByDefault(Return(position)); - - ON_CALL(this->plugin, GetRadarTargetForCallsign("BAW123")).WillByDefault(Return(pluginReturnedRt)); + SetupAutoStandSelectionMenu("EGGW", 1); + [[maybe_unused]] const auto selectedFlightplan = MakeSelectedFlightplanForAutoRequest("EGGW", 1); + SetupRadarTargetForCallsign("BAW123"); this->ExpectApiRequest() ->Post() .To("stand/assignment/requestauto") - .WithBody(nlohmann::json{ - {"callsign", "BAW123"}, - {"departure_airfield", "EGKK"}, - {"assignment_type", "departure"}, - {"latitude", 123}, - {"longitude", 456}, - }) + .WithBody(DepartureStandRequestBody()) .WillReturnForbidden(); - this->handler.StandSelected(1, "AUTO", {}); - - this->AwaitApiCallCompletion(); - EXPECT_EQ(this->handler.noStandAssigned, this->handler.GetAssignedStandForCallsign("BAW123")); + SelectAutoAndExpectNoStandAssigned(); } TEST_F(StandEventHandlerTest, DepartureStandRequestsHandlesUnknownStandId) { // Make "us" the delivery controller - std::vector> provisions; - provisions.push_back(std::make_shared( - UKControllerPlugin::Ownership::ServiceType::Delivery, userCallsign)); - airfieldOwnership->SetProvidersForAirfield("EGKK", provisions); - - // Trigger the menu first to set the last airport - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDestination()).WillByDefault(Return("EGGW")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(1)); - - this->handler.DisplayStandSelectionMenu(this->flightplan, this->radarTarget, "", {0, 0}); + SetProviderForAirfield("EGKK"); - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(true)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(true)); - - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(*pluginReturnedFp, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(*pluginReturnedFp, GetDestination()).WillByDefault(Return("EGGW")); - - ON_CALL(*pluginReturnedFp, GetDistanceFromOrigin()).WillByDefault(Return(1)); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); - - std::shared_ptr> pluginReturnedRt = - std::make_shared>(); - - EuroScopePlugIn::CPosition position; - position.m_Latitude = 123; - position.m_Longitude = 456; - ON_CALL(*pluginReturnedRt, GetPosition()).WillByDefault(Return(position)); - - ON_CALL(this->plugin, GetRadarTargetForCallsign("BAW123")).WillByDefault(Return(pluginReturnedRt)); + SetupAutoStandSelectionMenu("EGGW", 1); + [[maybe_unused]] const auto selectedFlightplan = MakeSelectedFlightplanForAutoRequest("EGGW", 1); + SetupRadarTargetForCallsign("BAW123"); this->ExpectApiRequest() ->Post() .To("stand/assignment/requestauto") - .WithBody(nlohmann::json{ - {"callsign", "BAW123"}, - {"departure_airfield", "EGKK"}, - {"assignment_type", "departure"}, - {"latitude", 123}, - {"longitude", 456}, - }) + .WithBody(DepartureStandRequestBody()) .WillReturnCreated() .WithResponseBody(nlohmann::json{{"stand_id", 999}}); - this->handler.StandSelected(1, "AUTO", {}); - - this->AwaitApiCallCompletion(); - EXPECT_EQ(this->handler.noStandAssigned, this->handler.GetAssignedStandForCallsign("BAW123")); + SelectAutoAndExpectNoStandAssigned(); } TEST_F(StandEventHandlerTest, DepartureStandRequestsHandlesStandIdNotInteger) { // Make "us" the delivery controller - std::vector> provisions; - provisions.push_back(std::make_shared( - UKControllerPlugin::Ownership::ServiceType::Delivery, userCallsign)); - airfieldOwnership->SetProvidersForAirfield("EGKK", provisions); - - // Trigger the menu first to set the last airport - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); + SetProviderForAirfield("EGKK"); - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDestination()).WillByDefault(Return("EGGW")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(1)); - - this->handler.DisplayStandSelectionMenu(this->flightplan, this->radarTarget, "", {0, 0}); - - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(true)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(true)); - - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(*pluginReturnedFp, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(*pluginReturnedFp, GetDestination()).WillByDefault(Return("EGGW")); - - ON_CALL(*pluginReturnedFp, GetDistanceFromOrigin()).WillByDefault(Return(1)); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); - - std::shared_ptr> pluginReturnedRt = - std::make_shared>(); - - EuroScopePlugIn::CPosition position; - position.m_Latitude = 123; - position.m_Longitude = 456; - ON_CALL(*pluginReturnedRt, GetPosition()).WillByDefault(Return(position)); - - ON_CALL(this->plugin, GetRadarTargetForCallsign("BAW123")).WillByDefault(Return(pluginReturnedRt)); + SetupAutoStandSelectionMenu("EGGW", 1); + [[maybe_unused]] const auto selectedFlightplan = MakeSelectedFlightplanForAutoRequest("EGGW", 1); + SetupRadarTargetForCallsign("BAW123"); this->ExpectApiRequest() ->Post() .To("stand/assignment/requestauto") - .WithBody(nlohmann::json{ - {"callsign", "BAW123"}, - {"departure_airfield", "EGKK"}, - {"assignment_type", "departure"}, - {"latitude", 123}, - {"longitude", 456}, - }) + .WithBody(DepartureStandRequestBody()) .WillReturnCreated() .WithResponseBody(nlohmann::json{{"stand_id", "abc"}}); - this->handler.StandSelected(1, "AUTO", {}); - - this->AwaitApiCallCompletion(); - EXPECT_EQ(this->handler.noStandAssigned, this->handler.GetAssignedStandForCallsign("BAW123")); + SelectAutoAndExpectNoStandAssigned(); } TEST_F(StandEventHandlerTest, DepartureStandRequestsHandlesNoStandIdInJson) { // Make "us" the delivery controller - std::vector> provisions; - provisions.push_back(std::make_shared( - UKControllerPlugin::Ownership::ServiceType::Delivery, userCallsign)); - airfieldOwnership->SetProvidersForAirfield("EGKK", provisions); - - // Trigger the menu first to set the last airport - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDestination()).WillByDefault(Return("EGGW")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(1)); - - this->handler.DisplayStandSelectionMenu(this->flightplan, this->radarTarget, "", {0, 0}); - - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(true)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(true)); + SetProviderForAirfield("EGKK"); - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(*pluginReturnedFp, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(*pluginReturnedFp, GetDestination()).WillByDefault(Return("EGGW")); - - ON_CALL(*pluginReturnedFp, GetDistanceFromOrigin()).WillByDefault(Return(1)); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); - - std::shared_ptr> pluginReturnedRt = - std::make_shared>(); - - EuroScopePlugIn::CPosition position; - position.m_Latitude = 123; - position.m_Longitude = 456; - ON_CALL(*pluginReturnedRt, GetPosition()).WillByDefault(Return(position)); - - ON_CALL(this->plugin, GetRadarTargetForCallsign("BAW123")).WillByDefault(Return(pluginReturnedRt)); + SetupAutoStandSelectionMenu("EGGW", 1); + [[maybe_unused]] const auto selectedFlightplan = MakeSelectedFlightplanForAutoRequest("EGGW", 1); + SetupRadarTargetForCallsign("BAW123"); this->ExpectApiRequest() ->Post() .To("stand/assignment/requestauto") - .WithBody(nlohmann::json{ - {"callsign", "BAW123"}, - {"departure_airfield", "EGKK"}, - {"assignment_type", "departure"}, - {"latitude", 123}, - {"longitude", 456}, - }) + .WithBody(DepartureStandRequestBody()) .WillReturnCreated() .WithResponseBody(nlohmann::json{{"not_stand_id", 3}}); - this->handler.StandSelected(1, "AUTO", {}); - - this->AwaitApiCallCompletion(); - EXPECT_EQ(this->handler.noStandAssigned, this->handler.GetAssignedStandForCallsign("BAW123")); + SelectAutoAndExpectNoStandAssigned(); } TEST_F(StandEventHandlerTest, DepartureStandRequestsHandlesNotFoundRadarTarget) { // Make "us" the delivery controller - std::vector> provisions; - provisions.push_back(std::make_shared( - UKControllerPlugin::Ownership::ServiceType::Delivery, userCallsign)); - airfieldOwnership->SetProvidersForAirfield("EGKK", provisions); - - // Trigger the menu first to set the last airport - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDestination()).WillByDefault(Return("EGGW")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(1)); - - this->handler.DisplayStandSelectionMenu(this->flightplan, this->radarTarget, "", {0, 0}); + SetProviderForAirfield("EGKK"); - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(true)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(true)); - - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(*pluginReturnedFp, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(*pluginReturnedFp, GetDestination()).WillByDefault(Return("EGGW")); - - ON_CALL(*pluginReturnedFp, GetDistanceFromOrigin()).WillByDefault(Return(1)); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); + SetupAutoStandSelectionMenu("EGGW", 1); + [[maybe_unused]] const auto selectedFlightplan = MakeSelectedFlightplanForAutoRequest("EGGW", 1); ON_CALL(this->plugin, GetRadarTargetForCallsign("BAW123")).WillByDefault(Return(nullptr)); this->ExpectNoApiRequests(); - this->handler.StandSelected(1, "AUTO", {}); - - this->AwaitApiCallCompletion(); - EXPECT_EQ(this->handler.noStandAssigned, this->handler.GetAssignedStandForCallsign("BAW123")); + SelectAutoAndExpectNoStandAssigned(); } TEST_F(StandEventHandlerTest, DepartureStandRequestsHandlesUnknownDistanceFromOrigin) { // Make "us" the delivery controller - std::vector> provisions; - provisions.push_back(std::make_shared( - UKControllerPlugin::Ownership::ServiceType::Delivery, userCallsign)); - airfieldOwnership->SetProvidersForAirfield("EGKK", provisions); - - // Trigger the menu first to set the last airport - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(false)); + SetProviderForAirfield("EGKK"); - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDestination()).WillByDefault(Return("EGGW")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(0.0)); - - this->handler.DisplayStandSelectionMenu(this->flightplan, this->radarTarget, "", {0, 0}); - - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(true)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(true)); - - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(*pluginReturnedFp, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(*pluginReturnedFp, GetDestination()).WillByDefault(Return("EGGW")); - - ON_CALL(*pluginReturnedFp, GetDistanceFromOrigin()).WillByDefault(Return(0.0)); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); - - std::shared_ptr> pluginReturnedRt = - std::make_shared>(); - - EuroScopePlugIn::CPosition position; - position.m_Latitude = 123; - position.m_Longitude = 456; - ON_CALL(*pluginReturnedRt, GetPosition()).WillByDefault(Return(position)); - - ON_CALL(this->plugin, GetRadarTargetForCallsign("BAW123")).WillByDefault(Return(pluginReturnedRt)); + SetupAutoStandSelectionMenu("EGGW", 0.0); + [[maybe_unused]] const auto selectedFlightplan = MakeSelectedFlightplanForAutoRequest("EGGW", 0.0); + SetupRadarTargetForCallsign("BAW123"); this->ExpectNoApiRequests(); - this->handler.StandSelected(1, "AUTO", {}); - - this->AwaitApiCallCompletion(); - EXPECT_EQ(this->handler.noStandAssigned, this->handler.GetAssignedStandForCallsign("BAW123")); + SelectAutoAndExpectNoStandAssigned(); } TEST_F(StandEventHandlerTest, DepartureStandRequestsHandlesUserNotProvidingDelivery) { // Make "us" the delivery controller - std::vector> provisions; - provisions.push_back(std::make_shared( - UKControllerPlugin::Ownership::ServiceType::Ground, userCallsign)); - airfieldOwnership->SetProvidersForAirfield("EGKK", provisions); - - // Trigger the menu first to set the last airport - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(false)); + SetProviderForAirfield("EGKK", UKControllerPlugin::Ownership::ServiceType::Ground); - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDestination()).WillByDefault(Return("EGGW")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(1)); - - this->handler.DisplayStandSelectionMenu(this->flightplan, this->radarTarget, "", {0, 0}); - - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(true)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(true)); - - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(*pluginReturnedFp, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(*pluginReturnedFp, GetDestination()).WillByDefault(Return("EGGW")); - - ON_CALL(*pluginReturnedFp, GetDistanceFromOrigin()).WillByDefault(Return(1)); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); - - std::shared_ptr> pluginReturnedRt = - std::make_shared>(); - - EuroScopePlugIn::CPosition position; - position.m_Latitude = 123; - position.m_Longitude = 456; - ON_CALL(*pluginReturnedRt, GetPosition()).WillByDefault(Return(position)); - - ON_CALL(this->plugin, GetRadarTargetForCallsign("BAW123")).WillByDefault(Return(pluginReturnedRt)); + SetupAutoStandSelectionMenu("EGGW", 1); + [[maybe_unused]] const auto selectedFlightplan = MakeSelectedFlightplanForAutoRequest("EGGW", 1); + SetupRadarTargetForCallsign("BAW123"); this->ExpectNoApiRequests(); - this->handler.StandSelected(1, "AUTO", {}); - - this->AwaitApiCallCompletion(); - EXPECT_EQ(this->handler.noStandAssigned, this->handler.GetAssignedStandForCallsign("BAW123")); + SelectAutoAndExpectNoStandAssigned(); } TEST_F(StandEventHandlerTest, ItRequestsAnArrivalStandFromApi) { // Make "us" the delivery controller - std::vector> provisions; - provisions.push_back(std::make_shared( - UKControllerPlugin::Ownership::ServiceType::Delivery, userCallsign)); - airfieldOwnership->SetProvidersForAirfield("EGGW", provisions); - - // Trigger the menu first to set the last airport - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(false)); + SetProviderForAirfield("EGGW"); - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDestination()).WillByDefault(Return("EGGW")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(1)); - - this->handler.DisplayStandSelectionMenu(this->flightplan, this->radarTarget, "", {0, 0}); - - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(true)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(true)); - - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(*pluginReturnedFp, GetDistanceFromOrigin()).WillByDefault(Return(55)); - - ON_CALL(*pluginReturnedFp, GetAircraftType()).WillByDefault(Return("B738")); - - ON_CALL(*pluginReturnedFp, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(*pluginReturnedFp, GetDestination()).WillByDefault(Return("EGGW")); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); + SetupAutoStandSelectionMenu("EGGW", 1); + [[maybe_unused]] const auto selectedFlightplan = MakeSelectedFlightplanForAutoRequest("EGGW", 55, "B738"); this->ExpectApiRequest() ->Post() .To("stand/assignment/requestauto") - .WithBody(nlohmann::json{ - {"callsign", "BAW123"}, - {"departure_airfield", "EGKK"}, - {"arrival_airfield", "EGGW"}, - {"assignment_type", "arrival"}, - {"aircraft_type", "B738"}}) + .WithBody(ArrivalStandRequestBody()) .WillReturnCreated() .WithResponseBody(nlohmann::json{{"stand_id", 3}}); @@ -2377,364 +1599,98 @@ namespace UKControllerPluginTest { TEST_F(StandEventHandlerTest, ArrivalStandRequestHandlesInvalidStatusCodeInResponse) { // Make "us" the delivery controller - std::vector> provisions; - provisions.push_back(std::make_shared( - UKControllerPlugin::Ownership::ServiceType::Delivery, userCallsign)); - airfieldOwnership->SetProvidersForAirfield("EGGW", provisions); - - // Trigger the menu first to set the last airport - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDestination()).WillByDefault(Return("EGGW")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(1)); - - this->handler.DisplayStandSelectionMenu(this->flightplan, this->radarTarget, "", {0, 0}); - - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(true)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(true)); + SetProviderForAirfield("EGGW"); - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(*pluginReturnedFp, GetDistanceFromOrigin()).WillByDefault(Return(55)); - - ON_CALL(*pluginReturnedFp, GetAircraftType()).WillByDefault(Return("B738")); - - ON_CALL(*pluginReturnedFp, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(*pluginReturnedFp, GetDestination()).WillByDefault(Return("EGGW")); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); + SetupAutoStandSelectionMenu("EGGW", 1); + [[maybe_unused]] const auto selectedFlightplan = MakeSelectedFlightplanForAutoRequest("EGGW", 55, "B738"); this->ExpectApiRequest() ->Post() .To("stand/assignment/requestauto") - .WithBody(nlohmann::json{ - {"callsign", "BAW123"}, - {"departure_airfield", "EGKK"}, - {"arrival_airfield", "EGGW"}, - {"assignment_type", "arrival"}, - {"aircraft_type", "B738"}}) + .WithBody(ArrivalStandRequestBody()) .WillReturnServerError(); - this->handler.StandSelected(1, "AUTO", {}); - - this->AwaitApiCallCompletion(); - EXPECT_EQ(this->handler.noStandAssigned, this->handler.GetAssignedStandForCallsign("BAW123")); + SelectAutoAndExpectNoStandAssigned(); } TEST_F(StandEventHandlerTest, ArrivalStandRequestHandlesInvalidStandIdInJson) { // Make "us" the delivery controller - std::vector> provisions; - provisions.push_back(std::make_shared( - UKControllerPlugin::Ownership::ServiceType::Delivery, userCallsign)); - airfieldOwnership->SetProvidersForAirfield("EGGW", provisions); - - // Trigger the menu first to set the last airport - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(false)); + SetProviderForAirfield("EGGW"); - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDestination()).WillByDefault(Return("EGGW")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(1)); - - this->handler.DisplayStandSelectionMenu(this->flightplan, this->radarTarget, "", {0, 0}); - - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(true)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(true)); - - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(*pluginReturnedFp, GetDistanceFromOrigin()).WillByDefault(Return(55)); - - ON_CALL(*pluginReturnedFp, GetAircraftType()).WillByDefault(Return("B738")); - - ON_CALL(*pluginReturnedFp, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(*pluginReturnedFp, GetDestination()).WillByDefault(Return("EGGW")); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); + SetupAutoStandSelectionMenu("EGGW", 1); + [[maybe_unused]] const auto selectedFlightplan = MakeSelectedFlightplanForAutoRequest("EGGW", 55, "B738"); this->ExpectApiRequest() ->Post() .To("stand/assignment/requestauto") - .WithBody(nlohmann::json{ - {"callsign", "BAW123"}, - {"departure_airfield", "EGKK"}, - {"arrival_airfield", "EGGW"}, - {"assignment_type", "arrival"}, - {"aircraft_type", "B738"}}) + .WithBody(ArrivalStandRequestBody()) .WillReturnCreated() .WithResponseBody(nlohmann::json{{"stand_id", 999}}); - this->handler.StandSelected(1, "AUTO", {}); - - this->AwaitApiCallCompletion(); - EXPECT_EQ(this->handler.noStandAssigned, this->handler.GetAssignedStandForCallsign("BAW123")); + SelectAutoAndExpectNoStandAssigned(); } TEST_F(StandEventHandlerTest, ArrivalStandRequestHandlesNonIntegerStandIdInJson) { // Make "us" the delivery controller - std::vector> provisions; - provisions.push_back(std::make_shared( - UKControllerPlugin::Ownership::ServiceType::Delivery, userCallsign)); - airfieldOwnership->SetProvidersForAirfield("EGGW", provisions); + SetProviderForAirfield("EGGW"); - // Trigger the menu first to set the last airport - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDestination()).WillByDefault(Return("EGGW")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(1)); - - this->handler.DisplayStandSelectionMenu(this->flightplan, this->radarTarget, "", {0, 0}); - - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(true)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(true)); - - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(*pluginReturnedFp, GetDistanceFromOrigin()).WillByDefault(Return(55)); - - ON_CALL(*pluginReturnedFp, GetAircraftType()).WillByDefault(Return("B738")); - - ON_CALL(*pluginReturnedFp, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(*pluginReturnedFp, GetDestination()).WillByDefault(Return("EGGW")); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); + SetupAutoStandSelectionMenu("EGGW", 1); + [[maybe_unused]] const auto selectedFlightplan = MakeSelectedFlightplanForAutoRequest("EGGW", 55, "B738"); this->ExpectApiRequest() ->Post() .To("stand/assignment/requestauto") - .WithBody(nlohmann::json{ - {"callsign", "BAW123"}, - {"departure_airfield", "EGKK"}, - {"arrival_airfield", "EGGW"}, - {"assignment_type", "arrival"}, - {"aircraft_type", "B738"}}) + .WithBody(ArrivalStandRequestBody()) .WillReturnCreated() .WithResponseBody(nlohmann::json{{"stand_id", "abc"}}); - this->handler.StandSelected(1, "AUTO", {}); - - this->AwaitApiCallCompletion(); - EXPECT_EQ(this->handler.noStandAssigned, this->handler.GetAssignedStandForCallsign("BAW123")); + SelectAutoAndExpectNoStandAssigned(); } TEST_F(StandEventHandlerTest, ArrivalStandRequestHandlesNoStandIdInJson) { // Make "us" the delivery controller - std::vector> provisions; - provisions.push_back(std::make_shared( - UKControllerPlugin::Ownership::ServiceType::Delivery, userCallsign)); - airfieldOwnership->SetProvidersForAirfield("EGGW", provisions); - - // Trigger the menu first to set the last airport - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDestination()).WillByDefault(Return("EGGW")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(1)); - - this->handler.DisplayStandSelectionMenu(this->flightplan, this->radarTarget, "", {0, 0}); - - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(true)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(true)); - - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(*pluginReturnedFp, GetDistanceFromOrigin()).WillByDefault(Return(55)); + SetProviderForAirfield("EGGW"); - ON_CALL(*pluginReturnedFp, GetAircraftType()).WillByDefault(Return("B738")); - - ON_CALL(*pluginReturnedFp, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(*pluginReturnedFp, GetDestination()).WillByDefault(Return("EGGW")); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); + SetupAutoStandSelectionMenu("EGGW", 1); + [[maybe_unused]] const auto selectedFlightplan = MakeSelectedFlightplanForAutoRequest("EGGW", 55, "B738"); this->ExpectApiRequest() ->Post() .To("stand/assignment/requestauto") - .WithBody(nlohmann::json{ - {"callsign", "BAW123"}, - {"departure_airfield", "EGKK"}, - {"arrival_airfield", "EGGW"}, - {"assignment_type", "arrival"}, - {"aircraft_type", "B738"}}) + .WithBody(ArrivalStandRequestBody()) .WillReturnCreated() .WithResponseBody(nlohmann::json{{"not_stand_id", 3}}); - this->handler.StandSelected(1, "AUTO", {}); - - this->AwaitApiCallCompletion(); - EXPECT_EQ(this->handler.noStandAssigned, this->handler.GetAssignedStandForCallsign("BAW123")); + SelectAutoAndExpectNoStandAssigned(); } TEST_F(StandEventHandlerTest, ArrivalStandRequestHandlesZeroDistanceToOrigin) { // Make "us" the delivery controller - std::vector> provisions; - provisions.push_back(std::make_shared( - UKControllerPlugin::Ownership::ServiceType::Delivery, userCallsign)); - airfieldOwnership->SetProvidersForAirfield("EGGW", provisions); - - // Trigger the menu first to set the last airport - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDestination()).WillByDefault(Return("EGGW")); + SetProviderForAirfield("EGGW"); - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(1)); - - this->handler.DisplayStandSelectionMenu(this->flightplan, this->radarTarget, "", {0, 0}); - - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(true)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(true)); - - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(*pluginReturnedFp, GetDistanceFromOrigin()).WillByDefault(Return(0.0)); - - ON_CALL(*pluginReturnedFp, GetAircraftType()).WillByDefault(Return("B738")); - - ON_CALL(*pluginReturnedFp, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(*pluginReturnedFp, GetDestination()).WillByDefault(Return("EGGW")); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); + SetupAutoStandSelectionMenu("EGGW", 1); + [[maybe_unused]] const auto selectedFlightplan = MakeSelectedFlightplanForAutoRequest("EGGW", 0.0, "B738"); this->ExpectNoApiRequests(); - this->handler.StandSelected(1, "AUTO", {}); - - this->AwaitApiCallCompletion(); - EXPECT_EQ(this->handler.noStandAssigned, this->handler.GetAssignedStandForCallsign("BAW123")); + SelectAutoAndExpectNoStandAssigned(); } TEST_F(StandEventHandlerTest, ArrivalStandRequestHandlesUserNotProvidingDelivery) { // Make "us" the delivery controller - std::vector> provisions; - provisions.push_back(std::make_shared( - UKControllerPlugin::Ownership::ServiceType::Ground, userCallsign)); - airfieldOwnership->SetProvidersForAirfield("EGGW", provisions); - - // Trigger the menu first to set the last airport - ON_CALL(this->flightplan, IsTracked()).WillByDefault(Return(false)); - - ON_CALL(this->flightplan, IsTrackedByUser()).WillByDefault(Return(false)); - - ON_CALL(this->plugin, GetUserControllerObject()).WillByDefault(Return(this->mockController)); - - ON_CALL(*this->mockController, IsVatsimRecognisedController()).WillByDefault(Return(true)); - - ON_CALL(this->flightplan, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(this->flightplan, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(this->flightplan, GetDestination()).WillByDefault(Return("EGGW")); - - ON_CALL(this->flightplan, GetDistanceFromOrigin()).WillByDefault(Return(1)); - - this->handler.DisplayStandSelectionMenu(this->flightplan, this->radarTarget, "", {0, 0}); - - std::shared_ptr> pluginReturnedFp = - std::make_shared>(); - - ON_CALL(*pluginReturnedFp, IsTracked()).WillByDefault(Return(true)); - - ON_CALL(*pluginReturnedFp, IsTrackedByUser()).WillByDefault(Return(true)); - - ON_CALL(*pluginReturnedFp, GetCallsign()).WillByDefault(Return("BAW123")); - - ON_CALL(*pluginReturnedFp, GetDistanceFromOrigin()).WillByDefault(Return(55)); + SetProviderForAirfield("EGGW", UKControllerPlugin::Ownership::ServiceType::Ground); - ON_CALL(*pluginReturnedFp, GetAircraftType()).WillByDefault(Return("B738")); - - ON_CALL(*pluginReturnedFp, GetOrigin()).WillByDefault(Return("EGKK")); - - ON_CALL(*pluginReturnedFp, GetDestination()).WillByDefault(Return("EGGW")); - - ON_CALL(this->plugin, GetSelectedFlightplan()).WillByDefault(Return(pluginReturnedFp)); + SetupAutoStandSelectionMenu("EGGW", 1); + [[maybe_unused]] const auto selectedFlightplan = MakeSelectedFlightplanForAutoRequest("EGGW", 55, "B738"); this->ExpectNoApiRequests(); - this->handler.StandSelected(1, "AUTO", {}); - - this->AwaitApiCallCompletion(); - EXPECT_EQ(this->handler.noStandAssigned, this->handler.GetAssignedStandForCallsign("BAW123")); + SelectAutoAndExpectNoStandAssigned(); } } // namespace Stands } // namespace UKControllerPluginTest