@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.
Files changed (30) hide show
  1. package/dist/@types/domains/user.d.ts +1 -0
  2. package/dist/@types/domains/user.d.ts.map +1 -1
  3. package/dist/channelRepsitory/channelMembership/observers/getMembers.d.ts.map +1 -1
  4. package/dist/commentRepository/api/tests/deleteComment.test.d.ts +2 -0
  5. package/dist/commentRepository/api/tests/deleteComment.test.d.ts.map +1 -0
  6. package/dist/communityRepository/communityMembership/observers/getMembers.d.ts.map +1 -1
  7. package/dist/index.cjs.js +71 -30
  8. package/dist/index.esm.js +71 -30
  9. package/dist/index.umd.js +1 -1
  10. package/dist/userRepository/observers/getUsers.d.ts.map +1 -1
  11. package/dist/userRepository/observers/index.d.ts +1 -0
  12. package/dist/userRepository/observers/index.d.ts.map +1 -1
  13. package/dist/userRepository/observers/searchUserByDisplayName.d.ts +19 -0
  14. package/dist/userRepository/observers/searchUserByDisplayName.d.ts.map +1 -0
  15. package/dist/userRepository/observers/tests/searchUserByDisplayName.test.d.ts +2 -0
  16. package/dist/userRepository/observers/tests/searchUserByDisplayName.test.d.ts.map +1 -0
  17. package/package.json +1 -1
  18. package/src/@types/domains/user.ts +2 -0
  19. package/src/channelRepsitory/channelMembership/observers/getMembers.ts +17 -10
  20. package/src/channelRepsitory/channelMembership/observers/tests/getMembers.test.ts +0 -62
  21. package/src/channelRepsitory/channelMembership/observers/tests/searchMembers.test.ts +0 -31
  22. package/src/commentRepository/api/tests/deleteComment.test.ts +60 -0
  23. package/src/communityRepository/communityMembership/observers/getMembers.ts +14 -10
  24. package/src/communityRepository/communityMembership/observers/tests/getMembers.test.ts +1 -27
  25. package/src/messageRepository/observers/getMessages.ts +1 -1
  26. package/src/userRepository/observers/getUsers.ts +18 -11
  27. package/src/userRepository/observers/index.ts +1 -0
  28. package/src/userRepository/observers/searchUserByDisplayName.ts +30 -0
  29. package/src/userRepository/observers/tests/getUsers.test.ts +1 -29
  30. 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,eAgHpC,CAAC"}
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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=searchUserByDisplayName.test.d.ts.map
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amityco/ts-sdk",
3
- "version": "6.3.2-aaaf497.0",
3
+ "version": "6.3.2-aafb737.0",
4
4
  "license": "CC-BY-ND-4.0",
5
5
  "author": "amity.co <developers@amity.co> (https://amity.co)",
6
6
  "description": "Amity Social Cloud Typescript SDK",
@@ -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 responder = (data: Amity.ChannelMembersLiveCollectionCache) => {
73
- let channelMembers: Amity.Membership<'channel'>[] =
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
- data: channelMembers,
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 responder = (data: Amity.CommunityMemberLiveCollectionCache) => {
74
- let communityMembers: Amity.Membership<'community'>[] =
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: [convertedCommunityUser2, convertedCommunityUser1], loading: false }),
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', { subChannelId: params.subChannelId }];
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, user.search
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 responder = (data: Amity.UserLiveCollectionCache) => {
73
- let users: Amity.User[] =
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
- data: users,
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) => {
@@ -2,3 +2,4 @@ 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';
@@ -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
+ });