2020-08-01 03:43:15 +02:00
|
|
|
"use strict";
|
|
|
|
|
2020-11-30 23:46:45 +01:00
|
|
|
const {strict: assert} = require("assert");
|
|
|
|
|
2020-12-01 00:19:42 +01:00
|
|
|
const {stub_templates} = require("../zjsunit/handlebars");
|
2021-03-06 19:05:17 +01:00
|
|
|
const {mock_module, set_global, zrequire} = require("../zjsunit/namespace");
|
2021-02-13 03:46:14 +01:00
|
|
|
const {make_stub} = require("../zjsunit/stub");
|
2020-12-01 00:39:47 +01:00
|
|
|
const {run_test} = require("../zjsunit/test");
|
2021-02-21 15:38:51 +01:00
|
|
|
const $ = require("../zjsunit/zjquery");
|
2020-12-01 00:02:16 +01:00
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
set_global("document", "document-stub");
|
2017-03-26 20:20:42 +02:00
|
|
|
|
2021-02-25 19:10:42 +01:00
|
|
|
const alice_user_id = 5;
|
2020-07-15 01:29:15 +02:00
|
|
|
set_global("page_params", {
|
2021-02-25 19:10:42 +01:00
|
|
|
user_id: alice_user_id,
|
2020-07-24 01:21:48 +02:00
|
|
|
});
|
|
|
|
|
2021-03-06 19:05:17 +01:00
|
|
|
const channel = mock_module("channel");
|
2021-02-28 01:26:16 +01:00
|
|
|
const emoji_picker = {
|
2020-07-20 22:18:43 +02:00
|
|
|
hide_emoji_popover() {},
|
2021-02-28 01:26:16 +01:00
|
|
|
};
|
|
|
|
|
2021-03-06 19:05:17 +01:00
|
|
|
mock_module("emoji_picker", emoji_picker);
|
2019-11-02 00:06:25 +01:00
|
|
|
const message = {
|
2017-05-28 16:18:12 +02:00
|
|
|
id: 1001,
|
|
|
|
reactions: [
|
2020-06-30 21:16:29 +02:00
|
|
|
{emoji_name: "smile", user_id: 5, reaction_type: "unicode_emoji", emoji_code: "1f642"},
|
|
|
|
{emoji_name: "smile", user_id: 6, reaction_type: "unicode_emoji", emoji_code: "1f642"},
|
2020-07-15 01:29:15 +02:00
|
|
|
{emoji_name: "frown", user_id: 7, reaction_type: "unicode_emoji", emoji_code: "1f641"},
|
2020-10-21 15:09:10 +02:00
|
|
|
|
|
|
|
{emoji_name: "tada", user_id: 7, reaction_type: "unicode_emoji", emoji_code: "1f389"},
|
|
|
|
{emoji_name: "tada", user_id: 8, reaction_type: "unicode_emoji", emoji_code: "1f389"},
|
|
|
|
|
|
|
|
{emoji_name: "rocket", user_id: 5, reaction_type: "unicode_emoji", emoji_code: "1f680"},
|
|
|
|
{emoji_name: "rocket", user_id: 6, reaction_type: "unicode_emoji", emoji_code: "1f680"},
|
|
|
|
{emoji_name: "rocket", user_id: 7, reaction_type: "unicode_emoji", emoji_code: "1f680"},
|
|
|
|
|
|
|
|
{emoji_name: "wave", user_id: 6, reaction_type: "unicode_emoji", emoji_code: "1f44b"},
|
|
|
|
{emoji_name: "wave", user_id: 7, reaction_type: "unicode_emoji", emoji_code: "1f44b"},
|
|
|
|
{emoji_name: "wave", user_id: 8, reaction_type: "unicode_emoji", emoji_code: "1f44b"},
|
|
|
|
|
2020-07-15 00:34:28 +02:00
|
|
|
{
|
|
|
|
emoji_name: "inactive_realm_emoji",
|
|
|
|
user_id: 5,
|
|
|
|
reaction_type: "realm_emoji",
|
|
|
|
emoji_code: "992",
|
|
|
|
},
|
2017-03-26 20:20:42 +02:00
|
|
|
|
2017-05-28 16:18:12 +02:00
|
|
|
// add some bogus user_ids
|
2020-07-15 01:29:15 +02:00
|
|
|
{emoji_name: "octopus", user_id: 8888, reaction_type: "unicode_emoji", emoji_code: "1f419"},
|
|
|
|
{emoji_name: "frown", user_id: 9999, reaction_type: "unicode_emoji", emoji_code: "1f641"},
|
2017-05-28 16:18:12 +02:00
|
|
|
],
|
|
|
|
};
|
|
|
|
|
2021-02-28 01:10:03 +01:00
|
|
|
const message_store = {
|
2020-07-20 22:18:43 +02:00
|
|
|
get(message_id) {
|
2017-05-28 16:18:12 +02:00
|
|
|
assert.equal(message_id, 1001);
|
|
|
|
return message;
|
|
|
|
},
|
2021-02-28 01:10:03 +01:00
|
|
|
};
|
|
|
|
|
2021-03-06 19:05:17 +01:00
|
|
|
mock_module("message_store", message_store);
|
2020-07-15 01:29:15 +02:00
|
|
|
set_global("current_msg_list", {
|
2020-07-20 22:18:43 +02:00
|
|
|
selected_message() {
|
2020-07-16 22:40:18 +02:00
|
|
|
return {sent_by_me: true};
|
2017-09-18 22:06:39 +02:00
|
|
|
},
|
2020-07-20 22:18:43 +02:00
|
|
|
selected_row() {
|
2020-07-15 01:29:15 +02:00
|
|
|
return $(".selected-row");
|
2017-09-18 22:06:39 +02:00
|
|
|
},
|
2020-07-20 22:18:43 +02:00
|
|
|
selected_id() {
|
2017-09-18 22:06:39 +02:00
|
|
|
return 42;
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
zjsunit: Remove rewiremock dependency.
We now just use a module._load hook to inject
stubs into our code.
For conversion purposes I temporarily maintain
the API of rewiremock, apart from the enable/disable
pieces, but I will make a better wrapper in an
upcoming commit.
We can detect when rewiremock is called after
zrequire now, and I fix all the violations in
this commit, mostly by using override.
We can also detect when a mock is needlessly
created, and I fix all the violations in this
commit.
The one minor nuisance that this commit introduces
is that you can only stub out modules in the Zulip
source tree, which is now static/js. This should
not really be a problem--there are usually better
techniques to deal with third party depenencies.
In the prior commit I show a typical workaround,
which is to create a one-line wrapper in your
test code. It's often the case that you can simply
use override(), as well.
In passing I kill off `reset_modules`, and I
eliminated the second argument to zrequire,
which dates back to pre-es6 days.
2021-03-06 12:47:54 +01:00
|
|
|
const emoji_codes = zrequire("../generated/emoji/emoji_codes.json");
|
|
|
|
const emoji = zrequire("../shared/js/emoji");
|
2020-12-01 23:21:38 +01:00
|
|
|
const people = zrequire("people");
|
|
|
|
const reactions = zrequire("reactions");
|
|
|
|
|
|
|
|
const emoji_params = {
|
|
|
|
realm_emoji: {
|
|
|
|
991: {
|
|
|
|
id: "991",
|
|
|
|
name: "realm_emoji",
|
|
|
|
source_url: "/url/for/991",
|
|
|
|
deactivated: false,
|
|
|
|
},
|
|
|
|
992: {
|
|
|
|
id: "992",
|
|
|
|
name: "inactive_realm_emoji",
|
|
|
|
source_url: "/url/for/992",
|
|
|
|
deactivated: true,
|
|
|
|
},
|
|
|
|
zulip: {
|
|
|
|
id: "zulip",
|
|
|
|
name: "zulip",
|
|
|
|
source_url: "/url/for/zulip",
|
|
|
|
deactivated: false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
emoji_codes,
|
|
|
|
};
|
|
|
|
|
|
|
|
emoji.initialize(emoji_params);
|
|
|
|
|
|
|
|
const alice = {
|
|
|
|
email: "alice@example.com",
|
|
|
|
user_id: alice_user_id,
|
|
|
|
full_name: "Alice",
|
|
|
|
};
|
|
|
|
const bob = {
|
|
|
|
email: "bob@example.com",
|
|
|
|
user_id: 6,
|
|
|
|
full_name: "Bob van Roberts",
|
|
|
|
};
|
|
|
|
const cali = {
|
|
|
|
email: "cali@example.com",
|
|
|
|
user_id: 7,
|
|
|
|
full_name: "Cali",
|
|
|
|
};
|
|
|
|
const alexus = {
|
|
|
|
email: "alexus@example.com",
|
|
|
|
user_id: 8,
|
|
|
|
full_name: "Alexus",
|
|
|
|
};
|
|
|
|
people.add_active_user(alice);
|
|
|
|
people.add_active_user(bob);
|
|
|
|
people.add_active_user(cali);
|
|
|
|
people.add_active_user(alexus);
|
|
|
|
|
2021-02-24 16:50:30 +01:00
|
|
|
run_test("open_reactions_popover (sent by me)", () => {
|
|
|
|
current_msg_list.selected_message = () => ({sent_by_me: true});
|
2021-02-22 17:01:29 +01:00
|
|
|
$(".selected-row").set_find_results(".actions_hover", ["action-stub"]);
|
2017-09-18 22:06:39 +02:00
|
|
|
|
2019-11-02 00:06:25 +01:00
|
|
|
let called = false;
|
2021-02-23 14:37:26 +01:00
|
|
|
emoji_picker.toggle_emoji_popover = (target, id) => {
|
2017-09-18 22:06:39 +02:00
|
|
|
called = true;
|
|
|
|
assert.equal(id, 42);
|
2021-02-22 17:01:29 +01:00
|
|
|
assert.equal(target, "action-stub");
|
2017-09-18 22:06:39 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
assert(reactions.open_reactions_popover());
|
|
|
|
assert(called);
|
2021-02-24 16:50:30 +01:00
|
|
|
});
|
2017-09-18 22:06:39 +02:00
|
|
|
|
2021-02-24 16:50:30 +01:00
|
|
|
run_test("open_reactions_popover (not sent by me)", () => {
|
2021-02-23 14:37:26 +01:00
|
|
|
current_msg_list.selected_message = () => ({sent_by_me: false});
|
2021-02-24 16:50:30 +01:00
|
|
|
$(".selected-row").set_find_results(".reaction_button", ["reaction-stub"]);
|
2017-09-18 22:06:39 +02:00
|
|
|
|
2021-02-24 16:50:30 +01:00
|
|
|
let called = false;
|
2021-02-23 14:37:26 +01:00
|
|
|
emoji_picker.toggle_emoji_popover = (target, id) => {
|
2017-09-18 22:06:39 +02:00
|
|
|
called = true;
|
|
|
|
assert.equal(id, 42);
|
2021-02-22 17:01:29 +01:00
|
|
|
assert.equal(target, "reaction-stub");
|
2017-09-18 22:06:39 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
assert(reactions.open_reactions_popover());
|
|
|
|
assert(called);
|
2018-05-15 12:40:07 +02:00
|
|
|
});
|
2017-09-18 22:06:39 +02:00
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
run_test("basics", () => {
|
|
|
|
blueslip.expect("warn", "Unknown user_id 8888 in reaction for message 1001");
|
|
|
|
blueslip.expect("warn", "Unknown user_id 9999 in reaction for message 1001");
|
2019-11-02 00:06:25 +01:00
|
|
|
const result = reactions.get_message_reactions(message);
|
2020-06-30 21:16:29 +02:00
|
|
|
assert(reactions.current_user_has_reacted_to_emoji(message, "unicode_emoji,1f642"));
|
2020-07-15 01:29:15 +02:00
|
|
|
assert(!reactions.current_user_has_reacted_to_emoji(message, "bogus"));
|
2017-05-11 17:00:24 +02:00
|
|
|
|
2020-07-02 01:45:54 +02:00
|
|
|
result.sort((a, b) => a.count - b.count);
|
2017-03-26 20:20:42 +02:00
|
|
|
|
2019-11-02 00:06:25 +01:00
|
|
|
const expected_result = [
|
2018-05-07 03:30:13 +02:00
|
|
|
{
|
2020-07-15 01:29:15 +02:00
|
|
|
emoji_name: "frown",
|
|
|
|
reaction_type: "unicode_emoji",
|
|
|
|
emoji_code: "1f641",
|
|
|
|
local_id: "unicode_emoji,1f641",
|
2018-05-07 03:30:13 +02:00
|
|
|
count: 1,
|
|
|
|
user_ids: [7],
|
2020-10-21 15:09:10 +02:00
|
|
|
label: "translated: Cali reacted with :frown:",
|
2018-05-07 03:30:13 +02:00
|
|
|
emoji_alt_code: false,
|
2020-07-15 01:29:15 +02:00
|
|
|
class: "message_reaction",
|
2018-05-07 03:30:13 +02:00
|
|
|
},
|
|
|
|
{
|
2020-07-15 01:29:15 +02:00
|
|
|
emoji_name: "inactive_realm_emoji",
|
|
|
|
reaction_type: "realm_emoji",
|
|
|
|
emoji_code: "992",
|
|
|
|
local_id: "realm_emoji,992",
|
2018-05-07 03:30:13 +02:00
|
|
|
count: 1,
|
|
|
|
user_ids: [5],
|
2020-10-21 15:09:10 +02:00
|
|
|
label: "translated: You (click to remove) reacted with :inactive_realm_emoji:",
|
2018-05-07 03:30:13 +02:00
|
|
|
emoji_alt_code: false,
|
|
|
|
is_realm_emoji: true,
|
2021-02-25 14:54:11 +01:00
|
|
|
url: "/url/for/992",
|
2020-07-15 01:29:15 +02:00
|
|
|
class: "message_reaction reacted",
|
2018-05-07 03:30:13 +02:00
|
|
|
},
|
|
|
|
{
|
2020-07-15 01:29:15 +02:00
|
|
|
emoji_name: "smile",
|
|
|
|
reaction_type: "unicode_emoji",
|
2020-06-30 21:16:29 +02:00
|
|
|
emoji_code: "1f642",
|
|
|
|
local_id: "unicode_emoji,1f642",
|
2018-05-07 03:30:13 +02:00
|
|
|
count: 2,
|
|
|
|
user_ids: [5, 6],
|
2020-10-21 15:09:10 +02:00
|
|
|
label: "translated: You (click to remove) and Bob van Roberts reacted with :smile:",
|
2018-05-07 03:30:13 +02:00
|
|
|
emoji_alt_code: false,
|
2020-07-15 01:29:15 +02:00
|
|
|
class: "message_reaction reacted",
|
2018-05-07 03:30:13 +02:00
|
|
|
},
|
2020-10-21 15:09:10 +02:00
|
|
|
{
|
|
|
|
emoji_name: "tada",
|
|
|
|
reaction_type: "unicode_emoji",
|
|
|
|
emoji_code: "1f389",
|
|
|
|
local_id: "unicode_emoji,1f389",
|
|
|
|
count: 2,
|
|
|
|
user_ids: [7, 8],
|
|
|
|
label: "translated: Cali and Alexus reacted with :tada:",
|
|
|
|
emoji_alt_code: false,
|
|
|
|
class: "message_reaction",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
emoji_name: "rocket",
|
|
|
|
reaction_type: "unicode_emoji",
|
|
|
|
emoji_code: "1f680",
|
|
|
|
local_id: "unicode_emoji,1f680",
|
|
|
|
count: 3,
|
|
|
|
user_ids: [5, 6, 7],
|
|
|
|
label:
|
|
|
|
"translated: You (click to remove), Bob van Roberts and Cali reacted with :rocket:",
|
|
|
|
emoji_alt_code: false,
|
|
|
|
class: "message_reaction reacted",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
emoji_name: "wave",
|
|
|
|
reaction_type: "unicode_emoji",
|
|
|
|
emoji_code: "1f44b",
|
|
|
|
local_id: "unicode_emoji,1f44b",
|
|
|
|
count: 3,
|
|
|
|
user_ids: [6, 7, 8],
|
|
|
|
label: "translated: Bob van Roberts, Cali and Alexus reacted with :wave:",
|
|
|
|
emoji_alt_code: false,
|
|
|
|
class: "message_reaction",
|
|
|
|
},
|
2018-05-07 03:30:13 +02:00
|
|
|
];
|
|
|
|
assert.deepEqual(result, expected_result);
|
2018-05-15 12:40:07 +02:00
|
|
|
});
|
2017-05-28 16:18:12 +02:00
|
|
|
|
2020-10-06 23:57:16 +02:00
|
|
|
run_test("unknown realm emojis (add)", () => {
|
|
|
|
blueslip.expect("error", "Cannot find/add realm emoji for code 'broken'.");
|
|
|
|
reactions.add_clean_reaction({
|
|
|
|
reaction_type: "realm_emoji",
|
|
|
|
emoji_code: "broken",
|
|
|
|
user_ids: [alice.user_id],
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
run_test("unknown realm emojis (insert)", () => {
|
|
|
|
blueslip.expect("error", "Cannot find/insert realm emoji for code 'bogus'.");
|
|
|
|
reactions.view.insert_new_reaction({
|
|
|
|
reaction_type: "realm_emoji",
|
|
|
|
emoji_code: "bogus",
|
|
|
|
user_id: bob.user_id,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-07-27 16:15:02 +02:00
|
|
|
run_test("sending", (override) => {
|
2019-11-02 00:06:25 +01:00
|
|
|
const message_id = 1001; // see above for setup
|
2020-07-15 01:29:15 +02:00
|
|
|
let emoji_name = "smile"; // should be a current reaction
|
2017-05-28 16:18:12 +02:00
|
|
|
|
2021-02-11 01:23:23 +01:00
|
|
|
override(reactions, "add_reaction", () => {});
|
|
|
|
override(reactions, "remove_reaction", () => {});
|
2017-12-19 00:55:40 +01:00
|
|
|
|
2021-02-13 03:46:14 +01:00
|
|
|
{
|
|
|
|
const stub = make_stub();
|
2020-12-01 00:57:57 +01:00
|
|
|
channel.del = stub.f;
|
2017-05-29 21:18:59 +02:00
|
|
|
reactions.toggle_emoji_reaction(message_id, emoji_name);
|
2021-02-13 03:46:14 +01:00
|
|
|
assert.equal(stub.num_calls, 1);
|
2020-07-15 01:29:15 +02:00
|
|
|
const args = stub.get_args("args").args;
|
|
|
|
assert.equal(args.url, "/json/messages/1001/reactions");
|
2017-10-31 22:33:28 +01:00
|
|
|
assert.deepEqual(args.data, {
|
2020-07-15 01:29:15 +02:00
|
|
|
reaction_type: "unicode_emoji",
|
|
|
|
emoji_name: "smile",
|
2020-06-30 21:16:29 +02:00
|
|
|
emoji_code: "1f642",
|
2017-10-31 22:33:28 +01:00
|
|
|
});
|
2017-05-28 16:18:12 +02:00
|
|
|
// args.success() does nothing; just make sure it doesn't crash
|
|
|
|
args.success();
|
|
|
|
|
|
|
|
// similarly, we only exercise the failure codepath
|
2018-07-10 09:14:51 +02:00
|
|
|
// Since this path calls blueslip.warn, we need to handle it.
|
2020-07-15 01:29:15 +02:00
|
|
|
blueslip.expect("warn", "XHR Error Message.");
|
2021-02-23 14:37:26 +01:00
|
|
|
channel.xhr_error_message = () => "XHR Error Message.";
|
2017-05-28 16:18:12 +02:00
|
|
|
args.error();
|
2021-02-13 03:46:14 +01:00
|
|
|
}
|
2020-07-15 01:29:15 +02:00
|
|
|
emoji_name = "alien"; // not set yet
|
2021-02-13 03:46:14 +01:00
|
|
|
{
|
|
|
|
const stub = make_stub();
|
2020-12-01 00:57:57 +01:00
|
|
|
channel.post = stub.f;
|
2017-05-29 21:18:59 +02:00
|
|
|
reactions.toggle_emoji_reaction(message_id, emoji_name);
|
2021-02-13 03:46:14 +01:00
|
|
|
assert.equal(stub.num_calls, 1);
|
2020-07-15 01:29:15 +02:00
|
|
|
const args = stub.get_args("args").args;
|
|
|
|
assert.equal(args.url, "/json/messages/1001/reactions");
|
2017-10-31 22:33:28 +01:00
|
|
|
assert.deepEqual(args.data, {
|
2020-07-15 01:29:15 +02:00
|
|
|
reaction_type: "unicode_emoji",
|
|
|
|
emoji_name: "alien",
|
|
|
|
emoji_code: "1f47d",
|
2017-10-31 22:33:28 +01:00
|
|
|
});
|
2021-02-13 03:46:14 +01:00
|
|
|
}
|
2017-05-28 16:18:12 +02:00
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
emoji_name = "inactive_realm_emoji";
|
2021-02-13 03:46:14 +01:00
|
|
|
{
|
2017-12-15 16:54:07 +01:00
|
|
|
// Test removing a deactivated realm emoji. An user can interact with a
|
|
|
|
// deactivated realm emoji only by clicking on a reaction, hence, only
|
|
|
|
// `process_reaction_click()` codepath supports deleting/adding a deactivated
|
|
|
|
// realm emoji.
|
2021-02-13 03:46:14 +01:00
|
|
|
const stub = make_stub();
|
2020-12-01 00:57:57 +01:00
|
|
|
channel.del = stub.f;
|
2020-07-15 01:29:15 +02:00
|
|
|
reactions.process_reaction_click(message_id, "realm_emoji,992");
|
2021-02-13 03:46:14 +01:00
|
|
|
assert.equal(stub.num_calls, 1);
|
2020-07-15 01:29:15 +02:00
|
|
|
const args = stub.get_args("args").args;
|
|
|
|
assert.equal(args.url, "/json/messages/1001/reactions");
|
2017-10-31 22:33:28 +01:00
|
|
|
assert.deepEqual(args.data, {
|
2020-07-15 01:29:15 +02:00
|
|
|
reaction_type: "realm_emoji",
|
|
|
|
emoji_name: "inactive_realm_emoji",
|
|
|
|
emoji_code: "992",
|
2017-10-31 22:33:28 +01:00
|
|
|
});
|
2021-02-13 03:46:14 +01:00
|
|
|
}
|
2017-10-08 17:02:14 +02:00
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
emoji_name = "zulip"; // Test adding zulip emoji.
|
2021-02-13 03:46:14 +01:00
|
|
|
{
|
|
|
|
const stub = make_stub();
|
2020-12-01 00:57:57 +01:00
|
|
|
channel.post = stub.f;
|
2017-10-31 22:33:28 +01:00
|
|
|
reactions.toggle_emoji_reaction(message_id, emoji_name);
|
2021-02-13 03:46:14 +01:00
|
|
|
assert.equal(stub.num_calls, 1);
|
2020-07-15 01:29:15 +02:00
|
|
|
const args = stub.get_args("args").args;
|
|
|
|
assert.equal(args.url, "/json/messages/1001/reactions");
|
2017-10-31 22:33:28 +01:00
|
|
|
assert.deepEqual(args.data, {
|
2020-07-15 01:29:15 +02:00
|
|
|
reaction_type: "zulip_extra_emoji",
|
|
|
|
emoji_name: "zulip",
|
|
|
|
emoji_code: "zulip",
|
2017-10-31 22:33:28 +01:00
|
|
|
});
|
2021-02-13 03:46:14 +01:00
|
|
|
}
|
2017-10-31 22:33:28 +01:00
|
|
|
|
2020-07-16 23:29:01 +02:00
|
|
|
emoji_name = "unknown-emoji"; // Test sending an emoji unknown to frontend.
|
2020-07-15 01:29:15 +02:00
|
|
|
blueslip.expect("warn", "Bad emoji name: " + emoji_name);
|
2017-05-29 21:18:59 +02:00
|
|
|
reactions.toggle_emoji_reaction(message_id, emoji_name);
|
2018-05-15 12:40:07 +02:00
|
|
|
});
|
2017-05-28 17:04:30 +02:00
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
run_test("set_reaction_count", () => {
|
|
|
|
const count_element = $.create("count-stub");
|
|
|
|
const reaction_element = $.create("reaction-stub");
|
2017-05-29 19:24:31 +02:00
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
reaction_element.set_find_results(".message_reaction_count", count_element);
|
2017-05-29 19:24:31 +02:00
|
|
|
|
|
|
|
reactions.set_reaction_count(reaction_element, 5);
|
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
assert.equal(count_element.text(), "5");
|
2018-05-15 12:40:07 +02:00
|
|
|
});
|
2017-05-29 19:24:31 +02:00
|
|
|
|
2021-02-24 22:45:47 +01:00
|
|
|
run_test("find_reaction", (override) => {
|
|
|
|
const message_id = 99;
|
|
|
|
const local_id = "unicode_emoji,1f44b";
|
|
|
|
const reaction_section = $.create("section-stub");
|
|
|
|
|
|
|
|
const reaction_stub = "reaction-stub";
|
|
|
|
reaction_section.set_find_results(
|
|
|
|
`[data-reaction-id='${CSS.escape(local_id)}']`,
|
|
|
|
reaction_stub,
|
|
|
|
);
|
|
|
|
|
|
|
|
override(reactions, "get_reaction_section", (arg) => {
|
|
|
|
assert.equal(arg, message_id);
|
|
|
|
return reaction_section;
|
|
|
|
});
|
|
|
|
|
|
|
|
assert.equal(reactions.find_reaction(message_id, local_id), reaction_stub);
|
|
|
|
});
|
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
run_test("get_reaction_section", () => {
|
|
|
|
const message_table = $.create(".message_table");
|
|
|
|
const message_row = $.create("some-message-row");
|
|
|
|
const message_reactions = $.create("our-reactions-section");
|
2017-06-29 17:19:14 +02:00
|
|
|
|
2021-02-03 23:23:32 +01:00
|
|
|
message_table.set_find_results(`[zid='${CSS.escape(555)}']`, message_row);
|
2020-07-15 01:29:15 +02:00
|
|
|
message_row.set_find_results(".message_reactions", message_reactions);
|
2017-06-29 17:19:14 +02:00
|
|
|
|
2019-11-02 00:06:25 +01:00
|
|
|
const section = reactions.get_reaction_section(555);
|
2017-06-29 17:19:14 +02:00
|
|
|
|
|
|
|
assert.equal(section, message_reactions);
|
2018-05-15 12:40:07 +02:00
|
|
|
});
|
2017-06-29 17:19:14 +02:00
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
run_test("emoji_reaction_title", () => {
|
2019-11-02 00:06:25 +01:00
|
|
|
const message_id = 1001;
|
2020-06-30 21:16:29 +02:00
|
|
|
const local_id = "unicode_emoji,1f642";
|
2019-04-04 14:56:54 +02:00
|
|
|
|
2020-07-15 00:34:28 +02:00
|
|
|
assert.equal(
|
|
|
|
reactions.get_reaction_title_data(message_id, local_id),
|
2020-10-21 15:09:10 +02:00
|
|
|
"translated: You (click to remove) and Bob van Roberts reacted with :smile:",
|
2020-07-15 00:34:28 +02:00
|
|
|
);
|
2019-04-04 14:56:54 +02:00
|
|
|
});
|
|
|
|
|
2021-02-25 14:21:01 +01:00
|
|
|
run_test("add_reaction/remove_reaction", (override) => {
|
2017-06-28 22:47:47 +02:00
|
|
|
// This function tests reaction events by mocking out calls to
|
|
|
|
// the view.
|
|
|
|
|
2019-11-02 00:06:25 +01:00
|
|
|
const message = {
|
2017-06-28 22:47:47 +02:00
|
|
|
id: 2001,
|
|
|
|
reactions: [],
|
|
|
|
};
|
|
|
|
|
2021-02-25 14:13:30 +01:00
|
|
|
override(message_store, "get", () => message);
|
2017-06-28 22:47:47 +02:00
|
|
|
|
2021-02-25 14:29:15 +01:00
|
|
|
let view_calls = [];
|
|
|
|
|
|
|
|
override(reactions.view, "insert_new_reaction", (opts) => {
|
|
|
|
view_calls.push({name: "insert_new_reaction", opts});
|
|
|
|
});
|
|
|
|
override(reactions.view, "update_existing_reaction", (opts) => {
|
|
|
|
view_calls.push({name: "update_existing_reaction", opts});
|
|
|
|
});
|
|
|
|
override(reactions.view, "remove_reaction", (opts) => {
|
|
|
|
view_calls.push({name: "remove_reaction", opts});
|
|
|
|
});
|
|
|
|
|
2017-06-28 22:47:47 +02:00
|
|
|
function test_view_calls(test_params) {
|
2021-02-25 14:29:15 +01:00
|
|
|
view_calls = [];
|
2017-06-28 22:47:47 +02:00
|
|
|
|
|
|
|
test_params.run_code();
|
|
|
|
|
2021-02-25 14:29:15 +01:00
|
|
|
assert.deepEqual(view_calls, test_params.expected_view_calls);
|
2021-02-25 14:21:01 +01:00
|
|
|
assert.deepEqual(
|
|
|
|
new Set(reactions.get_emojis_used_by_user_for_message_id(message.message_id)),
|
|
|
|
new Set(test_params.alice_emojis),
|
|
|
|
);
|
2017-06-28 22:47:47 +02:00
|
|
|
}
|
|
|
|
|
2019-11-02 00:06:25 +01:00
|
|
|
const alice_8ball_event = {
|
2017-06-28 22:47:47 +02:00
|
|
|
message_id: 2001,
|
2020-07-15 01:29:15 +02:00
|
|
|
reaction_type: "unicode_emoji",
|
|
|
|
emoji_name: "8ball",
|
|
|
|
emoji_code: "1f3b1",
|
2020-04-22 23:24:28 +02:00
|
|
|
user_id: alice.user_id,
|
2017-06-28 22:47:47 +02:00
|
|
|
};
|
|
|
|
|
2019-11-02 00:06:25 +01:00
|
|
|
const bob_8ball_event = {
|
2017-06-28 22:47:47 +02:00
|
|
|
message_id: 2001,
|
2020-07-15 01:29:15 +02:00
|
|
|
reaction_type: "unicode_emoji",
|
|
|
|
emoji_name: "8ball",
|
|
|
|
emoji_code: "1f3b1",
|
2020-04-22 23:24:28 +02:00
|
|
|
user_id: bob.user_id,
|
2017-06-28 22:47:47 +02:00
|
|
|
};
|
|
|
|
|
2019-11-02 00:06:25 +01:00
|
|
|
const cali_airplane_event = {
|
2017-06-28 22:47:47 +02:00
|
|
|
message_id: 2001,
|
2020-07-15 01:29:15 +02:00
|
|
|
reaction_type: "unicode_emoji",
|
|
|
|
emoji_name: "airplane",
|
|
|
|
emoji_code: "2708",
|
2020-04-22 23:24:28 +02:00
|
|
|
user_id: cali.user_id,
|
2017-06-28 22:47:47 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
test_view_calls({
|
2020-07-20 22:18:43 +02:00
|
|
|
run_code() {
|
2017-06-28 22:47:47 +02:00
|
|
|
reactions.add_reaction(alice_8ball_event);
|
|
|
|
},
|
|
|
|
expected_view_calls: [
|
|
|
|
{
|
2020-07-15 01:29:15 +02:00
|
|
|
name: "insert_new_reaction",
|
2017-06-28 22:47:47 +02:00
|
|
|
opts: {
|
|
|
|
message_id: 2001,
|
2020-07-15 01:29:15 +02:00
|
|
|
reaction_type: "unicode_emoji",
|
|
|
|
emoji_name: "8ball",
|
|
|
|
emoji_code: "1f3b1",
|
2017-06-28 22:47:47 +02:00
|
|
|
user_id: alice.user_id,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
],
|
2021-02-25 14:21:01 +01:00
|
|
|
alice_emojis: ["8ball"],
|
2017-06-28 22:47:47 +02:00
|
|
|
});
|
|
|
|
|
2021-02-25 18:02:11 +01:00
|
|
|
// Add redundant reaction.
|
|
|
|
test_view_calls({
|
|
|
|
run_code() {
|
|
|
|
reactions.add_reaction(alice_8ball_event);
|
|
|
|
},
|
|
|
|
expected_view_calls: [],
|
|
|
|
alice_emojis: ["8ball"],
|
|
|
|
});
|
|
|
|
|
2017-06-28 22:47:47 +02:00
|
|
|
test_view_calls({
|
2020-07-20 22:18:43 +02:00
|
|
|
run_code() {
|
2017-06-28 22:47:47 +02:00
|
|
|
reactions.add_reaction(bob_8ball_event);
|
|
|
|
},
|
|
|
|
expected_view_calls: [
|
|
|
|
{
|
2020-07-15 01:29:15 +02:00
|
|
|
name: "update_existing_reaction",
|
2017-06-28 22:47:47 +02:00
|
|
|
opts: {
|
|
|
|
message_id: 2001,
|
2020-07-15 01:29:15 +02:00
|
|
|
reaction_type: "unicode_emoji",
|
|
|
|
emoji_name: "8ball",
|
|
|
|
emoji_code: "1f3b1",
|
2017-06-28 22:47:47 +02:00
|
|
|
user_id: bob.user_id,
|
|
|
|
user_list: [alice.user_id, bob.user_id],
|
|
|
|
},
|
|
|
|
},
|
|
|
|
],
|
2021-02-25 14:21:01 +01:00
|
|
|
alice_emojis: ["8ball"],
|
2017-06-28 22:47:47 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
test_view_calls({
|
2020-07-20 22:18:43 +02:00
|
|
|
run_code() {
|
2017-06-28 22:47:47 +02:00
|
|
|
reactions.add_reaction(cali_airplane_event);
|
|
|
|
},
|
|
|
|
expected_view_calls: [
|
|
|
|
{
|
2020-07-15 01:29:15 +02:00
|
|
|
name: "insert_new_reaction",
|
2017-06-28 22:47:47 +02:00
|
|
|
opts: {
|
|
|
|
message_id: 2001,
|
2020-07-15 01:29:15 +02:00
|
|
|
reaction_type: "unicode_emoji",
|
|
|
|
emoji_name: "airplane",
|
|
|
|
emoji_code: "2708",
|
2017-06-28 22:47:47 +02:00
|
|
|
user_id: cali.user_id,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
],
|
2021-02-25 14:21:01 +01:00
|
|
|
alice_emojis: ["8ball"],
|
2017-06-28 22:47:47 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
test_view_calls({
|
2020-07-20 22:18:43 +02:00
|
|
|
run_code() {
|
2017-06-28 22:47:47 +02:00
|
|
|
reactions.remove_reaction(bob_8ball_event);
|
|
|
|
},
|
|
|
|
expected_view_calls: [
|
|
|
|
{
|
2020-07-15 01:29:15 +02:00
|
|
|
name: "remove_reaction",
|
2017-06-28 22:47:47 +02:00
|
|
|
opts: {
|
|
|
|
message_id: 2001,
|
2020-07-15 01:29:15 +02:00
|
|
|
reaction_type: "unicode_emoji",
|
|
|
|
emoji_name: "8ball",
|
|
|
|
emoji_code: "1f3b1",
|
2017-06-28 22:47:47 +02:00
|
|
|
user_id: bob.user_id,
|
|
|
|
user_list: [alice.user_id],
|
|
|
|
},
|
|
|
|
},
|
|
|
|
],
|
2021-02-25 14:21:01 +01:00
|
|
|
alice_emojis: ["8ball"],
|
2017-06-28 22:47:47 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
test_view_calls({
|
2020-07-20 22:18:43 +02:00
|
|
|
run_code() {
|
2017-06-28 22:47:47 +02:00
|
|
|
reactions.remove_reaction(alice_8ball_event);
|
|
|
|
},
|
|
|
|
expected_view_calls: [
|
|
|
|
{
|
2020-07-15 01:29:15 +02:00
|
|
|
name: "remove_reaction",
|
2017-06-28 22:47:47 +02:00
|
|
|
opts: {
|
|
|
|
message_id: 2001,
|
2020-07-15 01:29:15 +02:00
|
|
|
reaction_type: "unicode_emoji",
|
|
|
|
emoji_name: "8ball",
|
|
|
|
emoji_code: "1f3b1",
|
2017-06-28 22:47:47 +02:00
|
|
|
user_id: alice.user_id,
|
|
|
|
user_list: [],
|
|
|
|
},
|
|
|
|
},
|
|
|
|
],
|
2021-02-25 14:21:01 +01:00
|
|
|
alice_emojis: [],
|
2017-06-28 22:47:47 +02:00
|
|
|
});
|
2021-02-25 18:02:11 +01:00
|
|
|
|
|
|
|
// Test redundant remove.
|
|
|
|
test_view_calls({
|
|
|
|
run_code() {
|
|
|
|
reactions.remove_reaction(alice_8ball_event);
|
|
|
|
},
|
|
|
|
expected_view_calls: [],
|
|
|
|
alice_emojis: [],
|
|
|
|
});
|
2018-05-15 12:40:07 +02:00
|
|
|
});
|
2017-06-28 22:47:47 +02:00
|
|
|
|
2021-02-24 22:45:47 +01:00
|
|
|
run_test("view.insert_new_reaction (me w/unicode emoji)", (override) => {
|
|
|
|
const opts = {
|
|
|
|
message_id: 501,
|
|
|
|
reaction_type: "unicode_emoji",
|
|
|
|
emoji_name: "8ball",
|
|
|
|
emoji_code: "1f3b1",
|
|
|
|
user_id: alice.user_id,
|
|
|
|
};
|
|
|
|
|
|
|
|
const message_reactions = $.create("our-reactions");
|
|
|
|
|
|
|
|
override(reactions, "get_reaction_section", (message_id) => {
|
|
|
|
assert.equal(message_id, opts.message_id);
|
|
|
|
return message_reactions;
|
|
|
|
});
|
|
|
|
|
|
|
|
message_reactions.find = (selector) => {
|
|
|
|
assert.equal(selector, ".reaction_button");
|
|
|
|
return "reaction-button-stub";
|
|
|
|
};
|
|
|
|
|
|
|
|
let template_called;
|
|
|
|
stub_templates((template_name, data) => {
|
|
|
|
template_called = true;
|
|
|
|
assert.equal(template_name, "message_reaction");
|
|
|
|
assert.deepEqual(data, {
|
|
|
|
count: 1,
|
|
|
|
emoji_alt_code: false,
|
|
|
|
emoji_name: "8ball",
|
|
|
|
emoji_code: "1f3b1",
|
|
|
|
local_id: "unicode_emoji,1f3b1",
|
|
|
|
class: "message_reaction reacted",
|
|
|
|
message_id: opts.message_id,
|
|
|
|
label: "translated: You (click to remove) reacted with :8ball:",
|
|
|
|
});
|
|
|
|
return "<new reaction html>";
|
|
|
|
});
|
|
|
|
|
|
|
|
let insert_called;
|
|
|
|
$("<new reaction html>").insertBefore = (element) => {
|
|
|
|
assert.equal(element, "reaction-button-stub");
|
|
|
|
insert_called = true;
|
|
|
|
};
|
|
|
|
|
|
|
|
reactions.view.insert_new_reaction(opts);
|
|
|
|
assert(template_called);
|
|
|
|
assert(insert_called);
|
|
|
|
});
|
|
|
|
|
|
|
|
run_test("view.insert_new_reaction (them w/zulip emoji)", (override) => {
|
|
|
|
const zulip_emoji = emoji_params.realm_emoji.zulip;
|
|
|
|
const opts = {
|
|
|
|
message_id: 502,
|
|
|
|
reaction_type: "realm_emoji",
|
|
|
|
emoji_name: "zulip",
|
|
|
|
emoji_code: zulip_emoji.id,
|
|
|
|
user_id: bob.user_id,
|
|
|
|
source_url: zulip_emoji.source_url,
|
|
|
|
};
|
|
|
|
|
|
|
|
const message_reactions = $.create("our-reactions");
|
|
|
|
|
|
|
|
override(reactions, "get_reaction_section", (message_id) => {
|
|
|
|
assert.equal(message_id, opts.message_id);
|
|
|
|
return message_reactions;
|
|
|
|
});
|
|
|
|
|
|
|
|
message_reactions.find = (selector) => {
|
|
|
|
assert.equal(selector, ".reaction_button");
|
|
|
|
return "reaction-button-stub";
|
|
|
|
};
|
|
|
|
|
|
|
|
let template_called;
|
|
|
|
stub_templates((template_name, data) => {
|
|
|
|
template_called = true;
|
|
|
|
assert.equal(template_name, "message_reaction");
|
|
|
|
assert.deepEqual(data, {
|
|
|
|
count: 1,
|
|
|
|
url: "/static/generated/emoji/images/emoji/unicode/zulip.png",
|
|
|
|
is_realm_emoji: true,
|
|
|
|
emoji_alt_code: false,
|
|
|
|
emoji_name: "zulip",
|
|
|
|
emoji_code: "zulip",
|
|
|
|
local_id: "realm_emoji,zulip",
|
|
|
|
class: "message_reaction",
|
|
|
|
message_id: opts.message_id,
|
|
|
|
label: "translated: Bob van Roberts reacted with :zulip:",
|
|
|
|
});
|
|
|
|
return "<new reaction html>";
|
|
|
|
});
|
|
|
|
|
|
|
|
let insert_called;
|
|
|
|
$("<new reaction html>").insertBefore = (element) => {
|
|
|
|
assert.equal(element, "reaction-button-stub");
|
|
|
|
insert_called = true;
|
|
|
|
};
|
|
|
|
|
|
|
|
reactions.view.insert_new_reaction(opts);
|
|
|
|
assert(template_called);
|
|
|
|
assert(insert_called);
|
|
|
|
});
|
|
|
|
|
|
|
|
run_test("view.update_existing_reaction (me)", (override) => {
|
|
|
|
const opts = {
|
|
|
|
message_id: 503,
|
|
|
|
reaction_type: "unicode_emoji",
|
|
|
|
emoji_name: "8ball",
|
|
|
|
emoji_code: "1f3b1",
|
|
|
|
user_id: alice.user_id,
|
|
|
|
user_list: [alice.user_id, bob.user_id],
|
|
|
|
};
|
|
|
|
|
|
|
|
const our_reaction = $.create("our-reaction-stub");
|
|
|
|
|
|
|
|
override(reactions, "find_reaction", (message_id, local_id) => {
|
|
|
|
assert.equal(message_id, opts.message_id);
|
|
|
|
assert.equal(local_id, "unicode_emoji,1f3b1");
|
|
|
|
return our_reaction;
|
|
|
|
});
|
|
|
|
|
|
|
|
override(reactions, "set_reaction_count", (reaction, count) => {
|
|
|
|
assert.equal(reaction, our_reaction);
|
|
|
|
assert.equal(count, 2);
|
|
|
|
});
|
|
|
|
|
|
|
|
reactions.view.update_existing_reaction(opts);
|
|
|
|
|
|
|
|
assert(our_reaction.hasClass("reacted"));
|
|
|
|
assert.equal(
|
|
|
|
our_reaction.attr("aria-label"),
|
|
|
|
"translated: You (click to remove) and Bob van Roberts reacted with :8ball:",
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
run_test("view.update_existing_reaction (them)", (override) => {
|
|
|
|
const opts = {
|
|
|
|
message_id: 504,
|
|
|
|
reaction_type: "unicode_emoji",
|
|
|
|
emoji_name: "8ball",
|
|
|
|
emoji_code: "1f3b1",
|
|
|
|
user_id: bob.user_id,
|
|
|
|
user_list: [alice.user_id, bob.user_id, cali.user_id, alexus.user_id],
|
|
|
|
};
|
|
|
|
|
|
|
|
const our_reaction = $.create("our-reaction-stub");
|
|
|
|
|
|
|
|
override(reactions, "find_reaction", (message_id, local_id) => {
|
|
|
|
assert.equal(message_id, opts.message_id);
|
|
|
|
assert.equal(local_id, "unicode_emoji,1f3b1");
|
|
|
|
return our_reaction;
|
|
|
|
});
|
|
|
|
|
|
|
|
override(reactions, "set_reaction_count", (reaction, count) => {
|
|
|
|
assert.equal(reaction, our_reaction);
|
|
|
|
assert.equal(count, 4);
|
|
|
|
});
|
|
|
|
|
|
|
|
reactions.view.update_existing_reaction(opts);
|
|
|
|
|
|
|
|
assert(!our_reaction.hasClass("reacted"));
|
|
|
|
assert.equal(
|
|
|
|
our_reaction.attr("aria-label"),
|
|
|
|
"translated: You (click to remove), Bob van Roberts, Cali and Alexus reacted with :8ball:",
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
run_test("view.remove_reaction (me)", (override) => {
|
|
|
|
const opts = {
|
|
|
|
message_id: 505,
|
|
|
|
reaction_type: "unicode_emoji",
|
|
|
|
emoji_name: "8ball",
|
|
|
|
emoji_code: "1f3b1",
|
|
|
|
user_id: alice.user_id,
|
|
|
|
user_list: [bob.user_id, cali.user_id],
|
|
|
|
};
|
|
|
|
|
|
|
|
const our_reaction = $.create("our-reaction-stub");
|
|
|
|
our_reaction.addClass("reacted");
|
|
|
|
|
|
|
|
override(reactions, "find_reaction", (message_id, local_id) => {
|
|
|
|
assert.equal(message_id, opts.message_id);
|
|
|
|
assert.equal(local_id, "unicode_emoji,1f3b1");
|
|
|
|
return our_reaction;
|
|
|
|
});
|
|
|
|
|
|
|
|
override(reactions, "set_reaction_count", (reaction, count) => {
|
|
|
|
assert.equal(reaction, our_reaction);
|
|
|
|
assert.equal(count, 2);
|
|
|
|
});
|
|
|
|
|
|
|
|
reactions.view.remove_reaction(opts);
|
|
|
|
|
|
|
|
assert(!our_reaction.hasClass("reacted"));
|
|
|
|
assert.equal(
|
|
|
|
our_reaction.attr("aria-label"),
|
|
|
|
"translated: Bob van Roberts and Cali reacted with :8ball:",
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
run_test("view.remove_reaction (them)", (override) => {
|
|
|
|
const opts = {
|
|
|
|
message_id: 506,
|
|
|
|
reaction_type: "unicode_emoji",
|
|
|
|
emoji_name: "8ball",
|
|
|
|
emoji_code: "1f3b1",
|
|
|
|
user_id: bob.user_id,
|
|
|
|
user_list: [alice.user_id],
|
|
|
|
};
|
|
|
|
|
|
|
|
const our_reaction = $.create("our-reaction-stub");
|
|
|
|
our_reaction.addClass("reacted");
|
|
|
|
|
|
|
|
override(reactions, "find_reaction", (message_id, local_id) => {
|
|
|
|
assert.equal(message_id, opts.message_id);
|
|
|
|
assert.equal(local_id, "unicode_emoji,1f3b1");
|
|
|
|
return our_reaction;
|
|
|
|
});
|
|
|
|
|
|
|
|
override(reactions, "set_reaction_count", (reaction, count) => {
|
|
|
|
assert.equal(reaction, our_reaction);
|
|
|
|
assert.equal(count, 1);
|
|
|
|
});
|
|
|
|
|
|
|
|
our_reaction.addClass("reacted");
|
|
|
|
reactions.view.remove_reaction(opts);
|
|
|
|
|
|
|
|
assert(our_reaction.hasClass("reacted"));
|
|
|
|
assert.equal(
|
|
|
|
our_reaction.attr("aria-label"),
|
|
|
|
"translated: You (click to remove) reacted with :8ball:",
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
run_test("view.remove_reaction (last person)", (override) => {
|
|
|
|
const opts = {
|
|
|
|
message_id: 507,
|
|
|
|
reaction_type: "unicode_emoji",
|
|
|
|
emoji_name: "8ball",
|
|
|
|
emoji_code: "1f3b1",
|
|
|
|
user_id: bob.user_id,
|
|
|
|
user_list: [],
|
|
|
|
};
|
|
|
|
|
|
|
|
const our_reaction = $.create("our-reaction-stub");
|
|
|
|
|
|
|
|
override(reactions, "find_reaction", (message_id, local_id) => {
|
|
|
|
assert.equal(message_id, opts.message_id);
|
|
|
|
assert.equal(local_id, "unicode_emoji,1f3b1");
|
|
|
|
return our_reaction;
|
|
|
|
});
|
|
|
|
|
|
|
|
let removed;
|
|
|
|
our_reaction.remove = () => {
|
|
|
|
removed = true;
|
|
|
|
};
|
|
|
|
reactions.view.remove_reaction(opts);
|
|
|
|
assert(removed);
|
|
|
|
});
|
|
|
|
|
2021-02-14 08:44:04 +01:00
|
|
|
run_test("error_handling", (override) => {
|
2021-02-25 14:13:30 +01:00
|
|
|
override(message_store, "get", () => {});
|
2017-05-31 00:09:50 +02:00
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
blueslip.expect("error", "reactions: Bad message id: 55");
|
2017-05-31 00:09:50 +02:00
|
|
|
|
2020-07-16 23:29:01 +02:00
|
|
|
const bogus_event = {
|
2017-05-31 00:09:50 +02:00
|
|
|
message_id: 55,
|
2020-07-15 01:29:15 +02:00
|
|
|
reaction_type: "realm_emoji",
|
|
|
|
emoji_name: "realm_emoji",
|
|
|
|
emoji_code: "991",
|
2020-04-22 23:24:28 +02:00
|
|
|
user_id: 99,
|
2017-05-31 00:09:50 +02:00
|
|
|
};
|
2021-02-14 08:44:04 +01:00
|
|
|
override(reactions, "current_user_has_reacted_to_emoji", () => true);
|
|
|
|
reactions.toggle_emoji_reaction(55, bogus_event.emoji_name);
|
2017-05-31 00:09:50 +02:00
|
|
|
|
|
|
|
reactions.add_reaction(bogus_event);
|
|
|
|
reactions.remove_reaction(bogus_event);
|
2018-05-15 12:40:07 +02:00
|
|
|
});
|
2017-10-31 22:33:28 +01:00
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
run_test("remove spurious user", () => {
|
reactions: Rewrite code to use clean reactions.
Before this commit, the reactions code would
take the `message.reactions` structure from
the server and try to "collapse" all the reactions
for the same users into the same reactions,
but with each reaction having a list of user_ids.
It was a strangely denormalized structure that
was awkward to work with, and it made it really
hard to reason about whether the data was in
the original structure that the server sent or
the modified structure.
Now we use a cleaner, normalized Map to keep
each reaction (i.e. one per emoji), and we
write that to `message.clean_reactions`.
The `clean_reactions` structure is now the
authoritatize source for all reaction-related
operations. As soon as you try to do anything
with reactions, we build the `clean_reactions`
data on the fly from the server data.
In particular, when we process events, we just
directly manipulate the `clean_reactions` data,
which is much easier to work with, since it's
a Map and doesn't duplicate any data.
This rewrite should avoid some obscure bugs.
I use `r` as shorthand for the clean reaction
structures, so as not to confuse it with
data from the server's message.reactions.
It also avoids some confusion where we use
`reaction` as a var name for the reaction
elements.
2020-03-08 13:13:47 +01:00
|
|
|
// get coverage for removing non-user (it should just
|
|
|
|
// silently fail)
|
|
|
|
|
|
|
|
const event = {
|
2020-07-15 01:29:15 +02:00
|
|
|
reaction_type: "unicode_emoji",
|
|
|
|
emoji_name: "frown",
|
|
|
|
emoji_code: "1f641",
|
reactions: Rewrite code to use clean reactions.
Before this commit, the reactions code would
take the `message.reactions` structure from
the server and try to "collapse" all the reactions
for the same users into the same reactions,
but with each reaction having a list of user_ids.
It was a strangely denormalized structure that
was awkward to work with, and it made it really
hard to reason about whether the data was in
the original structure that the server sent or
the modified structure.
Now we use a cleaner, normalized Map to keep
each reaction (i.e. one per emoji), and we
write that to `message.clean_reactions`.
The `clean_reactions` structure is now the
authoritatize source for all reaction-related
operations. As soon as you try to do anything
with reactions, we build the `clean_reactions`
data on the fly from the server data.
In particular, when we process events, we just
directly manipulate the `clean_reactions` data,
which is much easier to work with, since it's
a Map and doesn't duplicate any data.
This rewrite should avoid some obscure bugs.
I use `r` as shorthand for the clean reaction
structures, so as not to confuse it with
data from the server's message.reactions.
It also avoids some confusion where we use
`reaction` as a var name for the reaction
elements.
2020-03-08 13:13:47 +01:00
|
|
|
message_id: message.id,
|
2020-04-22 23:24:28 +02:00
|
|
|
user_id: alice.user_id,
|
reactions: Rewrite code to use clean reactions.
Before this commit, the reactions code would
take the `message.reactions` structure from
the server and try to "collapse" all the reactions
for the same users into the same reactions,
but with each reaction having a list of user_ids.
It was a strangely denormalized structure that
was awkward to work with, and it made it really
hard to reason about whether the data was in
the original structure that the server sent or
the modified structure.
Now we use a cleaner, normalized Map to keep
each reaction (i.e. one per emoji), and we
write that to `message.clean_reactions`.
The `clean_reactions` structure is now the
authoritatize source for all reaction-related
operations. As soon as you try to do anything
with reactions, we build the `clean_reactions`
data on the fly from the server data.
In particular, when we process events, we just
directly manipulate the `clean_reactions` data,
which is much easier to work with, since it's
a Map and doesn't duplicate any data.
This rewrite should avoid some obscure bugs.
I use `r` as shorthand for the clean reaction
structures, so as not to confuse it with
data from the server's message.reactions.
It also avoids some confusion where we use
`reaction` as a var name for the reaction
elements.
2020-03-08 13:13:47 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
reactions.remove_reaction(event);
|
|
|
|
});
|
|
|
|
|
2021-02-25 14:29:15 +01:00
|
|
|
run_test("remove last user", (override) => {
|
|
|
|
override(reactions.view, "remove_reaction", () => {});
|
|
|
|
|
reactions: Rewrite code to use clean reactions.
Before this commit, the reactions code would
take the `message.reactions` structure from
the server and try to "collapse" all the reactions
for the same users into the same reactions,
but with each reaction having a list of user_ids.
It was a strangely denormalized structure that
was awkward to work with, and it made it really
hard to reason about whether the data was in
the original structure that the server sent or
the modified structure.
Now we use a cleaner, normalized Map to keep
each reaction (i.e. one per emoji), and we
write that to `message.clean_reactions`.
The `clean_reactions` structure is now the
authoritatize source for all reaction-related
operations. As soon as you try to do anything
with reactions, we build the `clean_reactions`
data on the fly from the server data.
In particular, when we process events, we just
directly manipulate the `clean_reactions` data,
which is much easier to work with, since it's
a Map and doesn't duplicate any data.
This rewrite should avoid some obscure bugs.
I use `r` as shorthand for the clean reaction
structures, so as not to confuse it with
data from the server's message.reactions.
It also avoids some confusion where we use
`reaction` as a var name for the reaction
elements.
2020-03-08 13:13:47 +01:00
|
|
|
function assert_names(names) {
|
|
|
|
assert.deepEqual(
|
|
|
|
reactions.get_message_reactions(message).map((r) => r.emoji_name),
|
2020-07-02 02:16:03 +02:00
|
|
|
names,
|
reactions: Rewrite code to use clean reactions.
Before this commit, the reactions code would
take the `message.reactions` structure from
the server and try to "collapse" all the reactions
for the same users into the same reactions,
but with each reaction having a list of user_ids.
It was a strangely denormalized structure that
was awkward to work with, and it made it really
hard to reason about whether the data was in
the original structure that the server sent or
the modified structure.
Now we use a cleaner, normalized Map to keep
each reaction (i.e. one per emoji), and we
write that to `message.clean_reactions`.
The `clean_reactions` structure is now the
authoritatize source for all reaction-related
operations. As soon as you try to do anything
with reactions, we build the `clean_reactions`
data on the fly from the server data.
In particular, when we process events, we just
directly manipulate the `clean_reactions` data,
which is much easier to work with, since it's
a Map and doesn't duplicate any data.
This rewrite should avoid some obscure bugs.
I use `r` as shorthand for the clean reaction
structures, so as not to confuse it with
data from the server's message.reactions.
It also avoids some confusion where we use
`reaction` as a var name for the reaction
elements.
2020-03-08 13:13:47 +01:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-02-24 22:45:47 +01:00
|
|
|
assert_names(["smile", "frown", "tada", "rocket", "wave", "inactive_realm_emoji"]);
|
reactions: Rewrite code to use clean reactions.
Before this commit, the reactions code would
take the `message.reactions` structure from
the server and try to "collapse" all the reactions
for the same users into the same reactions,
but with each reaction having a list of user_ids.
It was a strangely denormalized structure that
was awkward to work with, and it made it really
hard to reason about whether the data was in
the original structure that the server sent or
the modified structure.
Now we use a cleaner, normalized Map to keep
each reaction (i.e. one per emoji), and we
write that to `message.clean_reactions`.
The `clean_reactions` structure is now the
authoritatize source for all reaction-related
operations. As soon as you try to do anything
with reactions, we build the `clean_reactions`
data on the fly from the server data.
In particular, when we process events, we just
directly manipulate the `clean_reactions` data,
which is much easier to work with, since it's
a Map and doesn't duplicate any data.
This rewrite should avoid some obscure bugs.
I use `r` as shorthand for the clean reaction
structures, so as not to confuse it with
data from the server's message.reactions.
It also avoids some confusion where we use
`reaction` as a var name for the reaction
elements.
2020-03-08 13:13:47 +01:00
|
|
|
|
|
|
|
const event = {
|
2020-07-15 01:29:15 +02:00
|
|
|
reaction_type: "unicode_emoji",
|
|
|
|
emoji_name: "frown",
|
|
|
|
emoji_code: "1f641",
|
reactions: Rewrite code to use clean reactions.
Before this commit, the reactions code would
take the `message.reactions` structure from
the server and try to "collapse" all the reactions
for the same users into the same reactions,
but with each reaction having a list of user_ids.
It was a strangely denormalized structure that
was awkward to work with, and it made it really
hard to reason about whether the data was in
the original structure that the server sent or
the modified structure.
Now we use a cleaner, normalized Map to keep
each reaction (i.e. one per emoji), and we
write that to `message.clean_reactions`.
The `clean_reactions` structure is now the
authoritatize source for all reaction-related
operations. As soon as you try to do anything
with reactions, we build the `clean_reactions`
data on the fly from the server data.
In particular, when we process events, we just
directly manipulate the `clean_reactions` data,
which is much easier to work with, since it's
a Map and doesn't duplicate any data.
This rewrite should avoid some obscure bugs.
I use `r` as shorthand for the clean reaction
structures, so as not to confuse it with
data from the server's message.reactions.
It also avoids some confusion where we use
`reaction` as a var name for the reaction
elements.
2020-03-08 13:13:47 +01:00
|
|
|
message_id: message.id,
|
2020-04-22 23:24:28 +02:00
|
|
|
user_id: cali.user_id,
|
reactions: Rewrite code to use clean reactions.
Before this commit, the reactions code would
take the `message.reactions` structure from
the server and try to "collapse" all the reactions
for the same users into the same reactions,
but with each reaction having a list of user_ids.
It was a strangely denormalized structure that
was awkward to work with, and it made it really
hard to reason about whether the data was in
the original structure that the server sent or
the modified structure.
Now we use a cleaner, normalized Map to keep
each reaction (i.e. one per emoji), and we
write that to `message.clean_reactions`.
The `clean_reactions` structure is now the
authoritatize source for all reaction-related
operations. As soon as you try to do anything
with reactions, we build the `clean_reactions`
data on the fly from the server data.
In particular, when we process events, we just
directly manipulate the `clean_reactions` data,
which is much easier to work with, since it's
a Map and doesn't duplicate any data.
This rewrite should avoid some obscure bugs.
I use `r` as shorthand for the clean reaction
structures, so as not to confuse it with
data from the server's message.reactions.
It also avoids some confusion where we use
`reaction` as a var name for the reaction
elements.
2020-03-08 13:13:47 +01:00
|
|
|
};
|
|
|
|
reactions.remove_reaction(event);
|
|
|
|
|
2021-02-24 22:45:47 +01:00
|
|
|
assert_names(["smile", "tada", "rocket", "wave", "inactive_realm_emoji"]);
|
reactions: Rewrite code to use clean reactions.
Before this commit, the reactions code would
take the `message.reactions` structure from
the server and try to "collapse" all the reactions
for the same users into the same reactions,
but with each reaction having a list of user_ids.
It was a strangely denormalized structure that
was awkward to work with, and it made it really
hard to reason about whether the data was in
the original structure that the server sent or
the modified structure.
Now we use a cleaner, normalized Map to keep
each reaction (i.e. one per emoji), and we
write that to `message.clean_reactions`.
The `clean_reactions` structure is now the
authoritatize source for all reaction-related
operations. As soon as you try to do anything
with reactions, we build the `clean_reactions`
data on the fly from the server data.
In particular, when we process events, we just
directly manipulate the `clean_reactions` data,
which is much easier to work with, since it's
a Map and doesn't duplicate any data.
This rewrite should avoid some obscure bugs.
I use `r` as shorthand for the clean reaction
structures, so as not to confuse it with
data from the server's message.reactions.
It also avoids some confusion where we use
`reaction` as a var name for the reaction
elements.
2020-03-08 13:13:47 +01:00
|
|
|
});
|
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
run_test("local_reaction_id", () => {
|
2019-11-02 00:06:25 +01:00
|
|
|
const reaction_info = {
|
2020-07-15 01:29:15 +02:00
|
|
|
reaction_type: "unicode_emoji",
|
|
|
|
emoji_code: "1f44d",
|
2017-10-31 22:33:28 +01:00
|
|
|
};
|
2019-11-02 00:06:25 +01:00
|
|
|
const local_id = reactions.get_local_reaction_id(reaction_info);
|
2020-07-15 01:29:15 +02:00
|
|
|
assert.equal(local_id, "unicode_emoji,1f44d");
|
2018-05-15 12:40:07 +02:00
|
|
|
});
|
2017-10-31 22:33:28 +01:00
|
|
|
|
2021-02-25 14:13:30 +01:00
|
|
|
run_test("process_reaction_click", (override) => {
|
2021-02-25 14:29:15 +01:00
|
|
|
override(reactions.view, "remove_reaction", () => {});
|
|
|
|
|
2019-11-02 00:06:25 +01:00
|
|
|
const message_id = 1001;
|
|
|
|
let expected_reaction_info = {
|
2020-07-15 01:29:15 +02:00
|
|
|
reaction_type: "unicode_emoji",
|
|
|
|
emoji_code: "1f3b1",
|
2017-10-31 22:33:28 +01:00
|
|
|
};
|
2021-02-25 14:13:30 +01:00
|
|
|
override(message_store, "get", (message_id) => {
|
2017-10-31 22:33:28 +01:00
|
|
|
assert.equal(message_id, 1001);
|
|
|
|
return message;
|
2021-02-25 14:13:30 +01:00
|
|
|
});
|
2017-10-31 22:33:28 +01:00
|
|
|
|
|
|
|
expected_reaction_info = {
|
2020-07-15 01:29:15 +02:00
|
|
|
reaction_type: "unicode_emoji",
|
|
|
|
emoji_name: "smile",
|
2020-06-30 21:16:29 +02:00
|
|
|
emoji_code: "1f642",
|
2017-10-31 22:33:28 +01:00
|
|
|
};
|
2021-02-13 03:46:14 +01:00
|
|
|
{
|
|
|
|
const stub = make_stub();
|
2020-12-01 00:57:57 +01:00
|
|
|
channel.del = stub.f;
|
2020-06-30 21:16:29 +02:00
|
|
|
reactions.process_reaction_click(message_id, "unicode_emoji,1f642");
|
2021-02-13 03:46:14 +01:00
|
|
|
assert.equal(stub.num_calls, 1);
|
2020-07-15 01:29:15 +02:00
|
|
|
const args = stub.get_args("args").args;
|
|
|
|
assert.equal(args.url, "/json/messages/1001/reactions");
|
2017-10-31 22:33:28 +01:00
|
|
|
assert.deepEqual(args.data, expected_reaction_info);
|
2021-02-13 03:46:14 +01:00
|
|
|
}
|
2018-05-15 12:40:07 +02:00
|
|
|
});
|
reactions: Rewrite code to use clean reactions.
Before this commit, the reactions code would
take the `message.reactions` structure from
the server and try to "collapse" all the reactions
for the same users into the same reactions,
but with each reaction having a list of user_ids.
It was a strangely denormalized structure that
was awkward to work with, and it made it really
hard to reason about whether the data was in
the original structure that the server sent or
the modified structure.
Now we use a cleaner, normalized Map to keep
each reaction (i.e. one per emoji), and we
write that to `message.clean_reactions`.
The `clean_reactions` structure is now the
authoritatize source for all reaction-related
operations. As soon as you try to do anything
with reactions, we build the `clean_reactions`
data on the fly from the server data.
In particular, when we process events, we just
directly manipulate the `clean_reactions` data,
which is much easier to work with, since it's
a Map and doesn't duplicate any data.
This rewrite should avoid some obscure bugs.
I use `r` as shorthand for the clean reaction
structures, so as not to confuse it with
data from the server's message.reactions.
It also avoids some confusion where we use
`reaction` as a var name for the reaction
elements.
2020-03-08 13:13:47 +01:00
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
run_test("warnings", () => {
|
reactions: Rewrite code to use clean reactions.
Before this commit, the reactions code would
take the `message.reactions` structure from
the server and try to "collapse" all the reactions
for the same users into the same reactions,
but with each reaction having a list of user_ids.
It was a strangely denormalized structure that
was awkward to work with, and it made it really
hard to reason about whether the data was in
the original structure that the server sent or
the modified structure.
Now we use a cleaner, normalized Map to keep
each reaction (i.e. one per emoji), and we
write that to `message.clean_reactions`.
The `clean_reactions` structure is now the
authoritatize source for all reaction-related
operations. As soon as you try to do anything
with reactions, we build the `clean_reactions`
data on the fly from the server data.
In particular, when we process events, we just
directly manipulate the `clean_reactions` data,
which is much easier to work with, since it's
a Map and doesn't duplicate any data.
This rewrite should avoid some obscure bugs.
I use `r` as shorthand for the clean reaction
structures, so as not to confuse it with
data from the server's message.reactions.
It also avoids some confusion where we use
`reaction` as a var name for the reaction
elements.
2020-03-08 13:13:47 +01:00
|
|
|
// Clean the slate
|
|
|
|
delete message.clean_reactions;
|
2020-07-15 01:29:15 +02:00
|
|
|
blueslip.expect("warn", "Unknown user_id 8888 in reaction for message 1001");
|
|
|
|
blueslip.expect("warn", "Unknown user_id 9999 in reaction for message 1001");
|
reactions: Rewrite code to use clean reactions.
Before this commit, the reactions code would
take the `message.reactions` structure from
the server and try to "collapse" all the reactions
for the same users into the same reactions,
but with each reaction having a list of user_ids.
It was a strangely denormalized structure that
was awkward to work with, and it made it really
hard to reason about whether the data was in
the original structure that the server sent or
the modified structure.
Now we use a cleaner, normalized Map to keep
each reaction (i.e. one per emoji), and we
write that to `message.clean_reactions`.
The `clean_reactions` structure is now the
authoritatize source for all reaction-related
operations. As soon as you try to do anything
with reactions, we build the `clean_reactions`
data on the fly from the server data.
In particular, when we process events, we just
directly manipulate the `clean_reactions` data,
which is much easier to work with, since it's
a Map and doesn't duplicate any data.
This rewrite should avoid some obscure bugs.
I use `r` as shorthand for the clean reaction
structures, so as not to confuse it with
data from the server's message.reactions.
It also avoids some confusion where we use
`reaction` as a var name for the reaction
elements.
2020-03-08 13:13:47 +01:00
|
|
|
reactions.get_message_reactions(message);
|
|
|
|
});
|
|
|
|
|
2021-02-25 14:13:30 +01:00
|
|
|
run_test("code coverage", (override) => {
|
reactions: Rewrite code to use clean reactions.
Before this commit, the reactions code would
take the `message.reactions` structure from
the server and try to "collapse" all the reactions
for the same users into the same reactions,
but with each reaction having a list of user_ids.
It was a strangely denormalized structure that
was awkward to work with, and it made it really
hard to reason about whether the data was in
the original structure that the server sent or
the modified structure.
Now we use a cleaner, normalized Map to keep
each reaction (i.e. one per emoji), and we
write that to `message.clean_reactions`.
The `clean_reactions` structure is now the
authoritatize source for all reaction-related
operations. As soon as you try to do anything
with reactions, we build the `clean_reactions`
data on the fly from the server data.
In particular, when we process events, we just
directly manipulate the `clean_reactions` data,
which is much easier to work with, since it's
a Map and doesn't duplicate any data.
This rewrite should avoid some obscure bugs.
I use `r` as shorthand for the clean reaction
structures, so as not to confuse it with
data from the server's message.reactions.
It also avoids some confusion where we use
`reaction` as a var name for the reaction
elements.
2020-03-08 13:13:47 +01:00
|
|
|
/*
|
|
|
|
We just silently fail in a few places in the reaction
|
|
|
|
code, since events may come for messages that we don't
|
|
|
|
have yet, or reactions may be for deactivated users, etc.
|
|
|
|
|
|
|
|
Here we just cheaply ensure 100% line coverage to make
|
|
|
|
it easy to enforce 100% coverage for more significant
|
|
|
|
code additions.
|
|
|
|
*/
|
2021-02-25 14:13:30 +01:00
|
|
|
override(message_store, "get", (id) => {
|
reactions: Rewrite code to use clean reactions.
Before this commit, the reactions code would
take the `message.reactions` structure from
the server and try to "collapse" all the reactions
for the same users into the same reactions,
but with each reaction having a list of user_ids.
It was a strangely denormalized structure that
was awkward to work with, and it made it really
hard to reason about whether the data was in
the original structure that the server sent or
the modified structure.
Now we use a cleaner, normalized Map to keep
each reaction (i.e. one per emoji), and we
write that to `message.clean_reactions`.
The `clean_reactions` structure is now the
authoritatize source for all reaction-related
operations. As soon as you try to do anything
with reactions, we build the `clean_reactions`
data on the fly from the server data.
In particular, when we process events, we just
directly manipulate the `clean_reactions` data,
which is much easier to work with, since it's
a Map and doesn't duplicate any data.
This rewrite should avoid some obscure bugs.
I use `r` as shorthand for the clean reaction
structures, so as not to confuse it with
data from the server's message.reactions.
It also avoids some confusion where we use
`reaction` as a var name for the reaction
elements.
2020-03-08 13:13:47 +01:00
|
|
|
assert.equal(id, 42);
|
|
|
|
return {
|
|
|
|
reactions: [],
|
|
|
|
};
|
2021-02-25 14:13:30 +01:00
|
|
|
});
|
reactions: Rewrite code to use clean reactions.
Before this commit, the reactions code would
take the `message.reactions` structure from
the server and try to "collapse" all the reactions
for the same users into the same reactions,
but with each reaction having a list of user_ids.
It was a strangely denormalized structure that
was awkward to work with, and it made it really
hard to reason about whether the data was in
the original structure that the server sent or
the modified structure.
Now we use a cleaner, normalized Map to keep
each reaction (i.e. one per emoji), and we
write that to `message.clean_reactions`.
The `clean_reactions` structure is now the
authoritatize source for all reaction-related
operations. As soon as you try to do anything
with reactions, we build the `clean_reactions`
data on the fly from the server data.
In particular, when we process events, we just
directly manipulate the `clean_reactions` data,
which is much easier to work with, since it's
a Map and doesn't duplicate any data.
This rewrite should avoid some obscure bugs.
I use `r` as shorthand for the clean reaction
structures, so as not to confuse it with
data from the server's message.reactions.
It also avoids some confusion where we use
`reaction` as a var name for the reaction
elements.
2020-03-08 13:13:47 +01:00
|
|
|
|
|
|
|
reactions.remove_reaction({
|
2020-04-22 23:24:28 +02:00
|
|
|
message_id: 42, // TODO: REACTIONS API
|
reactions: Rewrite code to use clean reactions.
Before this commit, the reactions code would
take the `message.reactions` structure from
the server and try to "collapse" all the reactions
for the same users into the same reactions,
but with each reaction having a list of user_ids.
It was a strangely denormalized structure that
was awkward to work with, and it made it really
hard to reason about whether the data was in
the original structure that the server sent or
the modified structure.
Now we use a cleaner, normalized Map to keep
each reaction (i.e. one per emoji), and we
write that to `message.clean_reactions`.
The `clean_reactions` structure is now the
authoritatize source for all reaction-related
operations. As soon as you try to do anything
with reactions, we build the `clean_reactions`
data on the fly from the server data.
In particular, when we process events, we just
directly manipulate the `clean_reactions` data,
which is much easier to work with, since it's
a Map and doesn't duplicate any data.
This rewrite should avoid some obscure bugs.
I use `r` as shorthand for the clean reaction
structures, so as not to confuse it with
data from the server's message.reactions.
It also avoids some confusion where we use
`reaction` as a var name for the reaction
elements.
2020-03-08 13:13:47 +01:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-07-15 01:29:15 +02:00
|
|
|
run_test("duplicates", () => {
|
reactions: Rewrite code to use clean reactions.
Before this commit, the reactions code would
take the `message.reactions` structure from
the server and try to "collapse" all the reactions
for the same users into the same reactions,
but with each reaction having a list of user_ids.
It was a strangely denormalized structure that
was awkward to work with, and it made it really
hard to reason about whether the data was in
the original structure that the server sent or
the modified structure.
Now we use a cleaner, normalized Map to keep
each reaction (i.e. one per emoji), and we
write that to `message.clean_reactions`.
The `clean_reactions` structure is now the
authoritatize source for all reaction-related
operations. As soon as you try to do anything
with reactions, we build the `clean_reactions`
data on the fly from the server data.
In particular, when we process events, we just
directly manipulate the `clean_reactions` data,
which is much easier to work with, since it's
a Map and doesn't duplicate any data.
This rewrite should avoid some obscure bugs.
I use `r` as shorthand for the clean reaction
structures, so as not to confuse it with
data from the server's message.reactions.
It also avoids some confusion where we use
`reaction` as a var name for the reaction
elements.
2020-03-08 13:13:47 +01:00
|
|
|
const dup_reaction_message = {
|
|
|
|
id: 1001,
|
|
|
|
reactions: [
|
2020-06-30 21:16:29 +02:00
|
|
|
{emoji_name: "smile", user_id: 5, reaction_type: "unicode_emoji", emoji_code: "1f642"},
|
|
|
|
{emoji_name: "smile", user_id: 5, reaction_type: "unicode_emoji", emoji_code: "1f642"},
|
reactions: Rewrite code to use clean reactions.
Before this commit, the reactions code would
take the `message.reactions` structure from
the server and try to "collapse" all the reactions
for the same users into the same reactions,
but with each reaction having a list of user_ids.
It was a strangely denormalized structure that
was awkward to work with, and it made it really
hard to reason about whether the data was in
the original structure that the server sent or
the modified structure.
Now we use a cleaner, normalized Map to keep
each reaction (i.e. one per emoji), and we
write that to `message.clean_reactions`.
The `clean_reactions` structure is now the
authoritatize source for all reaction-related
operations. As soon as you try to do anything
with reactions, we build the `clean_reactions`
data on the fly from the server data.
In particular, when we process events, we just
directly manipulate the `clean_reactions` data,
which is much easier to work with, since it's
a Map and doesn't duplicate any data.
This rewrite should avoid some obscure bugs.
I use `r` as shorthand for the clean reaction
structures, so as not to confuse it with
data from the server's message.reactions.
It also avoids some confusion where we use
`reaction` as a var name for the reaction
elements.
2020-03-08 13:13:47 +01:00
|
|
|
],
|
|
|
|
};
|
|
|
|
|
2020-06-30 21:16:29 +02:00
|
|
|
blueslip.expect(
|
|
|
|
"error",
|
|
|
|
"server sent duplicate reactions for user 5 (key=unicode_emoji,1f642)",
|
|
|
|
);
|
reactions: Rewrite code to use clean reactions.
Before this commit, the reactions code would
take the `message.reactions` structure from
the server and try to "collapse" all the reactions
for the same users into the same reactions,
but with each reaction having a list of user_ids.
It was a strangely denormalized structure that
was awkward to work with, and it made it really
hard to reason about whether the data was in
the original structure that the server sent or
the modified structure.
Now we use a cleaner, normalized Map to keep
each reaction (i.e. one per emoji), and we
write that to `message.clean_reactions`.
The `clean_reactions` structure is now the
authoritatize source for all reaction-related
operations. As soon as you try to do anything
with reactions, we build the `clean_reactions`
data on the fly from the server data.
In particular, when we process events, we just
directly manipulate the `clean_reactions` data,
which is much easier to work with, since it's
a Map and doesn't duplicate any data.
This rewrite should avoid some obscure bugs.
I use `r` as shorthand for the clean reaction
structures, so as not to confuse it with
data from the server's message.reactions.
It also avoids some confusion where we use
`reaction` as a var name for the reaction
elements.
2020-03-08 13:13:47 +01:00
|
|
|
reactions.set_clean_reactions(dup_reaction_message);
|
|
|
|
});
|
2020-03-09 14:26:17 +01:00
|
|
|
|
2021-02-24 17:08:13 +01:00
|
|
|
run_test("process_reaction_click undefined", (override) => {
|
|
|
|
override(message_store, "get", () => undefined);
|
2020-07-15 01:29:15 +02:00
|
|
|
blueslip.expect("error", "reactions: Bad message id: 55");
|
|
|
|
blueslip.expect("error", "message_id for reaction click is unknown: 55");
|
|
|
|
reactions.process_reaction_click(55, "whatever");
|
2021-02-24 17:08:13 +01:00
|
|
|
});
|
2020-03-09 14:26:17 +01:00
|
|
|
|
2021-02-24 17:08:13 +01:00
|
|
|
run_test("process_reaction_click bad local id", (override) => {
|
|
|
|
override(message_store, "get", () => message);
|
2020-07-15 00:34:28 +02:00
|
|
|
blueslip.expect(
|
|
|
|
"error",
|
|
|
|
"Data integrity problem for reaction bad-local-id (message some-msg-id)",
|
|
|
|
);
|
2020-07-15 01:29:15 +02:00
|
|
|
reactions.process_reaction_click("some-msg-id", "bad-local-id");
|
2020-03-09 14:26:17 +01:00
|
|
|
});
|