From a021485b2e3ca02ed0a65da2ae96d85a16ce7404 Mon Sep 17 00:00:00 2001 From: knovokresch Date: Tue, 20 Mar 2018 21:32:38 +0300 Subject: [PATCH] copy_and_paste.js: Support copying recipient headers from several topics. Algorithm for copying messages from serveral topics was changed: - if there are selected messages from more than 1 recipient block then the recipient bar headers are copied; - If there are multiple messages from only one recipient block then recipient bar header is not copied. Fixes #7217. Also adds a full suite of Casper tests for the copy-paste functionality. --- .../casper_tests/16-copy-and-paste.js | 167 ++++++++++++++++++ static/js/copy_and_paste.js | 21 ++- 2 files changed, 186 insertions(+), 2 deletions(-) create mode 100644 frontend_tests/casper_tests/16-copy-and-paste.js diff --git a/frontend_tests/casper_tests/16-copy-and-paste.js b/frontend_tests/casper_tests/16-copy-and-paste.js new file mode 100644 index 0000000000..ee428deb3b --- /dev/null +++ b/frontend_tests/casper_tests/16-copy-and-paste.js @@ -0,0 +1,167 @@ +var common = require('../casper_lib/common.js').common; + +common.start_and_log_in(); + +casper.then(function () { + casper.test.info('Sending messages'); +}); + +// setup environment: several messages to different topics +common.then_send_many([ + { stream: 'Verona', subject: 'copy-paste-subject #1', + content: 'copy paste test A' }, + + { stream: 'Verona', subject: 'copy-paste-subject #1', + content: 'copy paste test B' }, + + { stream: 'Verona', subject: 'copy-paste-subject #2', + content: 'copy paste test C' }, + + { stream: 'Verona', subject: 'copy-paste-subject #2', + content: 'copy paste test D' }, + + { stream: 'Verona', subject: 'copy-paste-subject #2', + content: 'copy paste test E' }, + + { stream: 'Verona', subject: 'copy-paste-subject #3', + content: 'copy paste test F' }, + + { stream: 'Verona', subject: 'copy-paste-subject #3', + content: 'copy paste test G' }, +]); + +common.wait_for_receive(function () { + common.expected_messages('zhome', [ + 'Verona > copy-paste-subject #1', + 'Verona > copy-paste-subject #2', + 'Verona > copy-paste-subject #3', + ], [ + '

copy paste test A

', + '

copy paste test B

', + '

copy paste test C

', + '

copy paste test D

', + '

copy paste test E

', + '

copy paste test F

', + '

copy paste test G

