@amityco/ts-sdk 0.0.1-beta.31 → 0.0.1-beta.33
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/ingestInCache.d.ts +1 -1
- package/dist/cache/api/tests/ingestInCache.test.d.ts +2 -0
- package/dist/cache/api/tests/ingestInCache.test.d.ts.map +1 -0
- 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/model/idResolvers.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 +61 -51
- package/dist/index.esm.js +60 -51
- 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/channel.d.ts +6 -0
- package/dist/utils/tests/dummy/channel.d.ts.map +1 -1
- package/dist/utils/tests/dummy/community.d.ts +4 -0
- package/dist/utils/tests/dummy/community.d.ts.map +1 -0
- package/dist/utils/tests/dummy/file.d.ts +2 -0
- package/dist/utils/tests/dummy/file.d.ts.map +1 -0
- package/dist/utils/tests/dummy/follow.d.ts +1 -0
- package/dist/utils/tests/dummy/follow.d.ts.map +1 -1
- package/dist/utils/tests/dummy/index.d.ts +5 -0
- package/dist/utils/tests/dummy/index.d.ts.map +1 -1
- package/dist/utils/tests/dummy/message.d.ts +5 -0
- package/dist/utils/tests/dummy/message.d.ts.map +1 -1
- package/dist/utils/tests/dummy/poll.d.ts +3 -0
- package/dist/utils/tests/dummy/poll.d.ts.map +1 -0
- package/dist/utils/tests/dummy/post.d.ts +15 -1
- package/dist/utils/tests/dummy/post.d.ts.map +1 -1
- package/dist/utils/tests/dummy/reaction.d.ts +4 -0
- package/dist/utils/tests/dummy/reaction.d.ts.map +1 -0
- package/dist/utils/tests/dummy/role.d.ts +4 -0
- package/dist/utils/tests/dummy/role.d.ts.map +1 -0
- package/dist/utils/tests/dummy/user.d.ts +1 -0
- package/dist/utils/tests/dummy/user.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/cache/api/backupCache.ts +0 -1
- package/src/cache/api/ingestInCache.ts +2 -2
- package/src/cache/api/tests/ingestInCache.test.ts +87 -0
- 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/model/idResolvers.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 +17 -6
- package/src/reaction/api/removeReaction.ts +17 -6
- package/src/reaction/api/tests/addReaction.test.ts +73 -0
- package/src/reaction/api/tests/removeReaction.test.ts +79 -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/channel.ts +9 -1
- package/src/utils/tests/dummy/community.ts +44 -0
- package/src/utils/tests/dummy/file.ts +20 -0
- package/src/utils/tests/dummy/follow.ts +6 -0
- package/src/utils/tests/dummy/index.ts +9 -0
- package/src/utils/tests/dummy/message.ts +8 -1
- package/src/utils/tests/dummy/poll.ts +43 -0
- package/src/utils/tests/dummy/post.ts +65 -4
- package/src/utils/tests/dummy/reaction.ts +22 -0
- package/src/utils/tests/dummy/role.ts +21 -0
- package/src/utils/tests/dummy/user.ts +7 -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,108 @@
|
|
|
1
|
+
import { ASCApiError } from '~/core/errors';
|
|
2
|
+
import { disableCache, enableCache, pushToCache } from '~/cache/api';
|
|
3
|
+
import { client, channelQueryResponse } from '~/utils/tests';
|
|
4
|
+
|
|
5
|
+
import { pushToTombstone } from '~/cache/api/pushToTombstone';
|
|
6
|
+
import { isInTombstone } from '~/cache/api/isInTombstone';
|
|
7
|
+
|
|
8
|
+
import { getChannel } from '../getChannel';
|
|
9
|
+
|
|
10
|
+
const { channelId } = channelQueryResponse.data.channels[0];
|
|
11
|
+
const channel = channelQueryResponse.data.channels[0];
|
|
12
|
+
|
|
13
|
+
describe('getChannel', () => {
|
|
14
|
+
test('it should return a channel', async () => {
|
|
15
|
+
client.http.get = jest.fn().mockResolvedValueOnce(channelQueryResponse);
|
|
16
|
+
|
|
17
|
+
const expected = channel;
|
|
18
|
+
const { data: received } = await getChannel(channelId);
|
|
19
|
+
|
|
20
|
+
expect(received).toStrictEqual(expected);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('it should update cache after fetch from server', async () => {
|
|
24
|
+
enableCache();
|
|
25
|
+
client.http.get = jest.fn().mockResolvedValue(channelQueryResponse);
|
|
26
|
+
await getChannel(channelId);
|
|
27
|
+
|
|
28
|
+
expect(getChannel.locally(channelId)).toBeDefined();
|
|
29
|
+
|
|
30
|
+
disableCache();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test('it should return an error', async () => {
|
|
34
|
+
client.http.get = jest.fn().mockRejectedValueOnce(new Error('error'));
|
|
35
|
+
|
|
36
|
+
await expect(getChannel(channelId)).rejects.toThrow('error');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test('it should return an error if channel in cache but api throws not found', async () => {
|
|
40
|
+
enableCache();
|
|
41
|
+
pushToCache(['channel', 'get', channelId], channel, { cachedAt: Date.now() });
|
|
42
|
+
|
|
43
|
+
client.http.get = jest
|
|
44
|
+
.fn()
|
|
45
|
+
.mockRejectedValueOnce(
|
|
46
|
+
new ASCApiError('not found!', Amity.ServerError.ITEM_NOT_FOUND, Amity.ErrorLevel.ERROR),
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
await expect(getChannel(channelId)).rejects.toThrow();
|
|
50
|
+
expect(getChannel.locally(channelId)).toBeUndefined();
|
|
51
|
+
|
|
52
|
+
disableCache();
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
describe('getChannel locally', () => {
|
|
57
|
+
test('it should return data from cache', () => {
|
|
58
|
+
enableCache();
|
|
59
|
+
|
|
60
|
+
const cachedAt = Date.now();
|
|
61
|
+
|
|
62
|
+
pushToCache(['channel', 'get', channelId], channel, { cachedAt });
|
|
63
|
+
|
|
64
|
+
const data = getChannel.locally(channelId);
|
|
65
|
+
|
|
66
|
+
expect(data).toBeDefined();
|
|
67
|
+
expect(data?.data).toEqual(channel);
|
|
68
|
+
expect(data?.cachedAt).toEqual(cachedAt);
|
|
69
|
+
|
|
70
|
+
disableCache();
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test('should return undefined if channel not in cache', () => {
|
|
74
|
+
expect(getChannel.locally('non-existent-channel')).toBeUndefined();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test('should return undefined if cache not enabled', () => {
|
|
78
|
+
expect(getChannel.locally(channelId)).toBeUndefined();
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
describe('getChannel tombostone', () => {
|
|
83
|
+
test('it should add channel to tombostone if 404', async () => {
|
|
84
|
+
enableCache();
|
|
85
|
+
|
|
86
|
+
client.http.get = jest
|
|
87
|
+
.fn()
|
|
88
|
+
.mockRejectedValueOnce(
|
|
89
|
+
new ASCApiError('not found!', Amity.ServerError.ITEM_NOT_FOUND, Amity.ErrorLevel.ERROR),
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
await expect(getChannel(channelId)).rejects.toThrow();
|
|
93
|
+
expect(() => {
|
|
94
|
+
isInTombstone('channel', channelId);
|
|
95
|
+
}).toThrow();
|
|
96
|
+
|
|
97
|
+
disableCache();
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
test('it should throw error if channel not found in tombostone', async () => {
|
|
101
|
+
enableCache();
|
|
102
|
+
|
|
103
|
+
pushToTombstone('channel', channelId);
|
|
104
|
+
await expect(getChannel(channelId)).rejects.toThrow();
|
|
105
|
+
|
|
106
|
+
disableCache();
|
|
107
|
+
});
|
|
108
|
+
});
|
|
@@ -85,6 +85,26 @@ describe('queryChannels.locally', () => {
|
|
|
85
85
|
disableCache();
|
|
86
86
|
});
|
|
87
87
|
|
|
88
|
+
test('it should return undefined if params do not match', () => {
|
|
89
|
+
enableCache();
|
|
90
|
+
|
|
91
|
+
const { data } = channelQueryResponse;
|
|
92
|
+
const { channels: expected, paging } = data;
|
|
93
|
+
|
|
94
|
+
ingestInCache(data as Amity.ChannelPayload);
|
|
95
|
+
|
|
96
|
+
pushToCache(cacheKey, { channels: expected.map(getResolver('channel')), paging });
|
|
97
|
+
|
|
98
|
+
const { data: received } = queryChannels.locally()!;
|
|
99
|
+
const received2 = queryChannels.locally({ displayName: 'test' })!;
|
|
100
|
+
|
|
101
|
+
expect(received).toBeDefined();
|
|
102
|
+
expect(received).toEqual(expected);
|
|
103
|
+
expect(received2).toBeUndefined();
|
|
104
|
+
|
|
105
|
+
disableCache();
|
|
106
|
+
});
|
|
107
|
+
|
|
88
108
|
test('it should return undefined if data not in cache', () => {
|
|
89
109
|
enableCache();
|
|
90
110
|
|
|
@@ -22,7 +22,7 @@ import { prepareChannelPayload } from '../utils';
|
|
|
22
22
|
*/
|
|
23
23
|
export const onChannelMemberAdded = (
|
|
24
24
|
callback: (channel: Amity.Channel, member: Amity.Membership<'channel'>) => void,
|
|
25
|
-
) => {
|
|
25
|
+
): Amity.Unsubscriber => {
|
|
26
26
|
const client = getActiveClient();
|
|
27
27
|
|
|
28
28
|
const filter = (payload: Amity.ChannelMembershipPayload) => {
|
|
@@ -2,7 +2,6 @@ import { disableCache, enableCache, pushToCache } from '~/cache/api';
|
|
|
2
2
|
import { getResolver } from '~/core/model';
|
|
3
3
|
|
|
4
4
|
import { liveChannels } from '../liveChannels';
|
|
5
|
-
import { queryChannels } from '~/channel/api';
|
|
6
5
|
import { prepareChannelPayload } from '../../utils/prepareChannelPayload';
|
|
7
6
|
|
|
8
7
|
import {
|
package/src/core/events.ts
CHANGED
|
@@ -117,7 +117,7 @@ export const createEventSubscriber = <T extends keyof Amity.Events>(
|
|
|
117
117
|
export const createMqttMessageSubscriber = <T extends keyof Amity.Events>(
|
|
118
118
|
client: Amity.Client,
|
|
119
119
|
namespace: string,
|
|
120
|
-
event:
|
|
120
|
+
event: T,
|
|
121
121
|
fn: (params: Record<string, unknown>) => void,
|
|
122
122
|
): Amity.Unsubscriber => {
|
|
123
123
|
return createEventSubscriber(client, namespace, 'message', ([topic, message]) => {
|
|
@@ -38,4 +38,4 @@ const idResolvers: Resolvers = {
|
|
|
38
38
|
* @param name the domain name for the resolve
|
|
39
39
|
* @returns an idResolver function for the given domain name
|
|
40
40
|
*/
|
|
41
|
-
export const getResolver = <T extends Amity.Domain>(name: T) => idResolvers[name];
|
|
41
|
+
export const getResolver = <T extends Amity.Domain>(name: T): Resolvers[T] => idResolvers[name];
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import axios from 'axios';
|
|
2
|
+
import qs from 'qs';
|
|
2
3
|
import HttpAgent, { HttpsAgent } from 'agentkeepalive';
|
|
3
4
|
|
|
4
5
|
import { unwrapPayload } from './utils';
|
|
@@ -7,23 +8,8 @@ import { unwrapPayload } from './utils';
|
|
|
7
8
|
* Axios param serializer (for querystring)
|
|
8
9
|
* @hidden
|
|
9
10
|
*/
|
|
10
|
-
const stringify = (params: Record<string, unknown
|
|
11
|
-
return
|
|
12
|
-
.filter(([, value]) => value !== undefined)
|
|
13
|
-
.map(([name, value]) => {
|
|
14
|
-
const key = prefix ? `${prefix}[${name}]` : name;
|
|
15
|
-
|
|
16
|
-
if (Array.isArray(value)) {
|
|
17
|
-
return value.map(item => `${key}[]=${item}`).join('&');
|
|
18
|
-
}
|
|
19
|
-
if (typeof value !== 'object') {
|
|
20
|
-
return `${key}=${value}`;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// @ts-ignore
|
|
24
|
-
return stringify(value, prefix ?? name);
|
|
25
|
-
})
|
|
26
|
-
.join('&');
|
|
11
|
+
export const stringify = (params: Record<string, unknown>): string => {
|
|
12
|
+
return qs.stringify(params, { arrayFormat: 'brackets' });
|
|
27
13
|
};
|
|
28
14
|
|
|
29
15
|
/**
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { createHttpTransport, stringify } from '../http';
|
|
2
|
+
|
|
3
|
+
describe('core/transports', () => {
|
|
4
|
+
describe('stringify', () => {
|
|
5
|
+
test('should serializer simple string', () => {
|
|
6
|
+
const params = { a: 'c' };
|
|
7
|
+
const url = stringify(params);
|
|
8
|
+
expect(url).toBe('a=c');
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test('should serializer empty string', () => {
|
|
12
|
+
const params = { a: '' };
|
|
13
|
+
const url = stringify(params);
|
|
14
|
+
expect(url).toBe('a=');
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test('should serializer special character', () => {
|
|
18
|
+
const params = { a: '✓', b: 'ø' };
|
|
19
|
+
const url = stringify(params);
|
|
20
|
+
expect(url).toBe('a=%E2%9C%93&b=%C3%B8');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('should serializer boolean', () => {
|
|
24
|
+
const params = { a: true, b: false };
|
|
25
|
+
const url = stringify(params);
|
|
26
|
+
expect(url).toBe('a=true&b=false');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('should serializer null ', () => {
|
|
30
|
+
const params = { a: null };
|
|
31
|
+
const url = stringify(params);
|
|
32
|
+
expect(url).toBe('a=');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('should serializer undefined', () => {
|
|
36
|
+
const params = { a: undefined };
|
|
37
|
+
const url = stringify(params);
|
|
38
|
+
expect(url).toBe('');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('should serializer NaN', () => {
|
|
42
|
+
const params = { a: NaN };
|
|
43
|
+
const url = stringify(params);
|
|
44
|
+
expect(url).toBe('a=NaN');
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test('should serializer simple array', () => {
|
|
48
|
+
const params = { a: ['b', 'c', 'd'] };
|
|
49
|
+
const url = stringify(params);
|
|
50
|
+
expect(url).toBe('a%5B%5D=b&a%5B%5D=c&a%5B%5D=d');
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test('should serializer complex array', () => {
|
|
54
|
+
const params = { a: ['b', { c: 'd' }] };
|
|
55
|
+
const url = stringify(params);
|
|
56
|
+
expect(url).toBe('a%5B%5D=b&a%5B%5D%5Bc%5D=d');
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test('should serializer nested object', () => {
|
|
60
|
+
const params = { a: { b: 'c' } };
|
|
61
|
+
const url = stringify(params);
|
|
62
|
+
expect(url).toBe('a%5Bb%5D=c');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test('should serializer deep nested object', () => {
|
|
66
|
+
const params = { a: { b: { c: { d: { e: { f: { g: { h: { i: 'j' } } } } } } } } };
|
|
67
|
+
const url = stringify(params);
|
|
68
|
+
expect(url).toBe('a%5Bb%5D%5Bc%5D%5Bd%5D%5Be%5D%5Bf%5D%5Bg%5D%5Bh%5D%5Bi%5D=j');
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test('should serializer empty object', () => {
|
|
72
|
+
const params = { a: { b: [] } };
|
|
73
|
+
const url = stringify(params);
|
|
74
|
+
expect(url).toBe('');
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
describe('createHttpTransport', () => {
|
|
79
|
+
test('should create axios instance with out error', () => {
|
|
80
|
+
expect(createHttpTransport('/')).not.toThrow();
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
});
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { getActiveClient } from '~/client/api';
|
|
2
|
-
|
|
3
|
-
import { getMessage } from './getMessage';
|
|
4
|
-
|
|
5
2
|
import { pullFromCache, upsertInCache } from '~/cache/api';
|
|
6
3
|
import { fireEvent } from '~/core/events';
|
|
7
4
|
|
|
5
|
+
import { getMessage } from './getMessage';
|
|
6
|
+
|
|
8
7
|
/**
|
|
9
8
|
* ```js
|
|
10
9
|
* import { deleteMessage } from '@amityco/ts-sdk'
|
|
@@ -1,76 +1,99 @@
|
|
|
1
1
|
import { UNSYNCED_OBJECT_CACHED_AT_VALUE } from '~/utils/constants';
|
|
2
|
-
import { disableCache, enableCache, pullFromCache } from '~/cache/api';
|
|
2
|
+
import { disableCache, enableCache, pullFromCache, pushToCache } from '~/cache/api';
|
|
3
3
|
|
|
4
4
|
import { client, message11 } from '~/utils/tests';
|
|
5
5
|
|
|
6
6
|
import { onMessageCreated } from '../../events';
|
|
7
7
|
import { createMessage } from '../createMessage';
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const { messageId, ...messageBundle } = message11;
|
|
9
|
+
const messageToCreate = message11;
|
|
10
|
+
const { messageId, ...messageWithoutId } = message11;
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
12
|
+
const getResolvedMessageValue = () => ({
|
|
13
|
+
data: {
|
|
14
|
+
messages: [messageToCreate],
|
|
15
|
+
users: [],
|
|
16
|
+
files: [],
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
describe('createMessage', () => {
|
|
21
|
+
test('should return created message', async () => {
|
|
22
|
+
client.http.post = jest.fn().mockResolvedValue(getResolvedMessageValue());
|
|
23
|
+
|
|
24
|
+
const recieved = createMessage(messageWithoutId);
|
|
25
|
+
|
|
26
|
+
await expect(recieved).resolves.toEqual(expect.objectContaining({ data: messageToCreate }));
|
|
19
27
|
});
|
|
20
28
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
test('should throw an error if request fails', async () => {
|
|
30
|
+
client.http.post = jest.fn().mockRejectedValueOnce(new Error('error'));
|
|
31
|
+
|
|
32
|
+
await expect(createMessage(messageWithoutId)).rejects.toThrow('error');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('should create cache after created messages', async () => {
|
|
36
|
+
enableCache();
|
|
37
|
+
client.http.post = jest.fn().mockResolvedValue(getResolvedMessageValue());
|
|
38
|
+
|
|
39
|
+
const created = await createMessage(messageWithoutId);
|
|
40
|
+
const recieved = pullFromCache(['message', 'get', created.data.messageId])?.data;
|
|
41
|
+
|
|
42
|
+
expect(recieved).toEqual(expect.objectContaining(messageWithoutId));
|
|
43
|
+
|
|
44
|
+
disableCache();
|
|
32
45
|
});
|
|
33
46
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
47
|
+
test('should fire event `onMessageCreated`', async () => {
|
|
48
|
+
let dispose;
|
|
49
|
+
client.http.post = jest.fn().mockResolvedValueOnce(getResolvedMessageValue());
|
|
37
50
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
});
|
|
51
|
+
const callbackPromise = new Promise(resolve => {
|
|
52
|
+
dispose = onMessageCreated(resolve);
|
|
53
|
+
}).finally(dispose);
|
|
42
54
|
|
|
43
|
-
|
|
44
|
-
const { channelId } = messageBundle;
|
|
55
|
+
await createMessage(messageWithoutId);
|
|
45
56
|
|
|
46
|
-
|
|
47
|
-
|
|
57
|
+
await expect(callbackPromise).resolves.toEqual(expect.objectContaining(messageWithoutId));
|
|
58
|
+
});
|
|
59
|
+
});
|
|
48
60
|
|
|
49
|
-
|
|
61
|
+
describe('createMessage.optimistically', () => {
|
|
62
|
+
beforeEach(() => enableCache());
|
|
63
|
+
afterEach(() => disableCache());
|
|
50
64
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
});
|
|
65
|
+
test('should create cache after created message', () => {
|
|
66
|
+
const optimisticId = createMessage.optimistically(messageWithoutId)?.data?.messageId;
|
|
67
|
+
const recieved = pullFromCache(['message', 'get', optimisticId])?.data;
|
|
55
68
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
let dispose;
|
|
69
|
+
expect(recieved).toEqual(expect.objectContaining(messageWithoutId));
|
|
70
|
+
});
|
|
59
71
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
72
|
+
test('should increase message count after created message', () => {
|
|
73
|
+
const { channelId } = messageWithoutId;
|
|
74
|
+
pushToCache(['channel', 'get', channelId], { channelId, messageCount: 2 });
|
|
63
75
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
});
|
|
76
|
+
createMessage.optimistically(messageWithoutId);
|
|
77
|
+
const recieved = pullFromCache<Amity.Channel>(['channel', 'get', channelId])?.data;
|
|
67
78
|
|
|
68
|
-
|
|
69
|
-
|
|
79
|
+
expect(recieved?.messageCount).toBe(3);
|
|
80
|
+
});
|
|
70
81
|
|
|
71
|
-
|
|
82
|
+
test('should fire event `onMessageCreated`', async () => {
|
|
83
|
+
let dispose;
|
|
84
|
+
|
|
85
|
+
const callbackPromise = new Promise(resolve => {
|
|
86
|
+
dispose = onMessageCreated(resolve);
|
|
87
|
+
}).finally(dispose);
|
|
88
|
+
|
|
89
|
+
createMessage.optimistically(messageWithoutId);
|
|
90
|
+
|
|
91
|
+
await expect(callbackPromise).resolves.toEqual(expect.objectContaining(messageWithoutId));
|
|
92
|
+
});
|
|
72
93
|
|
|
73
|
-
|
|
74
|
-
|
|
94
|
+
test('should define object as unsynced object', async () => {
|
|
95
|
+
expect(createMessage.optimistically(messageWithoutId)?.cachedAt).toEqual(
|
|
96
|
+
UNSYNCED_OBJECT_CACHED_AT_VALUE,
|
|
97
|
+
);
|
|
75
98
|
});
|
|
76
99
|
});
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { disableCache, enableCache, pullFromCache, pushToCache } from '~/cache/api';
|
|
2
|
+
import { client, message11 } from '~/utils/tests';
|
|
3
|
+
|
|
4
|
+
import { deleteMessage } from '../deleteMessage';
|
|
5
|
+
import { onMessageDeleted } from '../../events';
|
|
6
|
+
|
|
7
|
+
const messageToDelete = { ...message11, isDeleted: false };
|
|
8
|
+
const { messageId: deleteId } = messageToDelete;
|
|
9
|
+
const deletedMessage = { ...messageToDelete, isDeleted: true };
|
|
10
|
+
const { updatedAt, ...deletedMessageWithoutTS } = deletedMessage;
|
|
11
|
+
|
|
12
|
+
const getResolvedMessageValue = () => ({
|
|
13
|
+
data: {
|
|
14
|
+
messages: [deletedMessage],
|
|
15
|
+
users: [],
|
|
16
|
+
files: [],
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
describe('deleteMessage', () => {
|
|
21
|
+
test('should return deleted message', async () => {
|
|
22
|
+
client.http.delete = jest.fn();
|
|
23
|
+
client.http.get = jest.fn().mockResolvedValueOnce(getResolvedMessageValue());
|
|
24
|
+
|
|
25
|
+
await expect(deleteMessage(deleteId)).resolves.toEqual(deletedMessageWithoutTS);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('should throw an error if request fails', async () => {
|
|
29
|
+
client.http.delete = jest.fn().mockRejectedValueOnce(new Error('error'));
|
|
30
|
+
|
|
31
|
+
await expect(deleteMessage(deleteId)).rejects.toThrow('error');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('should update cache after deleted messages', async () => {
|
|
35
|
+
enableCache();
|
|
36
|
+
client.http.delete = jest.fn();
|
|
37
|
+
client.http.get = jest.fn().mockResolvedValueOnce(getResolvedMessageValue());
|
|
38
|
+
pushToCache(['message', 'get', deleteId], messageToDelete);
|
|
39
|
+
|
|
40
|
+
await deleteMessage(deleteId);
|
|
41
|
+
const recieved = pullFromCache<Amity.Message>(['message', 'get', deleteId])?.data;
|
|
42
|
+
|
|
43
|
+
expect(recieved).toEqual(deletedMessageWithoutTS);
|
|
44
|
+
|
|
45
|
+
disableCache();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('should fire event `onMessageDeleted`', async () => {
|
|
49
|
+
let dispose;
|
|
50
|
+
client.http.delete = jest.fn();
|
|
51
|
+
client.http.get = jest.fn().mockResolvedValueOnce(getResolvedMessageValue());
|
|
52
|
+
|
|
53
|
+
const callbackPromise = new Promise(resolve => {
|
|
54
|
+
dispose = onMessageDeleted(resolve);
|
|
55
|
+
}).finally(dispose);
|
|
56
|
+
|
|
57
|
+
await deleteMessage(deleteId);
|
|
58
|
+
|
|
59
|
+
await expect(callbackPromise).resolves.toEqual(deletedMessageWithoutTS);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
describe('deleteMessage.optimistically', () => {
|
|
64
|
+
beforeEach(() => enableCache());
|
|
65
|
+
afterEach(() => disableCache());
|
|
66
|
+
|
|
67
|
+
test('should update `isDeleted` in cache after deleted message', () => {
|
|
68
|
+
pushToCache(['message', 'get', deleteId], messageToDelete);
|
|
69
|
+
|
|
70
|
+
deleteMessage.optimistically(deleteId);
|
|
71
|
+
const recieved = pullFromCache<Amity.Message>(['message', 'get', deleteId])?.data;
|
|
72
|
+
|
|
73
|
+
expect(recieved).toEqual(expect.objectContaining(deletedMessageWithoutTS));
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
/* TODO: re-enable this after fixed channel message count calculation */
|
|
77
|
+
test.skip('should decrease message count after deleted message', () => {
|
|
78
|
+
const { channelId } = messageToDelete;
|
|
79
|
+
pushToCache(['channel', 'get', channelId], { channelId, messageCount: 2 });
|
|
80
|
+
pushToCache(['message', 'get', deleteId], { ...messageToDelete, channelId });
|
|
81
|
+
|
|
82
|
+
deleteMessage.optimistically(deleteId);
|
|
83
|
+
const recieved = pullFromCache<Amity.Channel>(['channel', 'get', channelId])?.data;
|
|
84
|
+
|
|
85
|
+
expect(recieved?.messageCount).toBe(1);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test('should fire event `onMessageDeleted`', async () => {
|
|
89
|
+
pushToCache(['message', 'get', deleteId], messageToDelete);
|
|
90
|
+
let dispose;
|
|
91
|
+
|
|
92
|
+
const callbackPromise = new Promise(resolve => {
|
|
93
|
+
dispose = onMessageDeleted(data => {
|
|
94
|
+
resolve(data);
|
|
95
|
+
});
|
|
96
|
+
}).finally(dispose);
|
|
97
|
+
|
|
98
|
+
await deleteMessage.optimistically(deleteId);
|
|
99
|
+
|
|
100
|
+
await expect(callbackPromise).resolves.toEqual(
|
|
101
|
+
expect.objectContaining(deletedMessageWithoutTS),
|
|
102
|
+
);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
test('should define object as unsynced object', () => {
|
|
106
|
+
pushToCache(['message', 'get', deleteId], messageToDelete);
|
|
107
|
+
|
|
108
|
+
expect(deleteMessage.optimistically(deleteId)?.cachedAt).toBe(-1);
|
|
109
|
+
});
|
|
110
|
+
});
|