Improve AI music and add music world explore

هذا الالتزام موجود في:
boutmoun123
2026-06-09 16:56:52 +03:00
الأصل 1dd5a20846
التزام 16de76d9eb
13 ملفات معدلة مع 1100 إضافات و264 حذوفات

عرض الملف

@@ -0,0 +1,174 @@
import { MusicWorldController } from './music-world.controller';
import { MusicWorldService } from './music-world.service';
describe('MusicWorldController', () => {
const createController = (
feedService = { getExplore: jest.fn() },
searchService = { searchPosts: jest.fn() },
) => new MusicWorldController(new MusicWorldService(feedService as any, searchService as any));
it('returns Flutter-ready Arabic music discovery cards', () => {
const controller = createController();
const result = controller.getMusicWorld();
expect(result.title).toBe('عالم الموسيقى');
expect(result.searchPlaceholder).toBe('شو حابب تلاقي اليوم؟');
expect(result.cards).toHaveLength(6);
expect(result.cards[0]).toEqual({
key: 'oud',
title: 'عود',
subtitle: 'اكتشف عزف العود والمقامات الشرقية',
imageUrl: '/uploads/music-world/oud.jpg',
type: 'search',
endpoint: '/api/v1/search/posts',
query: 'عود',
});
expect(result.cards.some((card) => card.type === 'navigation')).toBe(true);
expect(result.sections.map((section) => section.key)).toEqual([
'trending',
'explore',
'artists',
]);
});
it('maps feed explore posts into Flutter grid items', async () => {
const feedService = {
getExplore: jest.fn().mockResolvedValue({
items: [
{
id: 'post-1',
feedItemType: 'post',
postType: 'video',
content: 'عود حجاز',
thumbnailUrl: '/uploads/thumb.jpg',
media: {
mediaType: 'video',
displayUrl: '/uploads/thumb-medium.jpg',
thumbnailUrl: '/uploads/thumb.jpg',
},
authorId: {
_id: 'user-1',
name: 'Artist',
username: 'artist',
avatar: '/avatar.jpg',
isVerified: true,
},
engagement: {
likesCount: 3,
commentsCount: 2,
viewCount: 10,
playCount: 7,
},
likedByMe: true,
savedByMe: false,
createdAt: '2026-06-09T00:00:00.000Z',
},
{
id: 'card-1',
feedItemType: 'featured_marketplace',
},
],
page: 1,
limit: 20,
total: 1,
totalPages: 1,
nextCursor: null,
pagination: { hasNextPage: false, nextCursor: null, page: 1, limit: 20 },
}),
};
const controller = createController(feedService);
const result = await controller.getExplore({ sub: 'viewer-1' } as any, {
page: 1,
limit: 20,
});
expect(feedService.getExplore).toHaveBeenCalledWith('viewer-1', { page: 1, limit: 20 });
expect(result.items).toHaveLength(1);
expect(result.items[0]).toMatchObject({
id: 'post-1',
postType: 'video',
content: 'عود حجاز',
thumbnailUrl: '/uploads/thumb.jpg',
displayUrl: '/uploads/thumb-medium.jpg',
author: {
id: 'user-1',
username: 'artist',
isVerified: true,
},
engagement: {
likesCount: 3,
commentsCount: 2,
viewCount: 10,
playCount: 7,
},
isLiked: true,
isSaved: false,
});
expect(result.pagination).toMatchObject({ hasNextPage: false });
});
it('maps music-world search results into the same grid item shape', async () => {
const searchService = {
searchPosts: jest.fn().mockResolvedValue({
items: [
{
_id: 'post-2',
postType: 'image',
content: 'ناي',
imageUrls: ['/uploads/ney.jpg'],
authorId: {
_id: 'user-2',
name: 'Ney Artist',
username: 'ney_artist',
avatar: '',
isVerified: false,
},
likesCount: 4,
commentsCount: 1,
isLiked: false,
isSaved: true,
createdAt: '2026-06-09T00:00:00.000Z',
},
],
page: 1,
limit: 20,
total: 1,
totalPages: 1,
nextCursor: null,
pagination: { hasNextPage: false },
}),
};
const controller = createController(undefined, searchService);
const result = await controller.search({ sub: 'viewer-1' } as any, {
q: 'ناي',
page: 1,
limit: 20,
});
expect(searchService.searchPosts).toHaveBeenCalledWith('viewer-1', {
q: 'ناي',
page: 1,
limit: 20,
type: 'posts',
});
expect(result.items[0]).toMatchObject({
id: 'post-2',
postType: 'image',
displayUrl: '/uploads/ney.jpg',
thumbnailUrl: '/uploads/ney.jpg',
author: {
id: 'user-2',
username: 'ney_artist',
},
engagement: {
likesCount: 4,
commentsCount: 1,
},
isLiked: false,
isSaved: true,
});
});
});