signal-sdk 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +23 -11
  2. package/dist/MultiAccountManager.js +11 -19
  3. package/dist/SignalBot.js +40 -36
  4. package/dist/SignalCli.d.ts +25 -301
  5. package/dist/SignalCli.js +226 -971
  6. package/dist/__tests__/DeviceManager.test.d.ts +1 -0
  7. package/dist/__tests__/DeviceManager.test.js +135 -0
  8. package/dist/__tests__/MultiAccountManager.coverage.test.d.ts +1 -0
  9. package/dist/__tests__/MultiAccountManager.coverage.test.js +33 -0
  10. package/dist/__tests__/MultiAccountManager.test.js +3 -3
  11. package/dist/__tests__/SignalBot.additional.test.js +40 -37
  12. package/dist/__tests__/SignalBot.coverage.test.d.ts +1 -0
  13. package/dist/__tests__/SignalBot.coverage.test.js +385 -0
  14. package/dist/__tests__/SignalBot.test.js +8 -8
  15. package/dist/__tests__/SignalCli.advanced.test.js +47 -58
  16. package/dist/__tests__/SignalCli.connections.test.d.ts +1 -0
  17. package/dist/__tests__/SignalCli.connections.test.js +110 -0
  18. package/dist/__tests__/SignalCli.e2e.test.js +28 -32
  19. package/dist/__tests__/SignalCli.events.test.d.ts +1 -0
  20. package/dist/__tests__/SignalCli.events.test.js +113 -0
  21. package/dist/__tests__/SignalCli.integration.test.js +6 -5
  22. package/dist/__tests__/SignalCli.methods.test.js +150 -66
  23. package/dist/__tests__/SignalCli.parsing.test.js +4 -13
  24. package/dist/__tests__/SignalCli.simple.test.d.ts +1 -0
  25. package/dist/__tests__/SignalCli.simple.test.js +77 -0
  26. package/dist/__tests__/SignalCli.test.js +133 -74
  27. package/dist/__tests__/config.test.js +19 -29
  28. package/dist/__tests__/errors.test.js +2 -2
  29. package/dist/__tests__/retry.test.js +10 -8
  30. package/dist/__tests__/robustness.test.d.ts +1 -0
  31. package/dist/__tests__/robustness.test.js +59 -0
  32. package/dist/__tests__/security.test.d.ts +1 -0
  33. package/dist/__tests__/security.test.js +50 -0
  34. package/dist/config.js +3 -3
  35. package/dist/interfaces.d.ts +27 -0
  36. package/dist/managers/AccountManager.d.ts +27 -0
  37. package/dist/managers/AccountManager.js +147 -0
  38. package/dist/managers/BaseManager.d.ts +9 -0
  39. package/dist/managers/BaseManager.js +17 -0
  40. package/dist/managers/ContactManager.d.ts +15 -0
  41. package/dist/managers/ContactManager.js +123 -0
  42. package/dist/managers/DeviceManager.d.ts +11 -0
  43. package/dist/managers/DeviceManager.js +139 -0
  44. package/dist/managers/GroupManager.d.ts +12 -0
  45. package/dist/managers/GroupManager.js +78 -0
  46. package/dist/managers/MessageManager.d.ts +18 -0
  47. package/dist/managers/MessageManager.js +301 -0
  48. package/dist/managers/StickerManager.d.ts +8 -0
  49. package/dist/managers/StickerManager.js +39 -0
  50. package/dist/retry.js +3 -3
  51. package/dist/validators.d.ts +9 -0
  52. package/dist/validators.js +20 -0
  53. package/package.json +11 -4
  54. package/scripts/install.js +1 -1
