Files
zulip/frontend_tests/node_tests/stream_events.js
Nat1405 d5f005fd61 wildcard_mentions_notify: Add per-stream override of global setting.
Adds required API and front-end changes to modify and read the
wildcard_mentions_notify field in the Subscription model.

It includes front-end code to add the setting to the user's "manage
streams" page. This setting will be greyed out when a stream is muted.
The PR also includes back-end code to add the setting the initial state of
a subscription.

New automated tests were added for the API, events system and front-end.
In manual testing, we checked that modifying the setting in the front end
persisted the change in the Subscription model. We noticed the notifications
were not behaving exactly as expected in manual testing; see
https://github.com/zulip/zulip/issues/13073#issuecomment-560263081 .

Tweaked by tabbott to fix real-time synchronization issues.

Fixes: #13429.
2019-12-09 16:09:38 -08:00

391 lines
13 KiB
JavaScript

const noop = function () {};
const return_true = function () { return true; };
set_global('$', global.make_zjquery());
set_global('document', 'document-stub');
set_global('colorspace', {
sRGB_to_linear: noop,
luminance_to_lightness: function () {
return 1;
},
});
zrequire('people');
zrequire('stream_data');
zrequire('stream_events');
const with_overrides = global.with_overrides;
const george = {
email: 'george@zulip.com',
full_name: 'George',
user_id: 103,
};
people.add(george);
const frontend = {
subscribed: false,
color: 'yellow',
name: 'frontend',
stream_id: 1,
is_muted: true,
invite_only: false,
};
stream_data.add_sub(frontend.name, frontend);
run_test('update_property', () => {
// Invoke error for non-existent stream/property
with_overrides(function (override) {
let errors = 0;
override('blueslip.warn', function () {
errors += 1;
});
stream_events.update_property(99, 'color', 'blue');
assert.equal(errors, 1);
stream_events.update_property(1, 'not_real', 42);
assert.equal(errors, 2);
});
// Test update color
with_overrides(function (override) {
global.with_stub(function (stub) {
override('stream_color.update_stream_color', stub.f);
stream_events.update_property(1, 'color', 'blue');
const args = stub.get_args('sub', 'val');
assert.equal(args.sub.stream_id, 1);
assert.equal(args.val, 'blue');
});
});
// Test in home view
with_overrides(function (override) {
global.with_stub(function (stub) {
override('stream_muting.update_is_muted', stub.f);
stream_events.update_property(1, 'in_home_view', false);
const args = stub.get_args('sub', 'val');
assert.equal(args.sub.stream_id, 1);
assert.equal(args.val, true);
});
});
// Test desktop notifications
stream_events.update_property(1, 'desktop_notifications', true);
assert.equal(frontend.desktop_notifications, true);
let checkbox = $("#desktop_notifications_1");
assert.equal(checkbox.prop('checked'), true);
// Tests audible notifications
stream_events.update_property(1, 'audible_notifications', true);
assert.equal(frontend.audible_notifications, true);
checkbox = $("#audible_notifications_1");
assert.equal(checkbox.prop('checked'), true);
// Tests push notifications
stream_events.update_property(1, 'push_notifications', true);
assert.equal(frontend.push_notifications, true);
checkbox = $("#push_notifications_1");
assert.equal(checkbox.prop('checked'), true);
// Tests email notifications
stream_events.update_property(1, 'email_notifications', true);
assert.equal(frontend.email_notifications, true);
checkbox = $("#email_notifications_1");
assert.equal(checkbox.prop('checked'), true);
// Tests wildcard_mentions_notify notifications
stream_events.update_property(1, 'wildcard_mentions_notify', true);
assert.equal(frontend.wildcard_mentions_notify, true);
checkbox = $("#wildcard_mentions_notify_1");
assert.equal(checkbox.prop('checked'), true);
// Test name change
with_overrides(function (override) {
global.with_stub(function (stub) {
override('subs.update_stream_name', stub.f);
stream_events.update_property(1, 'name', 'the frontend');
const args = stub.get_args('sub', 'val');
assert.equal(args.sub.stream_id, 1);
assert.equal(args.val, 'the frontend');
});
});
// Test description change
with_overrides(function (override) {
global.with_stub(function (stub) {
override('subs.update_stream_description', stub.f);
stream_events.update_property(1, 'description', 'we write code', {rendered_description: 'we write code'});
const args = stub.get_args('sub', 'val');
assert.equal(args.sub.stream_id, 1);
assert.equal(args.val, 'we write code');
});
});
// Test email address change
stream_events.update_property(1, 'email_address', 'zooly@zulip.com');
assert.equal(frontend.email_address, 'zooly@zulip.com');
// Test pin to top
with_overrides(function (override) {
override('stream_list.refresh_pinned_or_unpinned_stream', noop);
stream_events.update_property(1, 'pin_to_top', true);
checkbox = $("#pin_to_top_1");
assert.equal(checkbox.prop('checked'), true);
});
// Test stream privacy change event
with_overrides(function (override) {
global.with_stub(function (stub) {
override('subs.update_stream_privacy', stub.f);
stream_events.update_property(1, 'invite_only', true, {
history_public_to_subscribers: true,
});
const args = stub.get_args('sub', 'val');
assert.equal(args.sub.stream_id, 1);
assert.deepEqual(args.val, {
invite_only: true,
history_public_to_subscribers: true,
});
});
});
// Test stream is_announcement_only change event
with_overrides(function (override) {
global.with_stub(function (stub) {
override('subs.update_stream_announcement_only', stub.f);
stream_events.update_property(1, 'is_announcement_only', true);
const args = stub.get_args('sub', 'val');
assert.equal(args.sub.stream_id, 1);
assert.equal(args.val, true);
});
});
});
run_test('marked_subscribed', () => {
// Test undefined error
with_overrides(function (override) {
let errors = 0;
override('stream_color.update_stream_color', noop);
override('blueslip.error', function () {
errors += 1;
});
stream_events.mark_subscribed(undefined, [], 'yellow');
assert.equal(errors, 1);
});
// Test early return if subscribed
with_overrides(function (override) {
let completed = false;
override('message_util.do_unread_count_updates', function () {
completed = true; // This gets run if we continue and don't early return
});
const subscribed = {subscribed: true};
stream_events.mark_subscribed(subscribed, [], 'yellow');
assert.equal(completed, false);
});
set_global('message_list', {
all: {
all_messages: function () { return ['msg']; },
},
});
stream_data.subscribe_myself = noop;
stream_data.set_subscribers = noop;
stream_data.get_colors = noop;
stream_data.update_calculated_fields = noop;
set_global('subs', { update_settings_for_subscribed: noop });
set_global('narrow_state', { is_for_stream_id: noop });
set_global('overlays', { streams_open: return_true });
// Test unread count update
with_overrides(function (override) {
global.with_stub(function (stub) {
override('stream_color.update_stream_color', noop);
override('message_util.do_unread_count_updates', stub.f);
stream_events.mark_subscribed(frontend, [], '');
const args = stub.get_args('messages');
assert.deepEqual(args.messages, ['msg']);
});
});
set_global('message_util', { do_unread_count_updates: noop });
// Test jQuery event
with_overrides(function (override) {
override('stream_color.update_stream_color', noop);
global.with_stub(function (stub) {
$(document).on('subscription_add_done.zulip', stub.f);
stream_events.mark_subscribed(frontend, [], '');
const args = stub.get_args('event');
assert.equal(args.event.sub.stream_id, 1);
});
});
// Test bookend update
with_overrides(function (override) {
override('stream_color.update_stream_color', noop);
override('narrow_state.is_for_stream_id', function () {
return true;
});
let updated = false;
override('current_msg_list.update_trailing_bookend', function () {
updated = true;
});
stream_events.mark_subscribed(frontend, [], '');
assert.equal(updated, true);
});
// reset overridden value
set_global('narrow_state', { is_for_stream_id: noop });
// Test setting color
with_overrides(function (override) {
override('stream_color.update_stream_color', noop);
stream_events.mark_subscribed(frontend, [], 'blue');
assert.equal(frontend.color, 'blue');
});
// Test assigning generated color
with_overrides(function (override) {
frontend.color = undefined;
override('color_data.pick_color', function () {
return 'green';
});
let warnings = 0;
override('blueslip.warn', function () {
warnings += 1;
});
global.with_stub(function (stub) {
override('stream_color.update_stream_color', noop);
override('subs.set_color', stub.f);
stream_events.mark_subscribed(frontend, [], undefined);
const args = stub.get_args('id', 'color');
assert.equal(args.id, 1);
assert.equal(args.color, 'green');
assert.equal(warnings, 1);
});
});
// Test assigning subscriber emails
with_overrides(function (override) {
override('stream_color.update_stream_color', noop);
global.with_stub(function (stub) {
override('stream_data.set_subscribers', stub.f);
const user_ids = [15, 20, 25];
stream_events.mark_subscribed(frontend, user_ids, '');
const args = stub.get_args('sub', 'subscribers');
assert.deepEqual(frontend, args.sub);
assert.deepEqual(user_ids, args.subscribers);
});
// assign self as well
global.with_stub(function (stub) {
override('stream_data.subscribe_myself', stub.f);
stream_events.mark_subscribed(frontend, [], '');
const args = stub.get_args('sub');
assert.deepEqual(frontend, args.sub);
});
// and finally update subscriber settings
global.with_stub(function (stub) {
override('subs.update_settings_for_subscribed', stub.f);
stream_events.mark_subscribed(frontend, [], '');
const args = stub.get_args('sub');
assert.deepEqual(frontend, args.sub);
});
});
});
run_test('mark_unsubscribed', () => {
let removed_sub = false;
$(document).on('subscription_remove_done.zulip', function () {
removed_sub = true;
});
// take no action if no sub specified
stream_events.mark_unsubscribed();
assert.equal(removed_sub, false);
// take no action if already unsubscribed
frontend.subscribed = false;
stream_events.mark_unsubscribed(frontend);
assert.equal(removed_sub, false);
// Test unsubscribe
frontend.subscribed = true;
with_overrides(function (override) {
global.with_stub(function (stub) {
override('stream_data.unsubscribe_myself', stub.f);
override('subs.update_settings_for_unsubscribed', noop);
stream_events.mark_unsubscribed(frontend);
const args = stub.get_args('sub');
assert.deepEqual(args.sub, frontend);
});
});
// Test update settings after unsubscribe
with_overrides(function (override) {
global.with_stub(function (stub) {
override('subs.update_settings_for_unsubscribed', stub.f);
override('stream_data.unsubscribe_myself', noop);
stream_events.mark_unsubscribed(frontend);
const args = stub.get_args('sub');
assert.deepEqual(args.sub, frontend);
});
});
// Test update bookend and remove done event
with_overrides(function (override) {
override('stream_data.unsubscribe_myself', noop);
override('subs.update_settings_for_unsubscribed', noop);
override('narrow_state.is_for_stream_id', function () {
return true;
});
let updated = false;
override('current_msg_list.update_trailing_bookend', function () {
updated = true;
});
let event_triggered = false;
$(document).trigger = function (ev) {
assert.equal(ev.name, 'subscription_remove_done.zulip');
assert.deepEqual(ev.data.sub, frontend);
event_triggered = true;
};
stream_events.mark_unsubscribed(frontend);
assert.equal(updated, true);
assert.equal(event_triggered, true);
});
});
stream_data.clear_subscriptions();
const dev_help = {
subscribed: true,
color: 'blue',
name: 'dev help',
stream_id: 2,
is_muted: true,
invite_only: false,
};
stream_data.add_sub(dev_help.name, dev_help);
run_test('remove_deactivated_user_from_all_streams', () => {
subs.rerender_subscriptions_settings = () => {};
dev_help.can_access_subscribers = true;
// verify that deactivating user should unsubscribe user from all streams
assert(stream_data.add_subscriber(dev_help.name, george.user_id));
assert(dev_help.subscribers.has(george.user_id));
stream_events.remove_deactivated_user_from_all_streams(george.user_id);
assert(!dev_help.subscribers.has(george.user_id));
});