mirror of
https://github.com/mattermost/mattermost-mobile.git
synced 2026-11-06 02:40:15 +00:00
fix: extract product fixes from Detox PR and stabilize related E2E Move Saved, thread follow, bookmarks image_url, tables, search persist, create-channel retry, and sidebar padding onto their own branch so they can land or revert independently of the E2E harness. Also includes: - iOS search clear/Cancel overlap and resting margin fixes - Saved messages subscription distinctUntilChanged guards (no flicker) - Table horizontal inset derived from a single padding constant - Manual time entry commits on parse (not only blur/submit) - Presence sheet dismiss-before-status-update (Android Fabric crash) - Bounded keyboard dismiss on Android edge-to-edge only; iOS unbound - Create-channel retry leaves header button enabled on failure - E2E flakiness: Maestro attach_logs/subflows, bookmark Edit wait, status sheet timing, classification lock transport retries, apiCreatePost throws on network errors, flow-header contract in CI - Unit/integration coverage and CodeRabbit follow-ups for the above
111 lines
3.6 KiB
TypeScript
111 lines
3.6 KiB
TypeScript
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
import DatabaseManager from '@database/manager';
|
|
import {getThreadById, prepareThreadsFromReceivedPosts} from '@queries/servers/thread';
|
|
import TestHelper from '@test/test_helper';
|
|
|
|
import type ServerDataOperator from '@database/operator/server_data_operator';
|
|
import type {Database} from '@nozbe/watermelondb';
|
|
|
|
const serverUrl = 'baseHandler.test.com';
|
|
const teamId = 'team-id-1';
|
|
const channelId = 'channel-id-1';
|
|
|
|
describe('prepareThreadsFromReceivedPosts', () => {
|
|
let database: Database;
|
|
let operator: ServerDataOperator;
|
|
|
|
beforeEach(async () => {
|
|
await DatabaseManager.init([serverUrl]);
|
|
({database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl));
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await DatabaseManager.destroyServerDatabase(serverUrl);
|
|
});
|
|
|
|
it('should preserve is_following when the post payload omits the field', async () => {
|
|
const rootPost = TestHelper.fakePost({
|
|
channel_id: channelId,
|
|
id: 'root-post-id',
|
|
create_at: 1,
|
|
reply_count: 1,
|
|
});
|
|
|
|
await operator.handleThreads({
|
|
threads: [{
|
|
id: rootPost.id,
|
|
reply_count: 1,
|
|
last_reply_at: 1,
|
|
last_viewed_at: 0,
|
|
participants: [],
|
|
is_following: true,
|
|
unread_replies: 0,
|
|
unread_mentions: 0,
|
|
delete_at: 0,
|
|
lastFetchedAt: 0,
|
|
post: rootPost,
|
|
} as ThreadWithLastFetchedAt],
|
|
prepareRecordsOnly: false,
|
|
teamId,
|
|
});
|
|
|
|
const postWithoutFollowFlag = {
|
|
...rootPost,
|
|
reply_count: 2,
|
|
last_reply_at: 2,
|
|
};
|
|
delete (postWithoutFollowFlag as {is_following?: boolean}).is_following;
|
|
|
|
const models = await prepareThreadsFromReceivedPosts(operator, [postWithoutFollowFlag], true);
|
|
expect(models).toHaveLength(1);
|
|
await operator.batchRecords(models, 'prepareThreadsFromReceivedPosts');
|
|
|
|
const thread = await getThreadById(database, rootPost.id);
|
|
expect(thread).toBeDefined();
|
|
expect(thread?.isFollowing).toBe(true);
|
|
expect(thread?.replyCount).toBe(2);
|
|
});
|
|
|
|
it('should apply an explicit is_following false from the post payload', async () => {
|
|
const rootPost = TestHelper.fakePost({
|
|
channel_id: channelId,
|
|
id: 'root-post-id-2',
|
|
create_at: 1,
|
|
reply_count: 1,
|
|
is_following: true,
|
|
});
|
|
|
|
await operator.handleThreads({
|
|
threads: [{
|
|
id: rootPost.id,
|
|
reply_count: 1,
|
|
last_reply_at: 1,
|
|
last_viewed_at: 0,
|
|
participants: [],
|
|
is_following: true,
|
|
unread_replies: 0,
|
|
unread_mentions: 0,
|
|
delete_at: 0,
|
|
lastFetchedAt: 0,
|
|
post: rootPost,
|
|
} as ThreadWithLastFetchedAt],
|
|
prepareRecordsOnly: false,
|
|
teamId,
|
|
});
|
|
|
|
const models = await prepareThreadsFromReceivedPosts(operator, [{
|
|
...rootPost,
|
|
reply_count: 2,
|
|
is_following: false,
|
|
}], true);
|
|
expect(models).toHaveLength(1);
|
|
await operator.batchRecords(models, 'prepareThreadsFromReceivedPosts');
|
|
|
|
const thread = await getThreadById(database, rootPost.id);
|
|
expect(thread).toBeDefined();
|
|
expect(thread?.isFollowing).toBe(false);
|
|
});
|
|
});
|