@nyaruka/temba-components 0.109.0 → 0.110.0

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 (82) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/temba-components.js +361 -354
  3. package/dist/temba-components.js.map +1 -1
  4. package/out-tsc/src/compose/Compose.js +62 -106
  5. package/out-tsc/src/compose/Compose.js.map +1 -1
  6. package/out-tsc/src/contacts/ContactChat.js +64 -59
  7. package/out-tsc/src/contacts/ContactChat.js.map +1 -1
  8. package/out-tsc/src/vectoricon/index.js +0 -1
  9. package/out-tsc/src/vectoricon/index.js.map +1 -1
  10. package/out-tsc/test/temba-compose.test.js +24 -440
  11. package/out-tsc/test/temba-compose.test.js.map +1 -1
  12. package/out-tsc/test/temba-contact-chat.test.js +30 -167
  13. package/out-tsc/test/temba-contact-chat.test.js.map +1 -1
  14. package/package.json +1 -1
  15. package/screenshots/truth/compose/attachments-tab.png +0 -0
  16. package/screenshots/truth/compose/attachments-with-failures.png +0 -0
  17. package/screenshots/truth/compose/attachments-with-files-and-failures.png +0 -0
  18. package/screenshots/truth/compose/attachments-with-files-focused.png +0 -0
  19. package/screenshots/truth/compose/attachments-with-files.png +0 -0
  20. package/screenshots/truth/compose/intial-text.png +0 -0
  21. package/screenshots/truth/compose/no-counter.png +0 -0
  22. package/screenshots/truth/compose/wraps-text-and-spaces.png +0 -0
  23. package/screenshots/truth/compose/wraps-text-and-url.png +0 -0
  24. package/screenshots/truth/compose/wraps-text-no-spaces.png +0 -0
  25. package/screenshots/truth/contacts/chat-failure.png +0 -0
  26. package/src/compose/Compose.ts +69 -103
  27. package/src/contacts/ContactChat.ts +69 -70
  28. package/src/untyped.d.ts +1 -1
  29. package/src/vectoricon/index.ts +0 -1
  30. package/test/temba-compose.test.ts +29 -590
  31. package/test/temba-contact-chat.test.ts +30 -263
  32. package/web-test-runner.config.mjs +1 -0
  33. package/screenshots/truth/compose/attachments-and-send-button.png +0 -0
  34. package/screenshots/truth/compose/attachments-no-send-button.png +0 -0
  35. package/screenshots/truth/compose/attachments-with-all-files-and-click-send.png +0 -0
  36. package/screenshots/truth/compose/attachments-with-all-files.png +0 -0
  37. package/screenshots/truth/compose/attachments-with-failure-files.png +0 -0
  38. package/screenshots/truth/compose/attachments-with-success-files-and-click-send.png +0 -0
  39. package/screenshots/truth/compose/attachments-with-success-files.png +0 -0
  40. package/screenshots/truth/compose/chatbox-attachments-counter-and-send-button.png +0 -0
  41. package/screenshots/truth/compose/chatbox-attachments-counter-no-send-button.png +0 -0
  42. package/screenshots/truth/compose/chatbox-attachments-no-counter-and-send-button.png +0 -0
  43. package/screenshots/truth/compose/chatbox-attachments-no-counter-no-send-button.png +0 -0
  44. package/screenshots/truth/compose/chatbox-counter-and-send-button.png +0 -0
  45. package/screenshots/truth/compose/chatbox-counter-no-send-button.png +0 -0
  46. package/screenshots/truth/compose/chatbox-no-counter-and-send-button.png +0 -0
  47. package/screenshots/truth/compose/chatbox-no-counter-no-send-button.png +0 -0
  48. package/screenshots/truth/compose/chatbox-no-text-attachments-with-all-files-and-click-send.png +0 -0
  49. package/screenshots/truth/compose/chatbox-no-text-attachments-with-all-files.png +0 -0
  50. package/screenshots/truth/compose/chatbox-no-text-attachments-with-failure-files.png +0 -0
  51. package/screenshots/truth/compose/chatbox-no-text-attachments-with-success-files-and-click-send.png +0 -0
  52. package/screenshots/truth/compose/chatbox-no-text-attachments-with-success-files.png +0 -0
  53. package/screenshots/truth/compose/chatbox-with-text-and-click-send.png +0 -0
  54. package/screenshots/truth/compose/chatbox-with-text-and-hit-enter.png +0 -0
  55. package/screenshots/truth/compose/chatbox-with-text-and-spaces.png +0 -0
  56. package/screenshots/truth/compose/chatbox-with-text-and-url.png +0 -0
  57. package/screenshots/truth/compose/chatbox-with-text-attachments-no-files-and-click-send.png +0 -0
  58. package/screenshots/truth/compose/chatbox-with-text-attachments-no-files-and-hit-enter.png +0 -0
  59. package/screenshots/truth/compose/chatbox-with-text-attachments-no-files.png +0 -0
  60. package/screenshots/truth/compose/chatbox-with-text-attachments-with-all-files-and-click-send.png +0 -0
  61. package/screenshots/truth/compose/chatbox-with-text-attachments-with-all-files-and-hit-enter.png +0 -0
  62. package/screenshots/truth/compose/chatbox-with-text-attachments-with-all-files.png +0 -0
  63. package/screenshots/truth/compose/chatbox-with-text-attachments-with-failure-files.png +0 -0
  64. package/screenshots/truth/compose/chatbox-with-text-attachments-with-success-files-and-click-send.png +0 -0
  65. package/screenshots/truth/compose/chatbox-with-text-attachments-with-success-files-and-hit-enter.png +0 -0
  66. package/screenshots/truth/compose/chatbox-with-text-attachments-with-success-files.png +0 -0
  67. package/screenshots/truth/compose/chatbox-with-text-no-spaces.png +0 -0
  68. package/screenshots/truth/compose/chatbox-with-text.png +0 -0
  69. package/screenshots/truth/contacts/compose-attachments-no-text-failure.png +0 -0
  70. package/screenshots/truth/contacts/compose-text-and-attachments-failure-attachments.png +0 -0
  71. package/screenshots/truth/contacts/compose-text-and-attachments-failure-generic.png +0 -0
  72. package/screenshots/truth/contacts/compose-text-and-attachments-failure-text-and-attachments.png +0 -0
  73. package/screenshots/truth/contacts/compose-text-and-attachments-failure-text.png +0 -0
  74. package/screenshots/truth/contacts/compose-text-no-attachments-failure.png +0 -0
  75. package/screenshots/truth/contacts/compose-text-no-attachments-success.png +0 -0
  76. /package/screenshots/truth/contacts/{compose-attachments-no-text-success.png → chat-for-active-contact.png} +0 -0
  77. /package/screenshots/truth/contacts/{contact-archived-hide-chatbox.png → chat-for-archived-contact.png} +0 -0
  78. /package/screenshots/truth/contacts/{contact-blocked-hide-chatbox.png → chat-for-blocked-contact.png} +0 -0
  79. /package/screenshots/truth/contacts/{contact-stopped-hide-chatbox.png → chat-for-stopped-contact.png} +0 -0
  80. /package/screenshots/truth/contacts/{compose-text-and-attachments-success.png → chat-sends-attachments-only.png} +0 -0
  81. /package/screenshots/truth/contacts/{contact-active-default.png → chat-sends-text-and-attachments.png} +0 -0
  82. /package/screenshots/truth/contacts/{contact-active-show-chatbox.png → chat-sends-text-only.png} +0 -0
