@amityco/ts-sdk 0.0.1-beta.37 → 0.0.1-beta.38
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/.eslintrc.json +3 -5
- package/dist/@types/core/events.d.ts +1 -0
- package/dist/@types/core/events.d.ts.map +1 -1
- package/dist/@types/domains/category.d.ts +7 -0
- package/dist/@types/domains/category.d.ts.map +1 -1
- package/dist/@types/domains/community.d.ts +12 -0
- package/dist/@types/domains/community.d.ts.map +1 -1
- package/dist/@types/global.d.ts +5 -0
- package/dist/@types/global.d.ts.map +1 -1
- package/dist/category/api/queryCategories.d.ts +1 -5
- package/dist/category/api/queryCategories.d.ts.map +1 -1
- package/dist/category/observers/index.d.ts +2 -0
- package/dist/category/observers/index.d.ts.map +1 -0
- package/dist/category/observers/liveCategories.d.ts +18 -0
- package/dist/category/observers/liveCategories.d.ts.map +1 -0
- package/dist/category/observers/tests/liveCategories.test.d.ts +2 -0
- package/dist/category/observers/tests/liveCategories.test.d.ts.map +1 -0
- package/dist/channel/api/tests/getChannels.test.d.ts +2 -0
- package/dist/channel/api/tests/getChannels.test.d.ts.map +1 -0
- package/dist/channel/api/tests/leaveChannel.test.d.ts +2 -0
- package/dist/channel/api/tests/leaveChannel.test.d.ts.map +1 -0
- package/dist/channel/observers/liveChannel.d.ts.map +1 -1
- package/dist/client/api/accessTokenExpiryWatcher.d.ts +4 -1
- package/dist/client/api/accessTokenExpiryWatcher.d.ts.map +1 -1
- package/dist/client/api/getToken.d.ts +3 -1
- package/dist/client/api/getToken.d.ts.map +1 -1
- package/dist/client/utils/setClientToken.d.ts +3 -3
- package/dist/comment/api/deleteComment.d.ts.map +1 -1
- package/dist/comment/api/getComment.d.ts.map +1 -1
- package/dist/comment/observers/index.d.ts +1 -0
- package/dist/comment/observers/index.d.ts.map +1 -1
- package/dist/comment/observers/liveComment.d.ts +21 -0
- package/dist/comment/observers/liveComment.d.ts.map +1 -0
- package/dist/comment/observers/tests/liveComment.test.d.ts +2 -0
- package/dist/comment/observers/tests/liveComment.test.d.ts.map +1 -0
- package/dist/community/api/queryCommunities.d.ts +1 -10
- package/dist/community/api/queryCommunities.d.ts.map +1 -1
- package/dist/community/events/index.d.ts +1 -0
- package/dist/community/events/index.d.ts.map +1 -1
- package/dist/community/events/onCommunityUserChanged.d.ts +17 -0
- package/dist/community/events/onCommunityUserChanged.d.ts.map +1 -0
- package/dist/community/events/utils.d.ts +1 -0
- package/dist/community/events/utils.d.ts.map +1 -1
- package/dist/community/observers/index.d.ts +1 -0
- package/dist/community/observers/index.d.ts.map +1 -1
- package/dist/community/observers/liveCommunities.d.ts +20 -0
- package/dist/community/observers/liveCommunities.d.ts.map +1 -0
- package/dist/community/observers/tests/liveCommunities.test.d.ts +2 -0
- package/dist/community/observers/tests/liveCommunities.test.d.ts.map +1 -0
- package/dist/core/events.d.ts +3 -3
- package/dist/core/events.d.ts.map +1 -1
- package/dist/core/query/sorting.d.ts +6 -0
- package/dist/core/query/sorting.d.ts.map +1 -1
- package/dist/core/transports/http.d.ts +0 -5
- package/dist/core/transports/http.d.ts.map +1 -1
- package/dist/file/api/test/createImage.test.d.ts +2 -0
- package/dist/file/api/test/createImage.test.d.ts.map +1 -0
- package/dist/file/api/test/createVideo.test.d.ts +2 -0
- package/dist/file/api/test/createVideo.test.d.ts.map +1 -0
- package/dist/index.cjs.js +441 -195
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +436 -195
- package/dist/index.umd.js +4 -4
- package/dist/message/observers/liveMessage.d.ts.map +1 -1
- package/dist/post/observers/index.d.ts +1 -0
- package/dist/post/observers/index.d.ts.map +1 -1
- package/dist/post/observers/livePost.d.ts +21 -0
- package/dist/post/observers/livePost.d.ts.map +1 -0
- package/dist/post/observers/tests/livePost.test.d.ts +2 -0
- package/dist/post/observers/tests/livePost.test.d.ts.map +1 -0
- package/dist/subChannel/api/tests/deleteSubChannel.test.d.ts +2 -0
- package/dist/subChannel/api/tests/deleteSubChannel.test.d.ts.map +1 -0
- package/dist/subChannel/api/tests/getSubChannel.test.d.ts +2 -0
- package/dist/subChannel/api/tests/getSubChannel.test.d.ts.map +1 -0
- package/dist/subChannel/api/tests/getSubChannels.test.d.ts +2 -0
- package/dist/subChannel/api/tests/getSubChannels.test.d.ts.map +1 -0
- package/dist/subChannel/api/tests/updateSubChannel.test.d.ts +2 -0
- package/dist/subChannel/api/tests/updateSubChannel.test.d.ts.map +1 -0
- package/dist/subChannel/observers/liveSubChannel.d.ts.map +1 -1
- package/dist/user/api/tests/updateUser.test.d.ts +2 -0
- package/dist/user/api/tests/updateUser.test.d.ts.map +1 -0
- package/dist/user/observers/liveUser.d.ts.map +1 -1
- package/dist/utils/liveObject.d.ts +2 -0
- package/dist/utils/liveObject.d.ts.map +1 -0
- package/dist/utils/tests/dummy/category.d.ts +64 -0
- package/dist/utils/tests/dummy/category.d.ts.map +1 -0
- package/dist/utils/tests/dummy/channel.d.ts +50 -0
- package/dist/utils/tests/dummy/channel.d.ts.map +1 -1
- package/dist/utils/tests/dummy/community.d.ts +132 -0
- package/dist/utils/tests/dummy/community.d.ts.map +1 -1
- package/dist/utils/tests/dummy/file.d.ts +3 -0
- package/dist/utils/tests/dummy/file.d.ts.map +1 -1
- package/dist/utils/tests/dummy/index.d.ts +1 -0
- package/dist/utils/tests/dummy/index.d.ts.map +1 -1
- package/dist/utils/tests/dummy/post.d.ts +2 -0
- package/dist/utils/tests/dummy/post.d.ts.map +1 -1
- package/dist/utils/tests/dummy/subChannel.d.ts +0 -20
- package/dist/utils/tests/dummy/subChannel.d.ts.map +1 -1
- package/dist/utils/tests/dummy/user.d.ts +18 -0
- package/dist/utils/tests/dummy/user.d.ts.map +1 -1
- package/dist/utils/tests/liveObject.test.d.ts +2 -0
- package/dist/utils/tests/liveObject.test.d.ts.map +1 -0
- package/package.json +4 -4
- package/src/@types/core/events.ts +1 -0
- package/src/@types/domains/category.ts +13 -0
- package/src/@types/domains/community.ts +25 -0
- package/src/@types/global.ts +5 -0
- package/src/category/api/queryCategories.ts +3 -5
- package/src/category/observers/index.ts +1 -0
- package/src/category/observers/liveCategories.ts +141 -0
- package/src/category/observers/tests/liveCategories.test.ts +147 -0
- package/src/channel/api/tests/createChannel.test.ts +30 -6
- package/src/channel/api/tests/getChannel.test.ts +3 -1
- package/src/channel/api/tests/getChannels.test.ts +97 -0
- package/src/channel/api/tests/joinChannel.test.ts +62 -3
- package/src/channel/api/tests/leaveChannel.test.ts +90 -0
- package/src/channel/api/tests/queryChannels.test.ts +38 -1
- package/src/channel/observers/liveChannel.ts +8 -80
- package/src/client/api/accessTokenExpiryWatcher.ts +7 -5
- package/src/client/api/tests/accessTokenExpiryWatcher.test.ts +8 -5
- package/src/comment/api/deleteComment.ts +5 -5
- package/src/comment/api/getComment.ts +8 -3
- package/src/comment/observers/index.ts +1 -0
- package/src/comment/observers/liveComment.ts +43 -0
- package/src/comment/observers/tests/liveComment.test.ts +95 -0
- package/src/community/api/queryCommunities.ts +3 -10
- package/src/community/api/test/addCommunityMember.test.ts +14 -2
- package/src/community/api/test/joinCommunity.test.ts +14 -2
- package/src/community/api/test/leaveCommunity.test.ts +11 -1
- package/src/community/api/test/removeCommunityMembers.test.ts +11 -1
- package/src/community/events/index.ts +1 -0
- package/src/community/events/onCommunityUserChanged.ts +20 -0
- package/src/community/events/test/onCommunityJoined.test.ts +1 -1
- package/src/community/events/test/onCommunityUserAdded.test.ts +1 -1
- package/src/community/events/test/onCommunityUserBanned.test.ts +1 -1
- package/src/community/events/test/onCommunityUserUnbaned.test.ts +1 -1
- package/src/community/events/test/utils.test.ts +52 -3
- package/src/community/events/utils.ts +49 -0
- package/src/community/observers/index.ts +1 -0
- package/src/community/observers/liveCommunities.ts +188 -0
- package/src/community/observers/tests/liveCommunities.test.ts +284 -0
- package/src/core/query/sorting.ts +8 -0
- package/src/core/transports/http.ts +17 -13
- package/src/core/transports/test/http.test.ts +49 -60
- package/src/file/api/createFile.ts +1 -1
- package/src/file/api/createImage.ts +1 -1
- package/src/file/api/createVideo.ts +1 -1
- package/src/file/api/test/createImage.test.ts +69 -0
- package/src/file/api/test/createVideo.test.ts +81 -0
- package/src/index.ts +1 -0
- package/src/message/observers/liveMessage.ts +11 -83
- package/src/message/tests/observers/liveMessage.test.ts +1 -143
- package/src/post/observers/index.ts +1 -0
- package/src/post/observers/livePost.ts +47 -0
- package/src/post/observers/tests/livePost.test.ts +97 -0
- package/src/stream/api/tests/createStream.test.ts +3 -11
- package/src/stream/api/tests/deleteStream.test.ts +5 -3
- package/src/subChannel/api/tests/createSubChannel.test.ts +21 -14
- package/src/subChannel/api/tests/deleteSubChannel.test.ts +112 -0
- package/src/subChannel/api/tests/getSubChannel.test.ts +97 -0
- package/src/subChannel/api/tests/getSubChannels.test.ts +97 -0
- package/src/subChannel/api/tests/updateSubChannel.test.ts +86 -0
- package/src/subChannel/observers/liveSubChannel.ts +6 -56
- package/src/subChannel/observers/tests/liveSubChannel.test.ts +0 -82
- package/src/user/api/tests/updateUser.test.ts +60 -0
- package/src/user/observers/liveUser.ts +9 -61
- package/src/user/tests/observers/liveUser.test.ts +1 -154
- package/src/utils/liveObject.ts +86 -0
- package/src/utils/tests/dummy/category.ts +57 -0
- package/src/utils/tests/dummy/channel.ts +51 -1
- package/src/utils/tests/dummy/community.ts +94 -0
- package/src/utils/tests/dummy/file.ts +32 -0
- package/src/utils/tests/dummy/index.ts +1 -0
- package/src/utils/tests/dummy/post.ts +56 -45
- package/src/utils/tests/dummy/stream.ts +73 -73
- package/src/utils/tests/dummy/subChannel.ts +0 -22
- package/src/utils/tests/dummy/user.ts +21 -0
- package/src/utils/tests/liveObject.test.ts +172 -0
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { ASCApiError } from '~/core/errors';
|
|
2
1
|
import { disableCache, enableCache } from '~/cache/api';
|
|
3
2
|
import {
|
|
4
3
|
pause,
|
|
@@ -30,27 +29,6 @@ describe('liveSubChannel', () => {
|
|
|
30
29
|
|
|
31
30
|
afterEach(disableCache);
|
|
32
31
|
|
|
33
|
-
test('should get sub channel', async () => {
|
|
34
|
-
const callback = jest.fn();
|
|
35
|
-
client.http.get = jest.fn().mockResolvedValue(response);
|
|
36
|
-
|
|
37
|
-
liveSubChannel(rawSubChannel.messageFeedId, callback);
|
|
38
|
-
await pause();
|
|
39
|
-
|
|
40
|
-
expect(callback).toHaveBeenCalledTimes(2);
|
|
41
|
-
expect(callback).toHaveBeenNthCalledWith(
|
|
42
|
-
1,
|
|
43
|
-
expect.objectContaining({ data: undefined, loading: true }),
|
|
44
|
-
);
|
|
45
|
-
expect(callback).toHaveBeenNthCalledWith(
|
|
46
|
-
2,
|
|
47
|
-
expect.objectContaining({
|
|
48
|
-
data: convertFromRaw(rawSubChannel),
|
|
49
|
-
loading: false,
|
|
50
|
-
}),
|
|
51
|
-
);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
32
|
const events: [string, keyof Amity.Events][] = [
|
|
55
33
|
['should get update on message-feed.updated event', 'message-feed.updated'],
|
|
56
34
|
['should get update on message-feed.deleted event', 'message-feed.deleted'],
|
|
@@ -149,64 +127,4 @@ describe('liveSubChannel', () => {
|
|
|
149
127
|
);
|
|
150
128
|
});
|
|
151
129
|
});
|
|
152
|
-
|
|
153
|
-
test('should not get update on api failure', async () => {
|
|
154
|
-
const error = new ASCApiError(
|
|
155
|
-
'server error!',
|
|
156
|
-
Amity.ServerError.ITEM_NOT_FOUND,
|
|
157
|
-
Amity.ErrorLevel.ERROR,
|
|
158
|
-
);
|
|
159
|
-
const update = {
|
|
160
|
-
...rawSubChannel,
|
|
161
|
-
name: 'new name',
|
|
162
|
-
updatedAt: getFutureDate(rawSubChannel.updatedAt),
|
|
163
|
-
};
|
|
164
|
-
const callback = jest.fn();
|
|
165
|
-
client.http.get = jest.fn().mockRejectedValue(error);
|
|
166
|
-
|
|
167
|
-
liveSubChannel(subChannel.subChannelId, callback);
|
|
168
|
-
await pause();
|
|
169
|
-
client.emitter.emit('message-feed.updated', { messageFeeds: [update] });
|
|
170
|
-
await pause();
|
|
171
|
-
|
|
172
|
-
expect(callback).toHaveBeenCalledTimes(2);
|
|
173
|
-
expect(callback).toHaveBeenNthCalledWith(
|
|
174
|
-
2,
|
|
175
|
-
expect.objectContaining({
|
|
176
|
-
data: undefined,
|
|
177
|
-
error,
|
|
178
|
-
loading: false,
|
|
179
|
-
}),
|
|
180
|
-
);
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
test('should not call callback if liveMessage is disposed', async () => {
|
|
184
|
-
const update = {
|
|
185
|
-
...rawSubChannel,
|
|
186
|
-
name: 'new name',
|
|
187
|
-
updatedAt: getFutureDate(rawSubChannel.updatedAt),
|
|
188
|
-
};
|
|
189
|
-
const callback = jest.fn();
|
|
190
|
-
client.http.get = jest.fn().mockResolvedValue(response);
|
|
191
|
-
|
|
192
|
-
const dispose = liveSubChannel(subChannel.subChannelId, callback);
|
|
193
|
-
await pause();
|
|
194
|
-
dispose();
|
|
195
|
-
client.emitter.emit('message-feed.updated', { messageFeeds: [update] });
|
|
196
|
-
await pause();
|
|
197
|
-
|
|
198
|
-
expect(callback).toHaveBeenCalledTimes(2);
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
test('should not call callback if data is the same', async () => {
|
|
202
|
-
const callback = jest.fn();
|
|
203
|
-
client.http.get = jest.fn().mockResolvedValue(response);
|
|
204
|
-
|
|
205
|
-
liveSubChannel(subChannel.subChannelId, callback);
|
|
206
|
-
await pause();
|
|
207
|
-
client.emitter.emit('message-feed.updated', { messageFeeds: response.data.messageFeeds });
|
|
208
|
-
await pause();
|
|
209
|
-
|
|
210
|
-
expect(callback).toHaveBeenCalledTimes(2);
|
|
211
|
-
});
|
|
212
130
|
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { disableCache, enableCache, pushToCache, pullFromCache } from '~/cache/api';
|
|
2
|
+
|
|
3
|
+
import { client, userUpdateResponse } from '~/utils/tests';
|
|
4
|
+
|
|
5
|
+
import { updateUser } from '../updateUser';
|
|
6
|
+
import { onUserUpdated } from '../../events/onUserUpdated';
|
|
7
|
+
|
|
8
|
+
describe('updateUser', () => {
|
|
9
|
+
const displayName = 'updated-display-name';
|
|
10
|
+
const userId = 'test-user';
|
|
11
|
+
const avatarCustomUrl = 'updated-avatarUrl';
|
|
12
|
+
|
|
13
|
+
// integration_test_id: a1a8260f-3314-41ba-9f5f-3a96dd52453d
|
|
14
|
+
test('it should return updated user on success', async () => {
|
|
15
|
+
const { users: expected } = userUpdateResponse.data;
|
|
16
|
+
client.http.put = jest.fn().mockResolvedValue(userUpdateResponse);
|
|
17
|
+
|
|
18
|
+
const { data: received } = await updateUser(userId, { displayName, avatarCustomUrl });
|
|
19
|
+
|
|
20
|
+
expect(received).toStrictEqual(expected[0]);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// integration_test_id: 67cb7ad8-28a9-4950-a86c-35497bb5212c
|
|
24
|
+
test('it should return 400301 when updating another user', async () => {
|
|
25
|
+
client.http.put = jest.fn().mockRejectedValueOnce(new Error('400301'));
|
|
26
|
+
|
|
27
|
+
await expect(
|
|
28
|
+
updateUser('different-user', { displayName: 'updated-display-name' }),
|
|
29
|
+
).rejects.toThrow('400301');
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test('it should update cache with updated user', async () => {
|
|
33
|
+
enableCache();
|
|
34
|
+
|
|
35
|
+
const expected = userUpdateResponse.data.users[0];
|
|
36
|
+
pushToCache(['user', 'get', userId], { ...expected, displayName: 'old-displayName' });
|
|
37
|
+
|
|
38
|
+
client.http.put = jest.fn().mockResolvedValue(userUpdateResponse);
|
|
39
|
+
await updateUser(userId, { displayName, avatarCustomUrl });
|
|
40
|
+
|
|
41
|
+
const received = pullFromCache(['user', 'get', userId])?.data;
|
|
42
|
+
|
|
43
|
+
expect(received).toStrictEqual(expected);
|
|
44
|
+
disableCache();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test('it should fire event for updated user', async () => {
|
|
48
|
+
let dispose;
|
|
49
|
+
const { users: expected } = userUpdateResponse.data;
|
|
50
|
+
client.http.put = jest.fn().mockResolvedValue(userUpdateResponse);
|
|
51
|
+
|
|
52
|
+
const callbackPromise = new Promise(resolve => {
|
|
53
|
+
dispose = onUserUpdated(resolve);
|
|
54
|
+
}).finally(dispose);
|
|
55
|
+
|
|
56
|
+
await updateUser(userId, { displayName, avatarCustomUrl });
|
|
57
|
+
|
|
58
|
+
await expect(callbackPromise).resolves.toEqual(expect.objectContaining(expected[0]));
|
|
59
|
+
});
|
|
60
|
+
});
|
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { createQuery, runQuery } from '~/core/query';
|
|
3
|
-
|
|
4
|
-
import { LIVE_OBJECT_ENABLE_CACHE_MESSAGE } from '~/utils/constants';
|
|
5
|
-
|
|
6
|
-
import { hasUpdates } from '~/core/model';
|
|
1
|
+
import { liveObject } from '~/utils/liveObject';
|
|
7
2
|
import {
|
|
8
3
|
onUserDeleted,
|
|
9
4
|
onUserUpdated,
|
|
@@ -37,59 +32,12 @@ export const liveUser = (
|
|
|
37
32
|
userId: Amity.User['userId'],
|
|
38
33
|
callback: Amity.LiveObjectCallback<Amity.User>,
|
|
39
34
|
): Amity.Unsubscriber => {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
let user: Amity.User;
|
|
49
|
-
const disposers: Amity.Unsubscriber[] = [];
|
|
50
|
-
|
|
51
|
-
const dispatcher = (data: Amity.LiveObject<Amity.User>) => {
|
|
52
|
-
user = data.data;
|
|
53
|
-
callback(data);
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
const realtimeRouter = (eventUser: Amity.User) => {
|
|
57
|
-
if (userId !== eventUser.userId) {
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (user && !hasUpdates(user, eventUser)) {
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
dispatcher({ loading: false, data: eventUser, origin: 'event' });
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
const onFetch = () => {
|
|
69
|
-
const query = createQuery(getUser, userId, true);
|
|
70
|
-
|
|
71
|
-
runQuery(query, ({ loading, data, error, origin }) => {
|
|
72
|
-
dispatcher({ loading, data, origin, error });
|
|
73
|
-
|
|
74
|
-
if (error) {
|
|
75
|
-
disposers.forEach(fn => fn());
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
disposers.push(
|
|
81
|
-
onUserFetched(realtimeRouter),
|
|
82
|
-
onUserUpdated(realtimeRouter),
|
|
83
|
-
onUserDeleted(realtimeRouter),
|
|
84
|
-
onUserFlagged(realtimeRouter),
|
|
85
|
-
onUserUnflagged(realtimeRouter),
|
|
86
|
-
onUserFlagCleared(realtimeRouter),
|
|
87
|
-
);
|
|
88
|
-
|
|
89
|
-
onFetch();
|
|
90
|
-
|
|
91
|
-
return () => {
|
|
92
|
-
log(`liveUser(tmpid: ${timestamp}) > dispose`);
|
|
93
|
-
disposers.forEach(fn => fn());
|
|
94
|
-
};
|
|
35
|
+
return liveObject(userId, callback, 'userId', getUser, [
|
|
36
|
+
onUserFetched,
|
|
37
|
+
onUserUpdated,
|
|
38
|
+
onUserDeleted,
|
|
39
|
+
onUserFlagged,
|
|
40
|
+
onUserUnflagged,
|
|
41
|
+
onUserFlagCleared,
|
|
42
|
+
]);
|
|
95
43
|
};
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { ASCApiError } from '~/core/errors';
|
|
2
1
|
import { disableCache, enableCache } from '~/cache/api';
|
|
3
|
-
import { LIVE_OBJECT_ENABLE_CACHE_MESSAGE } from '~/utils/constants';
|
|
4
2
|
import {
|
|
5
3
|
client,
|
|
6
4
|
connectClient,
|
|
@@ -29,161 +27,10 @@ describe('liveUser', () => {
|
|
|
29
27
|
await disconnectClient();
|
|
30
28
|
});
|
|
31
29
|
|
|
32
|
-
beforeEach(
|
|
33
|
-
enableCache();
|
|
34
|
-
});
|
|
30
|
+
beforeEach(enableCache);
|
|
35
31
|
|
|
36
32
|
afterEach(disableCache);
|
|
37
33
|
|
|
38
|
-
test('it should show user if cache not enabled', () => {
|
|
39
|
-
/*
|
|
40
|
-
* NOTE: at the time of writing this test cache is diabled by default, but
|
|
41
|
-
* there is a proposal to enable cache by default. So I'm disabling cache
|
|
42
|
-
* here to ensure cache is disabled
|
|
43
|
-
*/
|
|
44
|
-
disableCache();
|
|
45
|
-
|
|
46
|
-
const callback = jest.fn();
|
|
47
|
-
jest.spyOn(global.console, 'log');
|
|
48
|
-
client.http.get = jest.fn();
|
|
49
|
-
|
|
50
|
-
// call liveUser check if mocked console get's called with the correct
|
|
51
|
-
// user
|
|
52
|
-
client.use();
|
|
53
|
-
liveUser(defaultUser.userId, callback);
|
|
54
|
-
|
|
55
|
-
expect(console.log).toBeCalledWith(LIVE_OBJECT_ENABLE_CACHE_MESSAGE);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
test('it should return user live object', async () => {
|
|
59
|
-
const snapshot = getSnapshot();
|
|
60
|
-
|
|
61
|
-
// mock response of queryUsers and validate
|
|
62
|
-
const callback = jest.fn();
|
|
63
|
-
client.http.get = jest.fn().mockResolvedValue(userQueryResponse);
|
|
64
|
-
|
|
65
|
-
liveUser(defaultUser.userId, callback);
|
|
66
|
-
|
|
67
|
-
expect(callback).toHaveBeenCalledTimes(1);
|
|
68
|
-
|
|
69
|
-
// check if cache data returned (should be empty)
|
|
70
|
-
expect(callback).toHaveBeenCalledWith(expect.objectContaining(snapshot));
|
|
71
|
-
|
|
72
|
-
await pause();
|
|
73
|
-
|
|
74
|
-
expect(callback).toHaveBeenCalledTimes(2);
|
|
75
|
-
|
|
76
|
-
snapshot.loading = false;
|
|
77
|
-
snapshot.data = defaultUser;
|
|
78
|
-
|
|
79
|
-
expect(callback).toHaveBeenCalledWith(expect.objectContaining(snapshot));
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
test('it should return error on api failure', async () => {
|
|
83
|
-
const snapshot = getSnapshot();
|
|
84
|
-
const error = new ASCApiError(
|
|
85
|
-
'server error!',
|
|
86
|
-
Amity.ServerError.ITEM_NOT_FOUND,
|
|
87
|
-
Amity.ErrorLevel.ERROR,
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
// mock response of queryUsers and validate
|
|
91
|
-
const callback = jest.fn();
|
|
92
|
-
client.http.get = jest.fn().mockRejectedValue(error);
|
|
93
|
-
|
|
94
|
-
liveUser(defaultUser.userId, callback);
|
|
95
|
-
|
|
96
|
-
expect(callback).toHaveBeenCalledTimes(1);
|
|
97
|
-
|
|
98
|
-
// check if cache data returned (should be empty)
|
|
99
|
-
expect(callback).toHaveBeenCalledWith(expect.objectContaining(snapshot));
|
|
100
|
-
|
|
101
|
-
await pause();
|
|
102
|
-
|
|
103
|
-
expect(callback).toHaveBeenCalledTimes(2);
|
|
104
|
-
|
|
105
|
-
snapshot.error = error;
|
|
106
|
-
snapshot.loading = false;
|
|
107
|
-
expect(callback).toHaveBeenLastCalledWith(expect.objectContaining(snapshot));
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
test('it should terminate updates on api failure', async () => {
|
|
111
|
-
const snapshot = getSnapshot();
|
|
112
|
-
const error = new ASCApiError(
|
|
113
|
-
'server error!',
|
|
114
|
-
Amity.ServerError.ITEM_NOT_FOUND,
|
|
115
|
-
Amity.ErrorLevel.ERROR,
|
|
116
|
-
);
|
|
117
|
-
|
|
118
|
-
// mock response of queryUsers and validate
|
|
119
|
-
const callback = jest.fn();
|
|
120
|
-
client.http.get = jest.fn().mockRejectedValue(error);
|
|
121
|
-
|
|
122
|
-
liveUser(defaultUser.userId, callback);
|
|
123
|
-
|
|
124
|
-
expect(callback).toHaveBeenCalledTimes(1);
|
|
125
|
-
|
|
126
|
-
// check if cache data returned (should be empty)
|
|
127
|
-
expect(callback).toHaveBeenCalledWith(expect.objectContaining(snapshot));
|
|
128
|
-
|
|
129
|
-
await pause();
|
|
130
|
-
|
|
131
|
-
expect(callback).toHaveBeenCalledTimes(2);
|
|
132
|
-
|
|
133
|
-
snapshot.error = error;
|
|
134
|
-
snapshot.loading = false;
|
|
135
|
-
expect(callback).toHaveBeenLastCalledWith(expect.objectContaining(snapshot));
|
|
136
|
-
|
|
137
|
-
const updatedAt = new Date(defaultUser?.updatedAt ?? new Date());
|
|
138
|
-
updatedAt.setDate(updatedAt.getDate() + 7);
|
|
139
|
-
|
|
140
|
-
const updatedUser = {
|
|
141
|
-
...defaultUser,
|
|
142
|
-
updatedAt: updatedAt.toISOString(),
|
|
143
|
-
};
|
|
144
|
-
client.emitter.emit('user.updated', { users: [updatedUser], files: [] });
|
|
145
|
-
|
|
146
|
-
delete snapshot.error;
|
|
147
|
-
snapshot.loading = false;
|
|
148
|
-
snapshot.data = updatedUser;
|
|
149
|
-
expect(callback).not.toHaveBeenNthCalledWith(3, expect.objectContaining(snapshot));
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
test('it should not return updates on obtain once!', async () => {
|
|
153
|
-
const snapshot = getSnapshot();
|
|
154
|
-
|
|
155
|
-
// mock response of queryUsers and validate
|
|
156
|
-
const callback = jest.fn();
|
|
157
|
-
client.http.get = jest.fn().mockResolvedValue(userQueryResponse);
|
|
158
|
-
|
|
159
|
-
const unsub = liveUser(defaultUser.userId, callback);
|
|
160
|
-
|
|
161
|
-
expect(callback).toHaveBeenCalledTimes(1);
|
|
162
|
-
|
|
163
|
-
// check if cache data returned (should be empty)
|
|
164
|
-
expect(callback).toHaveBeenCalledWith(expect.objectContaining(snapshot));
|
|
165
|
-
|
|
166
|
-
await pause();
|
|
167
|
-
|
|
168
|
-
expect(callback).toHaveBeenCalledTimes(2);
|
|
169
|
-
|
|
170
|
-
unsub();
|
|
171
|
-
|
|
172
|
-
const updatedAt = new Date(defaultUser?.updatedAt ?? new Date());
|
|
173
|
-
updatedAt.setDate(updatedAt.getDate() + 7);
|
|
174
|
-
|
|
175
|
-
const updatedUser = {
|
|
176
|
-
...defaultUser,
|
|
177
|
-
updatedAt: updatedAt.toISOString(),
|
|
178
|
-
};
|
|
179
|
-
client.emitter.emit('user.updated', { users: [updatedUser], files: [] });
|
|
180
|
-
|
|
181
|
-
delete snapshot.error;
|
|
182
|
-
snapshot.loading = false;
|
|
183
|
-
snapshot.data = updatedUser;
|
|
184
|
-
expect(callback).not.toHaveBeenNthCalledWith(3, expect.objectContaining(snapshot));
|
|
185
|
-
});
|
|
186
|
-
|
|
187
34
|
const events: [string, keyof Amity.Events][] = [
|
|
188
35
|
['it should return updated user on onFetch', 'user.fetched'],
|
|
189
36
|
['it should return updated user on onUpdate', 'user.updated'],
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { getActiveClient } from '~/client/api';
|
|
2
|
+
import {
|
|
3
|
+
LIVE_OBJECT_ENABLE_CACHE_MESSAGE,
|
|
4
|
+
UNSYNCED_OBJECT_CACHED_AT_MESSAGE,
|
|
5
|
+
UNSYNCED_OBJECT_CACHED_AT_VALUE,
|
|
6
|
+
} from '~/utils/constants';
|
|
7
|
+
import { hasUpdates } from '~/core/model';
|
|
8
|
+
import { createQuery, runQuery } from '~/core/query';
|
|
9
|
+
import { ASCApiError } from '~/core/errors';
|
|
10
|
+
|
|
11
|
+
export const liveObject = <
|
|
12
|
+
T extends Exclude<Amity.Model[Amity.Domain], Amity.Reaction | Amity.FollowCount>,
|
|
13
|
+
K extends keyof T,
|
|
14
|
+
>(
|
|
15
|
+
id: T[K],
|
|
16
|
+
callback: Amity.LiveObjectCallback<T>,
|
|
17
|
+
key: K,
|
|
18
|
+
fetcher: (id: T[K]) => Promise<Amity.Cached<T>>,
|
|
19
|
+
eventHandlers: Array<(callback: Amity.Listener<T>) => Amity.Unsubscriber>,
|
|
20
|
+
): Amity.Unsubscriber => {
|
|
21
|
+
const { cache } = getActiveClient();
|
|
22
|
+
|
|
23
|
+
if (!cache) {
|
|
24
|
+
console.log(LIVE_OBJECT_ENABLE_CACHE_MESSAGE);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let model: T;
|
|
28
|
+
let isUnsyncedModel = false; // for messages
|
|
29
|
+
const disposers: Amity.Unsubscriber[] = [];
|
|
30
|
+
|
|
31
|
+
const dispatcher = (data: Amity.LiveObject<T>) => {
|
|
32
|
+
model = data.data;
|
|
33
|
+
callback(data);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const realtimeRouter = (eventModel: T) => {
|
|
37
|
+
if (id !== eventModel[key]) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (model && !hasUpdates(model, eventModel)) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
dispatcher({ loading: false, data: eventModel, origin: 'event' });
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const onFetch = () => {
|
|
49
|
+
// @ts-ignore
|
|
50
|
+
const query = createQuery(fetcher, id, true);
|
|
51
|
+
|
|
52
|
+
runQuery(query, ({ error, data, loading, origin, cachedAt }) => {
|
|
53
|
+
if (cachedAt === UNSYNCED_OBJECT_CACHED_AT_VALUE) {
|
|
54
|
+
dispatcher({
|
|
55
|
+
// @ts-ignore
|
|
56
|
+
data,
|
|
57
|
+
origin,
|
|
58
|
+
loading: false,
|
|
59
|
+
error: new ASCApiError(
|
|
60
|
+
UNSYNCED_OBJECT_CACHED_AT_MESSAGE,
|
|
61
|
+
Amity.ClientError.DISALOOW_UNSYNCED_OBJECT,
|
|
62
|
+
Amity.ErrorLevel.ERROR,
|
|
63
|
+
),
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
isUnsyncedModel = true;
|
|
67
|
+
disposers.forEach(fn => fn());
|
|
68
|
+
} else if (!isUnsyncedModel) {
|
|
69
|
+
// @ts-ignore
|
|
70
|
+
dispatcher({ loading, data, origin, error });
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (error) {
|
|
74
|
+
disposers.forEach(fn => fn());
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
disposers.push(...eventHandlers.map(fn => fn(realtimeRouter)));
|
|
80
|
+
|
|
81
|
+
onFetch();
|
|
82
|
+
|
|
83
|
+
return () => {
|
|
84
|
+
disposers.forEach(fn => fn());
|
|
85
|
+
};
|
|
86
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export const category11 = {
|
|
2
|
+
name: 'a-hello',
|
|
3
|
+
updatedAt: '2022-11-25T04:19:34.446Z',
|
|
4
|
+
createdAt: '2022-11-25T04:19:34.446Z',
|
|
5
|
+
isDeleted: false,
|
|
6
|
+
categoryId: '2ddea5ad242d0a2bd5dc5be8ae9fc8c2',
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const category12 = {
|
|
10
|
+
name: 'b-testing-category',
|
|
11
|
+
updatedAt: '2022-11-25T03:56:06.238Z',
|
|
12
|
+
createdAt: '2022-11-25T03:56:06.238Z',
|
|
13
|
+
isDeleted: false,
|
|
14
|
+
categoryId: '88d175da65cbfeb39b81e722b322430e',
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const category13 = {
|
|
18
|
+
name: 'c-deleted-category',
|
|
19
|
+
updatedAt: '2022-11-25T03:56:06.238Z',
|
|
20
|
+
createdAt: '2022-11-25T03:56:06.238Z',
|
|
21
|
+
isDeleted: true,
|
|
22
|
+
categoryId: '88d175da65cbfeb39b81e722b322430d',
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const category21 = {
|
|
26
|
+
name: 'a-0asd',
|
|
27
|
+
updatedAt: '2022-11-25T04:18:59.180Z',
|
|
28
|
+
createdAt: '2022-11-25T04:18:59.180Z',
|
|
29
|
+
isDeleted: false,
|
|
30
|
+
categoryId: '10051d82a1f371c6be3a8f4a4654b8a1',
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const category22 = {
|
|
34
|
+
name: 'b-A Category',
|
|
35
|
+
updatedAt: '2022-11-25T03:56:29.037Z',
|
|
36
|
+
createdAt: '2022-11-25T03:56:29.037Z',
|
|
37
|
+
isDeleted: false,
|
|
38
|
+
categoryId: '639942c6b2f121bed3901cf4a4c296e7',
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const categoryQueryResponse = {
|
|
42
|
+
data: {
|
|
43
|
+
categories: [category11, category12, category13],
|
|
44
|
+
paging: {
|
|
45
|
+
next: 'eyJza2lwIjoxMCwibGltaXQiOjEwfQ==',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const categoryQueryResponsePage2 = {
|
|
51
|
+
data: {
|
|
52
|
+
categories: [category21, category22],
|
|
53
|
+
paging: {
|
|
54
|
+
next: 'eyJza2lwIjoxMCwibGltaXQiOjEwfQ==',
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
};
|
|
@@ -54,7 +54,13 @@ export const mockPage = {
|
|
|
54
54
|
},
|
|
55
55
|
};
|
|
56
56
|
|
|
57
|
-
export const channelRaw1: Amity.ChannelRaw = generateRawChannel();
|
|
57
|
+
export const channelRaw1: Amity.ChannelRaw = generateRawChannel({ type: 'community' });
|
|
58
|
+
|
|
59
|
+
export const channelRawLive1: Amity.ChannelRaw = generateRawChannel({ type: 'live' });
|
|
60
|
+
|
|
61
|
+
export const channelRawConversation1: Amity.ChannelRaw = generateRawChannel({
|
|
62
|
+
type: 'conversation',
|
|
63
|
+
});
|
|
58
64
|
|
|
59
65
|
export const channelRaw2: Amity.ChannelRaw = generateRawChannel({
|
|
60
66
|
channelId: 'channelId12',
|
|
@@ -132,6 +138,16 @@ export const channelQueryResponse = {
|
|
|
132
138
|
},
|
|
133
139
|
};
|
|
134
140
|
|
|
141
|
+
export const getChannelsResponse = {
|
|
142
|
+
data: {
|
|
143
|
+
channels: [channelRaw1, channelRaw2, channelRaw3],
|
|
144
|
+
channelUsers: [],
|
|
145
|
+
files: [],
|
|
146
|
+
users: [],
|
|
147
|
+
...mockPage,
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
|
|
135
151
|
export const channelQueryResponsePage2 = {
|
|
136
152
|
data: {
|
|
137
153
|
channels: [channelRaw3],
|
|
@@ -142,6 +158,26 @@ export const channelQueryResponsePage2 = {
|
|
|
142
158
|
},
|
|
143
159
|
};
|
|
144
160
|
|
|
161
|
+
export const channelTagQueryResponse = {
|
|
162
|
+
data: {
|
|
163
|
+
channels: [channelRaw2],
|
|
164
|
+
channelUsers: [],
|
|
165
|
+
files: [],
|
|
166
|
+
users: [],
|
|
167
|
+
...mockPage,
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
export const channelExcludeTagQueryResponse = {
|
|
172
|
+
data: {
|
|
173
|
+
channels: [channelRaw1, channelRaw3],
|
|
174
|
+
channelUsers: [],
|
|
175
|
+
files: [],
|
|
176
|
+
users: [],
|
|
177
|
+
...mockPage,
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
|
|
145
181
|
export const channelUserQueryResponse = {
|
|
146
182
|
data: {
|
|
147
183
|
channels: [channelRaw1],
|
|
@@ -191,3 +227,17 @@ export const channelPayload = {
|
|
|
191
227
|
users: [user14, user11],
|
|
192
228
|
files: [file11],
|
|
193
229
|
};
|
|
230
|
+
|
|
231
|
+
export const liveChannelPayload = {
|
|
232
|
+
channels: [channelRawLive1],
|
|
233
|
+
channelUsers: [rawChannelUserWithRole, rawMutedChannelUser],
|
|
234
|
+
users: [user14, user11],
|
|
235
|
+
files: [file11],
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
export const conversationChannelPayload = {
|
|
239
|
+
channels: [channelRawConversation1],
|
|
240
|
+
channelUsers: [rawChannelUserWithRole, rawMutedChannelUser],
|
|
241
|
+
users: [user14, user11],
|
|
242
|
+
files: [file11],
|
|
243
|
+
};
|