* typescript and view component for permalink with user and message * Old post edited handling in permalink * Added test and update flag value to EnablePermalinkPreview * Added test for permalink_preview component * Added test for content/index.tsx for permalink * Addressed review comments * Unit test for missing file and review comments * Added test to check handlePostEdited permalink sync only calls one time only * Change TouchableOpacity to Pressable * When user not found fetch the user from the server * Removed the redundant test in the test for permalink_preview/index? * ts to tsx * Removed the circular dependency * Address review comments * displayname fallback * remove permalink when permalink post is deleted * UX review comments * Linter fixes * Test fixes * File attachment in permalink preview component * Fix the width and height of the image in permalink * Added gredient when exceeds height of permalink container * Minor * Updated tests * Minor * Review comments * Minor review comments * type fixes * Review comments * Minor * Address review comments * Minor * Merge fixes * Addressed review comments * Some more review comments * linter fixes * UX review and remove show more height not require * Fix tests * Review fixes, dev and ux --------- Co-authored-by: yasserfaraazkhan <attitude3cena.yf@gmail.com>
358 lines
13 KiB
TypeScript
358 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 * as logModule from '@utils/log';
|
|
|
|
import {updatePermalinkMetadata} from './permalink_sync';
|
|
|
|
import type PostModel from '@typings/database/models/servers/post';
|
|
|
|
describe('Permalink Sync Utils', () => {
|
|
const serverUrl = 'permalinksync.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;
|
|
jest.clearAllMocks();
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await DatabaseManager.destroyServerDatabase(serverUrl);
|
|
});
|
|
|
|
describe('updatePermalinkMetadata', () => {
|
|
it('should return null when post has no metadata', async () => {
|
|
const referencedPostId = 'referenced_post_456';
|
|
const freshPostData = TestHelper.fakePost({id: referencedPostId});
|
|
|
|
const postWithoutMetadata = TestHelper.fakePost({
|
|
id: 'post_without_metadata',
|
|
channel_id: 'channel1',
|
|
metadata: undefined,
|
|
});
|
|
|
|
const models = await operator.handlePosts({
|
|
actionType: ActionType.POSTS.RECEIVED_NEW,
|
|
order: [postWithoutMetadata.id],
|
|
posts: [postWithoutMetadata],
|
|
prepareRecordsOnly: true,
|
|
});
|
|
await operator.batchRecords(models, 'test');
|
|
|
|
const postModel = await database.get('Post').find(postWithoutMetadata.id) as PostModel;
|
|
|
|
const result = updatePermalinkMetadata(postModel, referencedPostId, freshPostData);
|
|
|
|
expect(result).toBeNull();
|
|
});
|
|
|
|
it('should return null when post has no embeds', async () => {
|
|
const referencedPostId = 'referenced_post_456';
|
|
const freshPostData = TestHelper.fakePost({id: referencedPostId});
|
|
|
|
const postWithEmptyEmbeds = TestHelper.fakePost({
|
|
id: 'post_with_empty_embeds',
|
|
channel_id: 'channel1',
|
|
metadata: {
|
|
embeds: [],
|
|
},
|
|
});
|
|
|
|
const models = await operator.handlePosts({
|
|
actionType: ActionType.POSTS.RECEIVED_NEW,
|
|
order: [postWithEmptyEmbeds.id],
|
|
posts: [postWithEmptyEmbeds],
|
|
prepareRecordsOnly: true,
|
|
});
|
|
await operator.batchRecords(models, 'test');
|
|
|
|
const postModel = await database.get('Post').find(postWithEmptyEmbeds.id) as PostModel;
|
|
|
|
const result = updatePermalinkMetadata(postModel, referencedPostId, freshPostData);
|
|
|
|
expect(result).toBeNull();
|
|
});
|
|
|
|
it('should update permalink metadata when fresh post is newer', async () => {
|
|
const referencedPostId = 'referenced_post_456';
|
|
|
|
const referencingPost = TestHelper.fakePost({
|
|
id: 'referencing_post_123',
|
|
channel_id: 'channel1',
|
|
metadata: {
|
|
embeds: [
|
|
{
|
|
type: 'permalink',
|
|
url: '',
|
|
data: {
|
|
post_id: referencedPostId,
|
|
post: {
|
|
id: referencedPostId,
|
|
message: 'Old message',
|
|
edit_at: 1000,
|
|
update_at: 1000,
|
|
user_id: 'user_123',
|
|
create_at: 500,
|
|
},
|
|
},
|
|
},
|
|
],
|
|
},
|
|
});
|
|
|
|
const models = await operator.handlePosts({
|
|
actionType: ActionType.POSTS.RECEIVED_NEW,
|
|
order: [referencingPost.id],
|
|
posts: [referencingPost],
|
|
prepareRecordsOnly: true,
|
|
});
|
|
await operator.batchRecords(models, 'test');
|
|
|
|
const postModel = await database.get('Post').find(referencingPost.id) as PostModel;
|
|
|
|
const freshPostData = TestHelper.fakePost({
|
|
id: referencedPostId,
|
|
message: 'Updated message',
|
|
edit_at: 2000,
|
|
update_at: 2000,
|
|
user_id: 'user_123',
|
|
create_at: 500,
|
|
});
|
|
|
|
const result = updatePermalinkMetadata(postModel, referencedPostId, freshPostData);
|
|
|
|
expect(result).not.toBeNull();
|
|
expect(result!.id).toBe(referencingPost.id);
|
|
expect(result!._preparedState).toBe('update');
|
|
|
|
await operator.batchRecords([result!], 'test update');
|
|
});
|
|
|
|
it('should not update when fresh post is older or same age', async () => {
|
|
const referencedPostId = 'referenced_post_456';
|
|
|
|
const referencingPost = TestHelper.fakePost({
|
|
id: 'referencing_post_123',
|
|
channel_id: 'channel1',
|
|
metadata: {
|
|
embeds: [
|
|
{
|
|
type: 'permalink',
|
|
url: '',
|
|
data: {
|
|
post_id: referencedPostId,
|
|
post: {
|
|
id: referencedPostId,
|
|
message: 'Current message',
|
|
edit_at: 2000,
|
|
update_at: 2000,
|
|
user_id: 'user_123',
|
|
create_at: 500,
|
|
},
|
|
},
|
|
},
|
|
],
|
|
},
|
|
});
|
|
|
|
const models = await operator.handlePosts({
|
|
actionType: ActionType.POSTS.RECEIVED_NEW,
|
|
order: [referencingPost.id],
|
|
posts: [referencingPost],
|
|
prepareRecordsOnly: true,
|
|
});
|
|
await operator.batchRecords(models, 'test');
|
|
|
|
const postModel = await database.get('Post').find(referencingPost.id) as PostModel;
|
|
|
|
const freshPostData = TestHelper.fakePost({
|
|
id: referencedPostId,
|
|
message: 'Older message',
|
|
edit_at: 1000,
|
|
update_at: 1000,
|
|
});
|
|
|
|
const result = updatePermalinkMetadata(postModel, referencedPostId, freshPostData);
|
|
|
|
expect(result).toBeNull();
|
|
});
|
|
|
|
it('should update permalink metadata including file metadata when fresh post is newer', async () => {
|
|
const referencedPostId = 'referenced_post_with_files';
|
|
|
|
const oldFileMetadata: FileInfo[] = [
|
|
{
|
|
id: 'file1',
|
|
name: 'old_file.txt',
|
|
extension: 'txt',
|
|
size: 100,
|
|
mime_type: 'text/plain',
|
|
width: 0,
|
|
height: 0,
|
|
has_preview_image: false,
|
|
user_id: 'user_123',
|
|
},
|
|
];
|
|
|
|
const newFileMetadata: FileInfo[] = [
|
|
{
|
|
id: 'file1',
|
|
name: 'old_file.txt',
|
|
extension: 'txt',
|
|
size: 100,
|
|
mime_type: 'text/plain',
|
|
width: 0,
|
|
height: 0,
|
|
has_preview_image: false,
|
|
user_id: 'user_123',
|
|
},
|
|
{
|
|
id: 'file2',
|
|
name: 'new_file.jpg',
|
|
extension: 'jpg',
|
|
size: 2000,
|
|
mime_type: 'image/jpeg',
|
|
width: 1920,
|
|
height: 1080,
|
|
has_preview_image: true,
|
|
user_id: 'user_123',
|
|
},
|
|
];
|
|
|
|
const referencingPost = TestHelper.fakePost({
|
|
id: 'referencing_post_files',
|
|
channel_id: 'channel1',
|
|
metadata: {
|
|
embeds: [
|
|
{
|
|
type: 'permalink',
|
|
url: '',
|
|
data: {
|
|
post_id: referencedPostId,
|
|
post: {
|
|
id: referencedPostId,
|
|
message: 'Post with old files',
|
|
edit_at: 1000,
|
|
update_at: 1000,
|
|
user_id: 'user_123',
|
|
create_at: 500,
|
|
metadata: {
|
|
files: oldFileMetadata,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
],
|
|
},
|
|
});
|
|
|
|
const models = await operator.handlePosts({
|
|
actionType: ActionType.POSTS.RECEIVED_NEW,
|
|
order: [referencingPost.id],
|
|
posts: [referencingPost],
|
|
prepareRecordsOnly: true,
|
|
});
|
|
await operator.batchRecords(models, 'test');
|
|
|
|
const postModel = await database.get('Post').find(referencingPost.id) as PostModel;
|
|
|
|
const freshPostData = TestHelper.fakePost({
|
|
id: referencedPostId,
|
|
message: 'Post with updated files',
|
|
edit_at: 2000,
|
|
update_at: 2000,
|
|
user_id: 'user_123',
|
|
create_at: 500,
|
|
metadata: {
|
|
files: newFileMetadata,
|
|
},
|
|
});
|
|
|
|
const result = updatePermalinkMetadata(postModel, referencedPostId, freshPostData);
|
|
|
|
expect(result).not.toBeNull();
|
|
expect(result!.id).toBe(referencingPost.id);
|
|
expect(result!._preparedState).toBe('update');
|
|
|
|
// Verify the metadata changes
|
|
expect(result!.metadata!.embeds![0].data.post.message).toBe('Post with updated files');
|
|
expect(result!.metadata!.embeds![0].data.post.edit_at).toBe(2000);
|
|
expect(result!.metadata!.embeds![0].data.post.metadata).toEqual({
|
|
files: newFileMetadata,
|
|
});
|
|
expect(result!.metadata!.embeds![0].data.post.metadata!.files).toHaveLength(2);
|
|
expect(result!.metadata!.embeds![0].data.post.metadata!.files![1].name).toBe('new_file.jpg');
|
|
|
|
await operator.batchRecords([result!], 'test file metadata update');
|
|
});
|
|
|
|
it('should handle errors during post update gracefully', async () => {
|
|
const referencedPostId = 'referenced_post_456';
|
|
|
|
const referencingPost = TestHelper.fakePost({
|
|
id: 'referencing_post_123',
|
|
channel_id: 'channel1',
|
|
metadata: {
|
|
embeds: [
|
|
{
|
|
type: 'permalink',
|
|
url: '',
|
|
data: {
|
|
post_id: referencedPostId,
|
|
post: {
|
|
id: referencedPostId,
|
|
message: 'Old message',
|
|
edit_at: 1000,
|
|
update_at: 1000,
|
|
user_id: 'user_123',
|
|
create_at: 500,
|
|
},
|
|
},
|
|
},
|
|
],
|
|
},
|
|
});
|
|
|
|
const models = await operator.handlePosts({
|
|
actionType: ActionType.POSTS.RECEIVED_NEW,
|
|
order: [referencingPost.id],
|
|
posts: [referencingPost],
|
|
prepareRecordsOnly: true,
|
|
});
|
|
await operator.batchRecords(models, 'test');
|
|
|
|
const postModel = await database.get('Post').find(referencingPost.id) as PostModel;
|
|
|
|
const testError = new Error('Database update failed');
|
|
jest.spyOn(postModel, 'prepareUpdate').mockImplementationOnce(() => {
|
|
throw testError;
|
|
});
|
|
|
|
const logWarningSpy = jest.spyOn(logModule, 'logWarning').mockImplementationOnce(() => {});
|
|
|
|
const freshPostData = TestHelper.fakePost({
|
|
id: referencedPostId,
|
|
message: 'Updated message',
|
|
edit_at: 2000,
|
|
update_at: 2000,
|
|
user_id: 'user_123',
|
|
create_at: 500,
|
|
});
|
|
|
|
const result = updatePermalinkMetadata(postModel, referencedPostId, freshPostData);
|
|
|
|
expect(result).toBeNull();
|
|
expect(logWarningSpy).toHaveBeenCalledWith('Error updating permalink metadata:', testError);
|
|
});
|
|
});
|
|
});
|