@@ -1,7 +1,7 @@
1
1
  import { useFakeTimers } from 'sinon';
2
2
  import { Compose } from '../src/compose/Compose';
3
3
  import { ContactChat } from '../src/contacts/ContactChat';
4
- import { Attachment } from '../src/interfaces';
4
+ import { Attachment, CustomEventType } from '../src/interfaces';
5
5
  import {
6
6
  assertScreenshot,
7
7
  clearMockPosts,
@@ -13,12 +13,12 @@ import {
13
13
  mockPOST
14
14
  } from '../test/utils.test';
15
15
  import {
16
- getInvalidText,
17
16
  getValidAttachments,
18
17
  getValidText,
19
18
  updateComponent
20
19
  } from './temba-compose.test';
21
- import { Completion } from '../src/completion/Completion';
20
+
21
+ import { expect, oneEvent } from '@open-wc/testing';
22
22
 
23
23
  let clock: any;
24
24
  mockNow('2021-03-31T00:31:00.000-00:00');
@@ -48,13 +48,12 @@ const getResponseSuccessFiles = (attachments: Attachment[]) => {
48
48
  });
49
49
  return response_attachments;
50
50
  };
51
- const responseTextError = 'Maximum allowed text is 640 characters.';
52
- const responseAttachmentError = 'Maximum allowed attachments is 10 files.';
53
51
 