', + ]); +}); + +casper.then(function () { + casper.test.info('Messages were sent successfully'); +}); + +function get_message_node(message) { + return $('.message_row .message_content:contains("' + message + '")').get(0); +} + +function copy_messages(start_message, end_message) { + return casper.evaluate(function (get_message_node, start_message, end_message) { + // select messages from start_message to end_message + var selectedRange = document.createRange(); + selectedRange.setStart(get_message_node(start_message)); + selectedRange.setEnd(get_message_node(end_message)); + window.getSelection().removeAllRanges(); + window.getSelection().addRange(selectedRange); + + // emulate copy event + var event = document.createEvent('Event'); + event.initEvent('copy', true, true); + document.dispatchEvent(event); + + // find temp div with copied text + var temp_div = $('#copytempdiv'); + return temp_div.children('p').get().map(function (p) { return p.textContent; }); + }, { + get_message_node: get_message_node, + start_message: start_message, + end_message: end_message, + }); +} + +// test copying first message from topic +casper.then(function () { + var actual_copied_lines = copy_messages('copy paste test C', 'copy paste test C'); + var expected_copied_lines = []; + casper.test.assertEquals(actual_copied_lines, expected_copied_lines, 'Copying was handled by browser'); +}); + +// test copying last message from topic +casper.then(function () { + var actual_copied_lines = copy_messages('copy paste test E', 'copy paste test E'); + var expected_copied_lines = []; + casper.test.assertEquals(actual_copied_lines, expected_copied_lines, 'Copying was handled by browser'); +}); + +// test copying two first messages from topic +casper.then(function () { + var actual_copied_lines = copy_messages('copy paste test C', 'copy paste test D'); + var expected_copied_lines = ['Iago: copy paste test C', 'Iago: copy paste test D']; + casper.test.assertEquals(actual_copied_lines, expected_copied_lines, 'Copying was handled by custom handler'); +}); + +// test copying all messages from topic +casper.then(function () { + var actual_copied_lines = copy_messages('copy paste test C', 'copy paste test E'); + var expected_copied_lines = ['Iago: copy paste test C', 'Iago: copy paste test D', 'Iago: copy paste test E']; + casper.test.assertEquals(actual_copied_lines, expected_copied_lines, 'Copying was handled by custom handler'); +}); + +// test copying last message from previous topic and first message from next topic +casper.then(function () { + var actual_copied_lines = copy_messages('copy paste test B', 'copy paste test C'); + var expected_copied_lines = [ + 'Verona > copy-paste-subject #1 Today', + 'Iago: copy paste test B', + 'Verona > copy-paste-subject #2 Today', + 'Iago: copy paste test C', + ]; + casper.test.assertEquals(actual_copied_lines, expected_copied_lines, 'Copying was handled by custom handler'); +}); + +// test copying last message from previous topic and all messages from next topic +casper.then(function () { + var actual_copied_lines = copy_messages('copy paste test B', 'copy paste test E'); + var expected_copied_lines = [ + 'Verona > copy-paste-subject #1 Today', + 'Iago: copy paste test B', + 'Verona > copy-paste-subject #2 Today', + 'Iago: copy paste test C', + 'Iago: copy paste test D', + 'Iago: copy paste test E', + ]; + casper.test.assertEquals(actual_copied_lines, expected_copied_lines, 'Copying was handled by custom handler'); +}); + +// test copying all messages from previous topic and first message from next topic +casper.then(function () { + var actual_copied_lines = copy_messages('copy paste test A', 'copy paste test C'); + var expected_copied_lines = [ + 'Verona > copy-paste-subject #1 Today', + 'Iago: copy paste test A', + 'Iago: copy paste test B', + 'Verona > copy-paste-subject #2 Today', + 'Iago: copy paste test C', + ]; + casper.test.assertEquals(actual_copied_lines, expected_copied_lines, 'Copying was handled by custom handler'); +}); + +// test copying message from several topics +casper.then(function () { + var actual_copied_lines = copy_messages('copy paste test B', 'copy paste test F'); + var expected_copied_lines = [ + 'Verona > copy-paste-subject #1 Today', + 'Iago: copy paste test B', + 'Verona > copy-paste-subject #2 Today', + 'Iago: copy paste test C', + 'Iago: copy paste test D', + 'Iago: copy paste test E', + 'Verona > copy-paste-subject #3 Today', + 'Iago: copy paste test F', + ]; + casper.test.assertEquals(actual_copied_lines, expected_copied_lines, 'Copying was handled by custom handler'); +}); + +// Run the above queued actions. +casper.run(function () { + casper.test.done(); +}); diff --git a/static/js/copy_and_paste.js b/static/js/copy_and_paste.js index 5454501085..4e9c15624d 100644 --- a/static/js/copy_and_paste.js +++ b/static/js/copy_and_paste.js @@ -44,11 +44,24 @@ function construct_recipient_header(message_row) { } function construct_copy_div(div, start_id, end_id) { - for (var row = current_msg_list.get_row(start_id); + var start_row = current_msg_list.get_row(start_id); + var start_recipient_row = rows.get_message_recipient_row(start_row); + var start_recipient_row_id = rows.id_for_recipient_row(start_recipient_row); + var should_include_start_recipient_header = false; + + var last_recipient_row_id = start_recipient_row_id; + for (var row = start_row; rows.id(row) <= end_id; row = rows.next_visible(row)) { - if (row.prev().hasClass("message_header")) { + var recipient_row_id = rows.id_for_recipient_row(rows.get_message_recipient_row(row)); + // if we found a message from another recipient, + // it means that we have messages from several recipients, + // so we have to add new recipient's bar to final copied message + // and wouldn't forget to add start_recipient's bar at the beginning of final message + if (recipient_row_id !== last_recipient_row_id) { div.append(construct_recipient_header(row)); + last_recipient_row_id = recipient_row_id; + should_include_start_recipient_header = true; } var message = current_msg_list.get(rows.id(row)); var message_firstp = $(message.content).slice(0, 1); @@ -56,6 +69,10 @@ function construct_copy_div(div, start_id, end_id) { div.append(message_firstp); div.append($(message.content).slice(1)); } + + if (should_include_start_recipient_header) { + div.prepend(construct_recipient_header(start_row)); + } } function copy_handler() {