@@ -10,7 +10,8 @@ describe('SignalCli Advanced Features', () => {
10
10
  let sendJsonRpcRequestSpy;
11
11
  beforeEach(() => {
12
12
  signalCli = new SignalCli_1.SignalCli('+1234567890');
13
- sendJsonRpcRequestSpy = jest.spyOn(signalCli, 'sendJsonRpcRequest')
13
+ sendJsonRpcRequestSpy = jest
14
+ .spyOn(signalCli, 'sendJsonRpcRequest')
14
15
  .mockResolvedValue({ timestamp: Date.now(), results: [] });
15
16
  });
16
17
  afterEach(() => {
@@ -19,37 +20,29 @@ describe('SignalCli Advanced Features', () => {
19
20
  describe('Advanced sendMessage Options', () => {
20
21
  it('should send message with text styles', async () => {
21
22
  await signalCli.sendMessage('+33123456789', 'Hello *bold* text', {
22
- textStyles: [
23
- { start: 6, length: 6, style: 'BOLD' }
24
- ]
23
+ textStyles: [{ start: 6, length: 6, style: 'BOLD' }],
25
24
  });
26
25
  expect(sendJsonRpcRequestSpy).toHaveBeenCalledWith('send', expect.objectContaining({
27
26
  message: 'Hello *bold* text',
28
- textStyles: [
29
- { start: 6, length: 6, style: 'BOLD' }
30
- ]
27
+ textStyles: [{ start: 6, length: 6, style: 'BOLD' }],
31
28
  }));
32
29
  });
33
30
  it('should send message with mentions', async () => {
34
31
  await signalCli.sendMessage('+33123456789', 'Hello @John', {
35
- mentions: [
36
- { start: 6, length: 5, number: '+33111111111' }
37
- ]
32
+ mentions: [{ start: 6, length: 5, number: '+33111111111' }],
38
33
  });
39
34
  expect(sendJsonRpcRequestSpy).toHaveBeenCalledWith('send', expect.objectContaining({
40
35
  message: 'Hello @John',
41
- mentions: [
42
- { start: 6, length: 5, number: '+33111111111' }
43
- ]
36
+ mentions: [{ start: 6, length: 5, number: '+33111111111' }],
44
37
  }));
45
38
  });
46
39
  it('should send message with preview URL', async () => {
47
40
  await signalCli.sendMessage('+33123456789', 'Check this out', {
48
- previewUrl: 'https://example.com'
41
+ previewUrl: 'https://example.com',
49
42
  });
50
43
  expect(sendJsonRpcRequestSpy).toHaveBeenCalledWith('send', expect.objectContaining({
51
44
  message: 'Check this out',
52
- previewUrl: 'https://example.com'
45
+ previewUrl: 'https://example.com',
53
46
  }));
54
47
  });
55
48
  it('should send message with quote and advanced fields', async () => {
@@ -59,8 +52,8 @@ describe('SignalCli Advanced Features', () => {
59
52
  author: '+33111111111',
60
53
  text: 'Original message',
61
54
  mentions: [{ start: 0, length: 5, number: '+33222222222' }],
62
- textStyles: [{ start: 0, length: 8, style: 'BOLD' }]
63
- }
55
+ textStyles: [{ start: 0, length: 8, style: 'BOLD' }],
56
+ },
64
57
  });
65
58
  expect(sendJsonRpcRequestSpy).toHaveBeenCalledWith('send', expect.objectContaining({
66
59
  message: 'I agree!',
@@ -68,45 +61,45 @@ describe('SignalCli Advanced Features', () => {
68
61
  quoteAuthor: '+33111111111',
69
62
  quoteMessage: 'Original message',
70
63
  quoteMentions: [{ start: 0, length: 5, number: '+33222222222' }],
71
- quoteTextStyles: [{ start: 0, length: 8, style: 'BOLD' }]
64
+ quoteTextStyles: [{ start: 0, length: 8, style: 'BOLD' }],
72
65
  }));
73
66
  });
74
67
  it('should send message edit', async () => {
75
68
  await signalCli.sendMessage('+33123456789', 'Corrected text', {
76
- editTimestamp: 123456789
69
+ editTimestamp: 123456789,
77
70
  });
78
71
  expect(sendJsonRpcRequestSpy).toHaveBeenCalledWith('send', expect.objectContaining({
79
72
  message: 'Corrected text',
80
- editTimestamp: 123456789
73
+ editTimestamp: 123456789,
81
74
  }));
82
75
  });
83
76
  it('should send reply to story', async () => {
84
77
  await signalCli.sendMessage('+33123456789', 'Nice story!', {
85
78
  storyTimestamp: 123456789,
86
- storyAuthor: '+33111111111'
79
+ storyAuthor: '+33111111111',
87
80
  });
88
81
  expect(sendJsonRpcRequestSpy).toHaveBeenCalledWith('send', expect.objectContaining({
89
82
  message: 'Nice story!',
90
83
  storyTimestamp: 123456789,
91
- storyAuthor: '+33111111111'
84
+ storyAuthor: '+33111111111',
92
85
  }));
93
86
  });
94
87
  it('should send message with noteToSelf flag', async () => {
95
88
  await signalCli.sendMessage('+1234567890', 'Note to myself', {
96
- noteToSelf: true
89
+ noteToSelf: true,
97
90
  });
98
91
  expect(sendJsonRpcRequestSpy).toHaveBeenCalledWith('send', expect.objectContaining({
99
92
  message: 'Note to myself',
100
- noteToSelf: true
93
+ noteToSelf: true,
101
94
  }));
102
95
  });
103
96
  it('should send message with endSession flag', async () => {
104
97
  await signalCli.sendMessage('+33123456789', 'Goodbye', {
105
- endSession: true
98
+ endSession: true,
106
99
  });
107
100
  expect(sendJsonRpcRequestSpy).toHaveBeenCalledWith('send', expect.objectContaining({
108
101
  message: 'Goodbye',
109
- endSession: true
102
+ endSession: true,
110
103
  }));
111
104
  });
112
105
  });
@@ -116,12 +109,12 @@ describe('SignalCli Advanced Features', () => {
116
109
  {
117
110
  timestamp: 123456789,
118
111
  source: '+33123456789',
119
- dataMessage: { message: 'Hello!' }
120
- }
112
+ dataMessage: { message: 'Hello!' },
113
+ },
121
114
  ]);
122
115
  const messages = await signalCli.receive();
123
116
  expect(sendJsonRpcRequestSpy).toHaveBeenCalledWith('receive', expect.objectContaining({
124
- account: '+1234567890'
117
+ account: '+1234567890',
125
118
  }));
126
119
  expect(messages).toHaveLength(1);
127
120
  expect(messages[0].text).toBe('Hello!');
@@ -130,32 +123,32 @@ describe('SignalCli Advanced Features', () => {
130
123
  sendJsonRpcRequestSpy.mockResolvedValue([]);
131
124
  await signalCli.receive({ timeout: 10 });
132
125
  expect(sendJsonRpcRequestSpy).toHaveBeenCalledWith('receive', expect.objectContaining({
133
- timeout: 10
126
+ timeout: 10,
134
127
  }));
135
128
  });
136
129
  it('should receive messages with maxMessages limit', async () => {
137
130
  sendJsonRpcRequestSpy.mockResolvedValue([]);
138
131
  await signalCli.receive({ maxMessages: 5 });
139
132
  expect(sendJsonRpcRequestSpy).toHaveBeenCalledWith('receive', expect.objectContaining({
140
- maxMessages: 5
133
+ maxMessages: 5,
141
134
  }));
142
135
  });
143
136
  it('should receive messages with ignoreAttachments', async () => {
144
137
  await signalCli.receive({ ignoreAttachments: true });
145
138
  expect(sendJsonRpcRequestSpy).toHaveBeenCalledWith('receive', expect.objectContaining({
146
- ignoreAttachments: true
139
+ ignoreAttachments: true,
147
140
  }));
148
141
  });
149
142
  it('should receive messages with ignoreStories', async () => {
150
143
  await signalCli.receive({ ignoreStories: true });
151
144
  expect(sendJsonRpcRequestSpy).toHaveBeenCalledWith('receive', expect.objectContaining({
152
- ignoreStories: true
145
+ ignoreStories: true,
153
146
  }));
154
147
  });
155
148
  it('should receive messages with sendReadReceipts', async () => {
156
149
  await signalCli.receive({ sendReadReceipts: true });
157
150
  expect(sendJsonRpcRequestSpy).toHaveBeenCalledWith('receive', expect.objectContaining({
158
- sendReadReceipts: true
151
+ sendReadReceipts: true,
159
152
  }));
160
153
  });
161
154
  it('should handle empty message array', async () => {
@@ -168,11 +161,11 @@ describe('SignalCli Advanced Features', () => {
168
161
  it('should set username', async () => {
169
162
  sendJsonRpcRequestSpy.mockResolvedValue({
170
163
  username: 'myuser.123',
171
- usernameLink: 'https://signal.me/#myuser.123'
164
+ usernameLink: 'https://signal.me/#myuser.123',
172
165
  });
173
166
  const result = await signalCli.setUsername('myuser');
174
167
  expect(sendJsonRpcRequestSpy).toHaveBeenCalledWith('updateAccount', expect.objectContaining({
175
- username: 'myuser'
168
+ username: 'myuser',
176
169
  }));
177
170
  expect(result.success).toBe(true);
178
171
  expect(result.username).toBe('myuser.123');
@@ -181,7 +174,7 @@ describe('SignalCli Advanced Features', () => {
181
174
  sendJsonRpcRequestSpy.mockResolvedValue({});
182
175
  const result = await signalCli.deleteUsername();
183
176
  expect(sendJsonRpcRequestSpy).toHaveBeenCalledWith('updateAccount', expect.objectContaining({
184
- deleteUsername: true
177
+ deleteUsername: true,
185
178
  }));
186
179
  expect(result.success).toBe(true);
187
180
  });
@@ -192,12 +185,12 @@ describe('SignalCli Advanced Features', () => {
192
185
  {
193
186
  number: '+33123456789',
194
187
  safetyNumber: '12345 67890 12345 67890 12345 67890',
195
- trustLevel: 'TRUSTED'
196
- }
188
+ trustLevel: 'TRUSTED',
189
+ },
197
190
  ]);
198
191
  const safetyNumber = await signalCli.getSafetyNumber('+33123456789');
199
192
  expect(sendJsonRpcRequestSpy).toHaveBeenCalledWith('listIdentities', expect.objectContaining({
200
- number: '+33123456789'
193
+ number: '+33123456789',
201
194
  }));
202
195
  expect(safetyNumber).toBe('12345 67890 12345 67890 12345 67890');
203
196
  });
@@ -212,15 +205,15 @@ describe('SignalCli Advanced Features', () => {
212
205
  {
213
206
  number: '+33123456789',
214
207
  safetyNumber: '12345 67890 12345 67890 12345 67890',
215
- trustLevel: 'TRUSTED'
216
- }
208
+ trustLevel: 'TRUSTED',
209
+ },
217
210
  ]);
218
211
  // Mock trustIdentity response
219
212
  sendJsonRpcRequestSpy.mockResolvedValueOnce({});
220
213
  const verified = await signalCli.verifySafetyNumber('+33123456789', '12345 67890 12345 67890 12345 67890');
221
214
  expect(verified).toBe(true);
222
215
  expect(sendJsonRpcRequestSpy).toHaveBeenCalledWith('trust', expect.objectContaining({
223
- recipient: '+33123456789'
216
+ recipient: '+33123456789',
224
217
  }));
225
218
  });
226
219
  it('should fail to verify incorrect safety number', async () => {
@@ -228,8 +221,8 @@ describe('SignalCli Advanced Features', () => {
228
221
  {
229
222
  number: '+33123456789',
230
223
  safetyNumber: '12345 67890 12345 67890 12345 67890',
231
- trustLevel: 'TRUSTED'
232
- }
224
+ trustLevel: 'TRUSTED',
225
+ },
233
226
  ]);
234
227
  const verified = await signalCli.verifySafetyNumber('+33123456789', '99999 99999 99999 99999 99999 99999');
235
228
  expect(verified).toBe(false);
@@ -239,15 +232,11 @@ describe('SignalCli Advanced Features', () => {
239
232
  { number: '+33111111111', trustLevel: 'TRUSTED' },
240
233
  { number: '+33222222222', trustLevel: 'UNTRUSTED' },
241
234
  { number: '+33333333333', trustLevel: 'TRUST_ON_FIRST_USE' },
242
- { number: '+33444444444' }
235
+ { number: '+33444444444' },
243
236
  ]);
244
237
  const untrusted = await signalCli.listUntrustedIdentities();
245
238
  expect(untrusted).toHaveLength(3);
246
- expect(untrusted.map(i => i.number)).toEqual([
247
- '+33222222222',
248
- '+33333333333',
249
- '+33444444444'
250
- ]);
239
+ expect(untrusted.map((i) => i.number)).toEqual(['+33222222222', '+33333333333', '+33444444444']);
251
240
  });
252
241
  });
253
242
  describe('Advanced Group Management', () => {
@@ -257,23 +246,23 @@ describe('SignalCli Advanced Features', () => {
257
246
  {
258
247
  groupId: 'group123==',
259
248
  name: 'Test Group',
260
- groupInviteLink: 'https://signal.group/...'
261
- }
249
+ groupInviteLink: 'https://signal.group/...',
250
+ },
262
251
  ]);
263
252
  // Mock sendMessage response
264
253
  sendJsonRpcRequestSpy.mockResolvedValueOnce({ timestamp: Date.now() });
265
254
  await signalCli.sendGroupInviteLink('group123==', '+33123456789');
266
255
  expect(sendJsonRpcRequestSpy).toHaveBeenCalledWith('send', expect.objectContaining({
267
256
  message: expect.stringContaining('https://signal.group/'),
268
- recipients: ['+33123456789']
257
+ recipients: ['+33123456789'],
269
258
  }));
270
259
  });
271
260
  it('should throw error when group has no invite link', async () => {
272
261
  sendJsonRpcRequestSpy.mockResolvedValue([
273
262
  {
274
263
  groupId: 'group123==',
275
- name: 'Test Group'
276
- }
264
+ name: 'Test Group',
265
+ },
277
266
  ]);
278
267
  await expect(signalCli.sendGroupInviteLink('group123==', '+33123456789')).rejects.toThrow('Group not found or does not have an invite link');
279
268
  });
