@amityco/ts-sdk 0.0.1-beta.31 → 0.0.1-beta.32
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/cache/api/backupCache.d.ts.map +1 -1
- package/dist/cache/api/tests/pushToCache.test.d.ts +2 -0
- package/dist/cache/api/tests/pushToCache.test.d.ts.map +1 -0
- package/dist/channel/api/addChannelMembers.d.ts.map +1 -1
- package/dist/channel/api/getChannel.d.ts.map +1 -1
- package/dist/channel/api/tests/addChannelMembers.test.d.ts +2 -0
- package/dist/channel/api/tests/addChannelMembers.test.d.ts.map +1 -0
- package/dist/channel/api/tests/getChannel.test.d.ts +2 -0
- package/dist/channel/api/tests/getChannel.test.d.ts.map +1 -0
- package/dist/channel/events/onChannelMemberAdded.d.ts.map +1 -1
- package/dist/core/events.d.ts +1 -1
- package/dist/core/events.d.ts.map +1 -1
- package/dist/core/transports/http.d.ts +5 -0
- package/dist/core/transports/http.d.ts.map +1 -1
- package/dist/core/transports/test/http.test.d.ts +2 -0
- package/dist/core/transports/test/http.test.d.ts.map +1 -0
- package/dist/index.cjs.js +35 -45
- package/dist/index.esm.js +34 -45
- package/dist/index.umd.js +4 -4
- package/dist/message/api/deleteMessage.d.ts.map +1 -1
- package/dist/message/api/tests/deleteMessage.test.d.ts +2 -0
- package/dist/message/api/tests/deleteMessage.test.d.ts.map +1 -0
- package/dist/message/{tests/api → api/tests}/getMessage.test.d.ts +0 -0
- package/dist/message/api/tests/getMessage.test.d.ts.map +1 -0
- package/dist/message/api/tests/getMessages.test.d.ts +2 -0
- package/dist/message/api/tests/getMessages.test.d.ts.map +1 -0
- package/dist/message/api/tests/queryMessages.test.d.ts +2 -0
- package/dist/message/api/tests/queryMessages.test.d.ts.map +1 -0
- package/dist/message/api/tests/updateMessage.test.d.ts +2 -0
- package/dist/message/api/tests/updateMessage.test.d.ts.map +1 -0
- package/dist/reaction/api/addReaction.d.ts.map +1 -1
- package/dist/reaction/api/removeReaction.d.ts.map +1 -1
- package/dist/reaction/api/tests/addReaction.test.d.ts +2 -0
- package/dist/reaction/api/tests/addReaction.test.d.ts.map +1 -0
- package/dist/reaction/api/tests/removeReaction.test.d.ts +2 -0
- package/dist/reaction/api/tests/removeReaction.test.d.ts.map +1 -0
- package/dist/user/api/getUser.d.ts.map +1 -1
- package/dist/user/api/queryUsers.d.ts.map +1 -1
- package/dist/user/api/tests/queryUsers.test.d.ts +2 -0
- package/dist/user/api/tests/queryUsers.test.d.ts.map +1 -0
- package/dist/utils/tests/dummy/post.d.ts +12 -1
- package/dist/utils/tests/dummy/post.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/cache/api/backupCache.ts +0 -1
- package/src/cache/api/tests/pushToCache.test.ts +57 -0
- package/src/channel/api/addChannelMembers.ts +9 -1
- package/src/channel/api/getChannel.ts +20 -5
- package/src/channel/api/tests/addChannelMembers.test.ts +95 -0
- package/src/channel/api/tests/getChannel.test.ts +108 -0
- package/src/channel/api/tests/queryChannels.test.ts +20 -0
- package/src/channel/events/onChannelMemberAdded.ts +1 -1
- package/src/channel/observers/tests/liveChannels.test.ts +0 -1
- package/src/core/events.ts +1 -1
- package/src/core/transports/http.ts +3 -17
- package/src/core/transports/test/http.test.ts +83 -0
- package/src/message/api/deleteMessage.ts +2 -3
- package/src/message/api/tests/createMessage.test.ts +74 -51
- package/src/message/api/tests/deleteMessage.test.ts +110 -0
- package/src/message/api/tests/getMessage.test.ts +121 -0
- package/src/message/api/tests/getMessages.test.ts +108 -0
- package/src/message/api/tests/queryMessages.test.ts +115 -0
- package/src/message/api/tests/updateMessage.test.ts +100 -0
- package/src/post/tests/api/queryPosts.test.ts +117 -18
- package/src/reaction/api/addReaction.ts +1 -4
- package/src/reaction/api/removeReaction.ts +1 -4
- package/src/reaction/api/tests/addReaction.test.ts +37 -0
- package/src/reaction/api/tests/removeReaction.test.ts +43 -0
- package/src/user/api/getUser.ts +1 -2
- package/src/user/api/queryUsers.ts +24 -5
- package/src/user/api/tests/queryUsers.test.ts +124 -0
- package/src/utils/tests/dummy/post.ts +26 -3
- package/src/utils/tests/dummy/user.ts +1 -1
- package/dist/message/tests/api/getMessage.test.d.ts.map +0 -1
- package/src/message/tests/api/getMessage.test.ts +0 -96
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { disableCache, enableCache, pullFromCache, pushToCache } from '~/cache/api';
|
|
2
|
+
import { client, message11 } from '~/utils/tests';
|
|
3
|
+
|
|
4
|
+
import { updateMessage } from '../updateMessage';
|
|
5
|
+
import { onMessageUpdated } from '../../events';
|
|
6
|
+
|
|
7
|
+
const messageToUpdate = message11;
|
|
8
|
+
const { messageId } = messageToUpdate;
|
|
9
|
+
const patch = { data: { text: 'hello world' } };
|
|
10
|
+
const updatedMessage = { ...messageToUpdate, ...patch };
|
|
11
|
+
const { updatedAt, ...updatedMessageWithoutTS } = updatedMessage;
|
|
12
|
+
|
|
13
|
+
const getResolvedMessageValue = () => ({
|
|
14
|
+
data: {
|
|
15
|
+
messages: [updatedMessage],
|
|
16
|
+
users: [],
|
|
17
|
+
files: [],
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe('updateMessage', () => {
|
|
22
|
+
test('should return updated message', async () => {
|
|
23
|
+
client.http.put = jest.fn().mockResolvedValueOnce(getResolvedMessageValue());
|
|
24
|
+
|
|
25
|
+
const recieved = updateMessage(messageId, patch);
|
|
26
|
+
|
|
27
|
+
await expect(recieved).resolves.toEqual(
|
|
28
|
+
expect.objectContaining({ data: updatedMessageWithoutTS }),
|
|
29
|
+
);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test('should throw an error if request fails', async () => {
|
|
33
|
+
client.http.put = jest.fn().mockRejectedValueOnce(new Error('error'));
|
|
34
|
+
|
|
35
|
+
await expect(updateMessage(messageId, patch)).rejects.toThrow('error');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test('should update cache after updated messages', async () => {
|
|
39
|
+
enableCache();
|
|
40
|
+
client.http.put = jest.fn().mockResolvedValueOnce(getResolvedMessageValue());
|
|
41
|
+
|
|
42
|
+
await updateMessage(messageId, patch);
|
|
43
|
+
const recieved = pullFromCache<Amity.Message>(['message', 'get', messageId])?.data;
|
|
44
|
+
|
|
45
|
+
expect(recieved).toEqual(expect.objectContaining(patch));
|
|
46
|
+
|
|
47
|
+
disableCache();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('should fire event `onMessageUpdated`', async () => {
|
|
51
|
+
let dispose;
|
|
52
|
+
client.http.put = jest.fn().mockResolvedValueOnce(getResolvedMessageValue());
|
|
53
|
+
|
|
54
|
+
const callbackPromise = new Promise(resolve => {
|
|
55
|
+
dispose = onMessageUpdated(resolve);
|
|
56
|
+
}).finally(dispose);
|
|
57
|
+
|
|
58
|
+
await updateMessage(messageId, patch);
|
|
59
|
+
|
|
60
|
+
await expect(callbackPromise).resolves.toEqual(
|
|
61
|
+
expect.objectContaining(updatedMessageWithoutTS),
|
|
62
|
+
);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
describe('updateMessage.optimistically', () => {
|
|
67
|
+
beforeEach(() => enableCache());
|
|
68
|
+
afterEach(() => disableCache());
|
|
69
|
+
|
|
70
|
+
test('should update cache after updated message', () => {
|
|
71
|
+
pushToCache(['message', 'get', messageId], messageToUpdate);
|
|
72
|
+
|
|
73
|
+
updateMessage.optimistically(messageId, patch);
|
|
74
|
+
const recieved = pullFromCache<Amity.Message>(['message', 'get', messageId])?.data;
|
|
75
|
+
|
|
76
|
+
expect(recieved).toEqual(expect.objectContaining(patch));
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test('should fire event `onMessageUpdated`', async () => {
|
|
80
|
+
let dispose;
|
|
81
|
+
|
|
82
|
+
const callbackPromise = new Promise(resolve => {
|
|
83
|
+
dispose = onMessageUpdated(data => {
|
|
84
|
+
resolve(data);
|
|
85
|
+
});
|
|
86
|
+
}).finally(dispose);
|
|
87
|
+
|
|
88
|
+
updateMessage.optimistically(messageId, patch);
|
|
89
|
+
|
|
90
|
+
await expect(callbackPromise).resolves.toEqual(
|
|
91
|
+
expect.objectContaining(updatedMessageWithoutTS),
|
|
92
|
+
);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
test('should define object as unsynced object', () => {
|
|
96
|
+
pushToCache(['message', 'get', messageId], messageToUpdate);
|
|
97
|
+
|
|
98
|
+
expect(updateMessage.optimistically(messageId, patch)?.cachedAt).toBe(-1);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
@@ -1,23 +1,122 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
import { getResolver } from '~/core/model';
|
|
2
|
+
|
|
3
|
+
import { disableCache, enableCache, pushToCache } from '~/cache/api';
|
|
4
|
+
import { ingestInCache } from '~/cache/api/ingestInCache';
|
|
5
|
+
|
|
6
|
+
import { client, postQueryResponse } from '~/utils/tests';
|
|
7
|
+
|
|
8
|
+
import { queryPosts } from '../../api/queryPosts';
|
|
9
|
+
|
|
10
|
+
const params = { targetType: 'user', targetId: 'test' } as Amity.QueryPosts;
|
|
11
|
+
|
|
12
|
+
describe('queryPosts', () => {
|
|
13
|
+
test('it should return posts', async () => {
|
|
14
|
+
const { posts: expected } = postQueryResponse.data;
|
|
15
|
+
client.http.get = jest.fn().mockResolvedValue(postQueryResponse);
|
|
16
|
+
|
|
17
|
+
const { data } = await queryPosts(params);
|
|
18
|
+
|
|
19
|
+
expect(data).toEqual(expected);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test('it should throw error', async () => {
|
|
23
|
+
client.http.get = jest.fn().mockRejectedValueOnce(new Error('error'));
|
|
24
|
+
|
|
25
|
+
await expect(queryPosts(params)).rejects.toThrow('error');
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('it should update cache upon fetching data from server', async () => {
|
|
29
|
+
enableCache();
|
|
30
|
+
|
|
31
|
+
client.http.get = jest.fn().mockResolvedValue(postQueryResponse);
|
|
32
|
+
|
|
33
|
+
const { data: expected } = await queryPosts(params);
|
|
34
|
+
const { data: received } = queryPosts.locally(params)!;
|
|
35
|
+
|
|
36
|
+
expect(received).toBeDefined();
|
|
37
|
+
expect(received).toEqual(expected);
|
|
38
|
+
|
|
39
|
+
disableCache();
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
describe('queryPosts.locally', () => {
|
|
44
|
+
const cacheKey = ['post', 'query', { ...params, options: { limit: 10 } } as Amity.Serializable];
|
|
45
|
+
|
|
46
|
+
test('it should fetch query locally if present in cache', () => {
|
|
47
|
+
enableCache();
|
|
48
|
+
|
|
49
|
+
const { data } = postQueryResponse;
|
|
50
|
+
const { posts: expected, paging } = data;
|
|
51
|
+
|
|
52
|
+
ingestInCache(data as Amity.PostPayload);
|
|
53
|
+
|
|
54
|
+
pushToCache(cacheKey, { posts: expected.map(getResolver('post')), paging });
|
|
14
55
|
|
|
15
|
-
const data =
|
|
16
|
-
|
|
17
|
-
|
|
56
|
+
const { data: received } = queryPosts.locally(params)!;
|
|
57
|
+
|
|
58
|
+
expect(received).toBeDefined();
|
|
59
|
+
expect(received).toEqual(expected);
|
|
60
|
+
|
|
61
|
+
disableCache();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test('it should return undefined if only partial data in cache', () => {
|
|
65
|
+
enableCache();
|
|
66
|
+
|
|
67
|
+
const { data } = postQueryResponse;
|
|
68
|
+
const { posts, paging } = data;
|
|
69
|
+
|
|
70
|
+
// ingest incomplete data
|
|
71
|
+
ingestInCache({
|
|
72
|
+
...data,
|
|
73
|
+
posts: [data.posts[0]],
|
|
74
|
+
} as Amity.PostPayload);
|
|
75
|
+
|
|
76
|
+
pushToCache(cacheKey, {
|
|
77
|
+
posts: posts.map(getResolver('post')),
|
|
78
|
+
paging,
|
|
18
79
|
});
|
|
19
80
|
|
|
20
|
-
|
|
21
|
-
|
|
81
|
+
const received = queryPosts.locally(params)!;
|
|
82
|
+
|
|
83
|
+
expect(received).toBeUndefined();
|
|
84
|
+
|
|
85
|
+
disableCache();
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// added because of comment above cache key in queryPosts
|
|
89
|
+
test('it should return undefined if params do not match', () => {
|
|
90
|
+
enableCache();
|
|
91
|
+
|
|
92
|
+
const { data } = postQueryResponse;
|
|
93
|
+
const { posts: expected, paging } = data;
|
|
94
|
+
|
|
95
|
+
ingestInCache(data as Amity.PostPayload);
|
|
96
|
+
|
|
97
|
+
pushToCache(cacheKey, { posts: expected.map(getResolver('post')), paging });
|
|
98
|
+
|
|
99
|
+
const { data: received } = queryPosts.locally(params)!;
|
|
100
|
+
const received2 = queryPosts.locally({ ...params, tags: ['tag1'] })!;
|
|
101
|
+
|
|
102
|
+
expect(received).toBeDefined();
|
|
103
|
+
expect(received).toEqual(expected);
|
|
104
|
+
expect(received2).toBeUndefined();
|
|
105
|
+
|
|
106
|
+
disableCache();
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test('it should return undefined if data not in cache', () => {
|
|
110
|
+
enableCache();
|
|
111
|
+
|
|
112
|
+
const received = queryPosts.locally(params);
|
|
113
|
+
|
|
114
|
+
expect(received).toBeUndefined();
|
|
115
|
+
|
|
116
|
+
disableCache();
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test('it should return undefined if cache disabled', () => {
|
|
120
|
+
expect(queryPosts.locally(params)).toBeUndefined();
|
|
22
121
|
});
|
|
23
122
|
});
|
|
@@ -38,10 +38,7 @@ export const addReaction = async (
|
|
|
38
38
|
reactionName,
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
dispatchReactable(referenceType, model.data);
|
|
43
|
-
|
|
44
|
-
return model.data.myReactions?.includes(reactionName) ?? false;
|
|
41
|
+
return true;
|
|
45
42
|
};
|
|
46
43
|
|
|
47
44
|
/**
|
|
@@ -36,10 +36,7 @@ export const removeReaction = async (
|
|
|
36
36
|
data: { referenceId, referenceType, reactionName },
|
|
37
37
|
});
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
dispatchReactable(referenceType, model.data);
|
|
41
|
-
|
|
42
|
-
return !model.data.myReactions?.includes(reactionName) ?? false;
|
|
39
|
+
return true;
|
|
43
40
|
};
|
|
44
41
|
|
|
45
42
|
/**
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { disableCache, enableCache, pullFromCache, pushToCache } from '~/cache/api';
|
|
2
|
+
import { onMessageUpdated } from '~/message/events';
|
|
3
|
+
import { addReaction } from '~/reaction/api';
|
|
4
|
+
import { client, message11 as message, pause } from '~/utils/tests';
|
|
5
|
+
|
|
6
|
+
describe('addReaction', () => {
|
|
7
|
+
const cacheKey = ['message', 'get', message.messageId];
|
|
8
|
+
|
|
9
|
+
beforeEach(enableCache);
|
|
10
|
+
|
|
11
|
+
afterEach(disableCache);
|
|
12
|
+
|
|
13
|
+
test('should optimistically add a reaction', async () => {
|
|
14
|
+
const callback = jest.fn();
|
|
15
|
+
pushToCache(cacheKey, message);
|
|
16
|
+
onMessageUpdated(callback);
|
|
17
|
+
|
|
18
|
+
const success = await addReaction.optimistically('message', message.messageId, 'like');
|
|
19
|
+
|
|
20
|
+
expect(success).toEqual(true);
|
|
21
|
+
expect(pullFromCache(cacheKey)?.data).toMatchObject({
|
|
22
|
+
myReactions: ['like'],
|
|
23
|
+
reactions: { like: 1 },
|
|
24
|
+
reactionsCount: 1,
|
|
25
|
+
});
|
|
26
|
+
await pause();
|
|
27
|
+
expect(callback).toBeCalledTimes(1);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('should add a reaction', async () => {
|
|
31
|
+
client.http.post = jest.fn().mockResolvedValue({ data: { addedId: 'reactionId' } });
|
|
32
|
+
|
|
33
|
+
const success = await addReaction('message', message.messageId, 'like');
|
|
34
|
+
|
|
35
|
+
expect(success).toEqual(true);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { disableCache, enableCache, pullFromCache, pushToCache } from '~/cache/api';
|
|
2
|
+
import { onMessageUpdated } from '~/message/events';
|
|
3
|
+
import { removeReaction } from '~/reaction/api';
|
|
4
|
+
import { client, message11 as message, message11, pause } from '~/utils/tests';
|
|
5
|
+
|
|
6
|
+
describe('removeReaction', () => {
|
|
7
|
+
const message = {
|
|
8
|
+
...message11,
|
|
9
|
+
myReactions: ['like'],
|
|
10
|
+
reactions: { like: 1 },
|
|
11
|
+
reactionsCount: 1,
|
|
12
|
+
};
|
|
13
|
+
const cacheKey = ['message', 'get', message.messageId];
|
|
14
|
+
|
|
15
|
+
beforeEach(enableCache);
|
|
16
|
+
|
|
17
|
+
afterEach(disableCache);
|
|
18
|
+
|
|
19
|
+
test('should optimistically add a reaction', async () => {
|
|
20
|
+
const callback = jest.fn();
|
|
21
|
+
pushToCache(cacheKey, message);
|
|
22
|
+
onMessageUpdated(callback);
|
|
23
|
+
|
|
24
|
+
const success = await removeReaction.optimistically('message', message.messageId, 'like');
|
|
25
|
+
|
|
26
|
+
expect(success).toEqual(true);
|
|
27
|
+
expect(pullFromCache(cacheKey)?.data).toMatchObject({
|
|
28
|
+
myReactions: [],
|
|
29
|
+
reactions: { like: 0 },
|
|
30
|
+
reactionsCount: 0,
|
|
31
|
+
});
|
|
32
|
+
await pause();
|
|
33
|
+
expect(callback).toBeCalledTimes(1);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('should add a reaction', async () => {
|
|
37
|
+
client.http.delete = jest.fn().mockResolvedValue({ data: { removedId: 'reactionId' } });
|
|
38
|
+
|
|
39
|
+
const success = await removeReaction('message', message.messageId, 'like');
|
|
40
|
+
|
|
41
|
+
expect(success).toEqual(true);
|
|
42
|
+
});
|
|
43
|
+
});
|
package/src/user/api/getUser.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getActiveClient } from '~/client/api';
|
|
2
2
|
|
|
3
|
-
import { pullFromCache
|
|
3
|
+
import { pullFromCache } from '~/cache/api';
|
|
4
4
|
import { ingestInCache } from '~/cache/api/ingestInCache';
|
|
5
5
|
import { fireEvent } from '~/core/events';
|
|
6
6
|
|
|
@@ -38,7 +38,6 @@ export const getUser = async (
|
|
|
38
38
|
let data: Amity.UserPayload;
|
|
39
39
|
|
|
40
40
|
try {
|
|
41
|
-
// API-FIX: endpoint should not be /list, parameters should be querystring.
|
|
42
41
|
const response = await client.http.get<Amity.UserPayload>(
|
|
43
42
|
`/api/v3/users/${encodeURIComponent(userId)}`,
|
|
44
43
|
);
|
|
@@ -33,9 +33,14 @@ export const queryUsers = async (
|
|
|
33
33
|
const client = getActiveClient();
|
|
34
34
|
client.log('user/queryUsers', query);
|
|
35
35
|
|
|
36
|
-
const {
|
|
36
|
+
const {
|
|
37
|
+
page = { limit: 10 },
|
|
38
|
+
displayName,
|
|
39
|
+
filter = 'all',
|
|
40
|
+
sortBy = 'displayName',
|
|
41
|
+
...params
|
|
42
|
+
} = query;
|
|
37
43
|
|
|
38
|
-
// API-FIX: parameters should be querystring.
|
|
39
44
|
const { data } = await client.http.get<Amity.UserPayload & Amity.Pagination>(`/api/v3/users`, {
|
|
40
45
|
params: {
|
|
41
46
|
...params,
|
|
@@ -57,7 +62,11 @@ export const queryUsers = async (
|
|
|
57
62
|
if (client.cache) {
|
|
58
63
|
ingestInCache(payload as Amity.UserPayload, { cachedAt });
|
|
59
64
|
|
|
60
|
-
|
|
65
|
+
/*
|
|
66
|
+
* using query as cache key over params because if the keyword, filter, sort
|
|
67
|
+
* change the API will NOT cache results, when it should
|
|
68
|
+
*/
|
|
69
|
+
const cacheKey = ['user', 'query', { ...query, options: { ...page } } as Amity.Serializable];
|
|
61
70
|
pushToCache(cacheKey, { users: users.map(getResolver('user')), paging });
|
|
62
71
|
}
|
|
63
72
|
|
|
@@ -91,9 +100,19 @@ queryUsers.locally = (
|
|
|
91
100
|
|
|
92
101
|
if (!client.cache) return;
|
|
93
102
|
|
|
94
|
-
const
|
|
103
|
+
const { page = { limit: 10 } } = query ?? {};
|
|
104
|
+
|
|
105
|
+
const cacheKey = [
|
|
106
|
+
'user',
|
|
107
|
+
'query',
|
|
108
|
+
{
|
|
109
|
+
...query,
|
|
110
|
+
options: { ...page },
|
|
111
|
+
} as Amity.Serializable,
|
|
112
|
+
];
|
|
113
|
+
|
|
95
114
|
const { data, cachedAt } =
|
|
96
|
-
pullFromCache<{ users: Pick<Amity.User, 'userId'>[] } & Amity.Pagination>(
|
|
115
|
+
pullFromCache<{ users: Pick<Amity.User, 'userId'>[] } & Amity.Pagination>(cacheKey) ?? {};
|
|
97
116
|
|
|
98
117
|
const users: Amity.User[] =
|
|
99
118
|
data?.users
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { getResolver } from '~/core/model';
|
|
2
|
+
|
|
3
|
+
import { disableCache, enableCache, pushToCache } from '~/cache/api';
|
|
4
|
+
import { ingestInCache } from '~/cache/api/ingestInCache';
|
|
5
|
+
|
|
6
|
+
import { client, userQueryResponse } from '~/utils/tests';
|
|
7
|
+
|
|
8
|
+
import { queryUsers } from '../queryUsers';
|
|
9
|
+
|
|
10
|
+
describe('queryUsers', () => {
|
|
11
|
+
test('it should return users', async () => {
|
|
12
|
+
const { users: expected } = userQueryResponse.data;
|
|
13
|
+
client.http.get = jest.fn().mockResolvedValue(userQueryResponse);
|
|
14
|
+
|
|
15
|
+
const { data } = await queryUsers();
|
|
16
|
+
|
|
17
|
+
expect(data).toEqual(expected);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test('it should throw error', async () => {
|
|
21
|
+
client.http.get = jest.fn().mockRejectedValueOnce(new Error('error'));
|
|
22
|
+
|
|
23
|
+
await expect(queryUsers()).rejects.toThrow('error');
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test('it should update cache upon fetching data from server', async () => {
|
|
27
|
+
enableCache();
|
|
28
|
+
|
|
29
|
+
client.http.get = jest.fn().mockResolvedValue(userQueryResponse);
|
|
30
|
+
|
|
31
|
+
const { data: expected } = await queryUsers();
|
|
32
|
+
const { data: received } = queryUsers.locally()!;
|
|
33
|
+
|
|
34
|
+
expect(received).toBeDefined();
|
|
35
|
+
expect(received).toEqual(expected);
|
|
36
|
+
|
|
37
|
+
disableCache();
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
describe('queryUsers.locally', () => {
|
|
42
|
+
const cacheKey = [
|
|
43
|
+
'user',
|
|
44
|
+
'query',
|
|
45
|
+
{ options: { limit: 10, after: undefined } } as Amity.Serializable,
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
test('it should fetch query locally if present in cache', () => {
|
|
49
|
+
enableCache();
|
|
50
|
+
|
|
51
|
+
const { data } = userQueryResponse;
|
|
52
|
+
const { users: expected, paging } = data;
|
|
53
|
+
|
|
54
|
+
ingestInCache(data as Amity.UserPayload);
|
|
55
|
+
|
|
56
|
+
pushToCache(cacheKey, { users: expected.map(getResolver('user')), paging });
|
|
57
|
+
|
|
58
|
+
const { data: received } = queryUsers.locally()!;
|
|
59
|
+
|
|
60
|
+
expect(received).toBeDefined();
|
|
61
|
+
expect(received).toEqual(expected);
|
|
62
|
+
|
|
63
|
+
disableCache();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test('it should return undefined if only partial data in cache', () => {
|
|
67
|
+
enableCache();
|
|
68
|
+
|
|
69
|
+
const { data } = userQueryResponse;
|
|
70
|
+
const { users, paging } = data;
|
|
71
|
+
|
|
72
|
+
// ingest incomplete data
|
|
73
|
+
ingestInCache({
|
|
74
|
+
...data,
|
|
75
|
+
users: [data.users[0]],
|
|
76
|
+
} as Amity.UserPayload);
|
|
77
|
+
|
|
78
|
+
pushToCache(cacheKey, {
|
|
79
|
+
users: users.map(getResolver('user')),
|
|
80
|
+
paging,
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const received = queryUsers.locally()!;
|
|
84
|
+
|
|
85
|
+
expect(received).toBeUndefined();
|
|
86
|
+
|
|
87
|
+
disableCache();
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// added because of comment above cache key in queryUsers
|
|
91
|
+
test('it should return undefined if params do not match', () => {
|
|
92
|
+
enableCache();
|
|
93
|
+
|
|
94
|
+
const { data } = userQueryResponse;
|
|
95
|
+
const { users: expected, paging } = data;
|
|
96
|
+
|
|
97
|
+
ingestInCache(data as Amity.UserPayload);
|
|
98
|
+
|
|
99
|
+
pushToCache(cacheKey, { users: expected.map(getResolver('user')), paging });
|
|
100
|
+
|
|
101
|
+
const { data: received } = queryUsers.locally()!;
|
|
102
|
+
const received2 = queryUsers.locally({ displayName: 'test' })!;
|
|
103
|
+
|
|
104
|
+
expect(received).toBeDefined();
|
|
105
|
+
expect(received).toEqual(expected);
|
|
106
|
+
expect(received2).toBeUndefined();
|
|
107
|
+
|
|
108
|
+
disableCache();
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
test('it should return undefined if data not in cache', () => {
|
|
112
|
+
enableCache();
|
|
113
|
+
|
|
114
|
+
const received = queryUsers.locally();
|
|
115
|
+
|
|
116
|
+
expect(received).toBeUndefined();
|
|
117
|
+
|
|
118
|
+
disableCache();
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
test('it should return undefined if cache disabled', () => {
|
|
122
|
+
expect(queryUsers.locally()).toBeUndefined();
|
|
123
|
+
});
|
|
124
|
+
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { encodeJson } from '..';
|
|
1
2
|
import { user11, date } from '.';
|
|
2
3
|
|
|
3
|
-
export const
|
|
4
|
+
export const post11: Amity.Post = {
|
|
4
5
|
path: '',
|
|
5
6
|
feedId: '',
|
|
6
7
|
children: [],
|
|
@@ -15,17 +16,39 @@ export const post1: Amity.Post = {
|
|
|
15
16
|
postId: 'postId11',
|
|
16
17
|
targetType: 'user',
|
|
17
18
|
parentId: 'postId12',
|
|
18
|
-
data: { text: '
|
|
19
|
+
data: { text: 'post11' },
|
|
19
20
|
targetId: user11.userId,
|
|
20
21
|
hasFlaggedComment: false,
|
|
21
22
|
hasFlaggedChildren: false,
|
|
22
23
|
postedUserId: user11.userId,
|
|
23
24
|
};
|
|
24
25
|
|
|
26
|
+
export const post12: Amity.Post = {
|
|
27
|
+
...post11,
|
|
28
|
+
postId: 'post12',
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const post13: Amity.Post = {
|
|
32
|
+
...post11,
|
|
33
|
+
postId: 'post13',
|
|
34
|
+
};
|
|
35
|
+
|
|
25
36
|
export const posts = {
|
|
26
37
|
targetId: user11.userId,
|
|
27
38
|
targetType: 'user' as Amity.PostTargetType,
|
|
28
|
-
page1: [
|
|
39
|
+
page1: [post11.postId, post12.postId, post13.postId],
|
|
29
40
|
page2: ['postId21', 'postId22', 'postId23'],
|
|
30
41
|
page3: ['postId31', 'postId32', 'postId33'],
|
|
31
42
|
};
|
|
43
|
+
|
|
44
|
+
const nextPage = encodeJson({ before: post13.postId, limit: 10 });
|
|
45
|
+
|
|
46
|
+
export const postQueryResponse = {
|
|
47
|
+
data: {
|
|
48
|
+
posts: [post11, post12, post13],
|
|
49
|
+
files: [],
|
|
50
|
+
paging: {
|
|
51
|
+
next: nextPage,
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"getMessage.test.d.ts","sourceRoot":"","sources":["../../../../src/message/tests/api/getMessage.test.ts"],"names":[],"mappings":""}
|