54
- describe('temba-contact-chat - contact tests', () => {
52
+ describe('temba-contact-chat', () => {
55
53
  // map requests for contact history to our static files
56
54
  // we'll just us the same historylist for everybody for now
57
55
  beforeEach(() => {
56
+ clearMockPosts();
58
57
  mockGET(
59
58
  /\/contact\/history\/contact-.*/,
60
59
  '/test-assets/contacts/history.json'
@@ -66,16 +65,6 @@ describe('temba-contact-chat - contact tests', () => {
66
65
  clock.restore();
67
66
  });
68
67
 
69
- it('can be created', async () => {
70
- // we are a StoreElement, so load a store first
71
- await loadStore();
72
- const chat: ContactChat = await getContactChat({
73
- contact: 'contact-dave-active'
74
- });
75
-
76
- await assertScreenshot('contacts/contact-active-default', getClip(chat));
77
- });
78
-
79
68
  it('show history and show chatbox if contact is active', async () => {
80
69
  // we are a StoreElement, so load a store first
81
70
  await loadStore();
@@ -83,10 +72,7 @@ describe('temba-contact-chat - contact tests', () => {
83
72
  contact: 'contact-dave-active'
84
73
  });
85
74
 
86
- await assertScreenshot(
87
- 'contacts/contact-active-show-chatbox',
88
- getClip(chat)
89
- );
75
+ await assertScreenshot('contacts/chat-for-active-contact', getClip(chat));
90
76
  });
91
77
 
92
78
  it('show history and hide chatbox if contact is archived', async () => {
@@ -96,10 +82,7 @@ describe('temba-contact-chat - contact tests', () => {
96
82
  contact: 'contact-barack-archived'
97
83
  });
98
84
 
99
- await assertScreenshot(
100
- 'contacts/contact-archived-hide-chatbox',
101
- getClip(chat)
102
- );
85
+ await assertScreenshot('contacts/chat-for-archived-contact', getClip(chat));
103
86
  });
104
87
 
105
88
  it('show history and hide chatbox if contact is blocked', async () => {
@@ -109,10 +92,7 @@ describe('temba-contact-chat - contact tests', () => {
109
92
  contact: 'contact-michelle-blocked'
110
93
  });
111
94
 
112
- await assertScreenshot(
113
- 'contacts/contact-blocked-hide-chatbox',
114
- getClip(chat)
115
- );
95
+ await assertScreenshot('contacts/chat-for-blocked-contact', getClip(chat));
116
96
  });
117
97
 
118
98
  it('show history and hide chatbox if contact is stopped', async () => {
@@ -122,28 +102,10 @@ describe('temba-contact-chat - contact tests', () => {
122
102
  contact: 'contact-tim-stopped'
123
103
  });
124
104
 
125
- await assertScreenshot(
126
- 'contacts/contact-stopped-hide-chatbox',
127
- getClip(chat)
128
- );
129
- });
130
- });
131
-
132
- describe('temba-contact-chat - contact tests - handle send tests - text no attachments', () => {
133
- beforeEach(() => {
134
- clearMockPosts();
135
- mockGET(
136
- /\/contact\/history\/contact-.*/,
137
- '/test-assets/contacts/history.json'
138
- );
139
- clock = useFakeTimers();
140
- });
141
-
142
- afterEach(function () {
143
- clock.restore();
105
+ await assertScreenshot('contacts/chat-for-stopped-contact', getClip(chat));
144
106
  });
145
107
 
146
- it('with text no attachments - success', async () => {
108
+ it('sends text without attachments', async () => {
147
109
  // we are a StoreElement, so load a store first
148
110
  await loadStore();
149
111
  const chat: ContactChat = await getContactChat({
@@ -160,64 +122,14 @@ describe('temba-contact-chat - contact tests - handle send tests - text no attac
160
122
  };
161
123
  mockPOST(/api\/v2\/messages\.json/, response_body);
162
124
 
163
- // press enter
164
- const chatbox = compose.shadowRoot.querySelector('.chatbox') as Completion;
165
- chatbox.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' }));
166
-
167
- await assertScreenshot(
168
- 'contacts/compose-text-no-attachments-success',
169
- getClip(chat)
170
- );
171
- });
172
-
173
- it('with text no attachments - failure - more than 640 chars', async () => {
174
- // we are a StoreElement, so load a store first
175
- await loadStore();
176
- const chat: ContactChat = await getContactChat({
177
- contact: 'contact-dave-active'
178
- });
179
- const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;
180
- // set the chatbox to a string that is 640+ chars
181
- await updateComponent(compose, getInvalidText());
182
-
183
- const response_body = {
184
- text: [responseTextError]
185
- };
186
- const response_headers = {};
187
- const response_status = '400';
188
- mockPOST(
189
- /api\/v2\/messages\.json/,
190
- response_body,
191
- response_headers,
192
- response_status
193
- );
194
-
195
- // press enter
196
- const chatbox = compose.shadowRoot.querySelector('.chatbox') as Completion;
197
- chatbox.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' }));
198
-
199
- await assertScreenshot(
200
- 'contacts/compose-text-no-attachments-failure',
201
- getClip(chat)
202
- );
203
- });
204
- });
205
-
206
- describe('temba-contact-chat - contact tests - handle send tests - attachments no text', () => {
207
- beforeEach(() => {
208
- clearMockPosts();
209
- mockGET(
210
- /\/contact\/history\/contact-.*/,
211
- '/test-assets/contacts/history.json'
212
- );
213
- clock = useFakeTimers();
214
- });
125
+ const listener = oneEvent(compose, CustomEventType.Submitted, false);
126
+ await typeInto('temba-contact-chat:temba-compose', text, true, true);
127
+ expect(await listener).to.exist;
215
128
 
216
- afterEach(function () {
217
- clock.restore();
129
+ await assertScreenshot('contacts/chat-sends-text-only', getClip(chat));
218
130
  });
219
131
 
220
- it('with attachments no text - success', async () => {
132
+ it('sends attachments without text', async () => {
221
133
  // we are a StoreElement, so load a store first
222
134
  await loadStore();
223
135
  const chat: ContactChat = await getContactChat({
@@ -241,63 +153,17 @@ describe('temba-contact-chat - contact tests - handle send tests - attachments n
241
153
  response_status
242
154
  );
243
155
 
244
- // press enter
245
- const chatbox = compose.shadowRoot.querySelector('.chatbox') as Completion;
246
- chatbox.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' }));
247
-
248
- await assertScreenshot(
249
- 'contacts/compose-attachments-no-text-success',
250
- getClip(chat)
251
- );
252
- });
253
- it('with attachments no text - failure - more than 10 files', async () => {
254
- // we are a StoreElement, so load a store first
255
- await loadStore();
256
- const chat: ContactChat = await getContactChat({
257
- contact: 'contact-dave-active'
258
- });
259
- const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;
260
- // set the attachments to a list that is 10+ items
261
- await updateComponent(compose, null, getValidAttachments(11));
262
-
263
- const response_body = {
264
- attachments: [responseAttachmentError]
265
- };
266
- const response_headers = {};
267
- const response_status = '400';
268
- mockPOST(
269
- /api\/v2\/messages\.json/,
270
- response_body,
271
- response_headers,
272
- response_status
273
- );
274
-
275
- // press enter
276
- const chatbox = compose.shadowRoot.querySelector('.chatbox') as Completion;
277
- chatbox.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' }));
156
+ const listener = oneEvent(compose, CustomEventType.Submitted, false);
157
+ await typeInto('temba-contact-chat:temba-compose', '', false, true);
158
+ expect(await listener).to.exist;
278
159
 
279
160
  await assertScreenshot(
280
- 'contacts/compose-attachments-no-text-failure',
161
+ 'contacts/chat-sends-attachments-only',
281
162
  getClip(chat)
282
163
  );
283
164
  });
284
- });
285
-
286
- describe('temba-contact-chat - contact tests - handle send tests - text and attachments', () => {
287
- beforeEach(() => {
288
- clearMockPosts();
289
- mockGET(
290
- /\/contact\/history\/contact-.*/,
291
- '/test-assets/contacts/history.json'
292
- );
293
- clock = useFakeTimers();
294
- });
295
-
296
- afterEach(function () {
297
- clock.restore();
298
- });
299
165
 
300
- it('with text and attachments - success', async () => {
166
+ it('sends text with attachments', async () => {
301
167
  // we are a StoreElement, so load a store first
302
168
  await loadStore();
303
169
  const chat: ContactChat = await getContactChat({
@@ -316,114 +182,17 @@ describe('temba-contact-chat - contact tests - handle send tests - text and atta
316
182
  mockPOST(/api\/v2\/messages\.json/, response_body);
317
183
 
318
184
  // press enter
319
- const chatbox = compose.shadowRoot.querySelector('.chatbox') as Completion;
320
- chatbox.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' }));
321
-
322
- await assertScreenshot(
323
- 'contacts/compose-text-and-attachments-success',
324
- getClip(chat)
325
- );
326
- });
327
-
328
- it('with text and attachments - failure - more than 640 chars', async () => {
329
- // we are a StoreElement, so load a store first
330
- await loadStore();
331
- const chat: ContactChat = await getContactChat({
332
- contact: 'contact-dave-active'
333
- });
334
- const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;
335
- // set the chatbox to a string that is 640+ chars
336
- await updateComponent(compose, getInvalidText(), getValidAttachments());
337
-
338
- const response_body = {
339
- text: [responseTextError]
340
- };
341
- const response_headers = {};
342
- const response_status = '400';
343
- mockPOST(
344
- /api\/v2\/messages\.json/,
345
- response_body,
346
- response_headers,
347
- response_status
348
- );
349
-
350
- // press enter
351
- const chatbox = compose.shadowRoot.querySelector('.chatbox') as Completion;
352
- chatbox.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' }));
353
-
354
- await assertScreenshot(
355
- 'contacts/compose-text-and-attachments-failure-text',
356
- getClip(chat)
357
- );
358
- });
359
-
360
- it('with text and attachments - failure - more than 10 files', async () => {
361
- // we are a StoreElement, so load a store first
362
- await loadStore();
363
- const chat: ContactChat = await getContactChat({
364
- contact: 'contact-dave-active'
365
- });
366
- const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;
367
- // set the attachments to a list that is 10+ items
368
- await updateComponent(compose, getValidText(), getValidAttachments(11));
369
-
370
- const response_body = {
371
- attachments: [responseAttachmentError]
372
- };
373
- const response_headers = {};
374
- const response_status = '400';
375
- mockPOST(
376
- /api\/v2\/messages\.json/,
377
- response_body,
378
- response_headers,
379
- response_status
380
- );
381
-
382
- // press enter
383
- const chatbox = compose.shadowRoot.querySelector('.chatbox') as Completion;
384
- chatbox.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' }));
385
-
386
- await assertScreenshot(
387
- 'contacts/compose-text-and-attachments-failure-attachments',
388
- getClip(chat)
389
- );
390
- });
391
-
392
- it('with text and attachments - failure - more than 640 chars and more than 10 files', async () => {
393
- // we are a StoreElement, so load a store first
394
- await loadStore();
395
- const chat: ContactChat = await getContactChat({
396
- contact: 'contact-dave-active'
397
- });
398
- const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;
399
- // set the chatbox to a string that is 640+ chars
400
- // set the attachments to a list that is 10+ items
401
- await updateComponent(compose, getInvalidText(), getValidAttachments(11));
402
-
403
- const response_body = {
404
- text: [responseTextError],
405
- attachments: [responseAttachmentError]
406
- };
407
- const response_headers = {};
408
- const response_status = '400';
409
- mockPOST(
410
- /api\/v2\/messages\.json/,
411
- response_body,
412
- response_headers,
413
- response_status
414
- );
415
-
416
- // press enter
417
- const chatbox = compose.shadowRoot.querySelector('.chatbox') as Completion;
418
- chatbox.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' }));
185
+ const listener = oneEvent(compose, CustomEventType.Submitted, false);
186
+ await typeInto('temba-contact-chat:temba-compose', '', false, true);
187
+ expect(await listener).to.exist;
419
188
 
420
189
  await assertScreenshot(
421
- 'contacts/compose-text-and-attachments-failure-text-and-attachments',
190
+ 'contacts/chat-sends-text-and-attachments',
422
191
  getClip(chat)
423
192
  );
424
193
  });
425
194
 
426
- it('with text and attachments - failure - generic', async () => {
195
+ it('shows failure message with retry', async () => {
427
196
  // we are a StoreElement, so load a store first
428
197
  await loadStore();
429
198
  const chat: ContactChat = await getContactChat({
@@ -442,13 +211,11 @@ describe('temba-contact-chat - contact tests - handle send tests - text and atta
442
211
  response_status
443
212
  );
444
213
 
445
- // press enter
446
- const chatbox = compose.shadowRoot.querySelector('.chatbox') as Completion;
447
- chatbox.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' }));
214
+ // press
215
+ const listener = oneEvent(compose, CustomEventType.Submitted, false);
216
+ await typeInto('temba-contact-chat:temba-compose', '', false, true);
217
+ expect(await listener).to.exist;
448
218
 
449
- await assertScreenshot(
450
- 'contacts/compose-text-and-attachments-failure-generic',
451
- getClip(chat)
452
- );
219
+ await assertScreenshot('contacts/chat-failure', getClip(chat));
453
220
  });
454
221
  });
@@ -333,6 +333,7 @@ export default {
333
333
  '--disable-web-security',
334
334
  '--force-device-scale-factor=1',
335
335
  '--no-sandbox',
336
+ '--disable-gpu',
336
337
  ],
337
338
  headless: true,
338
339
  },