@@ -281,14 +270,14 @@ describe('SignalCli Advanced Features', () => {
281
270
  await signalCli.setBannedMembers('group123==', ['+33111111111', '+33222222222']);
282
271
  expect(sendJsonRpcRequestSpy).toHaveBeenCalledWith('updateGroup', expect.objectContaining({
283
272
  groupId: 'group123==',
284
- banMembers: ['+33111111111', '+33222222222']
273
+ banMembers: ['+33111111111', '+33222222222'],
285
274
  }));
286
275
  });
287
276
  it('should reset group link', async () => {
288
277
  await signalCli.resetGroupLink('group123==');
289
278
  expect(sendJsonRpcRequestSpy).toHaveBeenCalledWith('updateGroup', expect.objectContaining({
290
279
  groupId: 'group123==',
291
- resetLink: true
280
+ resetLink: true,
292
281
  }));
293
282
  });
294
283
  });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const SignalCli_1 = require("../SignalCli");
37
+ const net = __importStar(require("net"));
38
+ const http = __importStar(require("http"));
39
+ const events_1 = require("events");
40
+ jest.mock('net');
41
+ jest.mock('http');
42
+ jest.mock('https');
43
+ describe('SignalCli Connections', () => {
44
+ let signalCli;
45
+ let mockSocket;
46
+ beforeEach(() => {
47
+ jest.clearAllMocks();
48
+ mockSocket = new events_1.EventEmitter();
49
+ mockSocket.write = jest.fn();
50
+ mockSocket.destroy = jest.fn();
51
+ net.createConnection.mockReturnValue(mockSocket);
52
+ });
53
+ it('should connect via Unix socket', async () => {
54
+ signalCli = new SignalCli_1.SignalCli('+1234567890', undefined, {
55
+ daemonMode: 'unix-socket',
56
+ socketPath: '/tmp/test.sock'
57
+ });
58
+ const connectPromise = signalCli.connect();
59
+ setImmediate(() => mockSocket.emit('connect'));
60
+ await connectPromise;
61
+ expect(net.createConnection).toHaveBeenCalledWith('/tmp/test.sock');
62
+ });
63
+ it('should connect via TCP', async () => {
64
+ signalCli = new SignalCli_1.SignalCli('+1234567890', undefined, {
65
+ daemonMode: 'tcp',
66
+ tcpHost: '1.2.3.4',
67
+ tcpPort: 1234
68
+ });
69
+ const connectPromise = signalCli.connect();
70
+ setImmediate(() => mockSocket.emit('connect'));
71
+ await connectPromise;
72
+ expect(net.createConnection).toHaveBeenCalledWith(1234, '1.2.3.4');
73
+ });
74
+ it('should connect via HTTP', async () => {
75
+ const mockRes = new events_1.EventEmitter();
76
+ mockRes.on = jest.fn().mockImplementation((event, cb) => {
77
+ if (event === 'data')
78
+ cb(JSON.stringify({ jsonrpc: '2.0', result: 'ok', id: '1' }));
79
+ if (event === 'end')
80
+ cb();
81
+ return mockRes;
82
+ });
83
+ const mockReq = new events_1.EventEmitter();
84
+ mockReq.write = jest.fn();
85
+ mockReq.end = jest.fn();
86
+ mockReq.setTimeout = jest.fn();
87
+ http.request.mockImplementation((url, opts, cb) => {
88
+ setImmediate(() => cb(mockRes));
89
+ return mockReq;
90
+ });
91
+ signalCli = new SignalCli_1.SignalCli('+1234567890', undefined, {
92
+ daemonMode: 'http',
93
+ httpBaseUrl: 'http://localhost:8080'
94
+ });
95
+ await signalCli.connect();
96
+ expect(http.request).toHaveBeenCalled();
97
+ });
98
+ it('should handle socket data and errors', async () => {
99
+ signalCli = new SignalCli_1.SignalCli('+1234567890', undefined, {
100
+ daemonMode: 'tcp'
101
+ });
102
+ const connectPromise = signalCli.connect();
103
+ setImmediate(() => mockSocket.emit('connect'));
104
+ await connectPromise;
105
+ const errorSpy = jest.fn();
106
+ signalCli.on('error', errorSpy);
107
+ mockSocket.emit('data', Buffer.from('invalid json\n'));
108
+ expect(errorSpy).toHaveBeenCalled();
109
+ });
110
+ });
@@ -16,23 +16,17 @@ describe('SignalCli - E2E Workflow Tests (Phase 6)', () => {
16
16
  });
