@amityco/ts-sdk 6.3.2-aaaf497.0 → 6.3.2-aafb737.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/@types/domains/user.d.ts +1 -0
- package/dist/@types/domains/user.d.ts.map +1 -1
- package/dist/channelRepsitory/channelMembership/observers/getMembers.d.ts.map +1 -1
- package/dist/commentRepository/api/tests/deleteComment.test.d.ts +2 -0
- package/dist/commentRepository/api/tests/deleteComment.test.d.ts.map +1 -0
- package/dist/communityRepository/communityMembership/observers/getMembers.d.ts.map +1 -1
- package/dist/index.cjs.js +71 -30
- package/dist/index.esm.js +71 -30
- package/dist/index.umd.js +1 -1
- package/dist/userRepository/observers/getUsers.d.ts.map +1 -1
- package/dist/userRepository/observers/index.d.ts +1 -0
- package/dist/userRepository/observers/index.d.ts.map +1 -1
- package/dist/userRepository/observers/searchUserByDisplayName.d.ts +19 -0
- package/dist/userRepository/observers/searchUserByDisplayName.d.ts.map +1 -0
- package/dist/userRepository/observers/tests/searchUserByDisplayName.test.d.ts +2 -0
- package/dist/userRepository/observers/tests/searchUserByDisplayName.test.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/@types/domains/user.ts +2 -0
- package/src/channelRepsitory/channelMembership/observers/getMembers.ts +17 -10
- package/src/channelRepsitory/channelMembership/observers/tests/getMembers.test.ts +0 -62
- package/src/channelRepsitory/channelMembership/observers/tests/searchMembers.test.ts +0 -31
- package/src/commentRepository/api/tests/deleteComment.test.ts +60 -0
- package/src/communityRepository/communityMembership/observers/getMembers.ts +14 -10
- package/src/communityRepository/communityMembership/observers/tests/getMembers.test.ts +1 -27
- package/src/messageRepository/observers/getMessages.ts +1 -1
- package/src/userRepository/observers/getUsers.ts +18 -11
- package/src/userRepository/observers/index.ts +1 -0
- package/src/userRepository/observers/searchUserByDisplayName.ts +30 -0
- package/src/userRepository/observers/tests/getUsers.test.ts +1 -29
- package/src/userRepository/observers/tests/searchUserByDisplayName.test.ts +113 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getUsers.d.ts","sourceRoot":"","sources":["../../../src/userRepository/observers/getUsers.ts"],"names":[],"mappings":"AAiCA;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,QAAQ,WACX,MAAM,kBAAkB,YACtB,MAAM,sBAAsB,CAAC,MAAM,IAAI,CAAC,WACzC,MAAM,oBAAoB,
|
|
1
|
+
{"version":3,"file":"getUsers.d.ts","sourceRoot":"","sources":["../../../src/userRepository/observers/getUsers.ts"],"names":[],"mappings":"AAiCA;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,QAAQ,WACX,MAAM,kBAAkB,YACtB,MAAM,sBAAsB,CAAC,MAAM,IAAI,CAAC,WACzC,MAAM,oBAAoB,eAuHpC,CAAC"}
|
|
@@ -2,4 +2,5 @@ export { getUser } from './getUser';
|
|
|
2
2
|
export { getUsers } from './getUsers';
|
|
3
3
|
export { observeUser } from './observeUser';
|
|
4
4
|
export { getBlockedUsers } from './getBlockedUsers';
|
|
5
|
+
export { searchUserByDisplayName } from './searchUserByDisplayName';
|
|
5
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/userRepository/observers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/userRepository/observers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ```js
|
|
3
|
+
* import { UserRepository } from '@amityco/ts-sdk'
|
|
4
|
+
*
|
|
5
|
+
* let users = []
|
|
6
|
+
* const unsub = UserRepository.searchUserByDisplayName({}, response => merge(users, response.data))
|
|
7
|
+
* ```
|
|
8
|
+
*
|
|
9
|
+
* Observe all mutations on a list of {@link Amity.User}s
|
|
10
|
+
*
|
|
11
|
+
* @param params for searching users
|
|
12
|
+
* @param callback the function to call when new data are available
|
|
13
|
+
* @param config the configuration for the live collection
|
|
14
|
+
* @returns An {@link Amity.Unsubscriber} function to run when willing to stop observing the users
|
|
15
|
+
*
|
|
16
|
+
* @category Category Live Collection
|
|
17
|
+
*/
|
|
18
|
+
export declare const searchUserByDisplayName: (params: Amity.UserSearchLiveCollection, callback: Amity.LiveCollectionCallback<Amity.User>, config?: Amity.LiveCollectionConfig) => () => void;
|
|
19
|
+
//# sourceMappingURL=searchUserByDisplayName.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"searchUserByDisplayName.d.ts","sourceRoot":"","sources":["../../../src/userRepository/observers/searchUserByDisplayName.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,uBAAuB,WAC1B,MAAM,wBAAwB,YAC5B,MAAM,sBAAsB,CAAC,MAAM,IAAI,CAAC,WACzC,MAAM,oBAAoB,eAGpC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"searchUserByDisplayName.test.d.ts","sourceRoot":"","sources":["../../../../src/userRepository/observers/tests/searchUserByDisplayName.test.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -34,6 +34,8 @@ declare global {
|
|
|
34
34
|
|
|
35
35
|
type UserLiveCollection = Amity.LiveCollectionParams<Omit<QueryUsers, 'page'>>;
|
|
36
36
|
|
|
37
|
+
type UserSearchLiveCollection = Amity.LiveCollectionParams<Omit<QueryUsers, 'sortBy'>>;
|
|
38
|
+
|
|
37
39
|
type UserLiveCollectionCache = Amity.LiveCollectionCache<
|
|
38
40
|
Amity.User['userId'],
|
|
39
41
|
Pick<QueryUsers, 'page'>
|
|
@@ -69,14 +69,8 @@ export const getMembers = (
|
|
|
69
69
|
const disposers: Amity.Unsubscriber[] = [];
|
|
70
70
|
const cacheKey = ['channelUsers', 'collection', { channelId: params.channelId }];
|
|
71
71
|
|
|
72
|
-
const
|
|
73
|
-
let channelMembers
|
|
74
|
-
data.data
|
|
75
|
-
.map(id => pullFromCache<Amity.Membership<'channel'>>(['channelUsers', 'get', id])!)
|
|
76
|
-
.filter(Boolean)
|
|
77
|
-
.map(({ data }) => data) ?? [];
|
|
78
|
-
|
|
79
|
-
channelMembers = filterByPropIntersection(channelMembers, 'roles', params.roles);
|
|
72
|
+
const applyFilter = <T extends Amity.Membership<'channel'>>(data: T[]): T[] => {
|
|
73
|
+
let channelMembers = filterByPropIntersection(data, 'roles', params.roles);
|
|
80
74
|
|
|
81
75
|
if (params.memberships) {
|
|
82
76
|
/*
|
|
@@ -106,9 +100,22 @@ export const getMembers = (
|
|
|
106
100
|
sortBy === 'lastCreated' ? sortByLastCreated : sortByFirstCreated,
|
|
107
101
|
);
|
|
108
102
|
|
|
103
|
+
return channelMembers;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const responder = (data: Amity.ChannelMembersLiveCollectionCache, isEventModel = false) => {
|
|
107
|
+
const channelMembers: Amity.Membership<'channel'>[] =
|
|
108
|
+
data.data
|
|
109
|
+
.map(id => pullFromCache<Amity.Membership<'channel'>>(['channelUsers', 'get', id])!)
|
|
110
|
+
.filter(Boolean)
|
|
111
|
+
.map(({ data }) => data) ?? [];
|
|
112
|
+
|
|
109
113
|
callback({
|
|
110
114
|
onNextPage: onFetch,
|
|
111
|
-
|
|
115
|
+
/*
|
|
116
|
+
* Only apply filter to RTE Model
|
|
117
|
+
*/
|
|
118
|
+
data: isEventModel ? applyFilter(channelMembers) : channelMembers,
|
|
112
119
|
hasNextPage: !!data.params?.page,
|
|
113
120
|
loading: data.loading,
|
|
114
121
|
error: data.error,
|
|
@@ -137,7 +144,7 @@ export const getMembers = (
|
|
|
137
144
|
}
|
|
138
145
|
|
|
139
146
|
pushToCache(cacheKey, collection);
|
|
140
|
-
responder(collection);
|
|
147
|
+
responder(collection, true);
|
|
141
148
|
};
|
|
142
149
|
|
|
143
150
|
const onFetch = (initial = false) => {
|
|
@@ -59,68 +59,6 @@ describe('getMembers', () => {
|
|
|
59
59
|
);
|
|
60
60
|
});
|
|
61
61
|
|
|
62
|
-
const filters: [string, Amity.ChannelMembersLiveCollection, Amity.Membership<'channel'>[]][] = [
|
|
63
|
-
[
|
|
64
|
-
'roles',
|
|
65
|
-
{ channelId, roles: channelUserQueryResponsePage3.data.channelUsers[0].roles },
|
|
66
|
-
[channelUserWithRole],
|
|
67
|
-
],
|
|
68
|
-
['searched term', { channelId, search: 'use' }, [channelUserWithRole, bannedChannelUser]],
|
|
69
|
-
['member', { channelId, memberships: ['member'] }, [channelUserWithRole, mutedChannelUser]],
|
|
70
|
-
['muted members', { channelId, memberships: ['muted'] }, [mutedChannelUser]],
|
|
71
|
-
['banned members', { channelId, memberships: ['banned'] }, [bannedChannelUser]],
|
|
72
|
-
[
|
|
73
|
-
'muted and banned members',
|
|
74
|
-
{ channelId, memberships: ['muted', 'banned'] },
|
|
75
|
-
[mutedChannelUser, bannedChannelUser],
|
|
76
|
-
],
|
|
77
|
-
];
|
|
78
|
-
|
|
79
|
-
test.each(filters)('it should filter channelUsers by %s', async (filter, params, expected) => {
|
|
80
|
-
const callback = jest.fn();
|
|
81
|
-
client.http.get = jest.fn().mockResolvedValue(channelUserQueryResponsePage3);
|
|
82
|
-
|
|
83
|
-
getMembers(params, callback);
|
|
84
|
-
await pause();
|
|
85
|
-
|
|
86
|
-
expect(callback).toHaveBeenNthCalledWith(1, expect.objectContaining(getSnapshot()));
|
|
87
|
-
expect(callback).toHaveBeenNthCalledWith(
|
|
88
|
-
2,
|
|
89
|
-
expect.objectContaining({ data: expected, loading: false }),
|
|
90
|
-
);
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
test('it should return method to fetch next page', async () => {
|
|
94
|
-
const callback = jest.fn();
|
|
95
|
-
client.http.get = jest
|
|
96
|
-
.fn()
|
|
97
|
-
.mockResolvedValue(channelUserQueryResponse)
|
|
98
|
-
.mockResolvedValueOnce(channelUserQueryResponsePage2);
|
|
99
|
-
|
|
100
|
-
getMembers({ channelId }, callback);
|
|
101
|
-
await pause();
|
|
102
|
-
|
|
103
|
-
expect(callback).toHaveBeenCalled();
|
|
104
|
-
expect(callback.mock.lastCall).toHaveLength(1);
|
|
105
|
-
|
|
106
|
-
const { onNextPage, hasNextPage } = callback.mock.lastCall[0];
|
|
107
|
-
|
|
108
|
-
expect(hasNextPage).toBe(true);
|
|
109
|
-
expect(onNextPage).toBeTruthy();
|
|
110
|
-
|
|
111
|
-
onNextPage();
|
|
112
|
-
await pause();
|
|
113
|
-
|
|
114
|
-
const payload = convertRawChannelPayload(channelUserQueryResponse.data);
|
|
115
|
-
const payload2 = convertRawChannelPayload(channelUserQueryResponsePage2.data);
|
|
116
|
-
|
|
117
|
-
const snapshot = getSnapshot();
|
|
118
|
-
snapshot.loading = false;
|
|
119
|
-
snapshot.data = [...payload2.channelUsers, ...payload.channelUsers];
|
|
120
|
-
|
|
121
|
-
expect(callback).toHaveBeenNthCalledWith(4, expect.objectContaining(snapshot));
|
|
122
|
-
});
|
|
123
|
-
|
|
124
62
|
const events: [
|
|
125
63
|
string,
|
|
126
64
|
keyof Amity.Events,
|
|
@@ -59,37 +59,6 @@ describe('searchMembers', () => {
|
|
|
59
59
|
);
|
|
60
60
|
});
|
|
61
61
|
|
|
62
|
-
const filters: [string, Amity.ChannelMembersLiveCollection, Amity.Membership<'channel'>[]][] = [
|
|
63
|
-
[
|
|
64
|
-
'roles',
|
|
65
|
-
{ channelId, roles: channelUserQueryResponsePage3.data.channelUsers[0].roles },
|
|
66
|
-
[channelUserWithRole],
|
|
67
|
-
],
|
|
68
|
-
['searched term', { channelId, search: 'use' }, [channelUserWithRole, bannedChannelUser]],
|
|
69
|
-
['member', { channelId, memberships: ['member'] }, [channelUserWithRole, mutedChannelUser]],
|
|
70
|
-
['muted members', { channelId, memberships: ['muted'] }, [mutedChannelUser]],
|
|
71
|
-
['banned members', { channelId, memberships: ['banned'] }, [bannedChannelUser]],
|
|
72
|
-
[
|
|
73
|
-
'muted and banned members',
|
|
74
|
-
{ channelId, memberships: ['muted', 'banned'] },
|
|
75
|
-
[mutedChannelUser, bannedChannelUser],
|
|
76
|
-
],
|
|
77
|
-
];
|
|
78
|
-
|
|
79
|
-
test.each(filters)('it should filter channelUsers by %s', async (filter, params, expected) => {
|
|
80
|
-
const callback = jest.fn();
|
|
81
|
-
client.http.get = jest.fn().mockResolvedValue(channelUserQueryResponsePage3);
|
|
82
|
-
|
|
83
|
-
searchMembers(params, callback);
|
|
84
|
-
await pause();
|
|
85
|
-
|
|
86
|
-
expect(callback).toHaveBeenNthCalledWith(1, expect.objectContaining(getSnapshot()));
|
|
87
|
-
expect(callback).toHaveBeenNthCalledWith(
|
|
88
|
-
2,
|
|
89
|
-
expect.objectContaining({ data: expected, loading: false }),
|
|
90
|
-
);
|
|
91
|
-
});
|
|
92
|
-
|
|
93
62
|
test('it should return method to fetch next page', async () => {
|
|
94
63
|
const callback = jest.fn();
|
|
95
64
|
client.http.get = jest
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import {
|
|
2
|
+
client,
|
|
3
|
+
comment11,
|
|
4
|
+
connectClient,
|
|
5
|
+
disconnectClient,
|
|
6
|
+
emptyPostPayload,
|
|
7
|
+
generateComment,
|
|
8
|
+
generatePost,
|
|
9
|
+
textCommentResponse,
|
|
10
|
+
user11,
|
|
11
|
+
} from '~/utils/tests';
|
|
12
|
+
import { ASCApiError } from '~/core/errors';
|
|
13
|
+
import { deleteComment } from '../deleteComment';
|
|
14
|
+
|
|
15
|
+
const commentId = 'comment11';
|
|
16
|
+
const commentData = generateComment({ commentId });
|
|
17
|
+
|
|
18
|
+
const singlePostResponse = {
|
|
19
|
+
data: {
|
|
20
|
+
...emptyPostPayload,
|
|
21
|
+
posts: [generatePost({ comments: [commentId], commentsCount: 1 })],
|
|
22
|
+
comments: [commentData],
|
|
23
|
+
users: [user11],
|
|
24
|
+
} as Amity.ProcessedPostPayload,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
describe('deleteComment', () => {
|
|
28
|
+
beforeAll(connectClient);
|
|
29
|
+
afterAll(disconnectClient);
|
|
30
|
+
|
|
31
|
+
// integration_test_id: ff01df65-2cc0-4fd8-8c3e-a12cea5a359b
|
|
32
|
+
test('should return success for soft and hard delete', async () => {
|
|
33
|
+
client.http.get = jest.fn().mockImplementation(url => {
|
|
34
|
+
if (url === '/api/v3/comments/comment11') return textCommentResponse;
|
|
35
|
+
// /api/v3/posts/postId11
|
|
36
|
+
return singlePostResponse;
|
|
37
|
+
});
|
|
38
|
+
client.http.delete = jest.fn().mockResolvedValueOnce({ success: true });
|
|
39
|
+
|
|
40
|
+
const result = await deleteComment(commentId);
|
|
41
|
+
expect(result.isDeleted).toEqual(true);
|
|
42
|
+
expect(result.commentId).toEqual(commentId);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// integration_test_id: 322954d6-bc89-40ae-bd18-691ee0c60105
|
|
46
|
+
test('should return error for deletion not successful', async () => {
|
|
47
|
+
client.http.get = jest.fn().mockImplementation(url => {
|
|
48
|
+
if (url === '/api/v3/comments/comment11') return textCommentResponse;
|
|
49
|
+
// /api/v3/posts/postId11
|
|
50
|
+
return singlePostResponse;
|
|
51
|
+
});
|
|
52
|
+
client.http.delete = jest
|
|
53
|
+
.fn()
|
|
54
|
+
.mockRejectedValueOnce(
|
|
55
|
+
new ASCApiError('not found!', Amity.ServerError.ITEM_NOT_FOUND, Amity.ErrorLevel.ERROR),
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
await expect(deleteComment(commentId)).rejects.toThrow();
|
|
59
|
+
});
|
|
60
|
+
});
|
|
@@ -70,14 +70,8 @@ export const getMembers = (
|
|
|
70
70
|
const disposers: Amity.Unsubscriber[] = [];
|
|
71
71
|
const cacheKey = ['communityUsers', 'collection', { communityId: params.communityId }];
|
|
72
72
|
|
|
73
|
-
const
|
|
74
|
-
let communityMembers
|
|
75
|
-
data.data
|
|
76
|
-
.map(id => pullFromCache<Amity.Membership<'community'>>(['communityUsers', 'get', id])!)
|
|
77
|
-
.filter(Boolean)
|
|
78
|
-
.map(({ data }) => data) ?? [];
|
|
79
|
-
|
|
80
|
-
communityMembers = filterByPropIntersection(communityMembers, 'roles', params.roles);
|
|
73
|
+
const applyFilter = <T extends Amity.Membership<'community'>>(data: T[]): T[] => {
|
|
74
|
+
let communityMembers = filterByPropIntersection(data, 'roles', params.roles);
|
|
81
75
|
|
|
82
76
|
if (params.membership) {
|
|
83
77
|
communityMembers = communityMembers.filter(({ communityMembership }) =>
|
|
@@ -95,9 +89,19 @@ export const getMembers = (
|
|
|
95
89
|
sortBy === 'lastCreated' ? sortByLastCreated : sortByFirstCreated,
|
|
96
90
|
);
|
|
97
91
|
|
|
92
|
+
return communityMembers;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const responder = (data: Amity.CommunityMemberLiveCollectionCache, isEventModel = false) => {
|
|
96
|
+
const communityMembers: Amity.Membership<'community'>[] =
|
|
97
|
+
data.data
|
|
98
|
+
.map(id => pullFromCache<Amity.Membership<'community'>>(['communityUsers', 'get', id])!)
|
|
99
|
+
.filter(Boolean)
|
|
100
|
+
.map(({ data }) => data) ?? [];
|
|
101
|
+
|
|
98
102
|
callback({
|
|
99
103
|
onNextPage: onFetch,
|
|
100
|
-
data: communityMembers,
|
|
104
|
+
data: isEventModel ? applyFilter(communityMembers) : communityMembers,
|
|
101
105
|
hasNextPage: !!data.params?.page,
|
|
102
106
|
loading: data.loading,
|
|
103
107
|
error: data.error,
|
|
@@ -122,7 +126,7 @@ export const getMembers = (
|
|
|
122
126
|
collection.data = [...new Set([communityMemberCacheId, ...collection.data])];
|
|
123
127
|
|
|
124
128
|
pushToCache(cacheKey, collection);
|
|
125
|
-
responder(collection);
|
|
129
|
+
responder(collection, true);
|
|
126
130
|
};
|
|
127
131
|
|
|
128
132
|
const onFetch = (initial = false) => {
|
|
@@ -50,37 +50,11 @@ describe('getMembers', () => {
|
|
|
50
50
|
expect(callback).toHaveBeenNthCalledWith(
|
|
51
51
|
2,
|
|
52
52
|
expect.objectContaining(
|
|
53
|
-
getSnapshot({ data: [
|
|
53
|
+
getSnapshot({ data: [convertedCommunityUser1, convertedCommunityUser2], loading: false }),
|
|
54
54
|
),
|
|
55
55
|
);
|
|
56
56
|
});
|
|
57
57
|
|
|
58
|
-
const filters: [string, Amity.CommunityMemberLiveCollection, Amity.Membership<'community'>[]][] =
|
|
59
|
-
[
|
|
60
|
-
['roles', { communityId, roles: ['test-role'] }, [withRoleCommunityUser]],
|
|
61
|
-
[
|
|
62
|
-
'searched term',
|
|
63
|
-
{ communityId, search: 'use' },
|
|
64
|
-
[withRoleCommunityUser, bannedCommunityUser],
|
|
65
|
-
],
|
|
66
|
-
['member', { communityId, membership: ['member'] }, [withRoleCommunityUser]],
|
|
67
|
-
['banned members', { communityId, membership: ['banned'] }, [bannedCommunityUser]],
|
|
68
|
-
];
|
|
69
|
-
|
|
70
|
-
test.each(filters)('it should filter channelUsers by %s', async (filter, params, expected) => {
|
|
71
|
-
const callback = jest.fn();
|
|
72
|
-
client.http.get = jest.fn().mockResolvedValue(communityUserQueryResponsePage2);
|
|
73
|
-
|
|
74
|
-
getMembers(params, callback);
|
|
75
|
-
await pause();
|
|
76
|
-
|
|
77
|
-
expect(callback).toHaveBeenNthCalledWith(1, expect.objectContaining(getSnapshot()));
|
|
78
|
-
expect(callback).toHaveBeenNthCalledWith(
|
|
79
|
-
2,
|
|
80
|
-
expect.objectContaining({ data: expected, loading: false }),
|
|
81
|
-
);
|
|
82
|
-
});
|
|
83
|
-
|
|
84
58
|
test('it should return method to fetch next page', async () => {
|
|
85
59
|
const callback = jest.fn();
|
|
86
60
|
client.http.get = jest
|
|
@@ -66,7 +66,7 @@ export const getMessages = (
|
|
|
66
66
|
const { policy = COLLECTION_DEFAULT_CACHING_POLICY } = config ?? {};
|
|
67
67
|
|
|
68
68
|
const disposers: Amity.Unsubscriber[] = [];
|
|
69
|
-
const cacheKey = ['message', 'collection',
|
|
69
|
+
const cacheKey = ['message', 'collection', params];
|
|
70
70
|
|
|
71
71
|
const responder = (data: Amity.MessageLiveCollectionCache) => {
|
|
72
72
|
let messages: Amity.Message[] =
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
} from '../events';
|
|
30
30
|
|
|
31
31
|
/* begin_public_function
|
|
32
|
-
id: user.query
|
|
32
|
+
id: user.query
|
|
33
33
|
*/
|
|
34
34
|
/**
|
|
35
35
|
* ```js
|
|
@@ -69,14 +69,8 @@ export const getUsers = (
|
|
|
69
69
|
const disposers: Amity.Unsubscriber[] = [];
|
|
70
70
|
const cacheKey = ['user', 'collection', {}];
|
|
71
71
|
|
|
72
|
-
const
|
|
73
|
-
let users
|
|
74
|
-
data.data
|
|
75
|
-
.map(userId => pullFromCache<Amity.User>(['user', 'get', userId])!)
|
|
76
|
-
.filter(Boolean)
|
|
77
|
-
.map(({ data }) => data) ?? [];
|
|
78
|
-
|
|
79
|
-
users = filterByPropEquality(users, 'displayName', params.displayName);
|
|
72
|
+
const applyFilter = (data: Amity.User[]): Amity.User[] => {
|
|
73
|
+
let users = filterByPropEquality(data, 'displayName', params.displayName);
|
|
80
74
|
|
|
81
75
|
switch (params.sortBy) {
|
|
82
76
|
case 'firstCreated':
|
|
@@ -95,9 +89,22 @@ export const getUsers = (
|
|
|
95
89
|
.sort(sortByDisplayName);
|
|
96
90
|
}
|
|
97
91
|
|
|
92
|
+
return users;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const responder = (data: Amity.UserLiveCollectionCache, isEventModel = false) => {
|
|
96
|
+
const users: Amity.User[] =
|
|
97
|
+
data.data
|
|
98
|
+
.map(userId => pullFromCache<Amity.User>(['user', 'get', userId])!)
|
|
99
|
+
.filter(Boolean)
|
|
100
|
+
.map(({ data }) => data) ?? [];
|
|
101
|
+
|
|
98
102
|
callback({
|
|
99
103
|
onNextPage: onFetch,
|
|
100
|
-
|
|
104
|
+
/*
|
|
105
|
+
* Only apply filter to RTE Model
|
|
106
|
+
*/
|
|
107
|
+
data: isEventModel ? applyFilter(users) : users,
|
|
101
108
|
hasNextPage: !!data.params?.page,
|
|
102
109
|
loading: data.loading,
|
|
103
110
|
error: data.error,
|
|
@@ -111,7 +118,7 @@ export const getUsers = (
|
|
|
111
118
|
collection.data = [...new Set([user.userId, ...collection.data])];
|
|
112
119
|
|
|
113
120
|
pushToCache(cacheKey, collection);
|
|
114
|
-
responder(collection);
|
|
121
|
+
responder(collection, true);
|
|
115
122
|
};
|
|
116
123
|
|
|
117
124
|
const onFetch = (initial = false) => {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { getUsers } from './getUsers';
|
|
2
|
+
|
|
3
|
+
/* begin_public_function
|
|
4
|
+
id: user.search
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* ```js
|
|
8
|
+
* import { UserRepository } from '@amityco/ts-sdk'
|
|
9
|
+
*
|
|
10
|
+
* let users = []
|
|
11
|
+
* const unsub = UserRepository.searchUserByDisplayName({}, response => merge(users, response.data))
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* Observe all mutations on a list of {@link Amity.User}s
|
|
15
|
+
*
|
|
16
|
+
* @param params for searching users
|
|
17
|
+
* @param callback the function to call when new data are available
|
|
18
|
+
* @param config the configuration for the live collection
|
|
19
|
+
* @returns An {@link Amity.Unsubscriber} function to run when willing to stop observing the users
|
|
20
|
+
*
|
|
21
|
+
* @category Category Live Collection
|
|
22
|
+
*/
|
|
23
|
+
export const searchUserByDisplayName = (
|
|
24
|
+
params: Amity.UserSearchLiveCollection,
|
|
25
|
+
callback: Amity.LiveCollectionCallback<Amity.User>,
|
|
26
|
+
config?: Amity.LiveCollectionConfig,
|
|
27
|
+
) => {
|
|
28
|
+
return getUsers({ ...params, filter: 'all' }, callback, config);
|
|
29
|
+
};
|
|
30
|
+
/* end_public_function */
|
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
pause,
|
|
7
7
|
user11,
|
|
8
8
|
user12,
|
|
9
|
-
user21,
|
|
10
9
|
userQueryResponse,
|
|
11
10
|
userQueryResponsePage2,
|
|
12
11
|
} from '~/utils/tests';
|
|
@@ -114,6 +113,7 @@ describe('getUsers', () => {
|
|
|
114
113
|
});
|
|
115
114
|
|
|
116
115
|
describe('events', () => {
|
|
116
|
+
// integration_test_id: 60b4b354-efca-49bc-aa8b-d63a8da6ef31
|
|
117
117
|
const updatedUser = { ...user11, displayName: 'updated-user' };
|
|
118
118
|
const flaggedUser = { ...user11, flagCount: 1 };
|
|
119
119
|
const unflaggedUser = { ...user11, flagCount: 1 };
|
|
@@ -167,32 +167,4 @@ describe('getUsers', () => {
|
|
|
167
167
|
);
|
|
168
168
|
});
|
|
169
169
|
});
|
|
170
|
-
|
|
171
|
-
// integration_test_id: 60b4b354-efca-49bc-aa8b-d63a8da6ef31
|
|
172
|
-
const filters: [string, Amity.UserLiveCollection, Amity.User[]][] = [
|
|
173
|
-
['displayName', { displayName: 'displayName' }, [user21]],
|
|
174
|
-
];
|
|
175
|
-
|
|
176
|
-
test.each(filters)('it should filter by %s communities', async (filter, params, expected) => {
|
|
177
|
-
const callback = jest.fn();
|
|
178
|
-
client.http.get = jest.fn().mockResolvedValue(userQueryResponsePage2);
|
|
179
|
-
|
|
180
|
-
getUsers(params, callback);
|
|
181
|
-
|
|
182
|
-
expect(callback).toHaveBeenCalledTimes(1);
|
|
183
|
-
// check if cache data returned (should be empty)
|
|
184
|
-
expect(callback).toHaveBeenCalledWith(expect.objectContaining(getSnapshot()));
|
|
185
|
-
|
|
186
|
-
await pause();
|
|
187
|
-
|
|
188
|
-
expect(callback).toHaveBeenCalledTimes(2);
|
|
189
|
-
expect(callback).toHaveBeenCalledWith(
|
|
190
|
-
expect.objectContaining(
|
|
191
|
-
getSnapshot({
|
|
192
|
-
loading: false,
|
|
193
|
-
data: expected,
|
|
194
|
-
}),
|
|
195
|
-
),
|
|
196
|
-
);
|
|
197
|
-
});
|
|
198
170
|
});
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { disableCache, enableCache } from '~/cache/api';
|
|
2
|
+
import {
|
|
3
|
+
client,
|
|
4
|
+
connectClient,
|
|
5
|
+
disconnectClient,
|
|
6
|
+
pause,
|
|
7
|
+
user21,
|
|
8
|
+
userQueryResponse,
|
|
9
|
+
userQueryResponsePage2,
|
|
10
|
+
} from '~/utils/tests';
|
|
11
|
+
|
|
12
|
+
import { searchUserByDisplayName } from '../searchUserByDisplayName';
|
|
13
|
+
|
|
14
|
+
const getSnapshot = (params?: Record<string, any>) => {
|
|
15
|
+
return {
|
|
16
|
+
data: [] as Amity.User[],
|
|
17
|
+
loading: true,
|
|
18
|
+
error: undefined as any,
|
|
19
|
+
...params,
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const { paging, ...payload } = userQueryResponse.data;
|
|
24
|
+
const { paging: paging2, ...payload2 } = userQueryResponsePage2.data;
|
|
25
|
+
|
|
26
|
+
describe('searchUserByDisplayName', () => {
|
|
27
|
+
beforeAll(connectClient);
|
|
28
|
+
afterAll(disconnectClient);
|
|
29
|
+
|
|
30
|
+
beforeEach(enableCache);
|
|
31
|
+
|
|
32
|
+
afterEach(disableCache);
|
|
33
|
+
|
|
34
|
+
const params = { displayName: user21.displayName } as Amity.UserLiveCollection;
|
|
35
|
+
|
|
36
|
+
// integration_test_id: c7cb9776-5c72-4abe-9b3c-572d74d534fe
|
|
37
|
+
test('it should return users collection', async () => {
|
|
38
|
+
const callback = jest.fn();
|
|
39
|
+
client.http.get = jest.fn().mockResolvedValue(userQueryResponse);
|
|
40
|
+
|
|
41
|
+
searchUserByDisplayName(params, callback);
|
|
42
|
+
await pause();
|
|
43
|
+
|
|
44
|
+
expect(callback).toHaveBeenCalledTimes(2);
|
|
45
|
+
expect(callback).toHaveBeenNthCalledWith(1, expect.objectContaining(getSnapshot()));
|
|
46
|
+
expect(callback).toHaveBeenNthCalledWith(
|
|
47
|
+
2,
|
|
48
|
+
expect.objectContaining(
|
|
49
|
+
getSnapshot({
|
|
50
|
+
data: payload.users,
|
|
51
|
+
loading: false,
|
|
52
|
+
}),
|
|
53
|
+
),
|
|
54
|
+
);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test('it should return data from cache', async () => {
|
|
58
|
+
const callback = jest.fn();
|
|
59
|
+
client.http.get = jest.fn().mockResolvedValue(userQueryResponse);
|
|
60
|
+
|
|
61
|
+
searchUserByDisplayName(params, () => undefined);
|
|
62
|
+
await pause();
|
|
63
|
+
searchUserByDisplayName(params, callback);
|
|
64
|
+
await pause();
|
|
65
|
+
|
|
66
|
+
// The second `searchUserByDisplayName` call fetches data from the cache,
|
|
67
|
+
// so there is no loading state and the callback only fires once.
|
|
68
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
69
|
+
expect(callback).toHaveBeenNthCalledWith(
|
|
70
|
+
1,
|
|
71
|
+
expect.objectContaining(
|
|
72
|
+
getSnapshot({
|
|
73
|
+
data: payload.users,
|
|
74
|
+
loading: false,
|
|
75
|
+
}),
|
|
76
|
+
),
|
|
77
|
+
);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test('it should return method to fetch next page', async () => {
|
|
81
|
+
const callback = jest.fn();
|
|
82
|
+
client.http.get = jest
|
|
83
|
+
.fn()
|
|
84
|
+
.mockResolvedValue(userQueryResponse)
|
|
85
|
+
.mockResolvedValueOnce(userQueryResponsePage2);
|
|
86
|
+
|
|
87
|
+
searchUserByDisplayName(params, callback);
|
|
88
|
+
await pause();
|
|
89
|
+
|
|
90
|
+
expect(callback).toHaveBeenCalled();
|
|
91
|
+
expect(callback.mock.lastCall).toHaveLength(1);
|
|
92
|
+
|
|
93
|
+
const { onNextPage, hasNextPage } = callback.mock.lastCall[0];
|
|
94
|
+
|
|
95
|
+
expect(hasNextPage).toBe(true);
|
|
96
|
+
expect(onNextPage).toBeTruthy();
|
|
97
|
+
|
|
98
|
+
onNextPage();
|
|
99
|
+
await pause();
|
|
100
|
+
|
|
101
|
+
// 4 -> because 1 local & server call each per call (2)
|
|
102
|
+
expect(callback).toHaveBeenCalledTimes(4);
|
|
103
|
+
expect(callback).toHaveBeenNthCalledWith(
|
|
104
|
+
4,
|
|
105
|
+
expect.objectContaining(
|
|
106
|
+
getSnapshot({
|
|
107
|
+
loading: false,
|
|
108
|
+
data: [...payload2.users, ...payload.users],
|
|
109
|
+
}),
|
|
110
|
+
),
|
|
111
|
+
);
|
|
112
|
+
});
|
|
113
|
+
});
|