@nyaruka/temba-components 0.41.7 → 0.42.1
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/CHANGELOG.md +17 -0
- package/demo/index.html +22 -0
- package/dist/{973a6cc2.js → dae3a0ce.js} +398 -158
- package/dist/index.js +398 -158
- package/dist/sw.js +1 -1
- package/dist/sw.js.map +1 -1
- package/dist/templates/components-body.html +1 -1
- package/dist/templates/components-head.html +1 -1
- package/out-tsc/src/aliaseditor/AliasEditor.js +2 -1
- package/out-tsc/src/aliaseditor/AliasEditor.js.map +1 -1
- package/out-tsc/src/button/Button.js +3 -3
- package/out-tsc/src/button/Button.js.map +1 -1
- package/out-tsc/src/charcount/CharCount.js +5 -4
- package/out-tsc/src/charcount/CharCount.js.map +1 -1
- package/out-tsc/src/completion/Completion.js +5 -0
- package/out-tsc/src/completion/Completion.js.map +1 -1
- package/out-tsc/src/compose/Compose.js +532 -0
- package/out-tsc/src/compose/Compose.js.map +1 -0
- package/out-tsc/src/contacts/ContactChat.js +73 -69
- package/out-tsc/src/contacts/ContactChat.js.map +1 -1
- package/out-tsc/src/contacts/ContactHistory.js +1 -1
- package/out-tsc/src/contacts/ContactHistory.js.map +1 -1
- package/out-tsc/src/contacts/events.js +1 -0
- package/out-tsc/src/contacts/events.js.map +1 -1
- package/out-tsc/src/interfaces.js +2 -0
- package/out-tsc/src/interfaces.js.map +1 -1
- package/out-tsc/src/textinput/TextInput.js +3 -1
- package/out-tsc/src/textinput/TextInput.js.map +1 -1
- package/out-tsc/src/utils/index.js +10 -0
- package/out-tsc/src/utils/index.js.map +1 -1
- package/out-tsc/src/vectoricon/index.js +1 -0
- package/out-tsc/src/vectoricon/index.js.map +1 -1
- package/out-tsc/temba-modules.js +2 -0
- package/out-tsc/temba-modules.js.map +1 -1
- package/out-tsc/test/temba-compose.test.js +432 -0
- package/out-tsc/test/temba-compose.test.js.map +1 -0
- package/out-tsc/test/temba-contact-chat.test.js +219 -47
- package/out-tsc/test/temba-contact-chat.test.js.map +1 -1
- package/out-tsc/test/temba-contact-history.test.js +7 -3
- package/out-tsc/test/temba-contact-history.test.js.map +1 -1
- package/out-tsc/test/utils.test.js +12 -8
- package/out-tsc/test/utils.test.js.map +1 -1
- package/package.json +1 -1
- package/screenshots/truth/compose/attachments-and-send-button.png +0 -0
- package/screenshots/truth/compose/attachments-no-send-button.png +0 -0
- package/screenshots/truth/compose/attachments-with-all-files-and-click-send.png +0 -0
- package/screenshots/truth/compose/attachments-with-all-files.png +0 -0
- package/screenshots/truth/compose/attachments-with-failure-files.png +0 -0
- package/screenshots/truth/compose/attachments-with-success-files-and-click-send.png +0 -0
- package/screenshots/truth/compose/attachments-with-success-files.png +0 -0
- package/screenshots/truth/compose/chatbox-attachments-counter-and-send-button.png +0 -0
- package/screenshots/truth/compose/chatbox-attachments-counter-no-send-button.png +0 -0
- package/screenshots/truth/compose/chatbox-attachments-no-counter-and-send-button.png +0 -0
- package/screenshots/truth/compose/chatbox-attachments-no-counter-no-send-button.png +0 -0
- package/screenshots/truth/compose/chatbox-counter-and-send-button.png +0 -0
- package/screenshots/truth/compose/chatbox-counter-no-send-button.png +0 -0
- package/screenshots/truth/compose/chatbox-no-counter-and-send-button.png +0 -0
- package/screenshots/truth/compose/chatbox-no-counter-no-send-button.png +0 -0
- package/screenshots/truth/compose/chatbox-no-text-attachments-with-all-files-and-click-send.png +0 -0
- package/screenshots/truth/compose/chatbox-no-text-attachments-with-all-files.png +0 -0
- package/screenshots/truth/compose/chatbox-no-text-attachments-with-failure-files.png +0 -0
- package/screenshots/truth/compose/chatbox-no-text-attachments-with-success-files-and-click-send.png +0 -0
- package/screenshots/truth/compose/chatbox-no-text-attachments-with-success-files.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text-and-click-send.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text-and-hit-enter.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text-and-spaces.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text-and-url.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text-attachments-no-files-and-click-send.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text-attachments-no-files-and-hit-enter.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text-attachments-no-files.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text-attachments-with-all-files-and-click-send.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text-attachments-with-all-files-and-hit-enter.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text-attachments-with-all-files.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text-attachments-with-failure-files.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text-attachments-with-success-files-and-click-send.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text-attachments-with-success-files-and-hit-enter.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text-attachments-with-success-files.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text-no-spaces.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text.png +0 -0
- package/screenshots/truth/contacts/badges.png +0 -0
- package/screenshots/truth/contacts/compose-attachments-no-text-failure.png +0 -0
- package/screenshots/truth/contacts/compose-attachments-no-text-success.png +0 -0
- package/screenshots/truth/contacts/compose-text-and-attachments-failure-attachments.png +0 -0
- package/screenshots/truth/contacts/compose-text-and-attachments-failure-generic.png +0 -0
- package/screenshots/truth/contacts/compose-text-and-attachments-failure-text-and-attachments.png +0 -0
- package/screenshots/truth/contacts/compose-text-and-attachments-failure-text.png +0 -0
- package/screenshots/truth/contacts/compose-text-and-attachments-success.png +0 -0
- package/screenshots/truth/contacts/compose-text-no-attachments-failure.png +0 -0
- package/screenshots/truth/contacts/compose-text-no-attachments-success.png +0 -0
- package/screenshots/truth/contacts/contact-active-default.png +0 -0
- package/screenshots/truth/contacts/contact-active-show-chatbox.png +0 -0
- package/screenshots/truth/contacts/contact-active-ticket-closed-show-reopen-button.png +0 -0
- package/screenshots/truth/contacts/contact-active-ticket-open-show-chatbox.png +0 -0
- package/screenshots/truth/contacts/contact-archived-hide-chatbox.png +0 -0
- package/screenshots/truth/contacts/contact-archived-ticket-closed-hide-chatbox.png +0 -0
- package/screenshots/truth/contacts/contact-blocked-hide-chatbox.png +0 -0
- package/screenshots/truth/contacts/contact-stopped-hide-chatbox.png +0 -0
- package/screenshots/truth/contacts/history.png +0 -0
- package/screenshots/truth/counter/summary.png +0 -0
- package/screenshots/truth/counter/text.png +0 -0
- package/screenshots/truth/counter/unicode-variables.png +0 -0
- package/screenshots/truth/counter/unicode.png +0 -0
- package/screenshots/truth/counter/variable.png +0 -0
- package/src/aliaseditor/AliasEditor.ts +2 -1
- package/src/button/Button.ts +3 -3
- package/src/charcount/CharCount.ts +5 -4
- package/src/completion/Completion.ts +4 -0
- package/src/compose/Compose.ts +585 -0
- package/src/contacts/ContactChat.ts +75 -78
- package/src/contacts/ContactHistory.ts +1 -1
- package/src/contacts/events.ts +1 -0
- package/src/interfaces.ts +2 -0
- package/src/textinput/TextInput.ts +3 -1
- package/src/utils/index.ts +12 -0
- package/src/vectoricon/index.ts +1 -0
- package/static/css/temba-components.css +6 -0
- package/temba-modules.ts +2 -0
- package/test/temba-compose.test.ts +633 -0
- package/test/temba-contact-chat.test.ts +354 -110
- package/test/temba-contact-history.test.ts +10 -5
- package/test/utils.test.ts +24 -9
- package/screenshots/truth/contacts/history-expanded.png +0 -0
|
@@ -1,17 +1,25 @@
|
|
|
1
|
-
import { expect, waitUntil } from '@open-wc/testing';
|
|
2
1
|
import { useFakeTimers } from 'sinon';
|
|
2
|
+
import { Button } from '../src/button/Button';
|
|
3
|
+
import { Compose } from '../src/compose/Compose';
|
|
3
4
|
import { ContactChat } from '../src/contacts/ContactChat';
|
|
4
|
-
import { ContactHistory } from '../src/contacts/ContactHistory';
|
|
5
5
|
import { CustomEventType } from '../src/interfaces';
|
|
6
6
|
import { TicketList } from '../src/list/TicketList';
|
|
7
7
|
import {
|
|
8
8
|
assertScreenshot,
|
|
9
|
+
clearMockPosts,
|
|
9
10
|
getClip,
|
|
10
11
|
getComponent,
|
|
11
12
|
loadStore,
|
|
12
13
|
mockGET,
|
|
13
14
|
mockNow,
|
|
15
|
+
mockPOST,
|
|
14
16
|
} from '../test/utils.test';
|
|
17
|
+
import {
|
|
18
|
+
getFailText,
|
|
19
|
+
getSuccessFiles,
|
|
20
|
+
getSuccessText,
|
|
21
|
+
updateComponent,
|
|
22
|
+
} from './temba-compose.test';
|
|
15
23
|
|
|
16
24
|
let clock: any;
|
|
17
25
|
mockNow('2021-03-31T00:31:00.000-00:00');
|
|
@@ -85,21 +93,6 @@ describe('temba-contact-chat - contact tests', () => {
|
|
|
85
93
|
contact: 'contact-dave-active',
|
|
86
94
|
});
|
|
87
95
|
|
|
88
|
-
const chatHistoryEl = chat.shadowRoot.querySelector(
|
|
89
|
-
'temba-contact-history'
|
|
90
|
-
) as ContactHistory;
|
|
91
|
-
expect(chatHistoryEl).to.not.equal(null);
|
|
92
|
-
|
|
93
|
-
const chatboxDivEl = chat.shadowRoot.querySelector(
|
|
94
|
-
'.chatbox'
|
|
95
|
-
) as HTMLDivElement;
|
|
96
|
-
expect(chatboxDivEl).to.not.equal(null);
|
|
97
|
-
|
|
98
|
-
const reopenButton = chat.shadowRoot.querySelector(
|
|
99
|
-
'temba-button#reopen-button'
|
|
100
|
-
) as HTMLDivElement;
|
|
101
|
-
expect(reopenButton).to.equal(null);
|
|
102
|
-
|
|
103
96
|
await assertScreenshot(
|
|
104
97
|
'contacts/contact-active-show-chatbox',
|
|
105
98
|
getClip(chat)
|
|
@@ -113,21 +106,6 @@ describe('temba-contact-chat - contact tests', () => {
|
|
|
113
106
|
contact: 'contact-barack-archived',
|
|
114
107
|
});
|
|
115
108
|
|
|
116
|
-
const chatHistoryEl = chat.shadowRoot.querySelector(
|
|
117
|
-
'temba-contact-history'
|
|
118
|
-
) as ContactHistory;
|
|
119
|
-
expect(chatHistoryEl).to.not.equal(null);
|
|
120
|
-
|
|
121
|
-
const chatboxDiv = chat.shadowRoot.querySelector(
|
|
122
|
-
'.chatbox'
|
|
123
|
-
) as HTMLDivElement;
|
|
124
|
-
expect(chatboxDiv).to.equal(null);
|
|
125
|
-
|
|
126
|
-
const reopenButton = chat.shadowRoot.querySelector(
|
|
127
|
-
'temba-button#reopen-button'
|
|
128
|
-
) as HTMLDivElement;
|
|
129
|
-
expect(reopenButton).to.equal(null);
|
|
130
|
-
|
|
131
109
|
await assertScreenshot(
|
|
132
110
|
'contacts/contact-archived-hide-chatbox',
|
|
133
111
|
getClip(chat)
|
|
@@ -141,21 +119,6 @@ describe('temba-contact-chat - contact tests', () => {
|
|
|
141
119
|
contact: 'contact-michelle-blocked',
|
|
142
120
|
});
|
|
143
121
|
|
|
144
|
-
const chatHistoryEl = chat.shadowRoot.querySelector(
|
|
145
|
-
'temba-contact-history'
|
|
146
|
-
) as ContactHistory;
|
|
147
|
-
expect(chatHistoryEl).to.not.equal(null);
|
|
148
|
-
|
|
149
|
-
const chatboxDiv = chat.shadowRoot.querySelector(
|
|
150
|
-
'.chatbox'
|
|
151
|
-
) as HTMLDivElement;
|
|
152
|
-
expect(chatboxDiv).to.equal(null);
|
|
153
|
-
|
|
154
|
-
const reopenButton = chat.shadowRoot.querySelector(
|
|
155
|
-
'temba-button#reopen-button'
|
|
156
|
-
) as HTMLDivElement;
|
|
157
|
-
expect(reopenButton).to.equal(null);
|
|
158
|
-
|
|
159
122
|
await assertScreenshot(
|
|
160
123
|
'contacts/contact-blocked-hide-chatbox',
|
|
161
124
|
getClip(chat)
|
|
@@ -169,23 +132,338 @@ describe('temba-contact-chat - contact tests', () => {
|
|
|
169
132
|
contact: 'contact-tim-stopped',
|
|
170
133
|
});
|
|
171
134
|
|
|
172
|
-
|
|
173
|
-
'
|
|
174
|
-
|
|
175
|
-
|
|
135
|
+
await assertScreenshot(
|
|
136
|
+
'contacts/contact-stopped-hide-chatbox',
|
|
137
|
+
getClip(chat)
|
|
138
|
+
);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
describe('temba-contact-chat - contact tests - handle send tests - text no attachments', () => {
|
|
143
|
+
beforeEach(() => {
|
|
144
|
+
clearMockPosts();
|
|
145
|
+
mockGET(
|
|
146
|
+
/\/contact\/history\/contact-.*/,
|
|
147
|
+
'/test-assets/contacts/history.json'
|
|
148
|
+
);
|
|
149
|
+
clock = useFakeTimers();
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
afterEach(function () {
|
|
153
|
+
clock.restore();
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('with text no attachments - success', async () => {
|
|
157
|
+
// we are a StoreElement, so load a store first
|
|
158
|
+
await loadStore();
|
|
159
|
+
const chat: ContactChat = await getContactChat({
|
|
160
|
+
contact: 'contact-dave-active',
|
|
161
|
+
});
|
|
162
|
+
const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;
|
|
163
|
+
await updateComponent(compose, getSuccessText());
|
|
176
164
|
|
|
177
|
-
const
|
|
178
|
-
'
|
|
179
|
-
|
|
180
|
-
|
|
165
|
+
const response_body = {
|
|
166
|
+
contacts: [{ uuid: 'contact-dave-active', name: 'Dave Matthews' }],
|
|
167
|
+
text: { eng: 'sà-wàd-dee!' },
|
|
168
|
+
attachments: { eng: [] },
|
|
169
|
+
};
|
|
170
|
+
mockPOST(/api\/v2\/broadcasts\.json/, response_body);
|
|
181
171
|
|
|
182
|
-
const
|
|
183
|
-
'temba-button#
|
|
184
|
-
) as
|
|
185
|
-
|
|
172
|
+
const send = compose.shadowRoot.querySelector(
|
|
173
|
+
'temba-button#send-button'
|
|
174
|
+
) as Button;
|
|
175
|
+
send.click();
|
|
186
176
|
|
|
187
177
|
await assertScreenshot(
|
|
188
|
-
'contacts/
|
|
178
|
+
'contacts/compose-text-no-attachments-success',
|
|
179
|
+
getClip(chat)
|
|
180
|
+
);
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it('with text no attachments - failure - more than 640 chars', async () => {
|
|
184
|
+
// we are a StoreElement, so load a store first
|
|
185
|
+
await loadStore();
|
|
186
|
+
const chat: ContactChat = await getContactChat({
|
|
187
|
+
contact: 'contact-dave-active',
|
|
188
|
+
});
|
|
189
|
+
const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;
|
|
190
|
+
// set the chatbox to a string that is 640+ chars
|
|
191
|
+
await updateComponent(compose, getFailText());
|
|
192
|
+
|
|
193
|
+
const response_body = {
|
|
194
|
+
text: { eng: ['Ensure this field has no more than 640 characters.'] },
|
|
195
|
+
};
|
|
196
|
+
const response_headers = {};
|
|
197
|
+
const response_status = '400';
|
|
198
|
+
mockPOST(
|
|
199
|
+
/api\/v2\/broadcasts\.json/,
|
|
200
|
+
response_body,
|
|
201
|
+
response_headers,
|
|
202
|
+
response_status
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
const send = compose.shadowRoot.querySelector(
|
|
206
|
+
'temba-button#send-button'
|
|
207
|
+
) as Button;
|
|
208
|
+
send.click();
|
|
209
|
+
|
|
210
|
+
await assertScreenshot(
|
|
211
|
+
'contacts/compose-text-no-attachments-failure',
|
|
212
|
+
getClip(chat)
|
|
213
|
+
);
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
describe('temba-contact-chat - contact tests - handle send tests - attachments no text', () => {
|
|
218
|
+
beforeEach(() => {
|
|
219
|
+
clearMockPosts();
|
|
220
|
+
mockGET(
|
|
221
|
+
/\/contact\/history\/contact-.*/,
|
|
222
|
+
'/test-assets/contacts/history.json'
|
|
223
|
+
);
|
|
224
|
+
clock = useFakeTimers();
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
afterEach(function () {
|
|
228
|
+
clock.restore();
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
it('with attachments no text - success', async () => {
|
|
232
|
+
// we are a StoreElement, so load a store first
|
|
233
|
+
await loadStore();
|
|
234
|
+
const chat: ContactChat = await getContactChat({
|
|
235
|
+
contact: 'contact-dave-active',
|
|
236
|
+
});
|
|
237
|
+
const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;
|
|
238
|
+
const attachments = getSuccessFiles();
|
|
239
|
+
await updateComponent(compose, null, attachments);
|
|
240
|
+
const response_body = {
|
|
241
|
+
contacts: [{ uuid: 'contact-dave-active', name: 'Dave Matthews' }],
|
|
242
|
+
text: { eng: '' },
|
|
243
|
+
attachments: { eng: attachments },
|
|
244
|
+
};
|
|
245
|
+
const response_headers = {};
|
|
246
|
+
const response_status = '200';
|
|
247
|
+
mockPOST(
|
|
248
|
+
/api\/v2\/broadcasts\.json/,
|
|
249
|
+
response_body,
|
|
250
|
+
response_headers,
|
|
251
|
+
response_status
|
|
252
|
+
);
|
|
253
|
+
|
|
254
|
+
const send = compose.shadowRoot.querySelector(
|
|
255
|
+
'temba-button#send-button'
|
|
256
|
+
) as Button;
|
|
257
|
+
send.click();
|
|
258
|
+
|
|
259
|
+
await assertScreenshot(
|
|
260
|
+
'contacts/compose-attachments-no-text-success',
|
|
261
|
+
getClip(chat)
|
|
262
|
+
);
|
|
263
|
+
});
|
|
264
|
+
it('with attachments no text - failure - more than 10 files', async () => {
|
|
265
|
+
// we are a StoreElement, so load a store first
|
|
266
|
+
await loadStore();
|
|
267
|
+
const chat: ContactChat = await getContactChat({
|
|
268
|
+
contact: 'contact-dave-active',
|
|
269
|
+
});
|
|
270
|
+
const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;
|
|
271
|
+
// set the attachments to a list that is 10+ items
|
|
272
|
+
await updateComponent(compose, null, getSuccessFiles(11));
|
|
273
|
+
|
|
274
|
+
const response_body = {
|
|
275
|
+
attachments: { eng: ['Ensure this field has no more than 10 elements.'] },
|
|
276
|
+
};
|
|
277
|
+
const response_headers = {};
|
|
278
|
+
const response_status = '400';
|
|
279
|
+
mockPOST(
|
|
280
|
+
/api\/v2\/broadcasts\.json/,
|
|
281
|
+
response_body,
|
|
282
|
+
response_headers,
|
|
283
|
+
response_status
|
|
284
|
+
);
|
|
285
|
+
|
|
286
|
+
const send = compose.shadowRoot.querySelector(
|
|
287
|
+
'temba-button#send-button'
|
|
288
|
+
) as Button;
|
|
289
|
+
send.click();
|
|
290
|
+
|
|
291
|
+
await assertScreenshot(
|
|
292
|
+
'contacts/compose-attachments-no-text-failure',
|
|
293
|
+
getClip(chat)
|
|
294
|
+
);
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
describe('temba-contact-chat - contact tests - handle send tests - text and attachments', () => {
|
|
299
|
+
beforeEach(() => {
|
|
300
|
+
clearMockPosts();
|
|
301
|
+
mockGET(
|
|
302
|
+
/\/contact\/history\/contact-.*/,
|
|
303
|
+
'/test-assets/contacts/history.json'
|
|
304
|
+
);
|
|
305
|
+
clock = useFakeTimers();
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
afterEach(function () {
|
|
309
|
+
clock.restore();
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
it('with text and attachments - success', async () => {
|
|
313
|
+
// we are a StoreElement, so load a store first
|
|
314
|
+
await loadStore();
|
|
315
|
+
const chat: ContactChat = await getContactChat({
|
|
316
|
+
contact: 'contact-dave-active',
|
|
317
|
+
});
|
|
318
|
+
const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;
|
|
319
|
+
await updateComponent(compose, getSuccessText(), getSuccessFiles());
|
|
320
|
+
|
|
321
|
+
const text = getSuccessText();
|
|
322
|
+
const attachments = getSuccessFiles();
|
|
323
|
+
const response_body = {
|
|
324
|
+
contacts: [{ uuid: 'contact-dave-active', name: 'Dave Matthews' }],
|
|
325
|
+
text: { eng: text },
|
|
326
|
+
attachments: { eng: attachments },
|
|
327
|
+
};
|
|
328
|
+
mockPOST(/api\/v2\/broadcasts\.json/, response_body);
|
|
329
|
+
|
|
330
|
+
const send = compose.shadowRoot.querySelector(
|
|
331
|
+
'temba-button#send-button'
|
|
332
|
+
) as Button;
|
|
333
|
+
send.click();
|
|
334
|
+
|
|
335
|
+
await assertScreenshot(
|
|
336
|
+
'contacts/compose-text-and-attachments-success',
|
|
337
|
+
getClip(chat)
|
|
338
|
+
);
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
it('with text and attachments - failure - more than 640 chars', async () => {
|
|
342
|
+
// we are a StoreElement, so load a store first
|
|
343
|
+
await loadStore();
|
|
344
|
+
const chat: ContactChat = await getContactChat({
|
|
345
|
+
contact: 'contact-dave-active',
|
|
346
|
+
});
|
|
347
|
+
const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;
|
|
348
|
+
// set the chatbox to a string that is 640+ chars
|
|
349
|
+
await updateComponent(compose, getFailText(), getSuccessFiles());
|
|
350
|
+
|
|
351
|
+
const response_body = {
|
|
352
|
+
text: { eng: ['Ensure this field has no more than 640 characters.'] },
|
|
353
|
+
};
|
|
354
|
+
const response_headers = {};
|
|
355
|
+
const response_status = '400';
|
|
356
|
+
mockPOST(
|
|
357
|
+
/api\/v2\/broadcasts\.json/,
|
|
358
|
+
response_body,
|
|
359
|
+
response_headers,
|
|
360
|
+
response_status
|
|
361
|
+
);
|
|
362
|
+
|
|
363
|
+
const send = compose.shadowRoot.querySelector(
|
|
364
|
+
'temba-button#send-button'
|
|
365
|
+
) as Button;
|
|
366
|
+
send.click();
|
|
367
|
+
|
|
368
|
+
await assertScreenshot(
|
|
369
|
+
'contacts/compose-text-and-attachments-failure-text',
|
|
370
|
+
getClip(chat)
|
|
371
|
+
);
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
it('with text and attachments - failure - more than 10 files', async () => {
|
|
375
|
+
// we are a StoreElement, so load a store first
|
|
376
|
+
await loadStore();
|
|
377
|
+
const chat: ContactChat = await getContactChat({
|
|
378
|
+
contact: 'contact-dave-active',
|
|
379
|
+
});
|
|
380
|
+
const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;
|
|
381
|
+
// set the attachments to a list that is 10+ items
|
|
382
|
+
await updateComponent(compose, getSuccessText(), getSuccessFiles(11));
|
|
383
|
+
|
|
384
|
+
const response_body = {
|
|
385
|
+
attachments: { eng: ['Ensure this field has no more than 10 elements.'] },
|
|
386
|
+
};
|
|
387
|
+
const response_headers = {};
|
|
388
|
+
const response_status = '400';
|
|
389
|
+
mockPOST(
|
|
390
|
+
/api\/v2\/broadcasts\.json/,
|
|
391
|
+
response_body,
|
|
392
|
+
response_headers,
|
|
393
|
+
response_status
|
|
394
|
+
);
|
|
395
|
+
|
|
396
|
+
const send = compose.shadowRoot.querySelector(
|
|
397
|
+
'temba-button#send-button'
|
|
398
|
+
) as Button;
|
|
399
|
+
send.click();
|
|
400
|
+
|
|
401
|
+
await assertScreenshot(
|
|
402
|
+
'contacts/compose-text-and-attachments-failure-attachments',
|
|
403
|
+
getClip(chat)
|
|
404
|
+
);
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
it('with text and attachments - failure - more than 640 chars and more than 10 files', async () => {
|
|
408
|
+
// we are a StoreElement, so load a store first
|
|
409
|
+
await loadStore();
|
|
410
|
+
const chat: ContactChat = await getContactChat({
|
|
411
|
+
contact: 'contact-dave-active',
|
|
412
|
+
});
|
|
413
|
+
const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;
|
|
414
|
+
// set the chatbox to a string that is 640+ chars
|
|
415
|
+
// set the attachments to a list that is 10+ items
|
|
416
|
+
await updateComponent(compose, getFailText(), getSuccessFiles(11));
|
|
417
|
+
|
|
418
|
+
const response_body = {
|
|
419
|
+
text: { eng: ['Ensure this field has no more than 640 characters.'] },
|
|
420
|
+
};
|
|
421
|
+
const response_headers = {};
|
|
422
|
+
const response_status = '400';
|
|
423
|
+
mockPOST(
|
|
424
|
+
/api\/v2\/broadcasts\.json/,
|
|
425
|
+
response_body,
|
|
426
|
+
response_headers,
|
|
427
|
+
response_status
|
|
428
|
+
);
|
|
429
|
+
|
|
430
|
+
const send = compose.shadowRoot.querySelector(
|
|
431
|
+
'temba-button#send-button'
|
|
432
|
+
) as Button;
|
|
433
|
+
send.click();
|
|
434
|
+
|
|
435
|
+
await assertScreenshot(
|
|
436
|
+
'contacts/compose-text-and-attachments-failure-text-and-attachments',
|
|
437
|
+
getClip(chat)
|
|
438
|
+
);
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
it('with text and attachments - failure - generic', async () => {
|
|
442
|
+
// we are a StoreElement, so load a store first
|
|
443
|
+
await loadStore();
|
|
444
|
+
const chat: ContactChat = await getContactChat({
|
|
445
|
+
contact: 'contact-dave-active',
|
|
446
|
+
});
|
|
447
|
+
const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;
|
|
448
|
+
await updateComponent(compose, getSuccessText(), getSuccessFiles());
|
|
449
|
+
|
|
450
|
+
const response_body = {};
|
|
451
|
+
const response_headers = {};
|
|
452
|
+
const response_status = '500';
|
|
453
|
+
mockPOST(
|
|
454
|
+
/api\/v2\/broadcasts\.json/,
|
|
455
|
+
response_body,
|
|
456
|
+
response_headers,
|
|
457
|
+
response_status
|
|
458
|
+
);
|
|
459
|
+
|
|
460
|
+
const send = compose.shadowRoot.querySelector(
|
|
461
|
+
'temba-button#send-button'
|
|
462
|
+
) as Button;
|
|
463
|
+
send.click();
|
|
464
|
+
|
|
465
|
+
await assertScreenshot(
|
|
466
|
+
'contacts/compose-text-and-attachments-failure-generic',
|
|
189
467
|
getClip(chat)
|
|
190
468
|
);
|
|
191
469
|
});
|
|
@@ -221,29 +499,25 @@ describe('temba-contact-chat - ticket tests', () => {
|
|
|
221
499
|
|
|
222
500
|
chat.currentTicket = tickets.items[0];
|
|
223
501
|
chat.refresh();
|
|
502
|
+
await chat.httpComplete;
|
|
224
503
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
expect(chatHistoryEl).to.not.equal(null);
|
|
229
|
-
|
|
230
|
-
const chatboxDiv = chat.shadowRoot.querySelector(
|
|
231
|
-
'.chatbox'
|
|
232
|
-
) as HTMLDivElement;
|
|
233
|
-
expect(chatboxDiv).to.not.equal(null);
|
|
234
|
-
|
|
235
|
-
const reopenButton = chat.shadowRoot.querySelector(
|
|
236
|
-
'temba-button#reopen-button'
|
|
237
|
-
) as HTMLDivElement;
|
|
238
|
-
expect(reopenButton).to.equal(null);
|
|
239
|
-
|
|
504
|
+
// we want to wait until our scroll is finished before taking our screenshot
|
|
505
|
+
// once we have two scrollTops that are the same, we'll assume we're ready
|
|
506
|
+
let lastScroll = 0;
|
|
240
507
|
await assertScreenshot(
|
|
241
508
|
'contacts/contact-active-ticket-open-show-chatbox',
|
|
242
509
|
getClip(chat),
|
|
243
510
|
{
|
|
244
511
|
clock: clock,
|
|
245
|
-
predicate: () =>
|
|
246
|
-
|
|
512
|
+
predicate: () => {
|
|
513
|
+
const currentScroll = chat
|
|
514
|
+
.getContactHistory()
|
|
515
|
+
.getEventsPane().scrollTop;
|
|
516
|
+
if (currentScroll !== 0 && currentScroll === lastScroll) {
|
|
517
|
+
return true;
|
|
518
|
+
}
|
|
519
|
+
lastScroll = currentScroll;
|
|
520
|
+
},
|
|
247
521
|
}
|
|
248
522
|
);
|
|
249
523
|
});
|
|
@@ -260,31 +534,15 @@ describe('temba-contact-chat - ticket tests', () => {
|
|
|
260
534
|
});
|
|
261
535
|
chat.currentTicket = tickets.items[0];
|
|
262
536
|
chat.refresh();
|
|
263
|
-
|
|
264
537
|
await chat.httpComplete;
|
|
265
538
|
|
|
266
|
-
const chatHistoryEl = chat.shadowRoot.querySelector(
|
|
267
|
-
'temba-contact-history'
|
|
268
|
-
) as ContactHistory;
|
|
269
|
-
expect(chatHistoryEl).to.not.equal(null);
|
|
270
|
-
|
|
271
|
-
const chatboxDiv = chat.shadowRoot.querySelector(
|
|
272
|
-
'.chatbox'
|
|
273
|
-
) as HTMLDivElement;
|
|
274
|
-
expect(chatboxDiv).to.equal(null);
|
|
275
|
-
|
|
276
|
-
const reopenButton = chat.shadowRoot.querySelector(
|
|
277
|
-
'temba-button#reopen-button'
|
|
278
|
-
) as HTMLDivElement;
|
|
279
|
-
expect(reopenButton).to.not.equal(null);
|
|
280
|
-
|
|
281
539
|
await assertScreenshot(
|
|
282
540
|
'contacts/contact-active-ticket-closed-show-reopen-button',
|
|
283
541
|
getClip(chat),
|
|
284
542
|
{
|
|
285
543
|
clock: clock,
|
|
286
544
|
predicate: () => {
|
|
287
|
-
return chat.getContactHistory().getEventsPane().scrollTop ===
|
|
545
|
+
return chat.getContactHistory().getEventsPane().scrollTop === 921;
|
|
288
546
|
},
|
|
289
547
|
}
|
|
290
548
|
);
|
|
@@ -303,21 +561,7 @@ describe('temba-contact-chat - ticket tests', () => {
|
|
|
303
561
|
});
|
|
304
562
|
chat.currentTicket = tickets.items[0];
|
|
305
563
|
chat.refresh();
|
|
306
|
-
|
|
307
|
-
const chatHistoryEl = chat.shadowRoot.querySelector(
|
|
308
|
-
'temba-contact-history'
|
|
309
|
-
) as ContactHistory;
|
|
310
|
-
expect(chatHistoryEl).to.not.equal(null);
|
|
311
|
-
|
|
312
|
-
const chatboxDiv = chat.shadowRoot.querySelector(
|
|
313
|
-
'.chatbox'
|
|
314
|
-
) as HTMLDivElement;
|
|
315
|
-
expect(chatboxDiv).to.equal(null);
|
|
316
|
-
|
|
317
|
-
const reopenButton = chat.shadowRoot.querySelector(
|
|
318
|
-
'temba-button#reopen-button'
|
|
319
|
-
) as HTMLDivElement;
|
|
320
|
-
expect(reopenButton).to.equal(null);
|
|
564
|
+
await chat.httpComplete;
|
|
321
565
|
|
|
322
566
|
await assertScreenshot(
|
|
323
567
|
'contacts/contact-archived-ticket-closed-hide-chatbox',
|
|
@@ -325,7 +569,7 @@ describe('temba-contact-chat - ticket tests', () => {
|
|
|
325
569
|
{
|
|
326
570
|
clock: clock,
|
|
327
571
|
predicate: () => {
|
|
328
|
-
return chat.getContactHistory().getEventsPane().scrollTop ===
|
|
572
|
+
return chat.getContactHistory().getEventsPane().scrollTop === 870;
|
|
329
573
|
},
|
|
330
574
|
}
|
|
331
575
|
);
|
|
@@ -18,6 +18,10 @@ export const createHistory = async (def: string) => {
|
|
|
18
18
|
'width: 500px;height:750px;display:flex;flex-direction:column;flex-grow:1;min-height:0;'
|
|
19
19
|
);
|
|
20
20
|
const history = (await fixture(def, { parentNode })) as ContactHistory;
|
|
21
|
+
|
|
22
|
+
// make sure our initial fetch is made
|
|
23
|
+
await history.httpComplete;
|
|
24
|
+
|
|
21
25
|
return history;
|
|
22
26
|
};
|
|
23
27
|
|
|
@@ -57,7 +61,7 @@ describe('temba-contact-history', () => {
|
|
|
57
61
|
clock.restore();
|
|
58
62
|
});
|
|
59
63
|
|
|
60
|
-
it
|
|
64
|
+
it('can be created', async () => {
|
|
61
65
|
const history = await createHistory(getHistoryHTML());
|
|
62
66
|
assert.instanceOf(history, ContactHistory);
|
|
63
67
|
});
|
|
@@ -69,13 +73,14 @@ describe('temba-contact-history', () => {
|
|
|
69
73
|
})
|
|
70
74
|
);
|
|
71
75
|
|
|
72
|
-
// we should have scrolled to the bottom
|
|
76
|
+
// we should have scrolled to the bottom, but the scroll
|
|
77
|
+
// happens in a window timeout
|
|
78
|
+
await clock.runAllAsync();
|
|
79
|
+
await history.updateComplete;
|
|
80
|
+
|
|
73
81
|
const events = history.shadowRoot.querySelector('.events');
|
|
74
82
|
const top = events.scrollHeight - events.getBoundingClientRect().height;
|
|
75
|
-
|
|
76
83
|
expect(top).to.equal(549);
|
|
77
|
-
await clock.runAllAsync();
|
|
78
|
-
|
|
79
84
|
// make sure we actually scrolled to there
|
|
80
85
|
expect(events.scrollTop).to.equal(top);
|
|
81
86
|
await assertScreenshot('contacts/history', getHistoryClip(history));
|
package/test/utils.test.ts
CHANGED
|
@@ -16,10 +16,11 @@ export interface CodeMock {
|
|
|
16
16
|
endpoint: RegExp;
|
|
17
17
|
body: string;
|
|
18
18
|
headers: any;
|
|
19
|
+
status: string;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
const gets: CodeMock[] = [];
|
|
22
|
-
|
|
23
|
+
let posts: CodeMock[] = [];
|
|
23
24
|
let normalFetch;
|
|
24
25
|
|
|
25
26
|
export const showMouse = async () => {
|
|
@@ -53,14 +54,14 @@ export const getComponent = async (
|
|
|
53
54
|
${height > 0 ? `height:${height}px;` : ``}
|
|
54
55
|
${style ? style : ``}
|
|
55
56
|
`;
|
|
56
|
-
|
|
57
57
|
parentNode.setAttribute('style', styleAttribute);
|
|
58
|
-
|
|
58
|
+
const component = await fixture(spec, { parentNode });
|
|
59
|
+
return component;
|
|
59
60
|
};
|
|
60
61
|
|
|
61
62
|
const createResponse = mocked => {
|
|
62
63
|
const mockResponse = new window.Response(mocked.body, {
|
|
63
|
-
status:
|
|
64
|
+
status: mocked.status,
|
|
64
65
|
headers: {
|
|
65
66
|
'Content-type': 'text/html',
|
|
66
67
|
...mocked.headers,
|
|
@@ -72,7 +73,7 @@ const createResponse = mocked => {
|
|
|
72
73
|
|
|
73
74
|
const createJSONResponse = mocked => {
|
|
74
75
|
const mockResponse = new window.Response(JSON.stringify(mocked.body), {
|
|
75
|
-
status:
|
|
76
|
+
status: mocked.status,
|
|
76
77
|
headers: {
|
|
77
78
|
'Content-type': 'application/json',
|
|
78
79
|
...mocked.headers,
|
|
@@ -114,12 +115,26 @@ after(() => {
|
|
|
114
115
|
(window.fetch as any).restore();
|
|
115
116
|
});
|
|
116
117
|
|
|
117
|
-
export const mockGET = (
|
|
118
|
-
|
|
118
|
+
export const mockGET = (
|
|
119
|
+
endpoint: RegExp,
|
|
120
|
+
body: any,
|
|
121
|
+
headers: any = {},
|
|
122
|
+
status = '200'
|
|
123
|
+
) => {
|
|
124
|
+
gets.push({ endpoint, body, headers, status });
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
export const mockPOST = (
|
|
128
|
+
endpoint: RegExp,
|
|
129
|
+
body: any,
|
|
130
|
+
headers: any = {},
|
|
131
|
+
status = '200'
|
|
132
|
+
) => {
|
|
133
|
+
posts.push({ endpoint, body, headers, status });
|
|
119
134
|
};
|
|
120
135
|
|
|
121
|
-
export const
|
|
122
|
-
posts
|
|
136
|
+
export const clearMockPosts = () => {
|
|
137
|
+
posts = [];
|
|
123
138
|
};
|
|
124
139
|
|
|
125
140
|
export const checkTimers = (clock: any) => {
|
|
Binary file
|