summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Swift/Controllers/Chat/MUCController.cpp16
-rw-r--r--Swift/Controllers/Chat/MUCController.h4
-rw-r--r--Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp57
3 files changed, 69 insertions, 8 deletions
diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp
index 8f43b08..9d1459d 100644
--- a/Swift/Controllers/Chat/MUCController.cpp
+++ b/Swift/Controllers/Chat/MUCController.cpp
@@ -60,82 +60,82 @@ namespace Swift {
class MUCBookmarkPredicate {
public:
MUCBookmarkPredicate(const JID& mucJID) : roomJID_(mucJID) { }
bool operator()(const MUCBookmark& operand) {
return operand.getRoom() == roomJID_;
}
private:
JID roomJID_;
};
/**
* The controller does not gain ownership of the stanzaChannel, nor the factory.
*/
MUCController::MUCController (
const JID& self,
MUC::ref muc,
const boost::optional<std::string>& password,
const std::string &nick,
StanzaChannel* stanzaChannel,
IQRouter* iqRouter,
ChatWindowFactory* chatWindowFactory,
PresenceOracle* presenceOracle,
AvatarManager* avatarManager,
UIEventStream* uiEventStream,
bool useDelayForLatency,
TimerFactory* timerFactory,
EventController* eventController,
EntityCapsProvider* entityCapsProvider,
- XMPPRoster* roster,
+ XMPPRoster* xmppRoster,
HistoryController* historyController,
MUCRegistry* mucRegistry,
HighlightManager* highlightManager,
ClientBlockListManager* clientBlockListManager,
std::shared_ptr<ChatMessageParser> chatMessageParser,
bool isImpromptu,
AutoAcceptMUCInviteDecider* autoAcceptMUCInviteDecider,
VCardManager* vcardManager,
MUCBookmarkManager* mucBookmarkManager) :
ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, muc->getJID(), presenceOracle, avatarManager, useDelayForLatency, uiEventStream, eventController, timerFactory, entityCapsProvider, historyController, mucRegistry, highlightManager, chatMessageParser, autoAcceptMUCInviteDecider), muc_(muc), nick_(nick), desiredNick_(nick), password_(password), renameCounter_(0), isImpromptu_(isImpromptu), isImpromptuAlreadyConfigured_(false), clientBlockListManager_(clientBlockListManager), mucBookmarkManager_(mucBookmarkManager) {
parting_ = true;
joined_ = false;
lastWasPresence_ = false;
shouldJoinOnReconnect_ = true;
doneGettingHistory_ = false;
- xmppRoster_ = roster;
+ xmppRoster_ = xmppRoster;
- roster_ = new Roster(false, true);
- rosterVCardProvider_ = new RosterVCardProvider(roster_, vcardManager, JID::WithResource);
+ roster_ = std::unique_ptr<Roster>(new Roster(false, true));
+ rosterVCardProvider_ = new RosterVCardProvider(roster_.get(), vcardManager, JID::WithResource);
completer_ = new TabComplete();
- chatWindow_->setRosterModel(roster_);
+ chatWindow_->setRosterModel(roster_.get());
chatWindow_->setTabComplete(completer_);
chatWindow_->onClosed.connect(boost::bind(&MUCController::handleWindowClosed, this));
chatWindow_->onOccupantSelectionChanged.connect(boost::bind(&MUCController::handleWindowOccupantSelectionChanged, this, _1));
chatWindow_->onOccupantActionSelected.connect(boost::bind(&MUCController::handleActionRequestedOnOccupant, this, _1, _2));
chatWindow_->onChangeSubjectRequest.connect(boost::bind(&MUCController::handleChangeSubjectRequest, this, _1));
chatWindow_->onBookmarkRequest.connect(boost::bind(&MUCController::handleBookmarkRequest, this));
chatWindow_->onConfigureRequest.connect(boost::bind(&MUCController::handleConfigureRequest, this, _1));
chatWindow_->onConfigurationFormCancelled.connect(boost::bind(&MUCController::handleConfigurationCancelled, this));
chatWindow_->onDestroyRequest.connect(boost::bind(&MUCController::handleDestroyRoomRequest, this));
chatWindow_->onInviteToChat.connect(boost::bind(&MUCController::handleInvitePersonToThisMUCRequest, this, _1));
chatWindow_->onGetAffiliationsRequest.connect(boost::bind(&MUCController::handleGetAffiliationsRequest, this));
chatWindow_->onChangeAffiliationsRequest.connect(boost::bind(&MUCController::handleChangeAffiliationsRequest, this, _1));
chatWindow_->onUnblockUserRequest.connect(boost::bind(&MUCController::handleUnblockUserRequest, this));
muc_->onJoinComplete.connect(boost::bind(&MUCController::handleJoinComplete, this, _1));
muc_->onJoinFailed.connect(boost::bind(&MUCController::handleJoinFailed, this, _1));
muc_->onOccupantJoined.connect(boost::bind(&MUCController::handleOccupantJoined, this, _1));
muc_->onOccupantNicknameChanged.connect(boost::bind(&MUCController::handleOccupantNicknameChanged, this, _1, _2));
muc_->onOccupantPresenceChange.connect(boost::bind(&MUCController::handleOccupantPresenceChange, this, _1));
muc_->onOccupantLeft.connect(boost::bind(&MUCController::handleOccupantLeft, this, _1, _2, _3));
muc_->onRoleChangeFailed.connect(boost::bind(&MUCController::handleOccupantRoleChangeFailed, this, _1, _2, _3));
muc_->onAffiliationListReceived.connect(boost::bind(&MUCController::handleAffiliationListReceived, this, _1, _2));
muc_->onConfigurationFailed.connect(boost::bind(&MUCController::handleConfigurationFailed, this, _1));
muc_->onConfigurationFormReceived.connect(boost::bind(&MUCController::handleConfigurationFormReceived, this, _1));
highlighter_->setMode(isImpromptu_ ? Highlighter::ChatMode : Highlighter::MUCMode);
highlighter_->setNick(nick_);
if (timerFactory && stanzaChannel_->isAvailable()) {
loginCheckTimer_ = std::shared_ptr<Timer>(timerFactory->createTimer(MUC_JOIN_WARNING_TIMEOUT_MILLISECONDS));
loginCheckTimer_->onTick.connect(boost::bind(&MUCController::handleJoinTimeoutTick, this));
loginCheckTimer_->start();
}
@@ -152,61 +152,60 @@ MUCController::MUCController (
chatWindow_->setName(muc->getJID().getNode());
}
if (stanzaChannel->isAvailable()) {
MUCController::setOnline(true);
}
if (avatarManager_ != nullptr) {
avatarChangedConnection_ = (avatarManager_->onAvatarChanged.connect(boost::bind(&MUCController::handleAvatarChanged, this, _1)));
}
MUCController::handleBareJIDCapsChanged(muc->getJID());
eventStream_->onUIEvent.connect(boost::bind(&MUCController::handleUIEvent, this, _1));
// setup handling of MUC bookmark changes
mucBookmarkManagerBookmarkAddedConnection_ = (mucBookmarkManager_->onBookmarkAdded.connect(boost::bind(&MUCController::handleMUCBookmarkAdded, this, _1)));
mucBookmarkManagerBookmarkRemovedConnection_ = (mucBookmarkManager_->onBookmarkRemoved.connect(boost::bind(&MUCController::handleMUCBookmarkRemoved, this, _1)));
std::vector<MUCBookmark> mucBookmarks = mucBookmarkManager_->getBookmarks();
std::vector<MUCBookmark>::iterator bookmarkIterator = std::find_if(mucBookmarks.begin(), mucBookmarks.end(), MUCBookmarkPredicate(muc->getJID()));
if (bookmarkIterator != mucBookmarks.end()) {
updateChatWindowBookmarkStatus(*bookmarkIterator);
}
else {
updateChatWindowBookmarkStatus(boost::optional<MUCBookmark>());
}
}
MUCController::~MUCController() {
eventStream_->onUIEvent.disconnect(boost::bind(&MUCController::handleUIEvent, this, _1));
chatWindow_->setRosterModel(nullptr);
delete rosterVCardProvider_;
- delete roster_;
if (loginCheckTimer_) {
loginCheckTimer_->stop();
}
chatWindow_->setTabComplete(nullptr);
delete completer_;
}
void MUCController::cancelReplaces() {
lastWasPresence_ = false;
}
void MUCController::handleWindowOccupantSelectionChanged(ContactRosterItem* item) {
std::vector<ChatWindow::OccupantAction> actions;
if (item) {
MUCOccupant::Affiliation affiliation = muc_->getOccupant(getNick()).getAffiliation();
MUCOccupant::Role role = muc_->getOccupant(getNick()).getRole();
if (role == MUCOccupant::Moderator && !isImpromptu_)
{
if (affiliation == MUCOccupant::Admin || affiliation == MUCOccupant::Owner) {
actions.push_back(ChatWindow::Ban);
}
actions.push_back(ChatWindow::Kick);
actions.push_back(ChatWindow::MakeModerator);
actions.push_back(ChatWindow::MakeParticipant);
actions.push_back(ChatWindow::MakeVisitor);
}
// Add contact is available only if the real JID is also available
if (muc_->getOccupant(item->getJID().getResource()).getRealJID()) {
@@ -737,60 +736,65 @@ void MUCController::handleOccupantLeft(const MUCOccupant& occupant, MUC::Leaving
roster_->removeContact(JID(toJID_.getNode(), toJID_.getDomain(), occupant.getNick()));
} else {
addPresenceMessage(partMessage);
parting_ = true;
processUserPart();
}
if (clearAfter) {
clearPresenceQueue();
}
if (isImpromptu_) {
setImpromptuWindowTitle();
}
}
void MUCController::handleOccupantNicknameChanged(const std::string& oldNickname, const std::string& newNickname) {
addPresenceMessage(generateNicknameChangeString(oldNickname, newNickname));
JID oldJID = muc_->getJID().withResource(oldNickname);
JID newJID = muc_->getJID().withResource(newNickname);
// adjust occupants
currentOccupants_.erase(oldNickname);
currentOccupants_.insert(newNickname);
// adjust completer
completer_->removeWord(oldNickname);
completer_->addWord(newNickname);
// update contact
roster_->removeContact(oldJID);
+ auto it = currentOccupants_.find(newNickname);
+ if (it != currentOccupants_.end()) {
+ roster_->removeContact(newJID);
+ }
+
MUCOccupant occupant = muc_->getOccupant(newNickname);
JID realJID;
if (occupant.getRealJID()) {
realJID = occupant.getRealJID().get();
}
MUCOccupant::Role role = MUCOccupant::Participant;
MUCOccupant::Affiliation affiliation = MUCOccupant::NoAffiliation;
if (!isImpromptu_) {
role = occupant.getRole();
affiliation = occupant.getAffiliation();
}
std::string groupName(roleToGroupName(role));
roster_->addContact(newJID, realJID, newNickname, groupName, avatarManager_->getAvatarPath(newJID));
roster_->applyOnItems(SetMUC(newJID, role, affiliation));
if (avatarManager_ != nullptr) {
handleAvatarChanged(newJID);
}
clearPresenceQueue();
onUserNicknameChanged(oldNickname, newNickname);
}
void MUCController::handleOccupantPresenceChange(std::shared_ptr<Presence> presence) {
receivedActivity();
roster_->applyOnItems(SetPresence(presence, JID::WithResource));
}
bool MUCController::isIncomingMessageFromMe(std::shared_ptr<Message> message) {
JID from = message->getFrom();
diff --git a/Swift/Controllers/Chat/MUCController.h b/Swift/Controllers/Chat/MUCController.h
index 467f2e7..7aff627 100644
--- a/Swift/Controllers/Chat/MUCController.h
+++ b/Swift/Controllers/Chat/MUCController.h
@@ -27,61 +27,61 @@
#include <Swift/Controllers/UIInterfaces/ChatWindow.h>
namespace Swift {
class StanzaChannel;
class IQRouter;
class ChatWindowFactory;
class Roster;
class AvatarManager;
class UIEventStream;
class TimerFactory;
class TabComplete;
class XMPPRoster;
class HighlightManager;
class UIEvent;
class VCardManager;
class RosterVCardProvider;
class ClientBlockListManager;
class MUCBookmarkManager;
class MUCBookmark;
enum JoinPart {Join, Part, JoinThenPart, PartThenJoin};
struct NickJoinPart {
NickJoinPart(const std::string& nick, JoinPart type) : nick(nick), type(type) {}
std::string nick;
JoinPart type;
};
class MUCController : public ChatControllerBase {
public:
- MUCController(const JID& self, MUC::ref muc, const boost::optional<std::string>& password, const std::string &nick, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, PresenceOracle* presenceOracle, AvatarManager* avatarManager, UIEventStream* events, bool useDelayForLatency, TimerFactory* timerFactory, EventController* eventController, EntityCapsProvider* entityCapsProvider, XMPPRoster* roster, HistoryController* historyController, MUCRegistry* mucRegistry, HighlightManager* highlightManager, ClientBlockListManager* clientBlockListManager, std::shared_ptr<ChatMessageParser> chatMessageParser, bool isImpromptu, AutoAcceptMUCInviteDecider* autoAcceptMUCInviteDecider, VCardManager* vcardManager, MUCBookmarkManager* mucBookmarkManager);
+ MUCController(const JID& self, MUC::ref muc, const boost::optional<std::string>& password, const std::string &nick, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, PresenceOracle* presenceOracle, AvatarManager* avatarManager, UIEventStream* events, bool useDelayForLatency, TimerFactory* timerFactory, EventController* eventController, EntityCapsProvider* entityCapsProvider, XMPPRoster* xmppRoster, HistoryController* historyController, MUCRegistry* mucRegistry, HighlightManager* highlightManager, ClientBlockListManager* clientBlockListManager, std::shared_ptr<ChatMessageParser> chatMessageParser, bool isImpromptu, AutoAcceptMUCInviteDecider* autoAcceptMUCInviteDecider, VCardManager* vcardManager, MUCBookmarkManager* mucBookmarkManager);
virtual ~MUCController();
boost::signals2::signal<void ()> onUserLeft;
boost::signals2::signal<void ()> onUserJoined;
boost::signals2::signal<void ()> onImpromptuConfigCompleted;
boost::signals2::signal<void (const std::string&, const std::string& )> onUserNicknameChanged;
virtual void setOnline(bool online) SWIFTEN_OVERRIDE;
virtual void setAvailableServerFeatures(std::shared_ptr<DiscoInfo> info) SWIFTEN_OVERRIDE;
void rejoin();
static void appendToJoinParts(std::vector<NickJoinPart>& joinParts, const NickJoinPart& newEvent);
static std::string generateJoinPartString(const std::vector<NickJoinPart>& joinParts, bool isImpromptu);
static std::string concatenateListOfNames(const std::vector<NickJoinPart>& joinParts);
static std::string generateNicknameChangeString(const std::string& oldNickname, const std::string& newNickname);
bool isJoined();
const std::string& getNick();
const boost::optional<std::string> getPassword() const;
bool isImpromptu() const;
std::map<std::string, JID> getParticipantJIDs() const;
void sendInvites(const std::vector<JID>& jids, const std::string& reason) const;
protected:
virtual void preSendMessageRequest(std::shared_ptr<Message> message) SWIFTEN_OVERRIDE;
virtual bool isIncomingMessageFromMe(std::shared_ptr<Message> message) SWIFTEN_OVERRIDE;
virtual std::string senderHighlightNameFromMessage(const JID& from) SWIFTEN_OVERRIDE;
virtual std::string senderDisplayNameFromMessage(const JID& from) SWIFTEN_OVERRIDE;
virtual boost::optional<boost::posix_time::ptime> getMessageTimestamp(std::shared_ptr<Message> message) const SWIFTEN_OVERRIDE;
virtual void preHandleIncomingMessage(std::shared_ptr<MessageEvent>) SWIFTEN_OVERRIDE;
virtual void addMessageHandleIncomingMessage(const JID& from, const ChatWindow::ChatMessage& message, bool senderIsSelf, std::shared_ptr<SecurityLabel> label, const boost::posix_time::ptime& time) SWIFTEN_OVERRIDE;
virtual void postHandleIncomingMessage(std::shared_ptr<MessageEvent>, const ChatWindow::ChatMessage& chatMessage) SWIFTEN_OVERRIDE;
virtual void cancelReplaces() SWIFTEN_OVERRIDE;
virtual void logMessage(const std::string& message, const JID& fromJID, const JID& toJID, const boost::posix_time::ptime& timeStamp, bool isIncoming) SWIFTEN_OVERRIDE;
@@ -121,63 +121,63 @@ namespace Swift {
void handleConfigurationFormReceived(Form::ref);
void handleDestroyRoomRequest();
void handleInvitePersonToThisMUCRequest(const std::vector<JID>& jidsToInvite);
void handleConfigurationCancelled();
void handleOccupantRoleChangeFailed(ErrorPayload::ref, const JID&, MUCOccupant::Role);
void handleGetAffiliationsRequest();
void handleAffiliationListReceived(MUCOccupant::Affiliation affiliation, const std::vector<JID>& jids);
void handleChangeAffiliationsRequest(const std::vector<std::pair<MUCOccupant::Affiliation, JID> >& changes);
void handleInviteToMUCWindowDismissed();
void handleInviteToMUCWindowCompleted();
void handleUIEvent(std::shared_ptr<UIEvent> event);
void addRecentLogs();
void checkDuplicates(std::shared_ptr<Message> newMessage);
void setNick(const std::string& nick);
void setImpromptuWindowTitle();
void handleRoomUnlocked();
void configureAsImpromptuRoom(Form::ref form);
Form::ref buildImpromptuRoomConfiguration(Form::ref roomConfigurationForm);
void handleUnblockUserRequest();
void handleBlockingStateChanged();
void handleMUCBookmarkAdded(const MUCBookmark& bookmark);
void handleMUCBookmarkRemoved(const MUCBookmark& bookmark);
void updateChatWindowBookmarkStatus(const boost::optional<MUCBookmark>& bookmark);
private:
MUC::ref muc_;
std::string nick_;
std::string desiredNick_;
- Roster* roster_;
TabComplete* completer_;
bool parting_;
bool joined_;
bool shouldJoinOnReconnect_;
bool doneGettingHistory_;
boost::signals2::scoped_connection avatarChangedConnection_;
std::shared_ptr<Timer> loginCheckTimer_;
std::set<std::string> currentOccupants_;
std::vector<NickJoinPart> joinParts_;
boost::posix_time::ptime lastActivity_;
boost::optional<std::string> password_;
XMPPRoster* xmppRoster_;
+ std::unique_ptr<Roster> roster_;
std::vector<HistoryMessage> joinContext_;
size_t renameCounter_;
bool isImpromptu_;
bool isImpromptuAlreadyConfigured_;
RosterVCardProvider* rosterVCardProvider_;
std::string lastJoinMessageUID_;
ClientBlockListManager* clientBlockListManager_;
boost::signals2::scoped_connection blockingOnStateChangedConnection_;
boost::signals2::scoped_connection blockingOnItemAddedConnection_;
boost::signals2::scoped_connection blockingOnItemRemovedConnection_;
boost::optional<ChatWindow::AlertID> blockedContactAlert_;
MUCBookmarkManager* mucBookmarkManager_;
boost::signals2::scoped_connection mucBookmarkManagerBookmarkAddedConnection_;
boost::signals2::scoped_connection mucBookmarkManagerBookmarkRemovedConnection_;
};
}
diff --git a/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp b/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp
index 32639f6..59dcd77 100644
--- a/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp
+++ b/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp
@@ -35,60 +35,62 @@
#include <Swift/Controllers/Chat/MUCController.h>
#include <Swift/Controllers/Chat/UserSearchController.h>
#include <Swift/Controllers/Roster/GroupRosterItem.h>
#include <Swift/Controllers/Roster/Roster.h>
#include <Swift/Controllers/Settings/DummySettingsProvider.h>
#include <Swift/Controllers/UIEvents/UIEventStream.h>
#include <Swift/Controllers/UIInterfaces/ChatWindow.h>
#include <Swift/Controllers/UIInterfaces/ChatWindowFactory.h>
#include <Swift/Controllers/UIInterfaces/UserSearchWindowFactory.h>
#include <Swift/Controllers/UnitTest/MockChatWindow.h>
#include <Swift/Controllers/XMPPEvents/EventController.h>
using namespace Swift;
class MUCControllerTest : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(MUCControllerTest);
CPPUNIT_TEST(testJoinPartStringContructionSimple);
CPPUNIT_TEST(testJoinPartStringContructionMixed);
CPPUNIT_TEST(testAppendToJoinParts);
CPPUNIT_TEST(testAddressedToSelf);
CPPUNIT_TEST(testNotAddressedToSelf);
CPPUNIT_TEST(testAddressedToSelfBySelf);
CPPUNIT_TEST(testMessageWithEmptyLabelItem);
CPPUNIT_TEST(testMessageWithLabelItem);
CPPUNIT_TEST(testCorrectMessageWithLabelItem);
CPPUNIT_TEST(testRoleAffiliationStates);
CPPUNIT_TEST(testSubjectChangeCorrect);
CPPUNIT_TEST(testSubjectChangeIncorrectA);
CPPUNIT_TEST(testSubjectChangeIncorrectB);
CPPUNIT_TEST(testSubjectChangeIncorrectC);
+ CPPUNIT_TEST(testHandleOccupantNicknameChanged);
+ CPPUNIT_TEST(testHandleOccupantNicknameChangedRoster);
CPPUNIT_TEST_SUITE_END();
public:
void setUp() {
crypto_ = std::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create());
self_ = JID("girl@wonderland.lit/rabbithole");
nick_ = "aLiCe";
mucJID_ = JID("teaparty@rooms.wonderland.lit");
mocks_ = new MockRepository();
stanzaChannel_ = new DummyStanzaChannel();
iqChannel_ = new DummyIQChannel();
iqRouter_ = new IQRouter(iqChannel_);
eventController_ = new EventController();
chatWindowFactory_ = mocks_->InterfaceMock<ChatWindowFactory>();
userSearchWindowFactory_ = mocks_->InterfaceMock<UserSearchWindowFactory>();
xmppRoster_ = new XMPPRosterImpl();
presenceOracle_ = new PresenceOracle(stanzaChannel_, xmppRoster_);
presenceSender_ = new StanzaChannelPresenceSender(stanzaChannel_);
directedPresenceSender_ = new DirectedPresenceSender(presenceSender_);
uiEventStream_ = new UIEventStream();
avatarManager_ = new NullAvatarManager();
TimerFactory* timerFactory = nullptr;
window_ = new MockChatWindow();
mucRegistry_ = new MUCRegistry();
entityCapsProvider_ = new DummyEntityCapsProvider();
settings_ = new DummySettingsProvider();
highlightManager_ = new HighlightManager(settings_);
muc_ = std::make_shared<MockMUC>(mucJID_);
mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(muc_->getJID(), uiEventStream_).Return(window_);
chatMessageParser_ = std::make_shared<ChatMessageParser>(std::map<std::string, std::string>(), highlightManager_->getRules(), true);
@@ -474,60 +476,115 @@ public:
CPPUNIT_ASSERT_EQUAL(std::string("Trying to enter room teaparty@rooms.wonderland.lit"), std::dynamic_pointer_cast<ChatWindow::ChatTextMessagePart>(window_->lastAddedSystemMessage_.getParts()[0])->text);
}
}
/*
* Test that message stanzas with subject element and empty body element do not cause a subject change.
*/
void testSubjectChangeIncorrectC() {
std::string messageBody("test message");
window_->onSendMessageRequest(messageBody, false);
std::shared_ptr<Stanza> rawStanza = stanzaChannel_->sentStanzas[stanzaChannel_->sentStanzas.size() - 1];
Message::ref message = std::dynamic_pointer_cast<Message>(rawStanza);
CPPUNIT_ASSERT(stanzaChannel_->isAvailable()); /* Otherwise will prevent sends. */
CPPUNIT_ASSERT(message);
CPPUNIT_ASSERT_EQUAL(messageBody, message->getBody().get_value_or(""));
{
Message::ref message = std::make_shared<Message>();
message->setType(Message::Groupchat);
message->setTo(self_);
message->setFrom(mucJID_.withResource("SomeNickname"));
message->setID(iqChannel_->getNewIQID());
message->setSubject("New Room Subject");
message->setBody("");
controller_->handleIncomingMessage(std::make_shared<MessageEvent>(message));
CPPUNIT_ASSERT_EQUAL(std::string("Trying to enter room teaparty@rooms.wonderland.lit"), std::dynamic_pointer_cast<ChatWindow::ChatTextMessagePart>(window_->lastAddedSystemMessage_.getParts()[0])->text);
}
}
+ void testHandleOccupantNicknameChanged() {
+ const auto occupantCount = [&](const std::string & nick) {
+ auto roster = window_->getRosterModel();
+ CPPUNIT_ASSERT(roster != nullptr);
+ const auto currentOccupantsJIDs = roster->getJIDs();
+ int count = 0;
+ for (auto & p : currentOccupantsJIDs) {
+ if (p.getResource() == nick) {
+ ++count;
+ }
+ }
+ return count;
+ };
+
+ muc_->insertOccupant(MUCOccupant("TestUserOne", MUCOccupant::Participant, MUCOccupant::Owner));
+ muc_->insertOccupant(MUCOccupant("TestUserTwo", MUCOccupant::Participant, MUCOccupant::Owner));
+ muc_->insertOccupant(MUCOccupant("TestUserThree", MUCOccupant::Participant, MUCOccupant::Owner));
+
+ muc_->onOccupantNicknameChanged("TestUserOne", "TestUserTwo");
+
+ CPPUNIT_ASSERT_EQUAL(0, occupantCount("TestUserOne"));
+ CPPUNIT_ASSERT_EQUAL(1, occupantCount("TestUserTwo"));
+ CPPUNIT_ASSERT_EQUAL(1, occupantCount("TestUserThree"));
+ }
+
+ void testHandleOccupantNicknameChangedRoster() {
+ const auto occupantCount = [&](const std::string & nick) {
+ auto roster = window_->getRosterModel();
+ CPPUNIT_ASSERT(roster != nullptr);
+ const auto participants = roster->getGroup("Participants");
+ CPPUNIT_ASSERT(participants != nullptr);
+ const auto displayedParticipants = participants->getDisplayedChildren();
+ int count = 0;
+ for (auto & p : displayedParticipants) {
+ if (p->getDisplayName() == nick) {
+ ++count;
+ }
+ }
+ return count;
+ };
+
+ muc_->insertOccupant(MUCOccupant("TestUserOne", MUCOccupant::Participant, MUCOccupant::Owner));
+ muc_->insertOccupant(MUCOccupant("TestUserTwo", MUCOccupant::Participant, MUCOccupant::Owner));
+ muc_->insertOccupant(MUCOccupant("TestUserThree", MUCOccupant::Participant, MUCOccupant::Owner));
+ CPPUNIT_ASSERT_EQUAL(1, occupantCount("TestUserOne"));
+ CPPUNIT_ASSERT_EQUAL(1, occupantCount("TestUserTwo"));
+ CPPUNIT_ASSERT_EQUAL(1, occupantCount("TestUserThree"));
+
+ muc_->onOccupantNicknameChanged("TestUserOne", "TestUserTwo");
+
+ CPPUNIT_ASSERT_EQUAL(0, occupantCount("TestUserOne"));
+ CPPUNIT_ASSERT_EQUAL(1, occupantCount("TestUserTwo"));
+ CPPUNIT_ASSERT_EQUAL(1, occupantCount("TestUserThree"));
+ }
+
void testRoleAffiliationStatesVerify(const std::map<std::string, MUCOccupant> &occupants) {
/* verify that the roster is in sync */
GroupRosterItem* group = window_->getRosterModel()->getRoot();
for (auto rosterItem : group->getChildren()) {
GroupRosterItem* child = dynamic_cast<GroupRosterItem*>(rosterItem);
CPPUNIT_ASSERT(child);
for (auto childItem : child->getChildren()) {
ContactRosterItem* item = dynamic_cast<ContactRosterItem*>(childItem);
CPPUNIT_ASSERT(item);
std::map<std::string, MUCOccupant>::const_iterator occupant = occupants.find(item->getJID().getResource());
CPPUNIT_ASSERT(occupant != occupants.end());
CPPUNIT_ASSERT(item->getMUCRole() == occupant->second.getRole());
CPPUNIT_ASSERT(item->getMUCAffiliation() == occupant->second.getAffiliation());
}
}
}
private:
JID self_;
JID mucJID_;
MockMUC::ref muc_;
std::string nick_;
DummyStanzaChannel* stanzaChannel_;
DummyIQChannel* iqChannel_;
IQRouter* iqRouter_;
EventController* eventController_;
ChatWindowFactory* chatWindowFactory_;
UserSearchWindowFactory* userSearchWindowFactory_;
MUCController* controller_;
// NickResolver* nickResolver_;