Refactor Notifications reducer with Immutable.Record, start rewriting tests

This commit is contained in:
Alex Gleason 2022-03-11 13:51:34 -06:00
parent 4c2cdc4ac2
commit 7d91bb7ff9
No known key found for this signature in database
GPG Key ID: 7211D1F99744FBB7
2 changed files with 446 additions and 629 deletions

View File

@ -1,4 +1,8 @@
import { Map as ImmutableMap, OrderedMap as ImmutableOrderedMap, fromJS } from 'immutable'; import {
Map as ImmutableMap,
OrderedMap as ImmutableOrderedMap,
Record as ImmutableRecord,
} from 'immutable';
import { take } from 'lodash'; import { take } from 'lodash';
import intlMessages from 'soapbox/__fixtures__/intlMessages.json'; import intlMessages from 'soapbox/__fixtures__/intlMessages.json';
@ -27,24 +31,27 @@ import { TIMELINE_DELETE } from 'soapbox/actions/timelines';
import reducer from '../notifications'; import reducer from '../notifications';
const initialState = reducer(undefined, {});
describe('notifications reducer', () => { describe('notifications reducer', () => {
it('should return the initial state', () => { it('should return the initial state', () => {
expect(reducer(undefined, {})).toEqual(ImmutableMap({ const expected = {
items: ImmutableOrderedMap(), items: {},
hasMore: true, hasMore: true,
top: false, top: false,
unread: 0, unread: 0,
isLoading: false, isLoading: false,
queuedNotifications: ImmutableOrderedMap(), queuedNotifications: {},
totalQueuedNotificationsCount: 0, totalQueuedNotificationsCount: 0,
lastRead: -1, lastRead: -1,
})); };
expect(ImmutableRecord.isRecord(initialState)).toBe(true);
expect(initialState.toJS()).toMatchObject(expected);
}); });
describe('NOTIFICATIONS_EXPAND_SUCCESS', () => { describe('NOTIFICATIONS_EXPAND_SUCCESS', () => {
it('imports the notifications', () => { it('imports the notifications', () => {
const state = undefined;
const action = { const action = {
type: NOTIFICATIONS_EXPAND_SUCCESS, type: NOTIFICATIONS_EXPAND_SUCCESS,
notifications: take(notifications, 3), notifications: take(notifications, 3),
@ -52,47 +59,17 @@ describe('notifications reducer', () => {
skipLoading: true, skipLoading: true,
}; };
expect(reducer(state, action)).toEqual(ImmutableMap({ const result = reducer(undefined, action);
items: ImmutableOrderedMap([
['10744', ImmutableMap({ // The items are parsed as records
id: '10744', expect(ImmutableOrderedMap.isOrderedMap(result.items)).toBe(true);
type: 'pleroma:emoji_reaction', expect(ImmutableRecord.isRecord(result.items.get('10743'))).toBe(true);
account: '9vMAje101ngtjlMj7w',
target: null, // We can get an item
created_at: '2020-06-10T02:54:39.000Z', expect(result.items.get('10744').emoji).toEqual('😢');
status: '9vvNxoo5EFbbnfdXQu',
emoji: '😢', // hasMore is set to false because `next` is null
chat_message: undefined, expect(result.hasMore).toBe(false);
})],
['10743', ImmutableMap({
id: '10743',
type: 'favourite',
account: '9v5c6xSEgAi3Zu1Lv6',
target: null,
created_at: '2020-06-10T02:51:05.000Z',
status: '9vvNxoo5EFbbnfdXQu',
emoji: undefined,
chat_message: undefined,
})],
['10741', ImmutableMap({
id: '10741',
type: 'favourite',
account: '9v5cKMOPGqPcgfcWp6',
target: null,
created_at: '2020-06-10T02:05:06.000Z',
status: '9vvNxoo5EFbbnfdXQu',
emoji: undefined,
chat_message: undefined,
})],
]),
hasMore: false,
top: false,
unread: 0,
isLoading: false,
queuedNotifications: ImmutableOrderedMap(),
totalQueuedNotificationsCount: 0,
lastRead: -1,
}));
}); });
it('drops invalid notifications', () => { it('drops invalid notifications', () => {
@ -109,200 +86,132 @@ describe('notifications reducer', () => {
skipLoading: true, skipLoading: true,
}; };
const expected = ImmutableOrderedMap([ const result = reducer(undefined, action);
['4', fromJS({
id: '4',
type: 'mention',
account: '7',
target: null,
created_at: undefined,
status: 'a',
emoji: undefined,
chat_message: undefined,
})],
]);
expect(reducer(undefined, action).get('items')).toEqual(expected); // Only '4' is valid
expect(result.items.size).toEqual(1);
expect(result.items.get('4').id).toEqual('4');
}); });
}); });
it('should handle NOTIFICATIONS_EXPAND_REQUEST', () => { describe('NOTIFICATIONS_EXPAND_REQUEST', () => {
const state = ImmutableMap({ it('sets isLoading to true', () => {
isLoading: false, const state = initialState.set('isLoading', false);
const action = { type: NOTIFICATIONS_EXPAND_REQUEST };
expect(reducer(state, action).isLoading).toBe(true);
}); });
const action = {
type: NOTIFICATIONS_EXPAND_REQUEST,
};
expect(reducer(state, action)).toEqual(ImmutableMap({
isLoading: true,
}));
}); });
it('should handle NOTIFICATIONS_EXPAND_FAIL', () => { describe('NOTIFICATIONS_EXPAND_FAIL', () => {
const state = ImmutableMap({ it('sets isLoading to false', () => {
isLoading: true, const state = initialState.set('isLoading', true);
const action = { type: NOTIFICATIONS_EXPAND_FAIL };
expect(reducer(state, action).isLoading).toBe(false);
}); });
const action = {
type: NOTIFICATIONS_EXPAND_FAIL,
};
expect(reducer(state, action)).toEqual(ImmutableMap({
isLoading: false,
}));
}); });
it('should handle NOTIFICATIONS_FILTER_SET', () => { describe('NOTIFICATIONS_FILTER_SET', () => {
const state = ImmutableMap({ it('clears the items', () => {
items: ImmutableOrderedMap([ const actions = [{
['10744', ImmutableMap({ type: NOTIFICATIONS_EXPAND_SUCCESS,
id: '10744', notifications: [
type: 'pleroma:emoji_reaction', { id: '1', type: 'mention', status: { id: '4' }, account: { id: '7' } },
account: '9vMAje101ngtjlMj7w', { id: '2', type: 'mention', status: { id: '5' }, account: { id: '8' } },
target: null, { id: '3', type: 'mention', status: { id: '6' }, account: { id: '9' } },
created_at: '2020-06-10T02:54:39.000Z', ],
status: '9vvNxoo5EFbbnfdXQu', next: null,
emoji: '😢', skipLoading: true,
chat_message: undefined, }, {
})],
['10743', ImmutableMap({
id: '10743',
type: 'favourite',
account: '9v5c6xSEgAi3Zu1Lv6',
target: null,
created_at: '2020-06-10T02:51:05.000Z',
status: '9vvNxoo5EFbbnfdXQu',
emoji: undefined,
chat_message: undefined,
})],
['10741', ImmutableMap({
id: '10741',
type: 'favourite',
account: '9v5cKMOPGqPcgfcWp6',
target: null,
created_at: '2020-06-10T02:05:06.000Z',
status: '9vvNxoo5EFbbnfdXQu',
emoji: undefined,
chat_message: undefined,
})],
]),
hasMore: false,
top: false,
unread: 1,
isLoading: false,
queuedNotifications: ImmutableOrderedMap(),
totalQueuedNotificationsCount: 0,
lastRead: -1,
});
const action = {
type: NOTIFICATIONS_FILTER_SET, type: NOTIFICATIONS_FILTER_SET,
}; }];
expect(reducer(state, action)).toEqual(ImmutableMap({
items: ImmutableOrderedMap(), // Setup by expanding, then calling `NOTIFICATIONS_FILTER_SET`
hasMore: true, const result = actions.reduce((state, action) => reducer(state, action), initialState);
top: false,
unread: 1, // Setting the filter wipes notifications
isLoading: false, expect(result.items.isEmpty()).toBe(true);
queuedNotifications: ImmutableOrderedMap(),
totalQueuedNotificationsCount: 0,
lastRead: -1,
}));
}); });
it('should handle NOTIFICATIONS_SCROLL_TOP by changing unread to 0 when top = true', () => { it('sets hasMore to true', () => {
const state = ImmutableMap({ const state = initialState.set('hasMore', false);
unread: 1, const action = { type: NOTIFICATIONS_FILTER_SET };
const result = reducer(state, action);
expect(result.hasMore).toBe(true);
}); });
const action = {
type: NOTIFICATIONS_SCROLL_TOP,
top: true,
};
expect(reducer(state, action)).toEqual(ImmutableMap({
unread: 0,
top: true,
}));
}); });
it('should handle NOTIFICATIONS_SCROLL_TOP by not changing unread val when top = false', () => { describe('NOTIFICATIONS_SCROLL_TOP', () => {
const state = ImmutableMap({ it('resets `unread` counter to 0 when top is true (ie, scrolled to the top)', () => {
unread: 3, const state = initialState.set('unread', 1);
}); const action = { type: NOTIFICATIONS_SCROLL_TOP, top: true };
const action = { const result = reducer(state, action);
type: NOTIFICATIONS_SCROLL_TOP,
top: false, expect(result.unread).toEqual(0);
}; expect(result.top).toBe(true);
expect(reducer(state, action)).toEqual(ImmutableMap({
unread: 3,
top: false,
}));
}); });
it('should handle NOTIFICATIONS_UPDATE, when top = false, increment unread', () => { it('leaves `unread` alone when top is false (ie, not scrolled to top)', () => {
const state = ImmutableMap({ const state = initialState.set('unread', 3);
items: ImmutableOrderedMap(), const action = { type: NOTIFICATIONS_SCROLL_TOP, top: false };
top: false, const result = reducer(state, action);
unread: 1,
expect(result.unread).toEqual(3);
expect(result.top).toBe(false);
}); });
const action = {
type: NOTIFICATIONS_UPDATE,
notification: notification,
};
expect(reducer(state, action)).toEqual(ImmutableMap({
items: ImmutableOrderedMap([
['10743', ImmutableMap({
id: '10743',
type: 'favourite',
account: '9v5c6xSEgAi3Zu1Lv6',
target: null,
created_at: '2020-06-10T02:51:05.000Z',
status: '9vvNxoo5EFbbnfdXQu',
emoji: undefined,
chat_message: undefined,
})],
]),
top: false,
unread: 2,
}));
}); });
it('should handle NOTIFICATIONS_UPDATE_QUEUE', () => { describe('NOTIFICATIONS_UPDATE', () => {
const state = ImmutableMap({ it('imports the notification', () => {
items: ImmutableOrderedMap(), const action = { type: NOTIFICATIONS_UPDATE, notification };
queuedNotifications: ImmutableOrderedMap(), const result = reducer(initialState, action);
totalQueuedNotificationsCount: 0,
expect(result.items.get('10743').type).toEqual('favourite');
}); });
it('increments `unread` counter when top is false', () => {
const action = { type: NOTIFICATIONS_UPDATE, notification };
const result = reducer(initialState, action);
expect(result.unread).toEqual(1);
});
});
describe('NOTIFICATIONS_UPDATE_QUEUE', () => {
it('adds the notification to the queue (and increases the counter)', () => {
const action = { const action = {
type: NOTIFICATIONS_UPDATE_QUEUE, type: NOTIFICATIONS_UPDATE_QUEUE,
notification: notification, notification,
intlMessages: intlMessages, intlMessages,
intlLocale: 'en', intlLocale: 'en',
}; };
expect(reducer(state, action)).toEqual(ImmutableMap({
items: ImmutableOrderedMap(), const result = reducer(initialState, action);
queuedNotifications: ImmutableOrderedMap([[notification.id, {
notification: notification, // Doesn't add it as a regular item
intlMessages: intlMessages, expect(result.items.isEmpty()).toBe(true);
intlLocale: 'en',
}]]), // Adds it to the queued items
totalQueuedNotificationsCount: 1, expect(result.queuedNotifications.size).toEqual(1);
})); expect(result.totalQueuedNotificationsCount).toEqual(1);
expect(result.queuedNotifications.getIn(['10743', 'notification', 'type'])).toEqual('favourite');
});
}); });
it('should handle NOTIFICATIONS_DEQUEUE', () => { describe('NOTIFICATIONS_DEQUEUE', () => {
const state = ImmutableMap({ it('resets the queued counter to 0', () => {
items: ImmutableOrderedMap(), const state = initialState.set('totalQueuedNotificationsCount', 1);
queuedNotifications: take(notifications, 1), const action = { type: NOTIFICATIONS_DEQUEUE };
totalQueuedNotificationsCount: 1, const result = reducer(state, action);
expect(result.totalQueuedNotificationsCount).toEqual(0);
}); });
const action = {
type: NOTIFICATIONS_DEQUEUE,
};
expect(reducer(state, action)).toEqual(ImmutableMap({
items: ImmutableOrderedMap(),
queuedNotifications: ImmutableOrderedMap(),
totalQueuedNotificationsCount: 0,
}));
}); });
it('should handle NOTIFICATIONS_EXPAND_SUCCESS with non-empty items and next set true', () => { describe('NOTIFICATIONS_EXPAND_SUCCESS', () => {
it('with non-empty items and next set true', () => {
const state = ImmutableMap({ const state = ImmutableMap({
items: ImmutableOrderedMap([ items: ImmutableOrderedMap([
['10734', ImmutableMap({ ['10734', ImmutableMap({
@ -313,19 +222,21 @@ describe('notifications reducer', () => {
created_at: '2020-06-10T02:54:39.000Z', created_at: '2020-06-10T02:54:39.000Z',
status: '9vvNxoo5EFbbnfdXQu', status: '9vvNxoo5EFbbnfdXQu',
emoji: '😢', emoji: '😢',
chat_message: undefined, chat_message: null,
})], })],
]), ]),
unread: 1, unread: 1,
hasMore: true, hasMore: true,
isLoading: false, isLoading: false,
}); });
const action = { const action = {
type: NOTIFICATIONS_EXPAND_SUCCESS, type: NOTIFICATIONS_EXPAND_SUCCESS,
notifications: take(notifications, 3), notifications: take(notifications, 3),
next: true, next: true,
}; };
expect(reducer(state, action)).toEqual(ImmutableMap({
const expected = ImmutableMap({
items: ImmutableOrderedMap([ items: ImmutableOrderedMap([
['10744', ImmutableMap({ ['10744', ImmutableMap({
id: '10744', id: '10744',
@ -335,7 +246,7 @@ describe('notifications reducer', () => {
created_at: '2020-06-10T02:54:39.000Z', created_at: '2020-06-10T02:54:39.000Z',
status: '9vvNxoo5EFbbnfdXQu', status: '9vvNxoo5EFbbnfdXQu',
emoji: '😢', emoji: '😢',
chat_message: undefined, chat_message: null,
})], })],
['10743', ImmutableMap({ ['10743', ImmutableMap({
id: '10743', id: '10743',
@ -344,8 +255,8 @@ describe('notifications reducer', () => {
target: null, target: null,
created_at: '2020-06-10T02:51:05.000Z', created_at: '2020-06-10T02:51:05.000Z',
status: '9vvNxoo5EFbbnfdXQu', status: '9vvNxoo5EFbbnfdXQu',
emoji: undefined, emoji: null,
chat_message: undefined, chat_message: null,
})], })],
['10741', ImmutableMap({ ['10741', ImmutableMap({
id: '10741', id: '10741',
@ -354,8 +265,8 @@ describe('notifications reducer', () => {
target: null, target: null,
created_at: '2020-06-10T02:05:06.000Z', created_at: '2020-06-10T02:05:06.000Z',
status: '9vvNxoo5EFbbnfdXQu', status: '9vvNxoo5EFbbnfdXQu',
emoji: undefined, emoji: null,
chat_message: undefined, chat_message: null,
})], })],
['10734', ImmutableMap({ ['10734', ImmutableMap({
id: '10734', id: '10734',
@ -365,28 +276,32 @@ describe('notifications reducer', () => {
created_at: '2020-06-10T02:54:39.000Z', created_at: '2020-06-10T02:54:39.000Z',
status: '9vvNxoo5EFbbnfdXQu', status: '9vvNxoo5EFbbnfdXQu',
emoji: '😢', emoji: '😢',
chat_message: undefined, chat_message: null,
})], })],
]), ]),
unread: 1, unread: 1,
hasMore: true, hasMore: true,
isLoading: false, isLoading: false,
}));
}); });
it('should handle NOTIFICATIONS_EXPAND_SUCCESS with empty items and next set true', () => { expect(reducer(state, action).toJS()).toEqual(expected.toJS());
});
it('with empty items and next set true', () => {
const state = ImmutableMap({ const state = ImmutableMap({
items: ImmutableOrderedMap(), items: ImmutableOrderedMap(),
unread: 1, unread: 1,
hasMore: true, hasMore: true,
isLoading: false, isLoading: false,
}); });
const action = { const action = {
type: NOTIFICATIONS_EXPAND_SUCCESS, type: NOTIFICATIONS_EXPAND_SUCCESS,
notifications: take(notifications, 3), notifications: take(notifications, 3),
next: true, next: true,
}; };
expect(reducer(state, action)).toEqual(ImmutableMap({
const expected = ImmutableMap({
items: ImmutableOrderedMap([ items: ImmutableOrderedMap([
['10744', ImmutableMap({ ['10744', ImmutableMap({
id: '10744', id: '10744',
@ -396,7 +311,7 @@ describe('notifications reducer', () => {
created_at: '2020-06-10T02:54:39.000Z', created_at: '2020-06-10T02:54:39.000Z',
status: '9vvNxoo5EFbbnfdXQu', status: '9vvNxoo5EFbbnfdXQu',
emoji: '😢', emoji: '😢',
chat_message: undefined, chat_message: null,
})], })],
['10743', ImmutableMap({ ['10743', ImmutableMap({
id: '10743', id: '10743',
@ -405,8 +320,8 @@ describe('notifications reducer', () => {
target: null, target: null,
created_at: '2020-06-10T02:51:05.000Z', created_at: '2020-06-10T02:51:05.000Z',
status: '9vvNxoo5EFbbnfdXQu', status: '9vvNxoo5EFbbnfdXQu',
emoji: undefined, emoji: null,
chat_message: undefined, chat_message: null,
})], })],
['10741', ImmutableMap({ ['10741', ImmutableMap({
id: '10741', id: '10741',
@ -415,17 +330,21 @@ describe('notifications reducer', () => {
target: null, target: null,
created_at: '2020-06-10T02:05:06.000Z', created_at: '2020-06-10T02:05:06.000Z',
status: '9vvNxoo5EFbbnfdXQu', status: '9vvNxoo5EFbbnfdXQu',
emoji: undefined, emoji: null,
chat_message: undefined, chat_message: null,
})], })],
]), ]),
unread: 1, unread: 1,
hasMore: true, hasMore: true,
isLoading: false, isLoading: false,
}));
}); });
it('should handle ACCOUNT_BLOCK_SUCCESS', () => { expect(reducer(state, action).toJS()).toEqual(expected.toJS());
});
});
describe('ACCOUNT_BLOCK_SUCCESS', () => {
it('should handle', () => {
const state = ImmutableMap({ const state = ImmutableMap({
items: ImmutableOrderedMap([ items: ImmutableOrderedMap([
['10744', ImmutableMap({ ['10744', ImmutableMap({
@ -436,7 +355,7 @@ describe('notifications reducer', () => {
created_at: '2020-06-10T02:54:39.000Z', created_at: '2020-06-10T02:54:39.000Z',
status: '9vvNxoo5EFbbnfdXQu', status: '9vvNxoo5EFbbnfdXQu',
emoji: '😢', emoji: '😢',
chat_message: undefined, chat_message: null,
})], })],
['10743', ImmutableMap({ ['10743', ImmutableMap({
id: '10743', id: '10743',
@ -445,8 +364,8 @@ describe('notifications reducer', () => {
target: null, target: null,
created_at: '2020-06-10T02:51:05.000Z', created_at: '2020-06-10T02:51:05.000Z',
status: '9vvNxoo5EFbbnfdXQu', status: '9vvNxoo5EFbbnfdXQu',
emoji: undefined, emoji: null,
chat_message: undefined, chat_message: null,
})], })],
['10741', ImmutableMap({ ['10741', ImmutableMap({
id: '10741', id: '10741',
@ -455,14 +374,14 @@ describe('notifications reducer', () => {
target: null, target: null,
created_at: '2020-06-10T02:05:06.000Z', created_at: '2020-06-10T02:05:06.000Z',
status: '9vvNxoo5EFbbnfdXQu', status: '9vvNxoo5EFbbnfdXQu',
emoji: undefined, emoji: null,
chat_message: undefined, chat_message: null,
})], })],
]), ]),
}); });
const action = { const action = {
type: ACCOUNT_BLOCK_SUCCESS, type: ACCOUNT_BLOCK_SUCCESS,
relationship: relationship, relationship,
}; };
expect(reducer(state, action)).toEqual(ImmutableMap({ expect(reducer(state, action)).toEqual(ImmutableMap({
items: ImmutableOrderedMap([ items: ImmutableOrderedMap([
@ -473,8 +392,8 @@ describe('notifications reducer', () => {
target: null, target: null,
created_at: '2020-06-10T02:51:05.000Z', created_at: '2020-06-10T02:51:05.000Z',
status: '9vvNxoo5EFbbnfdXQu', status: '9vvNxoo5EFbbnfdXQu',
emoji: undefined, emoji: null,
chat_message: undefined, chat_message: null,
})], })],
['10741', ImmutableMap({ ['10741', ImmutableMap({
id: '10741', id: '10741',
@ -483,14 +402,16 @@ describe('notifications reducer', () => {
target: null, target: null,
created_at: '2020-06-10T02:05:06.000Z', created_at: '2020-06-10T02:05:06.000Z',
status: '9vvNxoo5EFbbnfdXQu', status: '9vvNxoo5EFbbnfdXQu',
emoji: undefined, emoji: null,
chat_message: undefined, chat_message: null,
})], })],
]), ]),
})); }));
}); });
});
it('should handle ACCOUNT_MUTE_SUCCESS', () => { describe('ACCOUNT_MUTE_SUCCESS', () => {
it('should handle', () => {
const state = ImmutableMap({ const state = ImmutableMap({
items: ImmutableOrderedMap([ items: ImmutableOrderedMap([
['10744', ImmutableMap({ ['10744', ImmutableMap({
@ -501,7 +422,7 @@ describe('notifications reducer', () => {
created_at: '2020-06-10T02:54:39.000Z', created_at: '2020-06-10T02:54:39.000Z',
status: '9vvNxoo5EFbbnfdXQu', status: '9vvNxoo5EFbbnfdXQu',
emoji: '😢', emoji: '😢',
chat_message: undefined, chat_message: null,
})], })],
['10743', ImmutableMap({ ['10743', ImmutableMap({
id: '10743', id: '10743',
@ -510,8 +431,8 @@ describe('notifications reducer', () => {
target: null, target: null,
created_at: '2020-06-10T02:51:05.000Z', created_at: '2020-06-10T02:51:05.000Z',
status: '9vvNxoo5EFbbnfdXQu', status: '9vvNxoo5EFbbnfdXQu',
emoji: undefined, emoji: null,
chat_message: undefined, chat_message: null,
})], })],
['10741', ImmutableMap({ ['10741', ImmutableMap({
id: '10741', id: '10741',
@ -520,8 +441,8 @@ describe('notifications reducer', () => {
target: null, target: null,
created_at: '2020-06-10T02:05:06.000Z', created_at: '2020-06-10T02:05:06.000Z',
status: '9vvNxoo5EFbbnfdXQu', status: '9vvNxoo5EFbbnfdXQu',
emoji: undefined, emoji: null,
chat_message: undefined, chat_message: null,
})], })],
]), ]),
}); });
@ -538,8 +459,8 @@ describe('notifications reducer', () => {
target: null, target: null,
created_at: '2020-06-10T02:51:05.000Z', created_at: '2020-06-10T02:51:05.000Z',
status: '9vvNxoo5EFbbnfdXQu', status: '9vvNxoo5EFbbnfdXQu',
emoji: undefined, emoji: null,
chat_message: undefined, chat_message: null,
})], })],
['10741', ImmutableMap({ ['10741', ImmutableMap({
id: '10741', id: '10741',
@ -548,157 +469,57 @@ describe('notifications reducer', () => {
target: null, target: null,
created_at: '2020-06-10T02:05:06.000Z', created_at: '2020-06-10T02:05:06.000Z',
status: '9vvNxoo5EFbbnfdXQu', status: '9vvNxoo5EFbbnfdXQu',
emoji: undefined, emoji: null,
chat_message: undefined, chat_message: null,
})], })],
]), ]),
})); }));
}); });
it('should handle NOTIFICATIONS_CLEAR', () => {
const state = ImmutableMap({
items: ImmutableOrderedMap(),
hasMore: true,
});
const action = {
type: NOTIFICATIONS_CLEAR,
};
expect(reducer(state, action)).toEqual(ImmutableMap({
items: ImmutableOrderedMap(),
hasMore: false,
}));
}); });
it('should handle NOTIFICATIONS_MARK_READ_REQUEST', () => { describe('NOTIFICATIONS_CLEAR', () => {
const state = ImmutableMap({ it('clears the items', () => {
items: ImmutableOrderedMap(), const state = initialState.set('items', ImmutableOrderedMap([['1', {}], ['2', {}]]));
const action = { type: NOTIFICATIONS_CLEAR };
const result = reducer(state, action);
expect(result.items.isEmpty()).toBe(true);
}); });
const action = {
type: NOTIFICATIONS_MARK_READ_REQUEST,
lastRead: 35098814,
};
expect(reducer(state, action)).toEqual(ImmutableMap({
items: ImmutableOrderedMap(),
lastRead: 35098814,
}));
}); });
it('should handle TIMELINE_DELETE', () => { describe('NOTIFICATIONS_MARK_READ_REQUEST', () => {
const state = ImmutableMap({ it('sets lastRead to the one in the action', () => {
items: ImmutableOrderedMap([ const action = { type: NOTIFICATIONS_MARK_READ_REQUEST, lastRead: '1234' };
['10744', ImmutableMap({ const result = reducer(undefined, action);
id: '10744',
type: 'pleroma:emoji_reaction', expect(result.lastRead).toEqual('1234');
account: '9vMAje101ngtjlMj7w',
target: null,
created_at: '2020-06-10T02:54:39.000Z',
status: '9vvNxoo5EFbbnfdXQu',
emoji: '😢',
chat_message: undefined,
})],
['10743', ImmutableMap({
id: '10743',
type: 'favourite',
account: '9v5c6xSEgAi3Zu1Lv6',
target: null,
created_at: '2020-06-10T02:51:05.000Z',
status: '9vvNxoo5EFbbnfdXQu',
emoji: undefined,
chat_message: undefined,
})],
['10741', ImmutableMap({
id: '10741',
type: 'favourite',
account: '9v5cKMOPGqPcgfcWp6',
target: null,
created_at: '2020-06-10T02:05:06.000Z',
status: '9vvNxoo5EFbbnfdXQu',
emoji: undefined,
chat_message: undefined,
})],
]),
}); });
const action = { });
describe('TIMELINE_DELETE', () => {
it('deletes notifications corresponding to the status ID', () => {
const actions = [{
type: NOTIFICATIONS_EXPAND_SUCCESS,
notifications: [
{ id: '1', type: 'mention', status: { id: '4' }, account: { id: '7' } },
{ id: '2', type: 'mention', status: { id: '5' }, account: { id: '8' } },
{ id: '3', type: 'mention', status: { id: '6' }, account: { id: '9' } },
{ id: '4', type: 'mention', status: { id: '5' }, account: { id: '7' } },
],
next: null,
skipLoading: true,
}, {
type: TIMELINE_DELETE, type: TIMELINE_DELETE,
id: '9vvNxoo5EFbbnfdXQu', id: '5',
}; }];
expect(reducer(state, action)).toEqual(ImmutableMap({
items: ImmutableOrderedMap(),
}));
});
// Disable for now // Setup by expanding, then calling `NOTIFICATIONS_FILTER_SET`
// https://gitlab.com/soapbox-pub/soapbox-fe/-/issues/432 const result = actions.reduce((state, action) => reducer(state, action), initialState);
//
// it('should handle TIMELINE_DISCONNECT', () => { expect(result.items.size).toEqual(2);
// const state = ImmutableMap({ expect(result.items.get('5')).toBe(undefined);
// items: ImmutableOrderedSet([ });
// ImmutableMap({ });
// id: '10744',
// type: 'pleroma:emoji_reaction',
// account: '9vMAje101ngtjlMj7w',
// created_at: '2020-06-10T02:54:39.000Z',
// status: '9vvNxoo5EFbbnfdXQu',
// emoji: '😢',
// chat_message: undefined,
// }),
// ImmutableMap({
// id: '10743',
// type: 'favourite',
// account: '9v5c6xSEgAi3Zu1Lv6',
// created_at: '2020-06-10T02:51:05.000Z',
// status: '9vvNxoo5EFbbnfdXQu',
// emoji: undefined,
// chat_message: undefined,
// }),
// ImmutableMap({
// id: '10741',
// type: 'favourite',
// account: '9v5cKMOPGqPcgfcWp6',
// created_at: '2020-06-10T02:05:06.000Z',
// status: '9vvNxoo5EFbbnfdXQu',
// emoji: undefined,
// chat_message: undefined,
// }),
// ]),
// });
// const action = {
// type: TIMELINE_DISCONNECT,
// timeline: 'home',
// };
// expect(reducer(state, action)).toEqual(ImmutableMap({
// items: ImmutableOrderedSet([
// null,
// ImmutableMap({
// id: '10744',
// type: 'pleroma:emoji_reaction',
// account: '9vMAje101ngtjlMj7w',
// created_at: '2020-06-10T02:54:39.000Z',
// status: '9vvNxoo5EFbbnfdXQu',
// emoji: '😢',
// chat_message: undefined,
// }),
// ImmutableMap({
// id: '10743',
// type: 'favourite',
// account: '9v5c6xSEgAi3Zu1Lv6',
// created_at: '2020-06-10T02:51:05.000Z',
// status: '9vvNxoo5EFbbnfdXQu',
// emoji: undefined,
// chat_message: undefined,
// }),
// ImmutableMap({
// id: '10741',
// type: 'favourite',
// account: '9v5cKMOPGqPcgfcWp6',
// created_at: '2020-06-10T02:05:06.000Z',
// status: '9vvNxoo5EFbbnfdXQu',
// emoji: undefined,
// chat_message: undefined,
// }),
// ]),
// }));
// });
describe('MARKER_FETCH_SUCCESS', () => { describe('MARKER_FETCH_SUCCESS', () => {
it('sets lastRead', () => { it('sets lastRead', () => {

View File

@ -1,10 +1,10 @@
import { Map as ImmutableMap, OrderedMap as ImmutableOrderedMap, fromJS } from 'immutable';
import { import {
MARKER_FETCH_SUCCESS, Record as ImmutableRecord,
MARKER_SAVE_REQUEST, OrderedMap as ImmutableOrderedMap,
MARKER_SAVE_SUCCESS, fromJS,
} from 'soapbox/actions/markers'; } from 'immutable';
import { normalizeNotification } from 'soapbox/normalizers/notification';
import { import {
ACCOUNT_BLOCK_SUCCESS, ACCOUNT_BLOCK_SUCCESS,
@ -12,6 +12,11 @@ import {
FOLLOW_REQUEST_AUTHORIZE_SUCCESS, FOLLOW_REQUEST_AUTHORIZE_SUCCESS,
FOLLOW_REQUEST_REJECT_SUCCESS, FOLLOW_REQUEST_REJECT_SUCCESS,
} from '../actions/accounts'; } from '../actions/accounts';
import {
MARKER_FETCH_SUCCESS,
MARKER_SAVE_REQUEST,
MARKER_SAVE_SUCCESS,
} from '../actions/markers';
import { import {
NOTIFICATIONS_UPDATE, NOTIFICATIONS_UPDATE,
NOTIFICATIONS_EXPAND_SUCCESS, NOTIFICATIONS_EXPAND_SUCCESS,
@ -27,7 +32,8 @@ import {
} from '../actions/notifications'; } from '../actions/notifications';
import { TIMELINE_DELETE } from '../actions/timelines'; import { TIMELINE_DELETE } from '../actions/timelines';
const initialState = ImmutableMap({ // Record for the whole reducer
const NotificationsRecord = ImmutableRecord({
items: ImmutableOrderedMap(), items: ImmutableOrderedMap(),
hasMore: true, hasMore: true,
top: false, top: false,
@ -48,16 +54,16 @@ const comparator = (a, b) => {
return 0; return 0;
}; };
const notificationToMap = notification => ImmutableMap({ const minifyNotification = notification => {
id: notification.id, return notification.mergeWith((o, n) => n || o, {
type: notification.type, account: notification.getIn(['account', 'id']),
account: notification.account.id, status: notification.getIn(['status', 'id']),
target: notification.target ? notification.target.id : null, });
created_at: notification.created_at, };
status: notification.status ? notification.status.id : null,
emoji: notification.emoji, const fixNotification = notification => {
chat_message: notification.chat_message, return minifyNotification(normalizeNotification(notification));
}); };
const isValid = notification => { const isValid = notification => {
try { try {
@ -88,7 +94,7 @@ const countFuture = (notifications, lastId) => {
}, 0); }, 0);
}; };
const normalizeNotification = (state, notification) => { const importNotification = (state, notification) => {
const top = state.get('top'); const top = state.get('top');
if (!top) state = state.update('unread', unread => unread + 1); if (!top) state = state.update('unread', unread => unread + 1);
@ -98,7 +104,7 @@ const normalizeNotification = (state, notification) => {
map = map.take(20); map = map.take(20);
} }
return map.set(notification.id, notificationToMap(notification)).sort(comparator); return map.set(notification.id, fixNotification(notification)).sort(comparator);
}); });
}; };
@ -106,7 +112,7 @@ const processRawNotifications = notifications => (
ImmutableOrderedMap( ImmutableOrderedMap(
notifications notifications
.filter(isValid) .filter(isValid)
.map(n => [n.id, notificationToMap(n)]), .map(n => [n.id, fixNotification(n)]),
)); ));
const expandNormalizedNotifications = (state, notifications, next) => { const expandNormalizedNotifications = (state, notifications, next) => {
@ -176,23 +182,23 @@ const importMarker = (state, marker) => {
}); });
}; };
export default function notifications(state = initialState, action) { export default function notifications(state = NotificationsRecord(), action) {
switch(action.type) { switch(action.type) {
case NOTIFICATIONS_EXPAND_REQUEST: case NOTIFICATIONS_EXPAND_REQUEST:
return state.set('isLoading', true); return state.set('isLoading', true);
case NOTIFICATIONS_EXPAND_FAIL: case NOTIFICATIONS_EXPAND_FAIL:
return state.set('isLoading', false); return state.set('isLoading', false);
case NOTIFICATIONS_FILTER_SET: case NOTIFICATIONS_FILTER_SET:
return state.set('items', ImmutableOrderedMap()).set('hasMore', true); return state.delete('items').set('hasMore', true);
case NOTIFICATIONS_SCROLL_TOP: case NOTIFICATIONS_SCROLL_TOP:
return updateTop(state, action.top); return updateTop(state, action.top);
case NOTIFICATIONS_UPDATE: case NOTIFICATIONS_UPDATE:
return normalizeNotification(state, action.notification); return importNotification(state, action.notification);
case NOTIFICATIONS_UPDATE_QUEUE: case NOTIFICATIONS_UPDATE_QUEUE:
return updateNotificationsQueue(state, action.notification, action.intlMessages, action.intlLocale); return updateNotificationsQueue(state, action.notification, action.intlMessages, action.intlLocale);
case NOTIFICATIONS_DEQUEUE: case NOTIFICATIONS_DEQUEUE:
return state.withMutations(mutable => { return state.withMutations(mutable => {
mutable.set('queuedNotifications', ImmutableOrderedMap()); mutable.delete('queuedNotifications');
mutable.set('totalQueuedNotificationsCount', 0); mutable.set('totalQueuedNotificationsCount', 0);
}); });
case NOTIFICATIONS_EXPAND_SUCCESS: case NOTIFICATIONS_EXPAND_SUCCESS:
@ -205,7 +211,7 @@ export default function notifications(state = initialState, action) {
case FOLLOW_REQUEST_REJECT_SUCCESS: case FOLLOW_REQUEST_REJECT_SUCCESS:
return filterNotificationIds(state, [action.id], 'follow_request'); return filterNotificationIds(state, [action.id], 'follow_request');
case NOTIFICATIONS_CLEAR: case NOTIFICATIONS_CLEAR:
return state.set('items', ImmutableOrderedMap()).set('hasMore', false); return state.delete('items').set('hasMore', false);
case NOTIFICATIONS_MARK_READ_REQUEST: case NOTIFICATIONS_MARK_READ_REQUEST:
return state.set('lastRead', action.lastRead); return state.set('lastRead', action.lastRead);
case MARKER_FETCH_SUCCESS: case MARKER_FETCH_SUCCESS:
@ -214,16 +220,6 @@ export default function notifications(state = initialState, action) {
return importMarker(state, fromJS(action.marker)); return importMarker(state, fromJS(action.marker));
case TIMELINE_DELETE: case TIMELINE_DELETE:
return deleteByStatus(state, action.id); return deleteByStatus(state, action.id);
// Disable for now
// https://gitlab.com/soapbox-pub/soapbox-fe/-/issues/432
//
// case TIMELINE_DISCONNECT:
// // This is kind of a hack - `null` renders a LoadGap in the component
// // https://github.com/tootsuite/mastodon/pull/6886
// return action.timeline === 'home' ?
// state.update('items', items => items.first() ? ImmutableOrderedSet([null]).union(items) : items) :
// state;
default: default:
return state; return state;
} }