## Description Adds the account-level `unread_count_for_filters` feature flag as the dark-launch gate for filtered sidebar unread counts. This reuses the deprecated `quoted_email_reply` flag slot, resets the reused bit for existing accounts, and removes stale defaults so new accounts do not reference the old flag. This also adds the feature where we are now calculating the unread counts for built in filters like mentions, participating and unattended along with unread count for saved filters/folders. Closes [CW-7262](https://linear.app/chatwoot/issue/CW-7262/unread-counts-for-filters-folders) ## Type of change - [ ] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality not to work as expected) - [ ] This change requires a documentation update
134 lines
4.3 KiB
JavaScript
134 lines
4.3 KiB
JavaScript
import axios from 'axios';
|
|
import { actions } from '../../conversationWatchers';
|
|
import types from '../../../mutation-types';
|
|
import { FEATURE_FLAGS } from '../../../../featureFlags';
|
|
|
|
const commit = vi.fn();
|
|
global.axios = axios;
|
|
vi.mock('axios');
|
|
|
|
const mockRetryJitter = value =>
|
|
vi.spyOn(Math, 'random').mockReturnValue(value);
|
|
|
|
afterEach(() => {
|
|
vi.restoreAllMocks();
|
|
vi.clearAllTimers();
|
|
vi.useRealTimers();
|
|
});
|
|
|
|
const conversationUnreadCountsEnabledRootGetters = {
|
|
getCurrentAccountId: 1,
|
|
getCurrentUserID: 1,
|
|
'accounts/isFeatureEnabledonAccount': vi.fn((_, featureFlag) =>
|
|
[
|
|
FEATURE_FLAGS.CONVERSATION_UNREAD_COUNTS,
|
|
FEATURE_FLAGS.UNREAD_COUNT_FOR_FILTERS,
|
|
].includes(featureFlag)
|
|
),
|
|
};
|
|
|
|
describe('#actions', () => {
|
|
describe('#get', () => {
|
|
it('sends correct actions if API is success', async () => {
|
|
axios.get.mockResolvedValue({ data: { id: 1 } });
|
|
await actions.show({ commit }, { conversationId: 1 });
|
|
expect(commit.mock.calls).toEqual([
|
|
[types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isFetching: true }],
|
|
[
|
|
types.SET_CONVERSATION_PARTICIPANTS,
|
|
{ conversationId: 1, data: { id: 1 } },
|
|
],
|
|
[types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isFetching: false }],
|
|
]);
|
|
});
|
|
it('sends correct actions if API is error', async () => {
|
|
axios.get.mockRejectedValue({ message: 'Incorrect header' });
|
|
await expect(
|
|
actions.show({ commit }, { conversationId: 1 })
|
|
).rejects.toThrow(Error);
|
|
expect(commit.mock.calls).toEqual([
|
|
[types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isFetching: true }],
|
|
[types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isFetching: false }],
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe('#update', () => {
|
|
it('sends correct actions if API is success', async () => {
|
|
axios.patch.mockResolvedValue({ data: [{ id: 2 }] });
|
|
await actions.update(
|
|
{ commit },
|
|
{ conversationId: 2, userIds: [{ id: 2 }] }
|
|
);
|
|
expect(commit.mock.calls).toEqual([
|
|
[types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isUpdating: true }],
|
|
[
|
|
types.SET_CONVERSATION_PARTICIPANTS,
|
|
{ conversationId: 2, data: [{ id: 2 }] },
|
|
],
|
|
[types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isUpdating: false }],
|
|
]);
|
|
});
|
|
it('refetches unread counts when the current user starts watching', async () => {
|
|
vi.useFakeTimers();
|
|
mockRetryJitter(0.5);
|
|
const dispatch = vi.fn();
|
|
const moduleState = { records: { 2: [] } };
|
|
const mutatingCommit = vi.fn((mutation, payload) => {
|
|
if (mutation === types.SET_CONVERSATION_PARTICIPANTS) {
|
|
moduleState.records[payload.conversationId] = payload.data;
|
|
}
|
|
});
|
|
axios.patch.mockResolvedValue({ data: [{ id: 1 }] });
|
|
|
|
await actions.update(
|
|
{
|
|
commit: mutatingCommit,
|
|
dispatch,
|
|
rootGetters: conversationUnreadCountsEnabledRootGetters,
|
|
state: moduleState,
|
|
},
|
|
{ conversationId: 2, userIds: [1] }
|
|
);
|
|
|
|
expect(dispatch).toHaveBeenCalledWith(
|
|
'conversationUnreadCounts/get',
|
|
{},
|
|
{ root: true }
|
|
);
|
|
|
|
vi.advanceTimersByTime(37499);
|
|
expect(dispatch).toHaveBeenCalledTimes(1);
|
|
|
|
vi.advanceTimersByTime(1);
|
|
expect(dispatch).toHaveBeenCalledTimes(2);
|
|
});
|
|
it('does not refetch unread counts when another watcher changes', async () => {
|
|
const dispatch = vi.fn();
|
|
axios.patch.mockResolvedValue({ data: [{ id: 1 }, { id: 2 }] });
|
|
|
|
await actions.update(
|
|
{
|
|
commit,
|
|
dispatch,
|
|
rootGetters: conversationUnreadCountsEnabledRootGetters,
|
|
state: { records: { 2: [{ id: 1 }] } },
|
|
},
|
|
{ conversationId: 2, userIds: [1, 2] }
|
|
);
|
|
|
|
expect(dispatch).not.toHaveBeenCalled();
|
|
});
|
|
it('sends correct actions if API is error', async () => {
|
|
axios.patch.mockRejectedValue({ message: 'Incorrect header' });
|
|
await expect(
|
|
actions.update({ commit }, { conversationId: 1, content: 'hi' })
|
|
).rejects.toThrow(Error);
|
|
expect(commit.mock.calls).toEqual([
|
|
[types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isUpdating: true }],
|
|
[types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isUpdating: false }],
|
|
]);
|
|
});
|
|
});
|
|
});
|