mattermost-mobile/app/queries/servers/scheduled_post.test.ts
Rajat Dabade 6bdcf2be49
Remaining test for draft and Scheduled post (#8887)
* Added test for draft_scheduled_post and header component

* Added test for drafts_button/index.ts

* Added test for send_button/index.ts

* Added test for servers/scheduled_post.ts queries

* Added test for global_scheduled_post_list/index.ts

* Added test for rescheduled draft index file and minor update

* Added test for core option and index

* Added test for scheduled post options

* Added test for send_draft index file

* updated test for draft_scheduled_post and draft_scheduled_post_header

* Updated test for drafts_button index

* Updated test for send_button index

* Updated test for server/scheduled_post

* Updated test for global_scheduled_post/index

* removed the unnecessary config and team data to populate in db for test

* Update app/components/draft_scheduled_post/draft_scheduled_post.test.tsx

Co-authored-by: Daniel Espino García <larkox@gmail.com>

* linter fixes

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
Co-authored-by: Daniel Espino García <larkox@gmail.com>
2025-07-01 13:47:02 +05:30

287 lines
13 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {Database} from '@nozbe/watermelondb';
import {ActionType} from '@constants';
import DatabaseManager from '@database/manager';
import ServerDataOperator from '@database/operator/server_data_operator';
import TestHelper from '@test/test_helper';
import {
observeFirstScheduledPost,
observeScheduledPostCount,
observeScheduledPostCountForChannel,
observeScheduledPostCountForThread,
observeScheduledPostsForTeam,
queryScheduledPost,
queryScheduledPostsForTeam,
} from './scheduled_post';
describe('Scheduled Post Queries', () => {
const serverUrl = 'scheduledpost.test.com';
let database: Database;
let operator: ServerDataOperator;
beforeEach(async () => {
await DatabaseManager.init([serverUrl]);
const serverDatabaseAndOperator = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
database = serverDatabaseAndOperator.database;
operator = serverDatabaseAndOperator.operator;
});
afterEach(async () => {
await DatabaseManager.destroyServerDatabase(serverUrl);
});
describe('queryScheduledPostsForTeam', () => {
it('should return posts for specific team', async () => {
const channel = TestHelper.fakeChannel({id: 'ch1', team_id: 'team1', type: 'O'});
const post = TestHelper.fakeScheduledPost({id: 'post1', channel_id: 'ch1', message: 'Test'});
const models = (await Promise.all([
operator.handleChannel({channels: [channel], prepareRecordsOnly: true}),
operator.handleScheduledPosts({
actionType: ActionType.SCHEDULED_POSTS.CREATE_OR_UPDATED_SCHEDULED_POST,
scheduledPosts: [post],
prepareRecordsOnly: true,
}),
])).flat();
await operator.batchRecords(models, 'test');
const result = await queryScheduledPostsForTeam(database, 'team1').fetch();
expect(result).toHaveLength(1);
expect(result[0].id).toBe('post1');
});
it('should return empty for non-existent team', async () => {
const result = await queryScheduledPostsForTeam(database, 'nonexistent').fetch();
expect(result).toHaveLength(0);
});
it('should include direct channels when specified', async () => {
const dmChannel = TestHelper.fakeChannel({id: 'dm1', team_id: '', type: 'D'});
const post = TestHelper.fakeScheduledPost({id: 'post1', channel_id: 'dm1', message: 'DM'});
const models = (await Promise.all([
operator.handleChannel({channels: [dmChannel], prepareRecordsOnly: true}),
operator.handleScheduledPosts({
actionType: ActionType.SCHEDULED_POSTS.CREATE_OR_UPDATED_SCHEDULED_POST,
scheduledPosts: [post],
prepareRecordsOnly: true,
}),
])).flat();
await operator.batchRecords(models, 'test');
const result = await queryScheduledPostsForTeam(database, 'team1', true).fetch();
expect(result).toHaveLength(1);
expect(result[0].id).toBe('post1');
});
});
describe('queryScheduledPost', () => {
it('should return posts for specific channel and root', async () => {
const channel = TestHelper.fakeChannel({id: 'ch1', team_id: 'team1'});
const posts = [
TestHelper.fakeScheduledPost({id: 'post1', channel_id: 'ch1', root_id: 'root1', message: 'Reply1'}),
TestHelper.fakeScheduledPost({id: 'post2', channel_id: 'ch1', root_id: 'root1', message: 'Reply2'}),
TestHelper.fakeScheduledPost({id: 'post3', channel_id: 'ch1', root_id: 'root2', message: 'Other'}),
];
const models = (await Promise.all([
operator.handleChannel({channels: [channel], prepareRecordsOnly: true}),
operator.handleScheduledPosts({
actionType: ActionType.SCHEDULED_POSTS.CREATE_OR_UPDATED_SCHEDULED_POST,
scheduledPosts: posts,
prepareRecordsOnly: true,
}),
])).flat();
await operator.batchRecords(models, 'test');
const result = await queryScheduledPost(database, 'ch1', 'root1').fetch();
expect(result).toHaveLength(2);
expect(result.map((p) => p.id).sort()).toEqual(['post1', 'post2']);
});
});
describe('observeScheduledPostsForTeam', () => {
it('should observe team posts', (done) => {
const channel = TestHelper.fakeChannel({id: 'ch1', team_id: 'team1', type: 'O'});
const post = TestHelper.fakeScheduledPost({id: 'post1', channel_id: 'ch1', message: 'Test'});
Promise.all([
operator.handleChannel({channels: [channel], prepareRecordsOnly: false}),
operator.handleScheduledPosts({
actionType: ActionType.SCHEDULED_POSTS.CREATE_OR_UPDATED_SCHEDULED_POST,
scheduledPosts: [post],
prepareRecordsOnly: false,
}),
]).then(() => {
observeScheduledPostsForTeam(database, 'team1').subscribe((posts) => {
if (posts.length === 1 && posts[0].id === 'post1') {
done();
}
});
});
}, 1500);
});
describe('observeScheduledPostCount', () => {
it('should count team posts correctly', (done) => {
const channels = [
TestHelper.fakeChannel({id: 'ch1', team_id: 'team1', type: 'O'}),
TestHelper.fakeChannel({id: 'ch2', team_id: 'team1', type: 'P'}),
];
const posts = [
TestHelper.fakeScheduledPost({id: 'post1', channel_id: 'ch1', message: 'Test1'}),
TestHelper.fakeScheduledPost({id: 'post2', channel_id: 'ch2', message: 'Test2'}),
];
Promise.all([
operator.handleChannel({channels, prepareRecordsOnly: false}),
operator.handleScheduledPosts({
actionType: ActionType.SCHEDULED_POSTS.CREATE_OR_UPDATED_SCHEDULED_POST,
scheduledPosts: posts,
prepareRecordsOnly: false,
}),
]).then(() => {
observeScheduledPostCount(database, 'team1', false).subscribe((count) => {
if (count === 2) {
done();
}
});
});
}, 1500);
it('should include direct channels when specified', (done) => {
const channels = [
TestHelper.fakeChannel({id: 'ch1', team_id: 'team1', type: 'O'}),
TestHelper.fakeChannel({id: 'dm1', team_id: '', type: 'D'}),
];
const posts = [
TestHelper.fakeScheduledPost({id: 'post1', channel_id: 'ch1', message: 'Team'}),
TestHelper.fakeScheduledPost({id: 'post2', channel_id: 'dm1', message: 'DM'}),
];
Promise.all([
operator.handleChannel({channels, prepareRecordsOnly: false}),
operator.handleScheduledPosts({
actionType: ActionType.SCHEDULED_POSTS.CREATE_OR_UPDATED_SCHEDULED_POST,
scheduledPosts: posts,
prepareRecordsOnly: false,
}),
]).then(() => {
observeScheduledPostCount(database, 'team1', true).subscribe((count) => {
if (count === 2) {
done();
}
});
});
}, 1500);
});
describe('observeScheduledPostCountForChannel', () => {
it('should count channel posts without errors', (done) => {
const channel = TestHelper.fakeChannel({id: 'ch1', team_id: 'team1'});
const posts = [
TestHelper.fakeScheduledPost({id: 'post1', channel_id: 'ch1', error_code: '', message: 'Success1'}),
TestHelper.fakeScheduledPost({id: 'post2', channel_id: 'ch1', error_code: '', message: 'Success2'}),
TestHelper.fakeScheduledPost({id: 'post3', channel_id: 'ch1', error_code: 'failed', message: 'Error'}),
];
Promise.all([
operator.handleChannel({channels: [channel], prepareRecordsOnly: false}),
operator.handleScheduledPosts({
actionType: ActionType.SCHEDULED_POSTS.CREATE_OR_UPDATED_SCHEDULED_POST,
scheduledPosts: posts,
prepareRecordsOnly: false,
}),
]).then(() => {
observeScheduledPostCountForChannel(database, 'ch1', false).subscribe((count) => {
if (count === 2) { // Only posts without errors
done();
}
});
});
}, 1500);
it('should handle CRT filtering', (done) => {
const channel = TestHelper.fakeChannel({id: 'ch1', team_id: 'team1'});
const posts = [
TestHelper.fakeScheduledPost({id: 'post1', channel_id: 'ch1', root_id: '', error_code: '', message: 'Root1'}),
TestHelper.fakeScheduledPost({id: 'post2', channel_id: 'ch1', root_id: '', error_code: '', message: 'Root2'}),
TestHelper.fakeScheduledPost({id: 'post3', channel_id: 'ch1', root_id: 'thread1', error_code: '', message: 'Reply'}),
];
Promise.all([
operator.handleChannel({channels: [channel], prepareRecordsOnly: false}),
operator.handleScheduledPosts({
actionType: ActionType.SCHEDULED_POSTS.CREATE_OR_UPDATED_SCHEDULED_POST,
scheduledPosts: posts,
prepareRecordsOnly: false,
}),
]).then(() => {
observeScheduledPostCountForChannel(database, 'ch1', true).subscribe((count) => {
if (count === 2) { // Only root posts when CRT enabled
done();
}
});
});
}, 1500);
});
describe('observeScheduledPostCountForThread', () => {
it('should count thread replies only', (done) => {
const channel = TestHelper.fakeChannel({id: 'ch1', team_id: 'team1'});
const posts = [
TestHelper.fakeScheduledPost({id: 'post1', channel_id: 'ch1', root_id: 'thread1', error_code: '', message: 'Reply1'}),
TestHelper.fakeScheduledPost({id: 'post2', channel_id: 'ch1', root_id: 'thread1', error_code: '', message: 'Reply2'}),
TestHelper.fakeScheduledPost({id: 'post3', channel_id: 'ch1', root_id: 'thread2', error_code: '', message: 'Other'}),
TestHelper.fakeScheduledPost({id: 'post4', channel_id: 'ch1', root_id: '', error_code: '', message: 'Root'}),
];
Promise.all([
operator.handleChannel({channels: [channel], prepareRecordsOnly: false}),
operator.handleScheduledPosts({
actionType: ActionType.SCHEDULED_POSTS.CREATE_OR_UPDATED_SCHEDULED_POST,
scheduledPosts: posts,
prepareRecordsOnly: false,
}),
]).then(() => {
observeScheduledPostCountForThread(database, 'thread1').subscribe((count) => {
if (count === 2) { // Only replies to thread1
done();
}
});
});
}, 1500);
});
describe('observeFirstScheduledPost', () => {
it('should return undefined for empty array', (done) => {
observeFirstScheduledPost([]).subscribe((result) => {
if (result === undefined) {
done();
}
});
});
it('should return first post when available', (done) => {
const mockPost = TestHelper.fakeScheduledPostModel({
id: 'first_post',
observe: jest.fn().mockReturnValue({
subscribe: (callback: (result: any) => void) => {
callback({id: 'first_post', message: 'First post'});
return {unsubscribe: jest.fn()};
},
}),
});
observeFirstScheduledPost([mockPost]).subscribe((result) => {
if (result?.id === 'first_post') {
done();
}
});
});
});
});