17
17
  describe('Complete Messaging Workflow', () => {
18
18
  it('should send message with full options and handle response', async () => {
19
- signal.sendJsonRpcRequest = jest.fn()
20
- .mockResolvedValue(mockSendResponse);
19
+ signal.sendJsonRpcRequest = jest.fn().mockResolvedValue(mockSendResponse);
21
20
  const result = await signal.sendMessage('+33987654321', 'Hello!', {
22
21
  attachments: ['/path/to/image.jpg'],
23
- textStyles: [
24
- { start: 0, length: 5, style: 'BOLD' },
25
- ],
26
- mentions: [
27
- { start: 0, length: 5, number: '+33987654321' },
28
- ],
22
+ textStyles: [{ start: 0, length: 5, style: 'BOLD' }],
23
+ mentions: [{ start: 0, length: 5, number: '+33987654321' }],
29
24
  });
30
25
  expect(result.timestamp).toBeDefined();
31
26
  expect(result.results).toBeDefined();
32
27
  });
33
28
  it('should send quoted message with attachments', async () => {
34
- signal.sendJsonRpcRequest = jest.fn()
35
- .mockResolvedValue(mockSendResponse);
29
+ signal.sendJsonRpcRequest = jest.fn().mockResolvedValue(mockSendResponse);
36
30
  const result = await signal.sendMessage('+33987654321', 'Reply', {
37
31
  quote: {
38
32
  timestamp: 1234567890,
@@ -60,7 +54,8 @@ describe('SignalCli - E2E Workflow Tests (Phase 6)', () => {
60
54
  blocked: false,
61
55
  },
62
56
  ];
63
- signal.sendJsonRpcRequest = jest.fn()
57
+ signal.sendJsonRpcRequest = jest
58
+ .fn()
64
59
  .mockResolvedValueOnce(mockContacts)
65
60
  .mockResolvedValueOnce(undefined)
66
61
  .mockResolvedValueOnce([mockContacts[0]]);
@@ -80,10 +75,7 @@ describe('SignalCli - E2E Workflow Tests (Phase 6)', () => {
80
75
  isMember: true,
81
76
  isBlocked: false,
82
77
  messageExpirationTime: 0,
83
- members: [
84
- { number: '+33111111111' },
85
- { number: '+33222222222' },
86
- ],
78
+ members: [{ number: '+33111111111' }, { number: '+33222222222' }],
87
79
  pendingMembers: [],
88
80
  requestingMembers: [],
89
81
  admins: [{ number: '+33111111111' }],
@@ -93,17 +85,15 @@ describe('SignalCli - E2E Workflow Tests (Phase 6)', () => {
93
85
  permissionSendMessage: 'EVERY_MEMBER',
94
86
  groupInviteLink: 'https://signal.group/test',
95
87
  };
96
- signal.sendJsonRpcRequest = jest.fn()
88
+ signal.sendJsonRpcRequest = jest
89
+ .fn()
97
90
  .mockResolvedValueOnce([mockGroup])
98
91
  .mockResolvedValueOnce(undefined)
99
92
  .mockResolvedValueOnce(mockSendResponse)
100
93
  .mockResolvedValueOnce([
101
94
  {
102
95
  ...mockGroup,
103
- members: [
104
- ...mockGroup.members,
105
- { number: '+33333333333' },
106
- ],
96
+ members: [...mockGroup.members, { number: '+33333333333' }],
107
97
  },
108
98
  ]);
109
99
  const groups = await signal.getGroupsWithDetails();
@@ -120,11 +110,14 @@ describe('SignalCli - E2E Workflow Tests (Phase 6)', () => {
120
110
  describe('Identity Management Workflow', () => {
121
111
  it('should verify safety number before sending', async () => {
122
112
  const mockSafetyNumber = '12345 67890 12345 67890 12345 67890';
123
- const mockIdentities = [{
113
+ const mockIdentities = [
114
+ {
124
115
  safetyNumber: mockSafetyNumber,
125
116
  number: '+33987654321',
126
- }];
127
- signal.sendJsonRpcRequest = jest.fn()
117
+ },
118
+ ];
119
+ signal.sendJsonRpcRequest = jest
120
+ .fn()
128
121
  .mockResolvedValueOnce(mockIdentities) // listIdentities
129
122
  .mockResolvedValueOnce(mockIdentities) // listIdentities again for verify
130
123
  .mockResolvedValueOnce(undefined) // trust
@@ -138,7 +131,8 @@ describe('SignalCli - E2E Workflow Tests (Phase 6)', () => {
138
131
  });
139
132
  describe('Username Management Workflow', () => {
140
133
  it('should manage username lifecycle', async () => {
141
- signal.sendJsonRpcRequest = jest.fn()
134
+ signal.sendJsonRpcRequest = jest
135
+ .fn()
142
136
  .mockResolvedValueOnce({ username: 'alice.01' })
143
137
  .mockResolvedValueOnce(mockSendResponse)
144
138
  .mockResolvedValueOnce(undefined);
@@ -176,7 +170,8 @@ describe('SignalCli - E2E Workflow Tests (Phase 6)', () => {
176
170
  },
177
171
  },
178
172
  ];
179
- signal.sendJsonRpcRequest = jest.fn()
173
+ signal.sendJsonRpcRequest = jest
174
+ .fn()
180
175
  .mockResolvedValueOnce(mockMessages)
181
176
  .mockResolvedValueOnce(mockSendResponse)
182
177
  .mockResolvedValueOnce(mockSendResponse);
@@ -188,7 +183,8 @@ describe('SignalCli - E2E Workflow Tests (Phase 6)', () => {
188
183
  if (msg0.envelope && msg0.envelope.source) {
189
184
  await signal.sendMessage(msg0.envelope.source, 'Hello back!');
190
185
  }
191
- if (msg1.envelope && msg1.envelope.dataMessage &&
186
+ if (msg1.envelope &&
187
+ msg1.envelope.dataMessage &&
192
188
  msg1.envelope.dataMessage.groupInfo &&
193
189
  msg1.envelope.dataMessage.groupInfo.groupId) {
194
190
  await signal.sendMessage(msg1.envelope.dataMessage.groupInfo.groupId, 'Hi everyone!');
@@ -200,7 +196,8 @@ describe('SignalCli - E2E Workflow Tests (Phase 6)', () => {
200
196
  describe('Multi-Step Group Operations', () => {
201
197
  it('should create group, add members, and send announcement', async () => {
202
198
  const mockGroupId = 'newgroup123==';
203
- signal.sendJsonRpcRequest = jest.fn()
199
+ signal.sendJsonRpcRequest = jest
200
+ .fn()
204
201
  .mockResolvedValueOnce({ groupId: mockGroupId })
205
202
  .mockResolvedValueOnce(undefined)
206
203
  .mockResolvedValueOnce(undefined)
@@ -220,7 +217,8 @@ describe('SignalCli - E2E Workflow Tests (Phase 6)', () => {
220
217
  });
221
218
  describe('Error Handling in Workflows', () => {
222
219
  it('should handle errors gracefully in message sending workflow', async () => {
223
- signal.sendJsonRpcRequest = jest.fn()
220
+ signal.sendJsonRpcRequest = jest
221
+ .fn()
224
222
  .mockRejectedValueOnce(new Error('Network error'))
225
223
  .mockResolvedValueOnce(mockSendResponse);
226
224
  await expect(signal.sendMessage('+33987654321', 'Test')).rejects.toThrow('Network error');
@@ -228,12 +226,10 @@ describe('SignalCli - E2E Workflow Tests (Phase 6)', () => {
228
226
  expect(result.timestamp).toBeDefined();
229
227
  });
230
228
  it('should handle non-existent group in workflow', async () => {
231
- signal.sendJsonRpcRequest = jest.fn()
232
- .mockResolvedValue([]);
229
+ signal.sendJsonRpcRequest = jest.fn().mockResolvedValue([]);
233
230
  const groups = await signal.getGroupsWithDetails();
234
231
  expect(groups).toHaveLength(0);
235
- signal.sendJsonRpcRequest = jest.fn()
236
- .mockRejectedValue(new Error('Group not found'));
232
+ signal.sendJsonRpcRequest = jest.fn().mockRejectedValue(new Error('Group not found'));
237
233
  await expect(signal.sendMessage('nonexistent==', 'Test')).rejects.toThrow('Group not found');
238
234
  });
239
235
  });
@@ -0,0 +1 @@
1
+ export {};