diff --git a/lib/shared/state-sync/entries-state-sync-spec.js b/lib/shared/state-sync/entries-state-sync-spec.js --- a/lib/shared/state-sync/entries-state-sync-spec.js +++ b/lib/shared/state-sync/entries-state-sync-spec.js @@ -4,6 +4,7 @@ import { createSelector } from 'reselect'; import type { StateSyncSpec, BoundStateSyncSpec } from './state-sync-spec.js'; +import { extractKeyserverIDFromID } from '../../keyserver-conn/keyserver-call-utils.js'; import { type CalendarQuery, type RawEntryInfos, @@ -61,16 +62,24 @@ beforeStateCheck: RawEntryInfos, afterStateCheck: RawEntryInfos, ) { + const keyserverID = action.payload.keyserverID; + const filteredBeforeStateCheck = values(beforeStateCheck).filter( + entry => entry.id && extractKeyserverIDFromID(entry.id) === keyserverID, + ); + const filteredAfterStateCheck = values(afterStateCheck).filter( + entry => entry.id && extractKeyserverIDFromID(entry.id) === keyserverID, + ); + const calendarQuery = action.payload.calendarQuery; // We don't want to bother reporting an inconsistency if it's just because // of extraneous EntryInfos (not within the current calendarQuery) on either // side const filteredBeforeResult = filterRawEntryInfosByCalendarQuery( - serverEntryInfosObject(values(beforeStateCheck)), + serverEntryInfosObject(filteredBeforeStateCheck), calendarQuery, ); const filteredAfterResult = filterRawEntryInfosByCalendarQuery( - serverEntryInfosObject(values(afterStateCheck)), + serverEntryInfosObject(filteredAfterStateCheck), calendarQuery, ); if (_isEqual(filteredBeforeResult)(filteredAfterResult)) { diff --git a/lib/shared/state-sync/entries-state-sync-spec.test.js b/lib/shared/state-sync/entries-state-sync-spec.test.js new file mode 100644 --- /dev/null +++ b/lib/shared/state-sync/entries-state-sync-spec.test.js @@ -0,0 +1,128 @@ +// @flow + +import { entriesStateSyncSpec } from './entries-state-sync-spec.js'; +import { processServerRequestsActionType } from '../../types/request-types.js'; + +jest.mock('../../utils/config.js'); + +describe('Entries state sync spec', () => { + describe('find store inconsistencies', () => { + it('should find inconsistencies from the same keyserver', () => { + const before = { + '256|93372': { + id: '256|93372', + threadID: '256|84459', + text: '123', + year: 2022, + month: 2, + day: 27, + creationTime: 1709035016680, + creatorID: '84447', + deleted: false, + }, + }; + + const after = { + '256|123': { + id: '256|123', + threadID: '256|84459', + text: '123', + year: 2022, + month: 2, + day: 27, + creationTime: 1709035016680, + creatorID: '84447', + deleted: false, + }, + '256|93372': { + id: '256|93372', + threadID: '256|84459', + text: '123', + year: 2022, + month: 2, + day: 27, + creationTime: 1709035016680, + creatorID: '84447', + deleted: false, + }, + }; + + const action = { + type: processServerRequestsActionType, + payload: { + serverRequests: [], + calendarQuery: { + startDate: '2022-01-01', + endDate: '2022-03-01', + filters: [], + }, + keyserverID: '256', + }, + }; + + expect( + entriesStateSyncSpec.findStoreInconsistencies(action, before, after) + .length, + ).toEqual(1); + }); + + it('should ignore inconsistencies from different keyservers', () => { + const before = { + '256|93372': { + id: '256|93372', + threadID: '256|84459', + text: '123', + year: 2022, + month: 2, + day: 27, + creationTime: 1709035016680, + creatorID: '84447', + deleted: false, + }, + }; + + const after = { + '123|123': { + id: '123|123', + threadID: '256|84459', + text: '123', + year: 2022, + month: 2, + day: 27, + creationTime: 1709035016680, + creatorID: '84447', + deleted: false, + }, + '256|93372': { + id: '256|93372', + threadID: '256|84459', + text: '123', + year: 2022, + month: 2, + day: 27, + creationTime: 1709035016680, + creatorID: '84447', + deleted: false, + }, + }; + + const action = { + type: processServerRequestsActionType, + payload: { + serverRequests: [], + calendarQuery: { + startDate: '2022-01-01', + endDate: '2022-03-01', + filters: [], + }, + keyserverID: '256', + }, + }; + + expect( + entriesStateSyncSpec.findStoreInconsistencies(action, before, after) + .length, + ).toEqual(0); + }); + }); +}); diff --git a/lib/shared/state-sync/threads-state-sync-spec.js b/lib/shared/state-sync/threads-state-sync-spec.js --- a/lib/shared/state-sync/threads-state-sync-spec.js +++ b/lib/shared/state-sync/threads-state-sync-spec.js @@ -1,9 +1,11 @@ // @flow import _isEqual from 'lodash/fp/isEqual.js'; +import _pickBy from 'lodash/fp/pickBy.js'; import { createSelector } from 'reselect'; import type { StateSyncSpec, BoundStateSyncSpec } from './state-sync-spec.js'; +import { extractKeyserverIDFromID } from '../../keyserver-conn/keyserver-call-utils.js'; import type { RawThreadInfo } from '../../types/minimally-encoded-thread-permissions-types.js'; import type { AppState } from '../../types/redux-types.js'; import { @@ -60,7 +62,13 @@ beforeStateCheck: MixedRawThreadInfos, afterStateCheck: MixedRawThreadInfos, ) { - if (_isEqual(beforeStateCheck)(afterStateCheck)) { + const keyserverID = action.payload.keyserverID; + const filter = _pickBy( + thread => extractKeyserverIDFromID(thread.id) === keyserverID, + ); + const filteredBeforeStateCheck = filter(beforeStateCheck); + const filteredAfterStateCheck = filter(afterStateCheck); + if (_isEqual(filteredBeforeStateCheck)(filteredAfterStateCheck)) { return emptyArray; } return [ diff --git a/lib/shared/state-sync/threads-state-sync-spec.test.js b/lib/shared/state-sync/threads-state-sync-spec.test.js new file mode 100644 --- /dev/null +++ b/lib/shared/state-sync/threads-state-sync-spec.test.js @@ -0,0 +1,217 @@ +// @flow + +import { threadsStateSyncSpec } from './threads-state-sync-spec.js'; +import { defaultCalendarQuery } from '../../types/entry-types.js'; +import { processServerRequestsActionType } from '../../types/request-types.js'; +import { threadTypes } from '../../types/thread-types-enum.js'; +import { getConfig } from '../../utils/config.js'; + +jest.mock('../../utils/config.js'); + +describe('Threads state sync spec', () => { + describe('find store inconsistencies', () => { + it('should find inconsistencies from the same keyserver', () => { + const before = { + '256|84459': { + minimallyEncoded: true, + id: '256|84459', + type: threadTypes.PRIVATE, + name: '', + description: '', + color: 'b8753d', + creationTime: 3663, + parentThreadID: '256|1', + containingThreadID: '256|1', + community: '256|1', + members: [], + roles: {}, + currentUser: { + role: '256|84460', + permissions: '3026f', + subscription: { + home: true, + pushNotifs: true, + }, + unread: false, + minimallyEncoded: true, + }, + repliesCount: 0, + pinnedCount: 0, + }, + }; + + const after = { + '256|84459': { + minimallyEncoded: true, + id: '256|84459', + type: threadTypes.PRIVATE, + name: '', + description: '', + color: 'b8753d', + creationTime: 3663, + parentThreadID: '256|1', + containingThreadID: '256|1', + community: '256|1', + members: [], + roles: {}, + currentUser: { + role: '256|84460', + permissions: '3026f', + subscription: { + home: true, + pushNotifs: true, + }, + unread: false, + minimallyEncoded: true, + }, + repliesCount: 0, + pinnedCount: 0, + }, + '256|123': { + minimallyEncoded: true, + id: '256|123', + type: threadTypes.PRIVATE, + name: '', + description: '', + color: 'b8753d', + creationTime: 3663, + parentThreadID: '256|1', + containingThreadID: '256|1', + community: '256|1', + members: [], + roles: {}, + currentUser: { + role: '256|84460', + permissions: '3026f', + subscription: { + home: true, + pushNotifs: true, + }, + unread: false, + minimallyEncoded: true, + }, + repliesCount: 0, + pinnedCount: 0, + }, + }; + + const action = { + type: processServerRequestsActionType, + payload: { + serverRequests: [], + calendarQuery: defaultCalendarQuery( + getConfig().platformDetails.platform, + ), + keyserverID: '256', + }, + }; + + expect( + threadsStateSyncSpec.findStoreInconsistencies(action, before, after) + .length, + ).toEqual(1); + }); + + it('should ignore inconsistencies from different keyservers', () => { + const before = { + '256|84459': { + minimallyEncoded: true, + id: '256|84459', + type: threadTypes.PRIVATE, + name: '', + description: '', + color: 'b8753d', + creationTime: 3663, + parentThreadID: '256|1', + containingThreadID: '256|1', + community: '256|1', + members: [], + roles: {}, + currentUser: { + role: '256|84460', + permissions: '3026f', + subscription: { + home: true, + pushNotifs: true, + }, + unread: false, + minimallyEncoded: true, + }, + repliesCount: 0, + pinnedCount: 0, + }, + }; + + const after = { + '256|84459': { + minimallyEncoded: true, + id: '256|84459', + type: threadTypes.PRIVATE, + name: '', + description: '', + color: 'b8753d', + creationTime: 3663, + parentThreadID: '256|1', + containingThreadID: '256|1', + community: '256|1', + members: [], + roles: {}, + currentUser: { + role: '256|84460', + permissions: '3026f', + subscription: { + home: true, + pushNotifs: true, + }, + unread: false, + minimallyEncoded: true, + }, + repliesCount: 0, + pinnedCount: 0, + }, + '123|123': { + minimallyEncoded: true, + id: '123|123', + type: threadTypes.PRIVATE, + name: '', + description: '', + color: 'b8753d', + creationTime: 3663, + parentThreadID: '256|1', + containingThreadID: '256|1', + community: '256|1', + members: [], + roles: {}, + currentUser: { + role: '256|84460', + permissions: '3026f', + subscription: { + home: true, + pushNotifs: true, + }, + unread: false, + minimallyEncoded: true, + }, + repliesCount: 0, + pinnedCount: 0, + }, + }; + + const action = { + type: processServerRequestsActionType, + payload: { + serverRequests: [], + calendarQuery: defaultCalendarQuery( + getConfig().platformDetails.platform, + ), + keyserverID: '256', + }, + }; + + expect( + threadsStateSyncSpec.findStoreInconsistencies(action, before, after) + .length, + ).toEqual(0); + }); + }); +});