mirror of
https://github.com/moodle/moodle.git
synced 2025-04-21 16:32:18 +02:00
Merge branch 'MDL-65060-master' of git://github.com/aanabit/moodle
This commit is contained in:
commit
d68718a7db
@ -95,6 +95,7 @@ class behat_partial_named_selector extends \Behat\Mink\Selector\PartialNamedSele
|
||||
'group_message_member' => 'group_message_member',
|
||||
'group_message_tab' => 'group_message_tab',
|
||||
'group_message_list_area' => 'group_message_list_area',
|
||||
'group_message_message_content' => 'group_message_message_content',
|
||||
'icon' => 'icon',
|
||||
'link' => 'link',
|
||||
'link_or_button' => 'link_or_button',
|
||||
@ -174,6 +175,9 @@ XPATH
|
||||
XPATH
|
||||
, 'group_message_list_area' => <<<XPATH
|
||||
.//*[@data-region='message-drawer']//*[contains(@data-region, concat('view-overview-', %locator%))]
|
||||
XPATH
|
||||
, 'group_message_message_content' => <<<XPATH
|
||||
.//*[@data-region='message-drawer']//*[@data-region='message' and @data-message-id and contains(., %locator%)]
|
||||
XPATH
|
||||
, 'icon' => <<<XPATH
|
||||
.//*[contains(concat(' ', normalize-space(@class), ' '), ' icon ') and ( contains(normalize-space(@title), %locator%))]
|
||||
|
@ -208,6 +208,11 @@ class behat_data_generators extends behat_base {
|
||||
'required' => array('user', 'contact'),
|
||||
'switchids' => array('user' => 'userid', 'contact' => 'contactid')
|
||||
),
|
||||
'group messages' => array(
|
||||
'datagenerator' => 'group_messages',
|
||||
'required' => array('user', 'group', 'message'),
|
||||
'switchids' => array('user' => 'userid', 'group' => 'groupid')
|
||||
),
|
||||
'language customisations' => array(
|
||||
'datagenerator' => 'customlang',
|
||||
'required' => array('component', 'stringid', 'value'),
|
||||
@ -956,6 +961,10 @@ class behat_data_generators extends behat_base {
|
||||
* @return void
|
||||
*/
|
||||
protected function process_private_messages(array $data) {
|
||||
if (empty($data['format'])) {
|
||||
$data['format'] = 'FORMAT_PLAIN';
|
||||
}
|
||||
|
||||
if (!$conversationid = \core_message\api::get_conversation_between_users([$data['userid'], $data['contactid']])) {
|
||||
$conversation = \core_message\api::create_conversation(
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
|
||||
@ -963,7 +972,48 @@ class behat_data_generators extends behat_base {
|
||||
);
|
||||
$conversationid = $conversation->id;
|
||||
}
|
||||
\core_message\api::send_message_to_conversation($data['userid'], $conversationid, $data['message'], FORMAT_PLAIN);
|
||||
\core_message\api::send_message_to_conversation(
|
||||
$data['userid'],
|
||||
$conversationid,
|
||||
$data['message'],
|
||||
constant($data['format'])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a new message from user to a group conversation
|
||||
*
|
||||
* @param array $data
|
||||
* @return void
|
||||
*/
|
||||
protected function process_group_messages(array $data) {
|
||||
global $DB;
|
||||
|
||||
if (empty($data['format'])) {
|
||||
$data['format'] = 'FORMAT_PLAIN';
|
||||
}
|
||||
|
||||
$group = $DB->get_record('groups', ['id' => $data['groupid']]);
|
||||
$coursecontext = context_course::instance($group->courseid);
|
||||
if (!$conversation = \core_message\api::get_conversation_by_area('core_group', 'groups', $data['groupid'],
|
||||
$coursecontext->id)) {
|
||||
$members = $DB->get_records_menu('groups_members', ['groupid' => $data['groupid']], '', 'userid, id');
|
||||
$conversation = \core_message\api::create_conversation(
|
||||
\core_message\api::MESSAGE_CONVERSATION_TYPE_GROUP,
|
||||
array_keys($members),
|
||||
$group->name,
|
||||
\core_message\api::MESSAGE_CONVERSATION_ENABLED,
|
||||
'core_group',
|
||||
'groups',
|
||||
$group->id,
|
||||
$coursecontext->id);
|
||||
}
|
||||
\core_message\api::send_message_to_conversation(
|
||||
$data['userid'],
|
||||
$conversation->id,
|
||||
$data['message'],
|
||||
constant($data['format'])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
File diff suppressed because one or more lines are too long
@ -97,11 +97,13 @@ function(
|
||||
var loadedAllMessages = false;
|
||||
var messagesOffset = 0;
|
||||
var newMessagesPollTimer = null;
|
||||
var isRendering = false;
|
||||
var renderBuffer = [];
|
||||
// If the UI is currently resetting.
|
||||
var isResetting = true;
|
||||
// If the UI is currently sending a message.
|
||||
var isSendingMessage = false;
|
||||
// This is the render function which will be generated when this module is
|
||||
// These functions which will be generated when this module is
|
||||
// first called. See generateRenderFunction for details.
|
||||
var render = null;
|
||||
// The list of renderers that have been registered to render
|
||||
@ -279,10 +281,9 @@ function(
|
||||
var conversationType = loggedInUserId == otherUserId ? CONVERSATION_TYPES.SELF : CONVERSATION_TYPES.PRIVATE;
|
||||
var newState = StateManager.setLoadingMembers(viewState, true);
|
||||
newState = StateManager.setLoadingMessages(newState, true);
|
||||
return render(newState)
|
||||
.then(function() {
|
||||
return Repository.getMemberInfo(loggedInUserId, [otherUserId], true, true);
|
||||
})
|
||||
render(newState);
|
||||
|
||||
return Repository.getMemberInfo(loggedInUserId, [otherUserId], true, true)
|
||||
.then(function(profiles) {
|
||||
if (profiles.length) {
|
||||
return profiles[0];
|
||||
@ -301,10 +302,8 @@ function(
|
||||
newState = StateManager.setType(newState, conversationType);
|
||||
newState = StateManager.setImageUrl(newState, profile.profileimageurl);
|
||||
newState = StateManager.setTotalMemberCount(newState, members.length);
|
||||
return render(newState)
|
||||
.then(function() {
|
||||
return profile;
|
||||
});
|
||||
render(newState);
|
||||
return profile;
|
||||
})
|
||||
.catch(function(error) {
|
||||
var newState = StateManager.setLoadingMembers(viewState, false);
|
||||
@ -374,20 +373,19 @@ function(
|
||||
var loggedInUserId = loggedInUserProfile.id;
|
||||
var newState = StateManager.setLoadingMembers(viewState, true);
|
||||
newState = StateManager.setLoadingMessages(newState, true);
|
||||
return render(newState)
|
||||
.then(function() {
|
||||
return Repository.getConversation(
|
||||
loggedInUserId,
|
||||
conversationId,
|
||||
true,
|
||||
true,
|
||||
0,
|
||||
0,
|
||||
messageLimit + 1,
|
||||
messageOffset,
|
||||
newestFirst
|
||||
);
|
||||
})
|
||||
render(newState);
|
||||
|
||||
return Repository.getConversation(
|
||||
loggedInUserId,
|
||||
conversationId,
|
||||
true,
|
||||
true,
|
||||
0,
|
||||
0,
|
||||
messageLimit + 1,
|
||||
messageOffset,
|
||||
newestFirst
|
||||
)
|
||||
.then(function(conversation) {
|
||||
if (conversation.messages.length > messageLimit) {
|
||||
conversation.messages = conversation.messages.slice(1);
|
||||
@ -450,37 +448,30 @@ function(
|
||||
conversation.members = conversation.members.concat([loggedInUserProfile]);
|
||||
}
|
||||
|
||||
var messageCount = conversation.messages.length;
|
||||
var hasLoadedEnoughMessages = messageCount >= messageLimit;
|
||||
var newState = updateStateFromConversation(conversation, loggedInUserProfile.id);
|
||||
newState = StateManager.setLoadingMembers(newState, false);
|
||||
newState = StateManager.setLoadingMessages(newState, true);
|
||||
var messageCount = conversation.messages.length;
|
||||
return render(newState)
|
||||
.then(function() {
|
||||
if (messageCount < messageLimit) {
|
||||
newState = StateManager.setLoadingMessages(newState, !hasLoadedEnoughMessages);
|
||||
var renderPromise = render(newState);
|
||||
|
||||
return renderPromise.then(function() {
|
||||
if (!hasLoadedEnoughMessages) {
|
||||
// We haven't got enough messages so let's load some more.
|
||||
return loadMessages(conversation.id, messageLimit, messageCount, newestFirst, [])
|
||||
.then(function(result) {
|
||||
// Give the list of messages to the next handler.
|
||||
return result.messages;
|
||||
});
|
||||
return loadMessages(conversation.id, messageLimit, messageCount, newestFirst, []);
|
||||
} else {
|
||||
// We've got enough messages. No need to load any more for now.
|
||||
var newState = StateManager.setLoadingMessages(viewState, false);
|
||||
return render(newState)
|
||||
.then(function() {
|
||||
// Give the list of messages to the next handler.
|
||||
return conversation.messages;
|
||||
});
|
||||
return {messages: conversation.messages};
|
||||
}
|
||||
})
|
||||
.then(function(messages) {
|
||||
.then(function() {
|
||||
var messages = viewState.messages;
|
||||
// Update the offset to reflect the number of messages we've loaded.
|
||||
setMessagesOffset(messages.length);
|
||||
markConversationAsRead(viewState.id);
|
||||
|
||||
return messages;
|
||||
})
|
||||
.then(function() {
|
||||
return markConversationAsRead(conversation.id);
|
||||
})
|
||||
.catch(Notification.exception);
|
||||
};
|
||||
|
||||
@ -627,14 +618,12 @@ function(
|
||||
* Tell the statemanager there is request to block a user and run the renderer
|
||||
* to show the block user dialogue.
|
||||
*
|
||||
* @param {Number} userId User id.
|
||||
* @return {Promise} Renderer promise.
|
||||
* @param {Number} userId User id.
|
||||
*/
|
||||
var requestBlockUser = function(userId) {
|
||||
return cancelRequest(userId).then(function() {
|
||||
var newState = StateManager.addPendingBlockUsersById(viewState, [userId]);
|
||||
return render(newState);
|
||||
});
|
||||
cancelRequest(userId);
|
||||
var newState = StateManager.addPendingBlockUsersById(viewState, [userId]);
|
||||
render(newState);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -646,10 +635,9 @@ function(
|
||||
*/
|
||||
var blockUser = function(userId) {
|
||||
var newState = StateManager.setLoadingConfirmAction(viewState, true);
|
||||
return render(newState)
|
||||
.then(function() {
|
||||
return Repository.blockUser(viewState.loggedInUserId, userId);
|
||||
})
|
||||
render(newState);
|
||||
|
||||
return Repository.blockUser(viewState.loggedInUserId, userId)
|
||||
.then(function(profile) {
|
||||
var newState = StateManager.addMembers(viewState, [profile]);
|
||||
newState = StateManager.removePendingBlockUsersById(newState, [userId]);
|
||||
@ -663,14 +651,12 @@ function(
|
||||
* Tell the statemanager there is a request to unblock a user and run the renderer
|
||||
* to show the unblock user dialogue.
|
||||
*
|
||||
* @param {Number} userId User id of user to unblock.
|
||||
* @return {Promise} Renderer promise.
|
||||
* @param {Number} userId User id of user to unblock.
|
||||
*/
|
||||
var requestUnblockUser = function(userId) {
|
||||
return cancelRequest(userId).then(function() {
|
||||
var newState = StateManager.addPendingUnblockUsersById(viewState, [userId]);
|
||||
return render(newState);
|
||||
});
|
||||
cancelRequest(userId);
|
||||
var newState = StateManager.addPendingUnblockUsersById(viewState, [userId]);
|
||||
render(newState);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -682,10 +668,9 @@ function(
|
||||
*/
|
||||
var unblockUser = function(userId) {
|
||||
var newState = StateManager.setLoadingConfirmAction(viewState, true);
|
||||
return render(newState)
|
||||
.then(function() {
|
||||
return Repository.unblockUser(viewState.loggedInUserId, userId);
|
||||
})
|
||||
render(newState);
|
||||
|
||||
return Repository.unblockUser(viewState.loggedInUserId, userId)
|
||||
.then(function(profile) {
|
||||
var newState = StateManager.addMembers(viewState, [profile]);
|
||||
newState = StateManager.removePendingUnblockUsersById(newState, [userId]);
|
||||
@ -699,14 +684,12 @@ function(
|
||||
* Tell the statemanager there is a request to remove a user from the contact list
|
||||
* and run the renderer to show the remove user from contacts dialogue.
|
||||
*
|
||||
* @param {Number} userId User id of user to remove from contacts.
|
||||
* @return {Promise} Renderer promise.
|
||||
* @param {Number} userId User id of user to remove from contacts.
|
||||
*/
|
||||
var requestRemoveContact = function(userId) {
|
||||
return cancelRequest(userId).then(function() {
|
||||
var newState = StateManager.addPendingRemoveContactsById(viewState, [userId]);
|
||||
return render(newState);
|
||||
});
|
||||
cancelRequest(userId);
|
||||
var newState = StateManager.addPendingRemoveContactsById(viewState, [userId]);
|
||||
render(newState);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -718,10 +701,9 @@ function(
|
||||
*/
|
||||
var removeContact = function(userId) {
|
||||
var newState = StateManager.setLoadingConfirmAction(viewState, true);
|
||||
return render(newState)
|
||||
.then(function() {
|
||||
return Repository.deleteContacts(viewState.loggedInUserId, [userId]);
|
||||
})
|
||||
render(newState);
|
||||
|
||||
return Repository.deleteContacts(viewState.loggedInUserId, [userId])
|
||||
.then(function(profiles) {
|
||||
var newState = StateManager.addMembers(viewState, profiles);
|
||||
newState = StateManager.removePendingRemoveContactsById(newState, [userId]);
|
||||
@ -735,14 +717,12 @@ function(
|
||||
* Tell the statemanager there is a request to add a user to the contact list
|
||||
* and run the renderer to show the add user to contacts dialogue.
|
||||
*
|
||||
* @param {Number} userId User id of user to add to contacts.
|
||||
* @return {Promise} Renderer promise.
|
||||
* @param {Number} userId User id of user to add to contacts.
|
||||
*/
|
||||
var requestAddContact = function(userId) {
|
||||
return cancelRequest(userId).then(function() {
|
||||
var newState = StateManager.addPendingAddContactsById(viewState, [userId]);
|
||||
return render(newState);
|
||||
});
|
||||
cancelRequest(userId);
|
||||
var newState = StateManager.addPendingAddContactsById(viewState, [userId]);
|
||||
render(newState);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -754,10 +734,9 @@ function(
|
||||
*/
|
||||
var addContact = function(userId) {
|
||||
var newState = StateManager.setLoadingConfirmAction(viewState, true);
|
||||
return render(newState)
|
||||
.then(function() {
|
||||
return Repository.createContactRequest(viewState.loggedInUserId, userId);
|
||||
})
|
||||
render(newState);
|
||||
|
||||
return Repository.createContactRequest(viewState.loggedInUserId, userId)
|
||||
.then(function(response) {
|
||||
if (!response.request) {
|
||||
throw new Error(response.warnings[0].message);
|
||||
@ -865,15 +844,13 @@ function(
|
||||
* Tell the statemanager there is a request to delete the selected messages
|
||||
* and run the renderer to show confirm delete messages dialogue.
|
||||
*
|
||||
* @param {Number} userId User id.
|
||||
* @return {Promise} Renderer promise.
|
||||
* @param {Number} userId User id.
|
||||
*/
|
||||
var requestDeleteSelectedMessages = function(userId) {
|
||||
var selectedMessageIds = viewState.selectedMessageIds;
|
||||
return cancelRequest(userId).then(function() {
|
||||
var newState = StateManager.addPendingDeleteMessagesById(viewState, selectedMessageIds);
|
||||
return render(newState);
|
||||
});
|
||||
cancelRequest(userId);
|
||||
var newState = StateManager.addPendingDeleteMessagesById(viewState, selectedMessageIds);
|
||||
render(newState);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -885,15 +862,18 @@ function(
|
||||
var deleteSelectedMessages = function() {
|
||||
var messageIds = viewState.pendingDeleteMessageIds;
|
||||
var newState = StateManager.setLoadingConfirmAction(viewState, true);
|
||||
return render(newState)
|
||||
.then(function() {
|
||||
if (newState.deleteMessagesForAllUsers) {
|
||||
return Repository.deleteMessagesForAllUsers(viewState.loggedInUserId, messageIds);
|
||||
}
|
||||
|
||||
return Repository.deleteMessages(viewState.loggedInUserId, messageIds);
|
||||
})
|
||||
.then(function() {
|
||||
render(newState);
|
||||
|
||||
var deleteMessagesPromise = null;
|
||||
|
||||
if (newState.deleteMessagesForAllUsers) {
|
||||
deleteMessagesPromise = Repository.deleteMessagesForAllUsers(viewState.loggedInUserId, messageIds);
|
||||
} else {
|
||||
deleteMessagesPromise = Repository.deleteMessages(viewState.loggedInUserId, messageIds);
|
||||
}
|
||||
|
||||
return deleteMessagesPromise.then(function() {
|
||||
var newState = StateManager.removeMessagesById(viewState, messageIds);
|
||||
newState = StateManager.removePendingDeleteMessagesById(newState, messageIds);
|
||||
newState = StateManager.removeSelectedMessagesById(newState, messageIds);
|
||||
@ -918,14 +898,12 @@ function(
|
||||
* Tell the statemanager there is a request to delete a conversation
|
||||
* and run the renderer to show confirm delete conversation dialogue.
|
||||
*
|
||||
* @param {Number} userId User id of other user.
|
||||
* @return {Promise} Renderer promise.
|
||||
* @param {Number} userId User id of other user.
|
||||
*/
|
||||
var requestDeleteConversation = function(userId) {
|
||||
return cancelRequest(userId).then(function() {
|
||||
var newState = StateManager.setPendingDeleteConversation(viewState, true);
|
||||
return render(newState);
|
||||
});
|
||||
cancelRequest(userId);
|
||||
var newState = StateManager.setPendingDeleteConversation(viewState, true);
|
||||
render(newState);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -936,10 +914,9 @@ function(
|
||||
*/
|
||||
var deleteConversation = function() {
|
||||
var newState = StateManager.setLoadingConfirmAction(viewState, true);
|
||||
return render(newState)
|
||||
.then(function() {
|
||||
return Repository.deleteConversation(viewState.loggedInUserId, viewState.id);
|
||||
})
|
||||
render(newState);
|
||||
|
||||
return Repository.deleteConversation(viewState.loggedInUserId, viewState.id)
|
||||
.then(function() {
|
||||
var newState = StateManager.removeMessages(viewState, viewState.messages);
|
||||
newState = StateManager.removeSelectedMessagesById(newState, viewState.selectedMessageIds);
|
||||
@ -955,7 +932,6 @@ function(
|
||||
* Tell the statemanager to cancel all pending actions.
|
||||
*
|
||||
* @param {Number} userId User id.
|
||||
* @return {Promise} Renderer promise.
|
||||
*/
|
||||
var cancelRequest = function(userId) {
|
||||
var pendingDeleteMessageIds = viewState.pendingDeleteMessageIds;
|
||||
@ -966,7 +942,7 @@ function(
|
||||
newState = StateManager.removePendingDeleteMessagesById(newState, pendingDeleteMessageIds);
|
||||
newState = StateManager.setPendingDeleteConversation(newState, false);
|
||||
newState = StateManager.setDeleteMessagesForAllUsers(newState, false);
|
||||
return render(newState);
|
||||
render(newState);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -984,10 +960,9 @@ function(
|
||||
});
|
||||
var request = requests[0];
|
||||
var newState = StateManager.setLoadingConfirmAction(viewState, true);
|
||||
return render(newState)
|
||||
.then(function() {
|
||||
return Repository.acceptContactRequest(userId, loggedInUserId);
|
||||
})
|
||||
render(newState);
|
||||
|
||||
return Repository.acceptContactRequest(userId, loggedInUserId)
|
||||
.then(function(profile) {
|
||||
var newState = StateManager.removeContactRequests(viewState, [request]);
|
||||
newState = StateManager.addMembers(viewState, [profile]);
|
||||
@ -1016,10 +991,9 @@ function(
|
||||
});
|
||||
var request = requests[0];
|
||||
var newState = StateManager.setLoadingConfirmAction(viewState, true);
|
||||
return render(newState)
|
||||
.then(function() {
|
||||
return Repository.declineContactRequest(userId, loggedInUserId);
|
||||
})
|
||||
render(newState);
|
||||
|
||||
return Repository.declineContactRequest(userId, loggedInUserId)
|
||||
.then(function(profile) {
|
||||
var newState = StateManager.removeContactRequests(viewState, [request]);
|
||||
newState = StateManager.addMembers(viewState, [profile]);
|
||||
@ -1044,24 +1018,26 @@ function(
|
||||
isSendingMessage = true;
|
||||
var newState = StateManager.setSendingMessage(viewState, true);
|
||||
var newConversationId = null;
|
||||
var newCanDeleteMessagesForAllUsers = false;
|
||||
return render(newState)
|
||||
.then(function() {
|
||||
if (!conversationId && (viewState.type != CONVERSATION_TYPES.PUBLIC)) {
|
||||
// If it's a new private conversation then we need to use the old
|
||||
// web service function to create the conversation.
|
||||
var otherUserId = getOtherUserId();
|
||||
return Repository.sendMessageToUser(otherUserId, text)
|
||||
.then(function(message) {
|
||||
newConversationId = parseInt(message.conversationid, 10);
|
||||
newCanDeleteMessagesForAllUsers = message.candeletemessagesforallusers;
|
||||
return message;
|
||||
});
|
||||
} else {
|
||||
return Repository.sendMessageToConversation(conversationId, text);
|
||||
}
|
||||
})
|
||||
.then(function(message) {
|
||||
|
||||
render(newState);
|
||||
|
||||
var sendMessagePromise = null;
|
||||
var newCanDeleteMessagesForAllUsers = null;
|
||||
if (!conversationId && (viewState.type != CONVERSATION_TYPES.PUBLIC)) {
|
||||
// If it's a new private conversation then we need to use the old
|
||||
// web service function to create the conversation.
|
||||
var otherUserId = getOtherUserId();
|
||||
sendMessagePromise = Repository.sendMessageToUser(otherUserId, text)
|
||||
.then(function(message) {
|
||||
newConversationId = parseInt(message.conversationid, 10);
|
||||
newCanDeleteMessagesForAllUsers = message.candeletemessagesforallusers;
|
||||
return message;
|
||||
});
|
||||
} else {
|
||||
sendMessagePromise = Repository.sendMessageToConversation(conversationId, text);
|
||||
}
|
||||
|
||||
sendMessagePromise.then(function(message) {
|
||||
var newState = StateManager.addMessages(viewState, [message]);
|
||||
newState = StateManager.setSendingMessage(newState, false);
|
||||
var conversation = formatConversationForEvent(newState);
|
||||
@ -1076,12 +1052,10 @@ function(
|
||||
newState = StateManager.setCanDeleteMessagesForAllUsers(newState, newCanDeleteMessagesForAllUsers);
|
||||
}
|
||||
|
||||
return render(newState)
|
||||
.then(function() {
|
||||
isSendingMessage = false;
|
||||
PubSub.publish(MessageDrawerEvents.CONVERSATION_NEW_LAST_MESSAGE, conversation);
|
||||
return;
|
||||
});
|
||||
render(newState);
|
||||
isSendingMessage = false;
|
||||
PubSub.publish(MessageDrawerEvents.CONVERSATION_NEW_LAST_MESSAGE, conversation);
|
||||
return;
|
||||
})
|
||||
.catch(function(error) {
|
||||
isSendingMessage = false;
|
||||
@ -1095,7 +1069,6 @@ function(
|
||||
* Toggle the selected messages update the statemanager and render the result.
|
||||
*
|
||||
* @param {Number} messageId The id of the message to be toggled
|
||||
* @return {Promise} Renderer promise.
|
||||
*/
|
||||
var toggleSelectMessage = function(messageId) {
|
||||
var newState = viewState;
|
||||
@ -1106,7 +1079,7 @@ function(
|
||||
newState = StateManager.addSelectedMessagesById(viewState, [messageId]);
|
||||
}
|
||||
|
||||
return render(newState);
|
||||
render(newState);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1115,10 +1088,45 @@ function(
|
||||
* @return {Promise} Renderer promise.
|
||||
*/
|
||||
var cancelEditMode = function() {
|
||||
return cancelRequest(getOtherUserId())
|
||||
cancelRequest(getOtherUserId());
|
||||
var newState = StateManager.removeSelectedMessagesById(viewState, viewState.selectedMessageIds);
|
||||
render(newState);
|
||||
};
|
||||
|
||||
/**
|
||||
* Process the patches in the render buffer one at a time in order until the
|
||||
* buffer is empty.
|
||||
*
|
||||
* @param {Object} header The conversation header container element.
|
||||
* @param {Object} body The conversation body container element.
|
||||
* @param {Object} footer The conversation footer container element.
|
||||
*/
|
||||
var processRenderBuffer = function(header, body, footer) {
|
||||
if (isRendering) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!renderBuffer.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
isRendering = true;
|
||||
var renderable = renderBuffer.shift();
|
||||
var renderPromises = renderers.map(function(renderFunc) {
|
||||
return renderFunc(renderable.patch);
|
||||
});
|
||||
|
||||
$.when.apply(null, renderPromises)
|
||||
.then(function() {
|
||||
var newState = StateManager.removeSelectedMessagesById(viewState, viewState.selectedMessageIds);
|
||||
return render(newState);
|
||||
isRendering = false;
|
||||
renderable.deferred.resolve(true);
|
||||
// Keep processing the buffer until it's empty.
|
||||
processRenderBuffer(header, body, footer);
|
||||
})
|
||||
.catch(function(error) {
|
||||
isRendering = false;
|
||||
renderable.deferred.reject(error);
|
||||
Notification.exception(error);
|
||||
});
|
||||
};
|
||||
|
||||
@ -1148,25 +1156,39 @@ function(
|
||||
|
||||
return function(newState) {
|
||||
var patch = Patcher.buildPatch(viewState, newState);
|
||||
var deferred = $.Deferred();
|
||||
|
||||
// Check if the patch has any data. Ignore empty patches.
|
||||
if (Object.keys(patch).length) {
|
||||
// Add the patch to the render buffer which gets processed in order.
|
||||
renderBuffer.push({
|
||||
patch: patch,
|
||||
deferred: deferred
|
||||
});
|
||||
} else {
|
||||
deferred.resolve(true);
|
||||
}
|
||||
// This is a great place to add in some console logging if you need
|
||||
// to debug something. You can log the current state, the next state,
|
||||
// and the generated patch and see exactly what will be updated.
|
||||
var renderPromises = renderers.map(function(renderFunc) {
|
||||
return renderFunc(patch);
|
||||
});
|
||||
return $.when.apply(null, renderPromises)
|
||||
.then(function() {
|
||||
viewState = newState;
|
||||
if (newState.id) {
|
||||
// Only cache created conversations.
|
||||
stateCache[newState.id] = {
|
||||
state: newState,
|
||||
messagesOffset: getMessagesOffset(),
|
||||
loadedAllMessages: hasLoadedAllMessages()
|
||||
};
|
||||
}
|
||||
return;
|
||||
});
|
||||
|
||||
// Optimistically update the state. We're going to assume that the rendering
|
||||
// will always succeed. The rendering is asynchronous (annoyingly) so it's buffered
|
||||
// but it'll reach eventual consistency with the current state.
|
||||
viewState = newState;
|
||||
if (newState.id) {
|
||||
// Only cache created conversations.
|
||||
stateCache[newState.id] = {
|
||||
state: newState,
|
||||
messagesOffset: getMessagesOffset(),
|
||||
loadedAllMessages: hasLoadedAllMessages()
|
||||
};
|
||||
}
|
||||
|
||||
// Start processing the buffer.
|
||||
processRenderBuffer(header, body, footer);
|
||||
|
||||
return deferred.promise();
|
||||
};
|
||||
};
|
||||
|
||||
@ -1179,12 +1201,9 @@ function(
|
||||
var generateConfirmActionHandler = function(actionCallback) {
|
||||
return function(e, data) {
|
||||
if (!viewState.loadingConfirmAction) {
|
||||
actionCallback(getOtherUserId())
|
||||
.catch(function(error) {
|
||||
var newState = StateManager.setLoadingConfirmAction(viewState, false);
|
||||
render(newState);
|
||||
Notification.exception(error);
|
||||
});
|
||||
actionCallback(getOtherUserId());
|
||||
var newState = StateManager.setLoadingConfirmAction(viewState, false);
|
||||
render(newState);
|
||||
}
|
||||
data.originalEvent.preventDefault();
|
||||
};
|
||||
@ -1232,7 +1251,7 @@ function(
|
||||
var element = target.closest(SELECTORS.MESSAGE);
|
||||
var messageId = parseInt(element.attr('data-message-id'), 10);
|
||||
|
||||
toggleSelectMessage(messageId).catch(Notification.exception);
|
||||
toggleSelectMessage(messageId);
|
||||
|
||||
data.originalEvent.preventDefault();
|
||||
};
|
||||
@ -1244,7 +1263,7 @@ function(
|
||||
* @param {Object} data Data for this event.
|
||||
*/
|
||||
var handleCancelEditMode = function(e, data) {
|
||||
cancelEditMode().catch(Notification.exception);
|
||||
cancelEditMode();
|
||||
data.originalEvent.preventDefault();
|
||||
};
|
||||
|
||||
@ -1413,10 +1432,9 @@ function(
|
||||
if (!isResetting && !isLoadingMoreMessages && !hasLoadedAllMessages() && hasMembers) {
|
||||
isLoadingMoreMessages = true;
|
||||
var newState = StateManager.setLoadingMessages(viewState, true);
|
||||
render(newState)
|
||||
.then(function() {
|
||||
return loadMessages(viewState.id, LOAD_MESSAGE_LIMIT, getMessagesOffset(), NEWEST_FIRST, []);
|
||||
})
|
||||
render(newState);
|
||||
|
||||
loadMessages(viewState.id, LOAD_MESSAGE_LIMIT, getMessagesOffset(), NEWEST_FIRST, [])
|
||||
.then(function() {
|
||||
isLoadingMoreMessages = false;
|
||||
setMessagesOffset(getMessagesOffset() + LOAD_MESSAGE_LIMIT);
|
||||
@ -1495,9 +1513,15 @@ function(
|
||||
* @param {Object} body Conversation body container element.
|
||||
* @param {Number|null} conversationId The conversation id.
|
||||
* @param {Object} loggedInUserProfile The logged in user's profile.
|
||||
* @return {Promise} Renderer promise.
|
||||
*/
|
||||
var resetState = function(body, conversationId, loggedInUserProfile) {
|
||||
// Reset all of the states back to the beginning if we're loading a new
|
||||
// conversation.
|
||||
isResetting = true;
|
||||
isRendering = false;
|
||||
renderBuffer = [];
|
||||
isSendingMessage = false;
|
||||
|
||||
var loggedInUserId = loggedInUserProfile.id;
|
||||
var midnight = parseInt(body.attr('data-midnight'), 10);
|
||||
var initialState = StateManager.buildInitialState(midnight, loggedInUserId, conversationId);
|
||||
@ -1510,7 +1534,7 @@ function(
|
||||
newMessagesPollTimer.stop();
|
||||
}
|
||||
|
||||
return render(initialState);
|
||||
render(initialState);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1524,32 +1548,34 @@ function(
|
||||
var resetNoConversation = function(body, loggedInUserProfile, otherUserId) {
|
||||
// Always reset the state back to the initial state so that the
|
||||
// state manager and patcher can work correctly.
|
||||
return resetState(body, null, loggedInUserProfile)
|
||||
.then(function() {
|
||||
if (loggedInUserProfile.id != otherUserId) {
|
||||
// Private conversation between two different users.
|
||||
return Repository.getConversationBetweenUsers(
|
||||
loggedInUserProfile.id,
|
||||
otherUserId,
|
||||
true,
|
||||
true,
|
||||
0,
|
||||
0,
|
||||
LOAD_MESSAGE_LIMIT,
|
||||
0,
|
||||
NEWEST_FIRST
|
||||
);
|
||||
} else {
|
||||
// Self conversation.
|
||||
return Repository.getSelfConversation(
|
||||
loggedInUserProfile.id,
|
||||
LOAD_MESSAGE_LIMIT,
|
||||
0,
|
||||
NEWEST_FIRST
|
||||
);
|
||||
}
|
||||
})
|
||||
.then(function(conversation) {
|
||||
resetState(body, null, loggedInUserProfile);
|
||||
|
||||
var resetNoConversationPromise = null;
|
||||
|
||||
if (loggedInUserProfile.id != otherUserId) {
|
||||
// Private conversation between two different users.
|
||||
resetNoConversationPromise = Repository.getConversationBetweenUsers(
|
||||
loggedInUserProfile.id,
|
||||
otherUserId,
|
||||
true,
|
||||
true,
|
||||
0,
|
||||
0,
|
||||
LOAD_MESSAGE_LIMIT,
|
||||
0,
|
||||
NEWEST_FIRST
|
||||
);
|
||||
} else {
|
||||
// Self conversation.
|
||||
resetNoConversationPromise = Repository.getSelfConversation(
|
||||
loggedInUserProfile.id,
|
||||
LOAD_MESSAGE_LIMIT,
|
||||
0,
|
||||
NEWEST_FIRST
|
||||
);
|
||||
}
|
||||
|
||||
return resetNoConversationPromise.then(function(conversation) {
|
||||
// Looks like we have a conversation after all! Let's use that.
|
||||
return resetByConversation(body, conversation, loggedInUserProfile);
|
||||
})
|
||||
@ -1575,31 +1601,32 @@ function(
|
||||
|
||||
// Always reset the state back to the initial state so that the
|
||||
// state manager and patcher can work correctly.
|
||||
return resetState(body, conversationId, loggedInUserProfile)
|
||||
.then(function() {
|
||||
if (cache) {
|
||||
// We've seen this conversation before so there is no need to
|
||||
// send any network requests.
|
||||
var newState = cache.state;
|
||||
// Reset some loading states just in case they were left weirdly.
|
||||
newState = StateManager.setLoadingMessages(newState, false);
|
||||
newState = StateManager.setLoadingMembers(newState, false);
|
||||
setMessagesOffset(cache.messagesOffset);
|
||||
setLoadedAllMessages(cache.loadedAllMessages);
|
||||
return render(newState);
|
||||
} else {
|
||||
return loadNewConversation(
|
||||
conversationId,
|
||||
loggedInUserProfile,
|
||||
LOAD_MESSAGE_LIMIT,
|
||||
0,
|
||||
NEWEST_FIRST
|
||||
);
|
||||
}
|
||||
})
|
||||
.then(function() {
|
||||
return resetMessagePollTimer(conversationId);
|
||||
});
|
||||
resetState(body, conversationId, loggedInUserProfile);
|
||||
|
||||
var promise = $.Deferred().resolve({}).promise();
|
||||
if (cache) {
|
||||
// We've seen this conversation before so there is no need to
|
||||
// send any network requests.
|
||||
var newState = cache.state;
|
||||
// Reset some loading states just in case they were left weirdly.
|
||||
newState = StateManager.setLoadingMessages(newState, false);
|
||||
newState = StateManager.setLoadingMembers(newState, false);
|
||||
setMessagesOffset(cache.messagesOffset);
|
||||
setLoadedAllMessages(cache.loadedAllMessages);
|
||||
render(newState);
|
||||
} else {
|
||||
promise = loadNewConversation(
|
||||
conversationId,
|
||||
loggedInUserProfile,
|
||||
LOAD_MESSAGE_LIMIT,
|
||||
0,
|
||||
NEWEST_FIRST
|
||||
);
|
||||
}
|
||||
|
||||
return promise.then(function() {
|
||||
return resetMessagePollTimer(conversationId);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1618,30 +1645,31 @@ function(
|
||||
|
||||
// Always reset the state back to the initial state so that the
|
||||
// state manager and patcher can work correctly.
|
||||
return resetState(body, conversation.id, loggedInUserProfile)
|
||||
.then(function() {
|
||||
if (cache) {
|
||||
// We've seen this conversation before so there is no need to
|
||||
// send any network requests.
|
||||
var newState = cache.state;
|
||||
// Reset some loading states just in case they were left weirdly.
|
||||
newState = StateManager.setLoadingMessages(newState, false);
|
||||
newState = StateManager.setLoadingMembers(newState, false);
|
||||
setMessagesOffset(cache.messagesOffset);
|
||||
setLoadedAllMessages(cache.loadedAllMessages);
|
||||
return render(newState);
|
||||
} else {
|
||||
return loadExistingConversation(
|
||||
conversation,
|
||||
loggedInUserProfile,
|
||||
LOAD_MESSAGE_LIMIT,
|
||||
NEWEST_FIRST
|
||||
);
|
||||
}
|
||||
})
|
||||
.then(function() {
|
||||
return resetMessagePollTimer(conversation.id);
|
||||
});
|
||||
resetState(body, conversation.id, loggedInUserProfile);
|
||||
|
||||
var promise = $.Deferred().resolve({}).promise();
|
||||
if (cache) {
|
||||
// We've seen this conversation before so there is no need to
|
||||
// send any network requests.
|
||||
var newState = cache.state;
|
||||
// Reset some loading states just in case they were left weirdly.
|
||||
newState = StateManager.setLoadingMessages(newState, false);
|
||||
newState = StateManager.setLoadingMembers(newState, false);
|
||||
setMessagesOffset(cache.messagesOffset);
|
||||
setLoadedAllMessages(cache.loadedAllMessages);
|
||||
render(newState);
|
||||
} else {
|
||||
promise = loadExistingConversation(
|
||||
conversation,
|
||||
loggedInUserProfile,
|
||||
LOAD_MESSAGE_LIMIT,
|
||||
NEWEST_FIRST
|
||||
);
|
||||
}
|
||||
|
||||
return promise.then(function() {
|
||||
return resetMessagePollTimer(conversation.id);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1702,9 +1730,6 @@ function(
|
||||
}
|
||||
|
||||
if (isNewConversation) {
|
||||
// Reset all of the states back to the beginning if we're loading a new
|
||||
// conversation.
|
||||
isResetting = true;
|
||||
var renderPromise = null;
|
||||
var loggedInUserProfile = getLoggedInUserProfile(body);
|
||||
if (conversation) {
|
||||
|
268
message/tests/behat/delete_messages.feature
Normal file
268
message/tests/behat/delete_messages.feature
Normal file
@ -0,0 +1,268 @@
|
||||
@core @core_message @javascript
|
||||
Feature: Delete messages from conversations
|
||||
In order to manage a course group in a course
|
||||
As a user
|
||||
I need to be able to delete messages from conversations
|
||||
|
||||
Background:
|
||||
Given the following "courses" exist:
|
||||
| fullname | shortname | category | groupmode |
|
||||
| Course 1 | C1 | 0 | 1 |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| student1 | Student | 1 | student1@example.com |
|
||||
| student2 | Student | 2 | student2@example.com |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| student1 | C1 | student |
|
||||
| student2 | C1 | student |
|
||||
And the following "groups" exist:
|
||||
| name | course | idnumber | enablemessaging |
|
||||
| Group 1 | C1 | G1 | 1 |
|
||||
And the following "group members" exist:
|
||||
| user | group |
|
||||
| student1 | G1 |
|
||||
| student2 | G1 |
|
||||
And the following "group messages" exist:
|
||||
| user | group | message |
|
||||
| student1 | G1 | Hi! |
|
||||
| student2 | G1 | How are you? |
|
||||
| student1 | G1 | Can somebody help me? |
|
||||
And the following "private messages" exist:
|
||||
| user | contact | message |
|
||||
| student1 | student2 | Hi! |
|
||||
| student2 | student1 | Hello! |
|
||||
| student1 | student2 | Are you free? |
|
||||
And the following config values are set as admin:
|
||||
| messaging | 1 |
|
||||
|
||||
Scenario: Delete a message sent by the user from a group conversation
|
||||
Given I log in as "student1"
|
||||
And I open messaging
|
||||
And "Group 1" "group_message" should exist
|
||||
And I select "Group 1" conversation in messaging
|
||||
And I click on "Hi!" "group_message_message_content"
|
||||
And I click on "How are you?" "group_message_message_content"
|
||||
And I click on "Can somebody help me?" "group_message_message_content"
|
||||
And I should see "3" in the "[data-region='message-selected-court']" "css_element"
|
||||
# Clicking to unselect
|
||||
And I click on "How are you?" "group_message_message_content"
|
||||
And I click on "Can somebody help me?" "group_message_message_content"
|
||||
And I should see "1" in the "[data-region='message-selected-court']" "css_element"
|
||||
And "Delete selected messages" "button" should exist
|
||||
When I click on "Delete selected messages" "button"
|
||||
# Deleting, so messages should not be there
|
||||
And I should see "Delete"
|
||||
And I click on "//button[@data-action='confirm-delete-selected-messages']" "xpath_element"
|
||||
Then I should not see "Delete"
|
||||
And I should not see "Hi!"
|
||||
And I should see "##today##j F##" in the "Group 1" "group_message_conversation"
|
||||
And I should see "How are you?" in the "Group 1" "group_message_conversation"
|
||||
And I should see "Can somebody help me?" in the "Group 1" "group_message_conversation"
|
||||
And I should not see "Messages selected"
|
||||
|
||||
Scenario: Delete two messages from a group conversation; one sent by another user.
|
||||
Given I log in as "student1"
|
||||
And I open messaging
|
||||
And "Group 1" "group_message" should exist
|
||||
And I select "Group 1" conversation in messaging
|
||||
And I click on "Hi!" "group_message_message_content"
|
||||
And I should see "1" in the "[data-region='message-selected-court']" "css_element"
|
||||
And I click on "How are you?" "group_message_message_content"
|
||||
And I should see "2" in the "[data-region='message-selected-court']" "css_element"
|
||||
And "Delete selected messages" "button" should exist
|
||||
When I click on "Delete selected messages" "button"
|
||||
# Deleting, so messages should not be there
|
||||
And I should see "Delete"
|
||||
And I click on "//button[@data-action='confirm-delete-selected-messages']" "xpath_element"
|
||||
Then I should not see "Delete"
|
||||
And I should not see "Hi!"
|
||||
And I should see "##today##j F##" in the "Group 1" "group_message_conversation"
|
||||
And I should not see "How are you?" in the "Group 1" "group_message_conversation"
|
||||
And I should see "Can somebody help me?" in the "Group 1" "group_message_conversation"
|
||||
And I should not see "Messages selected"
|
||||
# Check messages were not deleted for other users
|
||||
And I log out
|
||||
And I log in as "student2"
|
||||
And I open messaging
|
||||
And I select "Group 1" conversation in messaging
|
||||
And I should see "Hi!"
|
||||
And I should see "How are you?"
|
||||
And I should see "Can somebody help me?"
|
||||
|
||||
Scenario: Cancel deleting two messages from a group conversation
|
||||
Given I log in as "student1"
|
||||
And I open messaging
|
||||
And "Group 1" "group_message" should exist
|
||||
And I select "Group 1" conversation in messaging
|
||||
And I click on "Hi!" "group_message_message_content"
|
||||
And I click on "How are you?" "group_message_message_content"
|
||||
And "Delete selected messages" "button" should exist
|
||||
When I click on "Delete selected messages" "button"
|
||||
# Canceling deletion, so messages should be there
|
||||
And I should see "Cancel"
|
||||
And I click on "//button[@data-action='cancel-confirm']" "xpath_element"
|
||||
Then I should not see "Cancel"
|
||||
And I should see "Hi!"
|
||||
And I should see "How are you?" in the "Group 1" "group_message_conversation"
|
||||
And I should see "2" in the "[data-region='message-selected-court']" "css_element"
|
||||
|
||||
Scenario: Delete a message sent by the user from a private conversation
|
||||
Given I log in as "student1"
|
||||
And I open messaging
|
||||
And I should see "Private"
|
||||
And I open the "Private" conversations list
|
||||
And I should see "Student 2"
|
||||
And I select "Student 2" conversation in messaging
|
||||
And I click on "Hi!" "group_message_message_content"
|
||||
And I should see "1" in the "[data-region='message-selected-court']" "css_element"
|
||||
And "Delete selected messages" "button" should exist
|
||||
When I click on "Delete selected messages" "button"
|
||||
# Deleting, so messages should not be there
|
||||
And I should see "Delete"
|
||||
And I click on "//button[@data-action='confirm-delete-selected-messages']" "xpath_element"
|
||||
Then I should not see "Delete"
|
||||
And I should not see "Hi!"
|
||||
And I should see "##today##j F##" in the "Student 2" "group_message_conversation"
|
||||
And I should see "Hello!" in the "Student 2" "group_message_conversation"
|
||||
And I should see "Are you free?" in the "Student 2" "group_message_conversation"
|
||||
And I should not see "Messages selected"
|
||||
|
||||
Scenario: Delete two messages from a private conversation; one sent by another user
|
||||
Given I log in as "student1"
|
||||
And I open messaging
|
||||
And I should see "Private"
|
||||
And I open the "Private" conversations list
|
||||
And I should see "Student 2"
|
||||
And I select "Student 2" conversation in messaging
|
||||
And I click on "Hi!" "group_message_message_content"
|
||||
And I should see "1" in the "[data-region='message-selected-court']" "css_element"
|
||||
And I click on "Hello!" "group_message_message_content"
|
||||
And I should see "2" in the "[data-region='message-selected-court']" "css_element"
|
||||
And "Delete selected messages" "button" should exist
|
||||
When I click on "Delete selected messages" "button"
|
||||
# Deleting, so messages should not be there
|
||||
And I should see "Delete"
|
||||
And I click on "//button[@data-action='confirm-delete-selected-messages']" "xpath_element"
|
||||
Then I should not see "Delete"
|
||||
And I should not see "Hi!"
|
||||
And I should not see "Hello!" in the "Student 2" "group_message_conversation"
|
||||
And I should see "##today##j F##" in the "Student 2" "group_message_conversation"
|
||||
And I should see "Are you free?" in the "Student 2" "group_message_conversation"
|
||||
And I should not see "Messages selected"
|
||||
# Check messages were not deleted for the other user
|
||||
And I log out
|
||||
And I log in as "student2"
|
||||
And I open messaging
|
||||
And I open the "Private" conversations list
|
||||
And I select "Student 1" conversation in messaging
|
||||
And I should see "Hi!"
|
||||
And I should see "Hello!"
|
||||
And I should see "Are you free?"
|
||||
|
||||
Scenario: Cancel deleting two messages from a private conversation
|
||||
Given I log in as "student1"
|
||||
And I open messaging
|
||||
And I should see "Private"
|
||||
And I open the "Private" conversations list
|
||||
And I should see "Student 2"
|
||||
And I select "Student 2" conversation in messaging
|
||||
And I click on "Hi!" "group_message_message_content"
|
||||
And I click on "Hello!" "group_message_message_content"
|
||||
And "Delete selected messages" "button" should exist
|
||||
When I click on "Delete selected messages" "button"
|
||||
# Canceling deletion, so messages should be there
|
||||
And I should see "Cancel"
|
||||
And I click on "//button[@data-action='cancel-confirm']" "xpath_element"
|
||||
Then I should not see "Cancel"
|
||||
And I should see "Hi!"
|
||||
And I should see "Hello!" in the "Student 2" "group_message_conversation"
|
||||
And I should see "2" in the "[data-region='message-selected-court']" "css_element"
|
||||
|
||||
Scenario: Delete a message sent by the user from a favorite conversation
|
||||
Given the following "favourite conversations" exist:
|
||||
| user | contact |
|
||||
| student1 | student2 |
|
||||
And I log in as "student1"
|
||||
And I open messaging
|
||||
And I should see "Student 2"
|
||||
And I select "Student 2" conversation in messaging
|
||||
And I click on "Hi!" "group_message_message_content"
|
||||
And I should see "1" in the "[data-region='message-selected-court']" "css_element"
|
||||
And "Delete selected messages" "button" should exist
|
||||
When I click on "Delete selected messages" "button"
|
||||
# Deleting, so messages should not be there
|
||||
And I should see "Delete"
|
||||
And I click on "//button[@data-action='confirm-delete-selected-messages']" "xpath_element"
|
||||
Then I should not see "Delete"
|
||||
And I should not see "Hi!"
|
||||
And I should see "##today##j F##" in the "Student 2" "group_message_conversation"
|
||||
And I should see "Hello!" in the "Student 2" "group_message_conversation"
|
||||
And I should not see "Messages selected"
|
||||
|
||||
Scenario: Delete two messages from a favourite conversation; one sent by another user
|
||||
Given the following "favourite conversations" exist:
|
||||
| user | contact |
|
||||
| student1 | student2 |
|
||||
And I log in as "student1"
|
||||
And I open messaging
|
||||
And I should see "Student 2"
|
||||
And I select "Student 2" conversation in messaging
|
||||
And I click on "Hi!" "group_message_message_content"
|
||||
And I should see "1" in the "[data-region='message-selected-court']" "css_element"
|
||||
And I click on "Hello!" "group_message_message_content"
|
||||
And I should see "2" in the "[data-region='message-selected-court']" "css_element"
|
||||
And "Delete selected messages" "button" should exist
|
||||
When I click on "Delete selected messages" "button"
|
||||
# Deleting, so messages should not be there
|
||||
And I should see "Delete"
|
||||
And I click on "//button[@data-action='confirm-delete-selected-messages']" "xpath_element"
|
||||
Then I should not see "Delete"
|
||||
And I should not see "Hi!"
|
||||
And I should not see "Hello!" in the "Student 2" "group_message_conversation"
|
||||
And I should see "##today##j F##" in the "Student 2" "group_message_conversation"
|
||||
And I should see "Are you free?" in the "Student 2" "group_message_conversation"
|
||||
And I should not see "Messages selected"
|
||||
|
||||
Scenario: Cancel deleting two messages from a favourite conversation
|
||||
Given the following "favourite conversations" exist:
|
||||
| user | contact |
|
||||
| student1 | student2 |
|
||||
And I log in as "student1"
|
||||
And I open messaging
|
||||
And I should see "Student 2"
|
||||
And I select "Student 2" conversation in messaging
|
||||
And I click on "Hi!" "group_message_message_content"
|
||||
And I click on "Hello!" "group_message_message_content"
|
||||
And "Delete selected messages" "button" should exist
|
||||
When I click on "Delete selected messages" "button"
|
||||
# Canceling deletion, so messages should be there
|
||||
And I should see "Cancel"
|
||||
And I click on "//button[@data-action='cancel-confirm']" "xpath_element"
|
||||
Then I should not see "Cancel"
|
||||
And I should see "Hi!"
|
||||
And I should see "Hello!" in the "Student 2" "group_message_conversation"
|
||||
And I should see "2" in the "[data-region='message-selected-court']" "css_element"
|
||||
|
||||
Scenario: Check an empty favourite conversation is still favourite
|
||||
Given the following "favourite conversations" exist:
|
||||
| user | contact |
|
||||
| student1 | student2 |
|
||||
And I log in as "student1"
|
||||
And I open messaging
|
||||
And I should see "Student 2"
|
||||
And I select "Student 2" conversation in the "favourites" conversations list
|
||||
And I click on "Hi!" "group_message_message_content"
|
||||
And I click on "Hello!" "group_message_message_content"
|
||||
And I click on "Are you free?" "group_message_message_content"
|
||||
And "Delete selected messages" "button" should exist
|
||||
When I click on "Delete selected messages" "button"
|
||||
And I should see "Delete"
|
||||
And I click on "//button[@data-action='confirm-delete-selected-messages']" "xpath_element"
|
||||
And I go back in "view-conversation" message drawer
|
||||
Then I should not see "Student 2" in the "//*[@data-region='message-drawer']//div[@data-region='view-overview-favourites']" "xpath_element"
|
||||
And I send "Hi!" message to "Student 2" user
|
||||
And I go back in "view-conversation" message drawer
|
||||
And I go back in "view-search" message drawer
|
||||
And I open the "Starred" conversations list
|
||||
And I should see "Student 2" in the "//*[@data-region='message-drawer']//div[@data-region='view-overview-favourites']" "xpath_element"
|
Loading…
x
Reference in New Issue
Block a user