@objectstack/client 3.0.7 → 3.0.9
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/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +16 -0
- package/dist/index.d.mts +197 -2
- package/dist/index.d.ts +197 -2
- package/dist/index.js +330 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +330 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -9
- package/src/client.feed.test.ts +273 -0
- package/src/client.test.ts +179 -0
- package/src/index.ts +406 -5
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
|
|
2
|
+
|
|
3
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
4
|
+
import { ObjectStackClient } from './index';
|
|
5
|
+
|
|
6
|
+
/** Helper: create a client with mocked fetch */
|
|
7
|
+
function createMockClient(body: any, status = 200) {
|
|
8
|
+
const fetchMock = vi.fn().mockResolvedValue({
|
|
9
|
+
ok: status >= 200 && status < 300,
|
|
10
|
+
status,
|
|
11
|
+
statusText: status === 200 ? 'OK' : 'Error',
|
|
12
|
+
json: async () => body,
|
|
13
|
+
headers: new Headers()
|
|
14
|
+
});
|
|
15
|
+
const client = new ObjectStackClient({
|
|
16
|
+
baseUrl: 'http://localhost:3000',
|
|
17
|
+
fetch: fetchMock
|
|
18
|
+
});
|
|
19
|
+
return { client, fetchMock };
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
describe('ObjectStackClient - Feed Namespace', () => {
|
|
23
|
+
// ==========================================
|
|
24
|
+
// Feed CRUD
|
|
25
|
+
// ==========================================
|
|
26
|
+
|
|
27
|
+
it('feed.list should GET /api/v1/data/:object/:recordId/feed', async () => {
|
|
28
|
+
const { client, fetchMock } = createMockClient({
|
|
29
|
+
success: true,
|
|
30
|
+
data: { items: [], total: 0, hasMore: false }
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const result = await client.feed.list('account', 'rec_123', { type: 'all', limit: 10 });
|
|
34
|
+
|
|
35
|
+
expect(fetchMock).toHaveBeenCalledWith(
|
|
36
|
+
'http://localhost:3000/api/v1/data/account/rec_123/feed?type=all&limit=10',
|
|
37
|
+
expect.objectContaining({ headers: expect.any(Object) })
|
|
38
|
+
);
|
|
39
|
+
expect(result.items).toEqual([]);
|
|
40
|
+
expect(result.hasMore).toBe(false);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('feed.create should POST /api/v1/data/:object/:recordId/feed', async () => {
|
|
44
|
+
const { client, fetchMock } = createMockClient({
|
|
45
|
+
success: true,
|
|
46
|
+
data: { id: 'feed_1', type: 'comment', body: 'Hello' }
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const result = await client.feed.create('account', 'rec_123', {
|
|
50
|
+
type: 'comment',
|
|
51
|
+
body: 'Hello'
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
expect(fetchMock).toHaveBeenCalledWith(
|
|
55
|
+
'http://localhost:3000/api/v1/data/account/rec_123/feed',
|
|
56
|
+
expect.objectContaining({
|
|
57
|
+
method: 'POST',
|
|
58
|
+
body: JSON.stringify({ type: 'comment', body: 'Hello' })
|
|
59
|
+
})
|
|
60
|
+
);
|
|
61
|
+
expect(result.id).toBe('feed_1');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('feed.update should PUT /api/v1/data/:object/:recordId/feed/:feedId', async () => {
|
|
65
|
+
const { client, fetchMock } = createMockClient({
|
|
66
|
+
success: true,
|
|
67
|
+
data: { id: 'feed_1', type: 'comment', body: 'Updated' }
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const result = await client.feed.update('account', 'rec_123', 'feed_1', {
|
|
71
|
+
body: 'Updated'
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
expect(fetchMock).toHaveBeenCalledWith(
|
|
75
|
+
'http://localhost:3000/api/v1/data/account/rec_123/feed/feed_1',
|
|
76
|
+
expect.objectContaining({
|
|
77
|
+
method: 'PUT',
|
|
78
|
+
body: JSON.stringify({ body: 'Updated' })
|
|
79
|
+
})
|
|
80
|
+
);
|
|
81
|
+
expect(result.body).toBe('Updated');
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('feed.delete should DELETE /api/v1/data/:object/:recordId/feed/:feedId', async () => {
|
|
85
|
+
const { client, fetchMock } = createMockClient({
|
|
86
|
+
success: true,
|
|
87
|
+
data: { feedId: 'feed_1' }
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const result = await client.feed.delete('account', 'rec_123', 'feed_1');
|
|
91
|
+
|
|
92
|
+
expect(fetchMock).toHaveBeenCalledWith(
|
|
93
|
+
'http://localhost:3000/api/v1/data/account/rec_123/feed/feed_1',
|
|
94
|
+
expect.objectContaining({ method: 'DELETE' })
|
|
95
|
+
);
|
|
96
|
+
expect(result.feedId).toBe('feed_1');
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// ==========================================
|
|
100
|
+
// Reactions
|
|
101
|
+
// ==========================================
|
|
102
|
+
|
|
103
|
+
it('feed.addReaction should POST reactions endpoint', async () => {
|
|
104
|
+
const { client, fetchMock } = createMockClient({
|
|
105
|
+
success: true,
|
|
106
|
+
data: { reactions: [{ emoji: '👍', count: 1 }] }
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
const result = await client.feed.addReaction('account', 'rec_123', 'feed_1', '👍');
|
|
110
|
+
|
|
111
|
+
expect(fetchMock).toHaveBeenCalledWith(
|
|
112
|
+
'http://localhost:3000/api/v1/data/account/rec_123/feed/feed_1/reactions',
|
|
113
|
+
expect.objectContaining({
|
|
114
|
+
method: 'POST',
|
|
115
|
+
body: JSON.stringify({ emoji: '👍' })
|
|
116
|
+
})
|
|
117
|
+
);
|
|
118
|
+
expect(result.reactions).toHaveLength(1);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('feed.removeReaction should DELETE reactions/:emoji endpoint', async () => {
|
|
122
|
+
const { client, fetchMock } = createMockClient({
|
|
123
|
+
success: true,
|
|
124
|
+
data: { reactions: [] }
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
await client.feed.removeReaction('account', 'rec_123', 'feed_1', '👍');
|
|
128
|
+
|
|
129
|
+
expect(fetchMock).toHaveBeenCalledWith(
|
|
130
|
+
expect.stringContaining('/api/v1/data/account/rec_123/feed/feed_1/reactions/'),
|
|
131
|
+
expect.objectContaining({ method: 'DELETE' })
|
|
132
|
+
);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// ==========================================
|
|
136
|
+
// Pin / Star
|
|
137
|
+
// ==========================================
|
|
138
|
+
|
|
139
|
+
it('feed.pin should POST pin endpoint', async () => {
|
|
140
|
+
const { client, fetchMock } = createMockClient({
|
|
141
|
+
success: true,
|
|
142
|
+
data: { feedId: 'feed_1', pinned: true, pinnedAt: '2026-01-01T00:00:00Z' }
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
const result = await client.feed.pin('account', 'rec_123', 'feed_1');
|
|
146
|
+
|
|
147
|
+
expect(fetchMock).toHaveBeenCalledWith(
|
|
148
|
+
'http://localhost:3000/api/v1/data/account/rec_123/feed/feed_1/pin',
|
|
149
|
+
expect.objectContaining({ method: 'POST' })
|
|
150
|
+
);
|
|
151
|
+
expect(result.pinned).toBe(true);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('feed.unpin should DELETE pin endpoint', async () => {
|
|
155
|
+
const { client, fetchMock } = createMockClient({
|
|
156
|
+
success: true,
|
|
157
|
+
data: { feedId: 'feed_1', pinned: false }
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
const result = await client.feed.unpin('account', 'rec_123', 'feed_1');
|
|
161
|
+
|
|
162
|
+
expect(fetchMock).toHaveBeenCalledWith(
|
|
163
|
+
'http://localhost:3000/api/v1/data/account/rec_123/feed/feed_1/pin',
|
|
164
|
+
expect.objectContaining({ method: 'DELETE' })
|
|
165
|
+
);
|
|
166
|
+
expect(result.pinned).toBe(false);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it('feed.star should POST star endpoint', async () => {
|
|
170
|
+
const { client, fetchMock } = createMockClient({
|
|
171
|
+
success: true,
|
|
172
|
+
data: { feedId: 'feed_1', starred: true, starredAt: '2026-01-01T00:00:00Z' }
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
const result = await client.feed.star('account', 'rec_123', 'feed_1');
|
|
176
|
+
|
|
177
|
+
expect(fetchMock).toHaveBeenCalledWith(
|
|
178
|
+
'http://localhost:3000/api/v1/data/account/rec_123/feed/feed_1/star',
|
|
179
|
+
expect.objectContaining({ method: 'POST' })
|
|
180
|
+
);
|
|
181
|
+
expect(result.starred).toBe(true);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('feed.unstar should DELETE star endpoint', async () => {
|
|
185
|
+
const { client, fetchMock } = createMockClient({
|
|
186
|
+
success: true,
|
|
187
|
+
data: { feedId: 'feed_1', starred: false }
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
const result = await client.feed.unstar('account', 'rec_123', 'feed_1');
|
|
191
|
+
|
|
192
|
+
expect(fetchMock).toHaveBeenCalledWith(
|
|
193
|
+
'http://localhost:3000/api/v1/data/account/rec_123/feed/feed_1/star',
|
|
194
|
+
expect.objectContaining({ method: 'DELETE' })
|
|
195
|
+
);
|
|
196
|
+
expect(result.starred).toBe(false);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
// ==========================================
|
|
200
|
+
// Search & Changelog
|
|
201
|
+
// ==========================================
|
|
202
|
+
|
|
203
|
+
it('feed.search should GET search endpoint with query params', async () => {
|
|
204
|
+
const { client, fetchMock } = createMockClient({
|
|
205
|
+
success: true,
|
|
206
|
+
data: { items: [], total: 0, hasMore: false }
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
await client.feed.search('account', 'rec_123', 'follow up', { limit: 10 });
|
|
210
|
+
|
|
211
|
+
expect(fetchMock).toHaveBeenCalledWith(
|
|
212
|
+
expect.stringContaining('/api/v1/data/account/rec_123/feed/search?query=follow+up'),
|
|
213
|
+
expect.any(Object)
|
|
214
|
+
);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it('feed.getChangelog should GET changelog endpoint', async () => {
|
|
218
|
+
const { client, fetchMock } = createMockClient({
|
|
219
|
+
success: true,
|
|
220
|
+
data: { entries: [], total: 0, hasMore: false }
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
await client.feed.getChangelog('account', 'rec_123', { field: 'status' });
|
|
224
|
+
|
|
225
|
+
expect(fetchMock).toHaveBeenCalledWith(
|
|
226
|
+
'http://localhost:3000/api/v1/data/account/rec_123/changelog?field=status',
|
|
227
|
+
expect.any(Object)
|
|
228
|
+
);
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
// ==========================================
|
|
232
|
+
// Subscriptions
|
|
233
|
+
// ==========================================
|
|
234
|
+
|
|
235
|
+
it('feed.subscribe should POST subscribe endpoint', async () => {
|
|
236
|
+
const { client, fetchMock } = createMockClient({
|
|
237
|
+
success: true,
|
|
238
|
+
data: { object: 'account', recordId: 'rec_123', events: ['all'], channels: ['in_app'] }
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
const result = await client.feed.subscribe('account', 'rec_123', {
|
|
242
|
+
events: ['comment', 'field_change'],
|
|
243
|
+
channels: ['in_app', 'email']
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
expect(fetchMock).toHaveBeenCalledWith(
|
|
247
|
+
'http://localhost:3000/api/v1/data/account/rec_123/subscribe',
|
|
248
|
+
expect.objectContaining({
|
|
249
|
+
method: 'POST',
|
|
250
|
+
body: JSON.stringify({
|
|
251
|
+
events: ['comment', 'field_change'],
|
|
252
|
+
channels: ['in_app', 'email']
|
|
253
|
+
})
|
|
254
|
+
})
|
|
255
|
+
);
|
|
256
|
+
expect(result.object).toBe('account');
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
it('feed.unsubscribe should DELETE subscribe endpoint', async () => {
|
|
260
|
+
const { client, fetchMock } = createMockClient({
|
|
261
|
+
success: true,
|
|
262
|
+
data: { object: 'account', recordId: 'rec_123', unsubscribed: true }
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
const result = await client.feed.unsubscribe('account', 'rec_123');
|
|
266
|
+
|
|
267
|
+
expect(fetchMock).toHaveBeenCalledWith(
|
|
268
|
+
'http://localhost:3000/api/v1/data/account/rec_123/subscribe',
|
|
269
|
+
expect.objectContaining({ method: 'DELETE' })
|
|
270
|
+
);
|
|
271
|
+
expect(result.unsubscribed).toBe(true);
|
|
272
|
+
});
|
|
273
|
+
});
|
package/src/client.test.ts
CHANGED
|
@@ -648,3 +648,182 @@ describe('FilterBuilder enhancements', () => {
|
|
|
648
648
|
expect(f).toEqual(['phone', 'is_not_null', null]);
|
|
649
649
|
});
|
|
650
650
|
});
|
|
651
|
+
|
|
652
|
+
// ==========================================
|
|
653
|
+
// Automation Client Tests
|
|
654
|
+
// ==========================================
|
|
655
|
+
|
|
656
|
+
describe('ObjectStackClient.automation', () => {
|
|
657
|
+
it('should list flows', async () => {
|
|
658
|
+
const { client, fetchMock } = createMockClient({
|
|
659
|
+
success: true,
|
|
660
|
+
data: { flows: ['flow_a', 'flow_b'], total: 2, hasMore: false },
|
|
661
|
+
});
|
|
662
|
+
|
|
663
|
+
const result = await client.automation.list();
|
|
664
|
+
expect(fetchMock).toHaveBeenCalledWith(
|
|
665
|
+
'http://localhost:3000/api/v1/automation',
|
|
666
|
+
expect.any(Object),
|
|
667
|
+
);
|
|
668
|
+
expect(result.flows).toEqual(['flow_a', 'flow_b']);
|
|
669
|
+
});
|
|
670
|
+
|
|
671
|
+
it('should get a flow by name', async () => {
|
|
672
|
+
const { client, fetchMock } = createMockClient({
|
|
673
|
+
success: true,
|
|
674
|
+
data: { name: 'my_flow', label: 'My Flow' },
|
|
675
|
+
});
|
|
676
|
+
|
|
677
|
+
const result = await client.automation.get('my_flow');
|
|
678
|
+
expect(fetchMock).toHaveBeenCalledWith(
|
|
679
|
+
'http://localhost:3000/api/v1/automation/my_flow',
|
|
680
|
+
expect.any(Object),
|
|
681
|
+
);
|
|
682
|
+
expect(result.name).toBe('my_flow');
|
|
683
|
+
});
|
|
684
|
+
|
|
685
|
+
it('should create a flow', async () => {
|
|
686
|
+
const { client, fetchMock } = createMockClient({
|
|
687
|
+
success: true,
|
|
688
|
+
data: { name: 'new_flow' },
|
|
689
|
+
});
|
|
690
|
+
|
|
691
|
+
await client.automation.create('new_flow', { label: 'New' });
|
|
692
|
+
expect(fetchMock).toHaveBeenCalledWith(
|
|
693
|
+
'http://localhost:3000/api/v1/automation',
|
|
694
|
+
expect.objectContaining({ method: 'POST' }),
|
|
695
|
+
);
|
|
696
|
+
});
|
|
697
|
+
|
|
698
|
+
it('should update a flow', async () => {
|
|
699
|
+
const { client, fetchMock } = createMockClient({
|
|
700
|
+
success: true,
|
|
701
|
+
data: { name: 'my_flow', label: 'Updated' },
|
|
702
|
+
});
|
|
703
|
+
|
|
704
|
+
await client.automation.update('my_flow', { label: 'Updated' });
|
|
705
|
+
expect(fetchMock).toHaveBeenCalledWith(
|
|
706
|
+
'http://localhost:3000/api/v1/automation/my_flow',
|
|
707
|
+
expect.objectContaining({ method: 'PUT' }),
|
|
708
|
+
);
|
|
709
|
+
});
|
|
710
|
+
|
|
711
|
+
it('should delete a flow', async () => {
|
|
712
|
+
const { client, fetchMock } = createMockClient({
|
|
713
|
+
success: true,
|
|
714
|
+
data: { name: 'old_flow', deleted: true },
|
|
715
|
+
});
|
|
716
|
+
|
|
717
|
+
const result = await client.automation.delete('old_flow');
|
|
718
|
+
expect(fetchMock).toHaveBeenCalledWith(
|
|
719
|
+
'http://localhost:3000/api/v1/automation/old_flow',
|
|
720
|
+
expect.objectContaining({ method: 'DELETE' }),
|
|
721
|
+
);
|
|
722
|
+
expect(result.deleted).toBe(true);
|
|
723
|
+
});
|
|
724
|
+
|
|
725
|
+
it('should toggle a flow', async () => {
|
|
726
|
+
const { client, fetchMock } = createMockClient({
|
|
727
|
+
success: true,
|
|
728
|
+
data: { name: 'my_flow', enabled: false },
|
|
729
|
+
});
|
|
730
|
+
|
|
731
|
+
const result = await client.automation.toggle('my_flow', false);
|
|
732
|
+
expect(fetchMock).toHaveBeenCalledWith(
|
|
733
|
+
'http://localhost:3000/api/v1/automation/my_flow/toggle',
|
|
734
|
+
expect.objectContaining({ method: 'POST' }),
|
|
735
|
+
);
|
|
736
|
+
expect(result.enabled).toBe(false);
|
|
737
|
+
});
|
|
738
|
+
|
|
739
|
+
it('should list runs for a flow', async () => {
|
|
740
|
+
const { client, fetchMock } = createMockClient({
|
|
741
|
+
success: true,
|
|
742
|
+
data: { runs: [{ id: 'run_1' }], hasMore: false },
|
|
743
|
+
});
|
|
744
|
+
|
|
745
|
+
const result = await client.automation.runs.list('my_flow');
|
|
746
|
+
expect(fetchMock).toHaveBeenCalledWith(
|
|
747
|
+
'http://localhost:3000/api/v1/automation/my_flow/runs',
|
|
748
|
+
expect.any(Object),
|
|
749
|
+
);
|
|
750
|
+
expect(result.runs).toHaveLength(1);
|
|
751
|
+
});
|
|
752
|
+
|
|
753
|
+
it('should list runs with pagination options', async () => {
|
|
754
|
+
const { client, fetchMock } = createMockClient({
|
|
755
|
+
success: true,
|
|
756
|
+
data: { runs: [], hasMore: false },
|
|
757
|
+
});
|
|
758
|
+
|
|
759
|
+
await client.automation.runs.list('my_flow', { limit: 5, cursor: 'abc' });
|
|
760
|
+
expect(fetchMock).toHaveBeenCalledWith(
|
|
761
|
+
'http://localhost:3000/api/v1/automation/my_flow/runs?limit=5&cursor=abc',
|
|
762
|
+
expect.any(Object),
|
|
763
|
+
);
|
|
764
|
+
});
|
|
765
|
+
|
|
766
|
+
it('should get a single run', async () => {
|
|
767
|
+
const { client, fetchMock } = createMockClient({
|
|
768
|
+
success: true,
|
|
769
|
+
data: { id: 'run_1', status: 'completed' },
|
|
770
|
+
});
|
|
771
|
+
|
|
772
|
+
const result = await client.automation.runs.get('my_flow', 'run_1');
|
|
773
|
+
expect(fetchMock).toHaveBeenCalledWith(
|
|
774
|
+
'http://localhost:3000/api/v1/automation/my_flow/runs/run_1',
|
|
775
|
+
expect.any(Object),
|
|
776
|
+
);
|
|
777
|
+
expect(result.id).toBe('run_1');
|
|
778
|
+
});
|
|
779
|
+
|
|
780
|
+
it('should still support legacy trigger', async () => {
|
|
781
|
+
const { client, fetchMock } = createMockClient({ success: true, data: { result: 'ok' } });
|
|
782
|
+
|
|
783
|
+
await client.automation.trigger('my_flow', { key: 'val' });
|
|
784
|
+
expect(fetchMock).toHaveBeenCalledWith(
|
|
785
|
+
'http://localhost:3000/api/v1/automation/trigger/my_flow',
|
|
786
|
+
expect.objectContaining({ method: 'POST' }),
|
|
787
|
+
);
|
|
788
|
+
});
|
|
789
|
+
|
|
790
|
+
// ==========================================
|
|
791
|
+
// capabilities getter
|
|
792
|
+
// ==========================================
|
|
793
|
+
|
|
794
|
+
it('should return undefined capabilities before connect', () => {
|
|
795
|
+
const client = new ObjectStackClient({ baseUrl: 'http://localhost:3000' });
|
|
796
|
+
expect(client.capabilities).toBeUndefined();
|
|
797
|
+
});
|
|
798
|
+
|
|
799
|
+
it('should expose capabilities after connect', async () => {
|
|
800
|
+
const caps = {
|
|
801
|
+
feed: true,
|
|
802
|
+
comments: true,
|
|
803
|
+
automation: false,
|
|
804
|
+
cron: false,
|
|
805
|
+
search: true,
|
|
806
|
+
export: false,
|
|
807
|
+
chunkedUpload: false,
|
|
808
|
+
};
|
|
809
|
+
const fetchMock = vi.fn().mockResolvedValue({
|
|
810
|
+
ok: true,
|
|
811
|
+
json: async () => ({
|
|
812
|
+
version: 'v1',
|
|
813
|
+
apiName: 'ObjectStack API',
|
|
814
|
+
capabilities: caps,
|
|
815
|
+
}),
|
|
816
|
+
});
|
|
817
|
+
|
|
818
|
+
const client = new ObjectStackClient({
|
|
819
|
+
baseUrl: 'http://localhost:3000',
|
|
820
|
+
fetch: fetchMock,
|
|
821
|
+
});
|
|
822
|
+
|
|
823
|
+
await client.connect();
|
|
824
|
+
expect(client.capabilities).toBeDefined();
|
|
825
|
+
expect(client.capabilities!.feed).toBe(true);
|
|
826
|
+
expect(client.capabilities!.automation).toBe(false);
|
|
827
|
+
expect(client.capabilities!.search).toBe(true);
|
|
828
|
+
});
|
|
829
|
+
});
|