@nyaruka/temba-components 0.41.6 → 0.42.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.
- package/CHANGELOG.md +15 -0
- package/demo/index.html +22 -0
- package/dist/{ff5c26bf.js → f3b7c2f1.js} +397 -157
- package/dist/index.js +397 -157
- package/dist/static/img/schemes/ext.svg +34 -0
- package/dist/static/img/schemes/fcm.svg +34 -0
- 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/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 +531 -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/store/Store.js +3 -1
- package/out-tsc/src/store/Store.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 +3 -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 +5 -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/button/Button.ts +3 -3
- package/src/charcount/CharCount.ts +5 -4
- package/src/completion/Completion.ts +4 -0
- package/src/compose/Compose.ts +584 -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/store/Store.ts +3 -1
- package/src/textinput/TextInput.ts +3 -1
- package/src/utils/index.ts +12 -0
- package/src/vectoricon/index.ts +4 -0
- package/static/css/temba-components.css +6 -0
- package/static/img/schemes/ext.svg +34 -0
- package/static/img/schemes/fcm.svg +34 -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,7 +1,7 @@
|
|
|
1
|
-
import { expect } from '@open-wc/testing';
|
|
2
1
|
import { useFakeTimers } from 'sinon';
|
|
3
2
|
import { CustomEventType } from '../src/interfaces';
|
|
4
|
-
import { assertScreenshot, getClip, getComponent, loadStore, mockGET, mockNow, } from '../test/utils.test';
|
|
3
|
+
import { assertScreenshot, clearMockPosts, getClip, getComponent, loadStore, mockGET, mockNow, mockPOST, } from '../test/utils.test';
|
|
4
|
+
import { getFailText, getSuccessFiles, getSuccessText, updateComponent, } from './temba-compose.test';
|
|
5
5
|
let clock;
|
|
6
6
|
mockNow('2021-03-31T00:31:00.000-00:00');
|
|
7
7
|
const TAG = 'temba-contact-chat';
|
|
@@ -49,12 +49,6 @@ describe('temba-contact-chat - contact tests', () => {
|
|
|
49
49
|
const chat = await getContactChat({
|
|
50
50
|
contact: 'contact-dave-active',
|
|
51
51
|
});
|
|
52
|
-
const chatHistoryEl = chat.shadowRoot.querySelector('temba-contact-history');
|
|
53
|
-
expect(chatHistoryEl).to.not.equal(null);
|
|
54
|
-
const chatboxDivEl = chat.shadowRoot.querySelector('.chatbox');
|
|
55
|
-
expect(chatboxDivEl).to.not.equal(null);
|
|
56
|
-
const reopenButton = chat.shadowRoot.querySelector('temba-button#reopen-button');
|
|
57
|
-
expect(reopenButton).to.equal(null);
|
|
58
52
|
await assertScreenshot('contacts/contact-active-show-chatbox', getClip(chat));
|
|
59
53
|
});
|
|
60
54
|
it('show history and hide chatbox if contact is archived', async () => {
|
|
@@ -63,12 +57,6 @@ describe('temba-contact-chat - contact tests', () => {
|
|
|
63
57
|
const chat = await getContactChat({
|
|
64
58
|
contact: 'contact-barack-archived',
|
|
65
59
|
});
|
|
66
|
-
const chatHistoryEl = chat.shadowRoot.querySelector('temba-contact-history');
|
|
67
|
-
expect(chatHistoryEl).to.not.equal(null);
|
|
68
|
-
const chatboxDiv = chat.shadowRoot.querySelector('.chatbox');
|
|
69
|
-
expect(chatboxDiv).to.equal(null);
|
|
70
|
-
const reopenButton = chat.shadowRoot.querySelector('temba-button#reopen-button');
|
|
71
|
-
expect(reopenButton).to.equal(null);
|
|
72
60
|
await assertScreenshot('contacts/contact-archived-hide-chatbox', getClip(chat));
|
|
73
61
|
});
|
|
74
62
|
it('show history and hide chatbox if contact is blocked', async () => {
|
|
@@ -77,12 +65,6 @@ describe('temba-contact-chat - contact tests', () => {
|
|
|
77
65
|
const chat = await getContactChat({
|
|
78
66
|
contact: 'contact-michelle-blocked',
|
|
79
67
|
});
|
|
80
|
-
const chatHistoryEl = chat.shadowRoot.querySelector('temba-contact-history');
|
|
81
|
-
expect(chatHistoryEl).to.not.equal(null);
|
|
82
|
-
const chatboxDiv = chat.shadowRoot.querySelector('.chatbox');
|
|
83
|
-
expect(chatboxDiv).to.equal(null);
|
|
84
|
-
const reopenButton = chat.shadowRoot.querySelector('temba-button#reopen-button');
|
|
85
|
-
expect(reopenButton).to.equal(null);
|
|
86
68
|
await assertScreenshot('contacts/contact-blocked-hide-chatbox', getClip(chat));
|
|
87
69
|
});
|
|
88
70
|
it('show history and hide chatbox if contact is stopped', async () => {
|
|
@@ -91,15 +73,210 @@ describe('temba-contact-chat - contact tests', () => {
|
|
|
91
73
|
const chat = await getContactChat({
|
|
92
74
|
contact: 'contact-tim-stopped',
|
|
93
75
|
});
|
|
94
|
-
const chatHistoryEl = chat.shadowRoot.querySelector('temba-contact-history');
|
|
95
|
-
expect(chatHistoryEl).to.not.equal(null, 'Chat history missing');
|
|
96
|
-
const chatboxDiv = chat.shadowRoot.querySelector('.chatbox');
|
|
97
|
-
expect(chatboxDiv).to.equal(null);
|
|
98
|
-
const reopenButton = chat.shadowRoot.querySelector('temba-button#reopen-button');
|
|
99
|
-
expect(reopenButton).to.equal(null);
|
|
100
76
|
await assertScreenshot('contacts/contact-stopped-hide-chatbox', getClip(chat));
|
|
101
77
|
});
|
|
102
78
|
});
|
|
79
|
+
describe('temba-contact-chat - contact tests - handle send tests - text no attachments', () => {
|
|
80
|
+
beforeEach(() => {
|
|
81
|
+
clearMockPosts();
|
|
82
|
+
mockGET(/\/contact\/history\/contact-.*/, '/test-assets/contacts/history.json');
|
|
83
|
+
clock = useFakeTimers();
|
|
84
|
+
});
|
|
85
|
+
afterEach(function () {
|
|
86
|
+
clock.restore();
|
|
87
|
+
});
|
|
88
|
+
it('with text no attachments - success', async () => {
|
|
89
|
+
// we are a StoreElement, so load a store first
|
|
90
|
+
await loadStore();
|
|
91
|
+
const chat = await getContactChat({
|
|
92
|
+
contact: 'contact-dave-active',
|
|
93
|
+
});
|
|
94
|
+
const compose = chat.shadowRoot.querySelector('temba-compose');
|
|
95
|
+
await updateComponent(compose, getSuccessText());
|
|
96
|
+
const response_body = {
|
|
97
|
+
contacts: [{ uuid: 'contact-dave-active', name: 'Dave Matthews' }],
|
|
98
|
+
text: { eng: 'sà-wàd-dee!' },
|
|
99
|
+
attachments: { eng: [] },
|
|
100
|
+
};
|
|
101
|
+
mockPOST(/api\/v2\/broadcasts\.json/, response_body);
|
|
102
|
+
const send = compose.shadowRoot.querySelector('temba-button#send-button');
|
|
103
|
+
send.click();
|
|
104
|
+
await assertScreenshot('contacts/compose-text-no-attachments-success', getClip(chat));
|
|
105
|
+
});
|
|
106
|
+
it('with text no attachments - failure - more than 640 chars', async () => {
|
|
107
|
+
// we are a StoreElement, so load a store first
|
|
108
|
+
await loadStore();
|
|
109
|
+
const chat = await getContactChat({
|
|
110
|
+
contact: 'contact-dave-active',
|
|
111
|
+
});
|
|
112
|
+
const compose = chat.shadowRoot.querySelector('temba-compose');
|
|
113
|
+
// set the chatbox to a string that is 640+ chars
|
|
114
|
+
await updateComponent(compose, getFailText());
|
|
115
|
+
const response_body = {
|
|
116
|
+
text: { eng: ['Ensure this field has no more than 640 characters.'] },
|
|
117
|
+
};
|
|
118
|
+
const response_headers = {};
|
|
119
|
+
const response_status = '400';
|
|
120
|
+
mockPOST(/api\/v2\/broadcasts\.json/, response_body, response_headers, response_status);
|
|
121
|
+
const send = compose.shadowRoot.querySelector('temba-button#send-button');
|
|
122
|
+
send.click();
|
|
123
|
+
await assertScreenshot('contacts/compose-text-no-attachments-failure', getClip(chat));
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
describe('temba-contact-chat - contact tests - handle send tests - attachments no text', () => {
|
|
127
|
+
beforeEach(() => {
|
|
128
|
+
clearMockPosts();
|
|
129
|
+
mockGET(/\/contact\/history\/contact-.*/, '/test-assets/contacts/history.json');
|
|
130
|
+
clock = useFakeTimers();
|
|
131
|
+
});
|
|
132
|
+
afterEach(function () {
|
|
133
|
+
clock.restore();
|
|
134
|
+
});
|
|
135
|
+
it('with attachments no text - success', async () => {
|
|
136
|
+
// we are a StoreElement, so load a store first
|
|
137
|
+
await loadStore();
|
|
138
|
+
const chat = await getContactChat({
|
|
139
|
+
contact: 'contact-dave-active',
|
|
140
|
+
});
|
|
141
|
+
const compose = chat.shadowRoot.querySelector('temba-compose');
|
|
142
|
+
const attachments = getSuccessFiles();
|
|
143
|
+
await updateComponent(compose, null, attachments);
|
|
144
|
+
const response_body = {
|
|
145
|
+
contacts: [{ uuid: 'contact-dave-active', name: 'Dave Matthews' }],
|
|
146
|
+
text: { eng: '' },
|
|
147
|
+
attachments: { eng: attachments },
|
|
148
|
+
};
|
|
149
|
+
const response_headers = {};
|
|
150
|
+
const response_status = '200';
|
|
151
|
+
mockPOST(/api\/v2\/broadcasts\.json/, response_body, response_headers, response_status);
|
|
152
|
+
const send = compose.shadowRoot.querySelector('temba-button#send-button');
|
|
153
|
+
send.click();
|
|
154
|
+
await assertScreenshot('contacts/compose-attachments-no-text-success', getClip(chat));
|
|
155
|
+
});
|
|
156
|
+
it('with attachments no text - failure - more than 10 files', async () => {
|
|
157
|
+
// we are a StoreElement, so load a store first
|
|
158
|
+
await loadStore();
|
|
159
|
+
const chat = await getContactChat({
|
|
160
|
+
contact: 'contact-dave-active',
|
|
161
|
+
});
|
|
162
|
+
const compose = chat.shadowRoot.querySelector('temba-compose');
|
|
163
|
+
// set the attachments to a list that is 10+ items
|
|
164
|
+
await updateComponent(compose, null, getSuccessFiles(11));
|
|
165
|
+
const response_body = {
|
|
166
|
+
attachments: { eng: ['Ensure this field has no more than 10 elements.'] },
|
|
167
|
+
};
|
|
168
|
+
const response_headers = {};
|
|
169
|
+
const response_status = '400';
|
|
170
|
+
mockPOST(/api\/v2\/broadcasts\.json/, response_body, response_headers, response_status);
|
|
171
|
+
const send = compose.shadowRoot.querySelector('temba-button#send-button');
|
|
172
|
+
send.click();
|
|
173
|
+
await assertScreenshot('contacts/compose-attachments-no-text-failure', getClip(chat));
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
describe('temba-contact-chat - contact tests - handle send tests - text and attachments', () => {
|
|
177
|
+
beforeEach(() => {
|
|
178
|
+
clearMockPosts();
|
|
179
|
+
mockGET(/\/contact\/history\/contact-.*/, '/test-assets/contacts/history.json');
|
|
180
|
+
clock = useFakeTimers();
|
|
181
|
+
});
|
|
182
|
+
afterEach(function () {
|
|
183
|
+
clock.restore();
|
|
184
|
+
});
|
|
185
|
+
it('with text and attachments - success', async () => {
|
|
186
|
+
// we are a StoreElement, so load a store first
|
|
187
|
+
await loadStore();
|
|
188
|
+
const chat = await getContactChat({
|
|
189
|
+
contact: 'contact-dave-active',
|
|
190
|
+
});
|
|
191
|
+
const compose = chat.shadowRoot.querySelector('temba-compose');
|
|
192
|
+
await updateComponent(compose, getSuccessText(), getSuccessFiles());
|
|
193
|
+
const text = getSuccessText();
|
|
194
|
+
const attachments = getSuccessFiles();
|
|
195
|
+
const response_body = {
|
|
196
|
+
contacts: [{ uuid: 'contact-dave-active', name: 'Dave Matthews' }],
|
|
197
|
+
text: { eng: text },
|
|
198
|
+
attachments: { eng: attachments },
|
|
199
|
+
};
|
|
200
|
+
mockPOST(/api\/v2\/broadcasts\.json/, response_body);
|
|
201
|
+
const send = compose.shadowRoot.querySelector('temba-button#send-button');
|
|
202
|
+
send.click();
|
|
203
|
+
await assertScreenshot('contacts/compose-text-and-attachments-success', getClip(chat));
|
|
204
|
+
});
|
|
205
|
+
it('with text and attachments - failure - more than 640 chars', async () => {
|
|
206
|
+
// we are a StoreElement, so load a store first
|
|
207
|
+
await loadStore();
|
|
208
|
+
const chat = await getContactChat({
|
|
209
|
+
contact: 'contact-dave-active',
|
|
210
|
+
});
|
|
211
|
+
const compose = chat.shadowRoot.querySelector('temba-compose');
|
|
212
|
+
// set the chatbox to a string that is 640+ chars
|
|
213
|
+
await updateComponent(compose, getFailText(), getSuccessFiles());
|
|
214
|
+
const response_body = {
|
|
215
|
+
text: { eng: ['Ensure this field has no more than 640 characters.'] },
|
|
216
|
+
};
|
|
217
|
+
const response_headers = {};
|
|
218
|
+
const response_status = '400';
|
|
219
|
+
mockPOST(/api\/v2\/broadcasts\.json/, response_body, response_headers, response_status);
|
|
220
|
+
const send = compose.shadowRoot.querySelector('temba-button#send-button');
|
|
221
|
+
send.click();
|
|
222
|
+
await assertScreenshot('contacts/compose-text-and-attachments-failure-text', getClip(chat));
|
|
223
|
+
});
|
|
224
|
+
it('with text and attachments - failure - more than 10 files', async () => {
|
|
225
|
+
// we are a StoreElement, so load a store first
|
|
226
|
+
await loadStore();
|
|
227
|
+
const chat = await getContactChat({
|
|
228
|
+
contact: 'contact-dave-active',
|
|
229
|
+
});
|
|
230
|
+
const compose = chat.shadowRoot.querySelector('temba-compose');
|
|
231
|
+
// set the attachments to a list that is 10+ items
|
|
232
|
+
await updateComponent(compose, getSuccessText(), getSuccessFiles(11));
|
|
233
|
+
const response_body = {
|
|
234
|
+
attachments: { eng: ['Ensure this field has no more than 10 elements.'] },
|
|
235
|
+
};
|
|
236
|
+
const response_headers = {};
|
|
237
|
+
const response_status = '400';
|
|
238
|
+
mockPOST(/api\/v2\/broadcasts\.json/, response_body, response_headers, response_status);
|
|
239
|
+
const send = compose.shadowRoot.querySelector('temba-button#send-button');
|
|
240
|
+
send.click();
|
|
241
|
+
await assertScreenshot('contacts/compose-text-and-attachments-failure-attachments', getClip(chat));
|
|
242
|
+
});
|
|
243
|
+
it('with text and attachments - failure - more than 640 chars and more than 10 files', async () => {
|
|
244
|
+
// we are a StoreElement, so load a store first
|
|
245
|
+
await loadStore();
|
|
246
|
+
const chat = await getContactChat({
|
|
247
|
+
contact: 'contact-dave-active',
|
|
248
|
+
});
|
|
249
|
+
const compose = chat.shadowRoot.querySelector('temba-compose');
|
|
250
|
+
// set the chatbox to a string that is 640+ chars
|
|
251
|
+
// set the attachments to a list that is 10+ items
|
|
252
|
+
await updateComponent(compose, getFailText(), getSuccessFiles(11));
|
|
253
|
+
const response_body = {
|
|
254
|
+
text: { eng: ['Ensure this field has no more than 640 characters.'] },
|
|
255
|
+
};
|
|
256
|
+
const response_headers = {};
|
|
257
|
+
const response_status = '400';
|
|
258
|
+
mockPOST(/api\/v2\/broadcasts\.json/, response_body, response_headers, response_status);
|
|
259
|
+
const send = compose.shadowRoot.querySelector('temba-button#send-button');
|
|
260
|
+
send.click();
|
|
261
|
+
await assertScreenshot('contacts/compose-text-and-attachments-failure-text-and-attachments', getClip(chat));
|
|
262
|
+
});
|
|
263
|
+
it('with text and attachments - failure - generic', async () => {
|
|
264
|
+
// we are a StoreElement, so load a store first
|
|
265
|
+
await loadStore();
|
|
266
|
+
const chat = await getContactChat({
|
|
267
|
+
contact: 'contact-dave-active',
|
|
268
|
+
});
|
|
269
|
+
const compose = chat.shadowRoot.querySelector('temba-compose');
|
|
270
|
+
await updateComponent(compose, getSuccessText(), getSuccessFiles());
|
|
271
|
+
const response_body = {};
|
|
272
|
+
const response_headers = {};
|
|
273
|
+
const response_status = '500';
|
|
274
|
+
mockPOST(/api\/v2\/broadcasts\.json/, response_body, response_headers, response_status);
|
|
275
|
+
const send = compose.shadowRoot.querySelector('temba-button#send-button');
|
|
276
|
+
send.click();
|
|
277
|
+
await assertScreenshot('contacts/compose-text-and-attachments-failure-generic', getClip(chat));
|
|
278
|
+
});
|
|
279
|
+
});
|
|
103
280
|
describe('temba-contact-chat - ticket tests', () => {
|
|
104
281
|
// map requests for contact history to our static files
|
|
105
282
|
// we'll just us the same history for everybody for now
|
|
@@ -122,15 +299,21 @@ describe('temba-contact-chat - ticket tests', () => {
|
|
|
122
299
|
});
|
|
123
300
|
chat.currentTicket = tickets.items[0];
|
|
124
301
|
chat.refresh();
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
const reopenButton = chat.shadowRoot.querySelector('temba-button#reopen-button');
|
|
130
|
-
expect(reopenButton).to.equal(null);
|
|
302
|
+
await chat.httpComplete;
|
|
303
|
+
// we want to wait until our scroll is finished before taking our screenshot
|
|
304
|
+
// once we have two scrollTops that are the same, we'll assume we're ready
|
|
305
|
+
let lastScroll = 0;
|
|
131
306
|
await assertScreenshot('contacts/contact-active-ticket-open-show-chatbox', getClip(chat), {
|
|
132
307
|
clock: clock,
|
|
133
|
-
predicate: () =>
|
|
308
|
+
predicate: () => {
|
|
309
|
+
const currentScroll = chat
|
|
310
|
+
.getContactHistory()
|
|
311
|
+
.getEventsPane().scrollTop;
|
|
312
|
+
if (currentScroll !== 0 && currentScroll === lastScroll) {
|
|
313
|
+
return true;
|
|
314
|
+
}
|
|
315
|
+
lastScroll = currentScroll;
|
|
316
|
+
},
|
|
134
317
|
});
|
|
135
318
|
});
|
|
136
319
|
it('show history and show reopen button if contact is active and ticket is closed', async () => {
|
|
@@ -145,16 +328,10 @@ describe('temba-contact-chat - ticket tests', () => {
|
|
|
145
328
|
chat.currentTicket = tickets.items[0];
|
|
146
329
|
chat.refresh();
|
|
147
330
|
await chat.httpComplete;
|
|
148
|
-
const chatHistoryEl = chat.shadowRoot.querySelector('temba-contact-history');
|
|
149
|
-
expect(chatHistoryEl).to.not.equal(null);
|
|
150
|
-
const chatboxDiv = chat.shadowRoot.querySelector('.chatbox');
|
|
151
|
-
expect(chatboxDiv).to.equal(null);
|
|
152
|
-
const reopenButton = chat.shadowRoot.querySelector('temba-button#reopen-button');
|
|
153
|
-
expect(reopenButton).to.not.equal(null);
|
|
154
331
|
await assertScreenshot('contacts/contact-active-ticket-closed-show-reopen-button', getClip(chat), {
|
|
155
332
|
clock: clock,
|
|
156
333
|
predicate: () => {
|
|
157
|
-
return chat.getContactHistory().getEventsPane().scrollTop ===
|
|
334
|
+
return chat.getContactHistory().getEventsPane().scrollTop === 921;
|
|
158
335
|
},
|
|
159
336
|
});
|
|
160
337
|
});
|
|
@@ -169,16 +346,11 @@ describe('temba-contact-chat - ticket tests', () => {
|
|
|
169
346
|
});
|
|
170
347
|
chat.currentTicket = tickets.items[0];
|
|
171
348
|
chat.refresh();
|
|
172
|
-
|
|
173
|
-
expect(chatHistoryEl).to.not.equal(null);
|
|
174
|
-
const chatboxDiv = chat.shadowRoot.querySelector('.chatbox');
|
|
175
|
-
expect(chatboxDiv).to.equal(null);
|
|
176
|
-
const reopenButton = chat.shadowRoot.querySelector('temba-button#reopen-button');
|
|
177
|
-
expect(reopenButton).to.equal(null);
|
|
349
|
+
await chat.httpComplete;
|
|
178
350
|
await assertScreenshot('contacts/contact-archived-ticket-closed-hide-chatbox', getClip(chat), {
|
|
179
351
|
clock: clock,
|
|
180
352
|
predicate: () => {
|
|
181
|
-
return chat.getContactHistory().getEventsPane().scrollTop ===
|
|
353
|
+
return chat.getContactHistory().getEventsPane().scrollTop === 870;
|
|
182
354
|
},
|
|
183
355
|
});
|
|
184
356
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"temba-contact-chat.test.js","sourceRoot":"","sources":["../../test/temba-contact-chat.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAa,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAGtC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EACL,gBAAgB,EAChB,OAAO,EACP,YAAY,EACZ,SAAS,EACT,OAAO,EACP,OAAO,GACR,MAAM,oBAAoB,CAAC;AAE5B,IAAI,KAAU,CAAC;AACf,OAAO,CAAC,+BAA+B,CAAC,CAAC;AAEzC,MAAM,GAAG,GAAG,oBAAoB,CAAC;AACjC,MAAM,cAAc,GAAG,KAAK,EAAE,QAAa,EAAE,EAAE,EAAE;IAC/C,KAAK,CAAC,UAAU,CAAC,GAAG,wBAAwB,CAAC;IAC7C,gEAAgE;IAChE,MAAM,IAAI,GAAG,CAAC,MAAM,YAAY,CAC9B,GAAG,EACH,KAAK,EACL,EAAE,EACF,GAAG,EACH,GAAG,EACH,8DAA8D,CAC/D,CAAgB,CAAC;IAElB,oDAAoD;IACpD,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;IACnB,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,QAAQ,GAAG,YAAY,CAAC;AAC9B,MAAM,aAAa,GAAG,KAAK,EAAE,QAAa,EAAE,EAAE,EAAE;IAC9C,MAAM,IAAI,GAAG,CAAC,MAAM,YAAY,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAe,CAAC;IAEjE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;QAClB,OAAO,IAAI,CAAC;KACb;IAED,OAAO,IAAI,OAAO,CAAa,OAAO,CAAC,EAAE;QACvC,IAAI,CAAC,gBAAgB,CACnB,eAAe,CAAC,aAAa,EAC7B,KAAK,IAAI,EAAE;YACT,OAAO,CAAC,IAAI,CAAC,CAAC;QAChB,CAAC,EACD,EAAE,IAAI,EAAE,IAAI,EAAE,CACf,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,QAAQ,CAAC,oCAAoC,EAAE,GAAG,EAAE;IAClD,uDAAuD;IACvD,2DAA2D;IAC3D,UAAU,CAAC,GAAG,EAAE;QACd,OAAO,CACL,gCAAgC,EAChC,oCAAoC,CACrC,CAAC;QACF,KAAK,GAAG,aAAa,EAAE,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC;QACR,KAAK,CAAC,OAAO,EAAE,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gBAAgB,EAAE,KAAK,IAAI,EAAE;QAC9B,+CAA+C;QAC/C,MAAM,SAAS,EAAE,CAAC;QAClB,MAAM,IAAI,GAAgB,MAAM,cAAc,CAAC;YAC7C,OAAO,EAAE,qBAAqB;SAC/B,CAAC,CAAC;QAEH,MAAM,gBAAgB,CAAC,iCAAiC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,+CAA+C;QAC/C,MAAM,SAAS,EAAE,CAAC;QAClB,MAAM,IAAI,GAAgB,MAAM,cAAc,CAAC;YAC7C,OAAO,EAAE,qBAAqB;SAC/B,CAAC,CAAC;QAEH,MAAM,aAAa,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CACjD,uBAAuB,CACN,CAAC;QACpB,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEzC,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAChD,UAAU,CACO,CAAC;QACpB,MAAM,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAExC,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAChD,4BAA4B,CACX,CAAC;QACpB,MAAM,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEpC,MAAM,gBAAgB,CACpB,sCAAsC,EACtC,OAAO,CAAC,IAAI,CAAC,CACd,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;QACpE,+CAA+C;QAC/C,MAAM,SAAS,EAAE,CAAC;QAClB,MAAM,IAAI,GAAgB,MAAM,cAAc,CAAC;YAC7C,OAAO,EAAE,yBAAyB;SACnC,CAAC,CAAC;QAEH,MAAM,aAAa,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CACjD,uBAAuB,CACN,CAAC;QACpB,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEzC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAC9C,UAAU,CACO,CAAC;QACpB,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAElC,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAChD,4BAA4B,CACX,CAAC;QACpB,MAAM,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEpC,MAAM,gBAAgB,CACpB,wCAAwC,EACxC,OAAO,CAAC,IAAI,CAAC,CACd,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,+CAA+C;QAC/C,MAAM,SAAS,EAAE,CAAC;QAClB,MAAM,IAAI,GAAgB,MAAM,cAAc,CAAC;YAC7C,OAAO,EAAE,0BAA0B;SACpC,CAAC,CAAC;QAEH,MAAM,aAAa,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CACjD,uBAAuB,CACN,CAAC;QACpB,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEzC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAC9C,UAAU,CACO,CAAC;QACpB,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAElC,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAChD,4BAA4B,CACX,CAAC;QACpB,MAAM,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEpC,MAAM,gBAAgB,CACpB,uCAAuC,EACvC,OAAO,CAAC,IAAI,CAAC,CACd,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,+CAA+C;QAC/C,MAAM,SAAS,EAAE,CAAC;QAClB,MAAM,IAAI,GAAgB,MAAM,cAAc,CAAC;YAC7C,OAAO,EAAE,qBAAqB;SAC/B,CAAC,CAAC;QAEH,MAAM,aAAa,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CACjD,uBAAuB,CACN,CAAC;QACpB,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAAC;QAEjE,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAC9C,UAAU,CACO,CAAC;QACpB,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAElC,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAChD,4BAA4B,CACX,CAAC;QACpB,MAAM,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEpC,MAAM,gBAAgB,CACpB,uCAAuC,EACvC,OAAO,CAAC,IAAI,CAAC,CACd,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,mCAAmC,EAAE,GAAG,EAAE;IACjD,uDAAuD;IACvD,uDAAuD;IACvD,UAAU,CAAC,GAAG,EAAE;QACd,OAAO,CACL,gCAAgC,EAChC,oCAAoC,CACrC,CAAC;QAEF,OAAO,CAAC,4BAA4B,EAAE,iCAAiC,CAAC,CAAC;QACzE,KAAK,GAAG,aAAa,EAAE,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC;QACR,KAAK,CAAC,OAAO,EAAE,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uEAAuE,EAAE,KAAK,IAAI,EAAE;QACrF,+CAA+C;QAC/C,MAAM,SAAS,EAAE,CAAC;QAClB,MAAM,IAAI,GAAgB,MAAM,cAAc,CAAC;YAC7C,OAAO,EAAE,uBAAuB;SACjC,CAAC,CAAC;QAEH,MAAM,OAAO,GAAe,MAAM,aAAa,CAAC;YAC9C,QAAQ,EAAE,8CAA8C;SACzD,CAAC,CAAC;QAEH,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACtC,IAAI,CAAC,OAAO,EAAE,CAAC;QAEf,MAAM,aAAa,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CACjD,uBAAuB,CACN,CAAC;QACpB,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEzC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAC9C,UAAU,CACO,CAAC;QACpB,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEtC,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAChD,4BAA4B,CACX,CAAC;QACpB,MAAM,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEpC,MAAM,gBAAgB,CACpB,kDAAkD,EAClD,OAAO,CAAC,IAAI,CAAC,EACb;YACE,KAAK,EAAE,KAAK;YACZ,SAAS,EAAE,GAAG,EAAE,CACd,IAAI,CAAC,iBAAiB,EAAE,CAAC,aAAa,EAAE,CAAC,SAAS,KAAK,GAAG;SAC7D,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+EAA+E,EAAE,KAAK,IAAI,EAAE;QAC7F,+CAA+C;QAC/C,MAAM,SAAS,EAAE,CAAC;QAClB,MAAM,IAAI,GAAgB,MAAM,cAAc,CAAC;YAC7C,OAAO,EAAE,uBAAuB;SACjC,CAAC,CAAC;QAEH,MAAM,OAAO,GAAe,MAAM,aAAa,CAAC;YAC9C,QAAQ,EAAE,gDAAgD;SAC3D,CAAC,CAAC;QACH,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACtC,IAAI,CAAC,OAAO,EAAE,CAAC;QAEf,MAAM,IAAI,CAAC,YAAY,CAAC;QAExB,MAAM,aAAa,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CACjD,uBAAuB,CACN,CAAC;QACpB,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEzC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAC9C,UAAU,CACO,CAAC;QACpB,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAElC,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAChD,4BAA4B,CACX,CAAC;QACpB,MAAM,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAExC,MAAM,gBAAgB,CACpB,0DAA0D,EAC1D,OAAO,CAAC,IAAI,CAAC,EACb;YACE,KAAK,EAAE,KAAK;YACZ,SAAS,EAAE,GAAG,EAAE;gBACd,OAAO,IAAI,CAAC,iBAAiB,EAAE,CAAC,aAAa,EAAE,CAAC,SAAS,KAAK,GAAG,CAAC;YACpE,CAAC;SACF,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2EAA2E,EAAE,KAAK,IAAI,EAAE;QACzF,+CAA+C;QAC/C,MAAM,SAAS,EAAE,CAAC;QAElB,MAAM,IAAI,GAAgB,MAAM,cAAc,CAAC;YAC7C,OAAO,EAAE,yBAAyB;SACnC,CAAC,CAAC;QAEH,MAAM,OAAO,GAAe,MAAM,aAAa,CAAC;YAC9C,QAAQ,EAAE,gDAAgD;SAC3D,CAAC,CAAC;QACH,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACtC,IAAI,CAAC,OAAO,EAAE,CAAC;QAEf,MAAM,aAAa,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CACjD,uBAAuB,CACN,CAAC;QACpB,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEzC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAC9C,UAAU,CACO,CAAC;QACpB,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAElC,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAChD,4BAA4B,CACX,CAAC;QACpB,MAAM,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEpC,MAAM,gBAAgB,CACpB,sDAAsD,EACtD,OAAO,CAAC,IAAI,CAAC,EACb;YACE,KAAK,EAAE,KAAK;YACZ,SAAS,EAAE,GAAG,EAAE;gBACd,OAAO,IAAI,CAAC,iBAAiB,EAAE,CAAC,aAAa,EAAE,CAAC,SAAS,KAAK,GAAG,CAAC;YACpE,CAAC;SACF,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { expect, waitUntil } from '@open-wc/testing';\nimport { useFakeTimers } from 'sinon';\nimport { ContactChat } from '../src/contacts/ContactChat';\nimport { ContactHistory } from '../src/contacts/ContactHistory';\nimport { CustomEventType } from '../src/interfaces';\nimport { TicketList } from '../src/list/TicketList';\nimport {\n assertScreenshot,\n getClip,\n getComponent,\n loadStore,\n mockGET,\n mockNow,\n} from '../test/utils.test';\n\nlet clock: any;\nmockNow('2021-03-31T00:31:00.000-00:00');\n\nconst TAG = 'temba-contact-chat';\nconst getContactChat = async (attrs: any = {}) => {\n attrs['endpoint'] = '/test-assets/contacts/';\n // add some sizes and styles to force our chat history to scroll\n const chat = (await getComponent(\n TAG,\n attrs,\n '',\n 500,\n 500,\n 'display:flex;flex-direction:column;flex-grow:1;min-height:0;'\n )) as ContactChat;\n\n // TODO: this should be waiting for an event instead\n await waitFor(100);\n return chat;\n};\n\nconst list_TAG = 'temba-list';\nconst getTicketList = async (attrs: any = {}) => {\n const list = (await getComponent(list_TAG, attrs)) as TicketList;\n\n if (!list.endpoint) {\n return list;\n }\n\n return new Promise<TicketList>(resolve => {\n list.addEventListener(\n CustomEventType.FetchComplete,\n async () => {\n resolve(list);\n },\n { once: true }\n );\n });\n};\n\ndescribe('temba-contact-chat - contact tests', () => {\n // map requests for contact history to our static files\n // we'll just us the same historylist for everybody for now\n beforeEach(() => {\n mockGET(\n /\\/contact\\/history\\/contact-.*/,\n '/test-assets/contacts/history.json'\n );\n clock = useFakeTimers();\n });\n\n afterEach(function () {\n clock.restore();\n });\n\n it('can be created', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n\n await assertScreenshot('contacts/contact-active-default', getClip(chat));\n });\n\n it('show history and show chatbox if contact is active', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n\n const chatHistoryEl = chat.shadowRoot.querySelector(\n 'temba-contact-history'\n ) as ContactHistory;\n expect(chatHistoryEl).to.not.equal(null);\n\n const chatboxDivEl = chat.shadowRoot.querySelector(\n '.chatbox'\n ) as HTMLDivElement;\n expect(chatboxDivEl).to.not.equal(null);\n\n const reopenButton = chat.shadowRoot.querySelector(\n 'temba-button#reopen-button'\n ) as HTMLDivElement;\n expect(reopenButton).to.equal(null);\n\n await assertScreenshot(\n 'contacts/contact-active-show-chatbox',\n getClip(chat)\n );\n });\n\n it('show history and hide chatbox if contact is archived', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-barack-archived',\n });\n\n const chatHistoryEl = chat.shadowRoot.querySelector(\n 'temba-contact-history'\n ) as ContactHistory;\n expect(chatHistoryEl).to.not.equal(null);\n\n const chatboxDiv = chat.shadowRoot.querySelector(\n '.chatbox'\n ) as HTMLDivElement;\n expect(chatboxDiv).to.equal(null);\n\n const reopenButton = chat.shadowRoot.querySelector(\n 'temba-button#reopen-button'\n ) as HTMLDivElement;\n expect(reopenButton).to.equal(null);\n\n await assertScreenshot(\n 'contacts/contact-archived-hide-chatbox',\n getClip(chat)\n );\n });\n\n it('show history and hide chatbox if contact is blocked', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-michelle-blocked',\n });\n\n const chatHistoryEl = chat.shadowRoot.querySelector(\n 'temba-contact-history'\n ) as ContactHistory;\n expect(chatHistoryEl).to.not.equal(null);\n\n const chatboxDiv = chat.shadowRoot.querySelector(\n '.chatbox'\n ) as HTMLDivElement;\n expect(chatboxDiv).to.equal(null);\n\n const reopenButton = chat.shadowRoot.querySelector(\n 'temba-button#reopen-button'\n ) as HTMLDivElement;\n expect(reopenButton).to.equal(null);\n\n await assertScreenshot(\n 'contacts/contact-blocked-hide-chatbox',\n getClip(chat)\n );\n });\n\n it('show history and hide chatbox if contact is stopped', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-tim-stopped',\n });\n\n const chatHistoryEl = chat.shadowRoot.querySelector(\n 'temba-contact-history'\n ) as ContactHistory;\n expect(chatHistoryEl).to.not.equal(null, 'Chat history missing');\n\n const chatboxDiv = chat.shadowRoot.querySelector(\n '.chatbox'\n ) as HTMLDivElement;\n expect(chatboxDiv).to.equal(null);\n\n const reopenButton = chat.shadowRoot.querySelector(\n 'temba-button#reopen-button'\n ) as HTMLDivElement;\n expect(reopenButton).to.equal(null);\n\n await assertScreenshot(\n 'contacts/contact-stopped-hide-chatbox',\n getClip(chat)\n );\n });\n});\n\ndescribe('temba-contact-chat - ticket tests', () => {\n // map requests for contact history to our static files\n // we'll just us the same history for everybody for now\n beforeEach(() => {\n mockGET(\n /\\/contact\\/history\\/contact-.*/,\n '/test-assets/contacts/history.json'\n );\n\n mockGET(/\\/api\\/v2\\/tickets\\.json.*/, '/test-assets/tickets/empty.json');\n clock = useFakeTimers();\n });\n\n afterEach(function () {\n clock.restore();\n });\n\n it('show history and show chatbox if contact is active and ticket is open', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-carter-active',\n });\n\n const tickets: TicketList = await getTicketList({\n endpoint: '/test-assets/tickets/ticket-carter-open.json',\n });\n\n chat.currentTicket = tickets.items[0];\n chat.refresh();\n\n const chatHistoryEl = chat.shadowRoot.querySelector(\n 'temba-contact-history'\n ) as ContactHistory;\n expect(chatHistoryEl).to.not.equal(null);\n\n const chatboxDiv = chat.shadowRoot.querySelector(\n '.chatbox'\n ) as HTMLDivElement;\n expect(chatboxDiv).to.not.equal(null);\n\n const reopenButton = chat.shadowRoot.querySelector(\n 'temba-button#reopen-button'\n ) as HTMLDivElement;\n expect(reopenButton).to.equal(null);\n\n await assertScreenshot(\n 'contacts/contact-active-ticket-open-show-chatbox',\n getClip(chat),\n {\n clock: clock,\n predicate: () =>\n chat.getContactHistory().getEventsPane().scrollTop === 982,\n }\n );\n });\n\n it('show history and show reopen button if contact is active and ticket is closed', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-carter-active',\n });\n\n const tickets: TicketList = await getTicketList({\n endpoint: '/test-assets/tickets/ticket-carter-closed.json',\n });\n chat.currentTicket = tickets.items[0];\n chat.refresh();\n\n await chat.httpComplete;\n\n const chatHistoryEl = chat.shadowRoot.querySelector(\n 'temba-contact-history'\n ) as ContactHistory;\n expect(chatHistoryEl).to.not.equal(null);\n\n const chatboxDiv = chat.shadowRoot.querySelector(\n '.chatbox'\n ) as HTMLDivElement;\n expect(chatboxDiv).to.equal(null);\n\n const reopenButton = chat.shadowRoot.querySelector(\n 'temba-button#reopen-button'\n ) as HTMLDivElement;\n expect(reopenButton).to.not.equal(null);\n\n await assertScreenshot(\n 'contacts/contact-active-ticket-closed-show-reopen-button',\n getClip(chat),\n {\n clock: clock,\n predicate: () => {\n return chat.getContactHistory().getEventsPane().scrollTop === 918;\n },\n }\n );\n });\n\n it('show history and hide chatbox if contact is archived and ticket is closed', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n\n const chat: ContactChat = await getContactChat({\n contact: 'contact-barack-archived',\n });\n\n const tickets: TicketList = await getTicketList({\n endpoint: '/test-assets/tickets/ticket-barack-closed.json',\n });\n chat.currentTicket = tickets.items[0];\n chat.refresh();\n\n const chatHistoryEl = chat.shadowRoot.querySelector(\n 'temba-contact-history'\n ) as ContactHistory;\n expect(chatHistoryEl).to.not.equal(null);\n\n const chatboxDiv = chat.shadowRoot.querySelector(\n '.chatbox'\n ) as HTMLDivElement;\n expect(chatboxDiv).to.equal(null);\n\n const reopenButton = chat.shadowRoot.querySelector(\n 'temba-button#reopen-button'\n ) as HTMLDivElement;\n expect(reopenButton).to.equal(null);\n\n await assertScreenshot(\n 'contacts/contact-archived-ticket-closed-hide-chatbox',\n getClip(chat),\n {\n clock: clock,\n predicate: () => {\n return chat.getContactHistory().getEventsPane().scrollTop === 867;\n },\n }\n );\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"temba-contact-chat.test.js","sourceRoot":"","sources":["../../test/temba-contact-chat.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { useFakeTimers } from 'sinon';\nimport { Button } from '../src/button/Button';\nimport { Compose } from '../src/compose/Compose';\nimport { ContactChat } from '../src/contacts/ContactChat';\nimport { CustomEventType } from '../src/interfaces';\nimport { TicketList } from '../src/list/TicketList';\nimport {\n assertScreenshot,\n clearMockPosts,\n getClip,\n getComponent,\n loadStore,\n mockGET,\n mockNow,\n mockPOST,\n} from '../test/utils.test';\nimport {\n getFailText,\n getSuccessFiles,\n getSuccessText,\n updateComponent,\n} from './temba-compose.test';\n\nlet clock: any;\nmockNow('2021-03-31T00:31:00.000-00:00');\n\nconst TAG = 'temba-contact-chat';\nconst getContactChat = async (attrs: any = {}) => {\n attrs['endpoint'] = '/test-assets/contacts/';\n // add some sizes and styles to force our chat history to scroll\n const chat = (await getComponent(\n TAG,\n attrs,\n '',\n 500,\n 500,\n 'display:flex;flex-direction:column;flex-grow:1;min-height:0;'\n )) as ContactChat;\n\n // TODO: this should be waiting for an event instead\n await waitFor(100);\n return chat;\n};\n\nconst list_TAG = 'temba-list';\nconst getTicketList = async (attrs: any = {}) => {\n const list = (await getComponent(list_TAG, attrs)) as TicketList;\n\n if (!list.endpoint) {\n return list;\n }\n\n return new Promise<TicketList>(resolve => {\n list.addEventListener(\n CustomEventType.FetchComplete,\n async () => {\n resolve(list);\n },\n { once: true }\n );\n });\n};\n\ndescribe('temba-contact-chat - contact tests', () => {\n // map requests for contact history to our static files\n // we'll just us the same historylist for everybody for now\n beforeEach(() => {\n mockGET(\n /\\/contact\\/history\\/contact-.*/,\n '/test-assets/contacts/history.json'\n );\n clock = useFakeTimers();\n });\n\n afterEach(function () {\n clock.restore();\n });\n\n it('can be created', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n\n await assertScreenshot('contacts/contact-active-default', getClip(chat));\n });\n\n it('show history and show chatbox if contact is active', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n\n await assertScreenshot(\n 'contacts/contact-active-show-chatbox',\n getClip(chat)\n );\n });\n\n it('show history and hide chatbox if contact is archived', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-barack-archived',\n });\n\n await assertScreenshot(\n 'contacts/contact-archived-hide-chatbox',\n getClip(chat)\n );\n });\n\n it('show history and hide chatbox if contact is blocked', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-michelle-blocked',\n });\n\n await assertScreenshot(\n 'contacts/contact-blocked-hide-chatbox',\n getClip(chat)\n );\n });\n\n it('show history and hide chatbox if contact is stopped', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-tim-stopped',\n });\n\n await assertScreenshot(\n 'contacts/contact-stopped-hide-chatbox',\n getClip(chat)\n );\n });\n});\n\ndescribe('temba-contact-chat - contact tests - handle send tests - text no attachments', () => {\n beforeEach(() => {\n clearMockPosts();\n mockGET(\n /\\/contact\\/history\\/contact-.*/,\n '/test-assets/contacts/history.json'\n );\n clock = useFakeTimers();\n });\n\n afterEach(function () {\n clock.restore();\n });\n\n it('with text no attachments - success', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;\n await updateComponent(compose, getSuccessText());\n\n const response_body = {\n contacts: [{ uuid: 'contact-dave-active', name: 'Dave Matthews' }],\n text: { eng: 'sà-wàd-dee!' },\n attachments: { eng: [] },\n };\n mockPOST(/api\\/v2\\/broadcasts\\.json/, response_body);\n\n const send = compose.shadowRoot.querySelector(\n 'temba-button#send-button'\n ) as Button;\n send.click();\n\n await assertScreenshot(\n 'contacts/compose-text-no-attachments-success',\n getClip(chat)\n );\n });\n\n it('with text no attachments - failure - more than 640 chars', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;\n // set the chatbox to a string that is 640+ chars\n await updateComponent(compose, getFailText());\n\n const response_body = {\n text: { eng: ['Ensure this field has no more than 640 characters.'] },\n };\n const response_headers = {};\n const response_status = '400';\n mockPOST(\n /api\\/v2\\/broadcasts\\.json/,\n response_body,\n response_headers,\n response_status\n );\n\n const send = compose.shadowRoot.querySelector(\n 'temba-button#send-button'\n ) as Button;\n send.click();\n\n await assertScreenshot(\n 'contacts/compose-text-no-attachments-failure',\n getClip(chat)\n );\n });\n});\n\ndescribe('temba-contact-chat - contact tests - handle send tests - attachments no text', () => {\n beforeEach(() => {\n clearMockPosts();\n mockGET(\n /\\/contact\\/history\\/contact-.*/,\n '/test-assets/contacts/history.json'\n );\n clock = useFakeTimers();\n });\n\n afterEach(function () {\n clock.restore();\n });\n\n it('with attachments no text - success', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;\n const attachments = getSuccessFiles();\n await updateComponent(compose, null, attachments);\n const response_body = {\n contacts: [{ uuid: 'contact-dave-active', name: 'Dave Matthews' }],\n text: { eng: '' },\n attachments: { eng: attachments },\n };\n const response_headers = {};\n const response_status = '200';\n mockPOST(\n /api\\/v2\\/broadcasts\\.json/,\n response_body,\n response_headers,\n response_status\n );\n\n const send = compose.shadowRoot.querySelector(\n 'temba-button#send-button'\n ) as Button;\n send.click();\n\n await assertScreenshot(\n 'contacts/compose-attachments-no-text-success',\n getClip(chat)\n );\n });\n it('with attachments no text - failure - more than 10 files', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;\n // set the attachments to a list that is 10+ items\n await updateComponent(compose, null, getSuccessFiles(11));\n\n const response_body = {\n attachments: { eng: ['Ensure this field has no more than 10 elements.'] },\n };\n const response_headers = {};\n const response_status = '400';\n mockPOST(\n /api\\/v2\\/broadcasts\\.json/,\n response_body,\n response_headers,\n response_status\n );\n\n const send = compose.shadowRoot.querySelector(\n 'temba-button#send-button'\n ) as Button;\n send.click();\n\n await assertScreenshot(\n 'contacts/compose-attachments-no-text-failure',\n getClip(chat)\n );\n });\n});\n\ndescribe('temba-contact-chat - contact tests - handle send tests - text and attachments', () => {\n beforeEach(() => {\n clearMockPosts();\n mockGET(\n /\\/contact\\/history\\/contact-.*/,\n '/test-assets/contacts/history.json'\n );\n clock = useFakeTimers();\n });\n\n afterEach(function () {\n clock.restore();\n });\n\n it('with text and attachments - success', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;\n await updateComponent(compose, getSuccessText(), getSuccessFiles());\n\n const text = getSuccessText();\n const attachments = getSuccessFiles();\n const response_body = {\n contacts: [{ uuid: 'contact-dave-active', name: 'Dave Matthews' }],\n text: { eng: text },\n attachments: { eng: attachments },\n };\n mockPOST(/api\\/v2\\/broadcasts\\.json/, response_body);\n\n const send = compose.shadowRoot.querySelector(\n 'temba-button#send-button'\n ) as Button;\n send.click();\n\n await assertScreenshot(\n 'contacts/compose-text-and-attachments-success',\n getClip(chat)\n );\n });\n\n it('with text and attachments - failure - more than 640 chars', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;\n // set the chatbox to a string that is 640+ chars\n await updateComponent(compose, getFailText(), getSuccessFiles());\n\n const response_body = {\n text: { eng: ['Ensure this field has no more than 640 characters.'] },\n };\n const response_headers = {};\n const response_status = '400';\n mockPOST(\n /api\\/v2\\/broadcasts\\.json/,\n response_body,\n response_headers,\n response_status\n );\n\n const send = compose.shadowRoot.querySelector(\n 'temba-button#send-button'\n ) as Button;\n send.click();\n\n await assertScreenshot(\n 'contacts/compose-text-and-attachments-failure-text',\n getClip(chat)\n );\n });\n\n it('with text and attachments - failure - more than 10 files', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;\n // set the attachments to a list that is 10+ items\n await updateComponent(compose, getSuccessText(), getSuccessFiles(11));\n\n const response_body = {\n attachments: { eng: ['Ensure this field has no more than 10 elements.'] },\n };\n const response_headers = {};\n const response_status = '400';\n mockPOST(\n /api\\/v2\\/broadcasts\\.json/,\n response_body,\n response_headers,\n response_status\n );\n\n const send = compose.shadowRoot.querySelector(\n 'temba-button#send-button'\n ) as Button;\n send.click();\n\n await assertScreenshot(\n 'contacts/compose-text-and-attachments-failure-attachments',\n getClip(chat)\n );\n });\n\n it('with text and attachments - failure - more than 640 chars and more than 10 files', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;\n // set the chatbox to a string that is 640+ chars\n // set the attachments to a list that is 10+ items\n await updateComponent(compose, getFailText(), getSuccessFiles(11));\n\n const response_body = {\n text: { eng: ['Ensure this field has no more than 640 characters.'] },\n };\n const response_headers = {};\n const response_status = '400';\n mockPOST(\n /api\\/v2\\/broadcasts\\.json/,\n response_body,\n response_headers,\n response_status\n );\n\n const send = compose.shadowRoot.querySelector(\n 'temba-button#send-button'\n ) as Button;\n send.click();\n\n await assertScreenshot(\n 'contacts/compose-text-and-attachments-failure-text-and-attachments',\n getClip(chat)\n );\n });\n\n it('with text and attachments - failure - generic', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;\n await updateComponent(compose, getSuccessText(), getSuccessFiles());\n\n const response_body = {};\n const response_headers = {};\n const response_status = '500';\n mockPOST(\n /api\\/v2\\/broadcasts\\.json/,\n response_body,\n response_headers,\n response_status\n );\n\n const send = compose.shadowRoot.querySelector(\n 'temba-button#send-button'\n ) as Button;\n send.click();\n\n await assertScreenshot(\n 'contacts/compose-text-and-attachments-failure-generic',\n getClip(chat)\n );\n });\n});\n\ndescribe('temba-contact-chat - ticket tests', () => {\n // map requests for contact history to our static files\n // we'll just us the same history for everybody for now\n beforeEach(() => {\n mockGET(\n /\\/contact\\/history\\/contact-.*/,\n '/test-assets/contacts/history.json'\n );\n\n mockGET(/\\/api\\/v2\\/tickets\\.json.*/, '/test-assets/tickets/empty.json');\n clock = useFakeTimers();\n });\n\n afterEach(function () {\n clock.restore();\n });\n\n it('show history and show chatbox if contact is active and ticket is open', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-carter-active',\n });\n\n const tickets: TicketList = await getTicketList({\n endpoint: '/test-assets/tickets/ticket-carter-open.json',\n });\n\n chat.currentTicket = tickets.items[0];\n chat.refresh();\n await chat.httpComplete;\n\n // we want to wait until our scroll is finished before taking our screenshot\n // once we have two scrollTops that are the same, we'll assume we're ready\n let lastScroll = 0;\n await assertScreenshot(\n 'contacts/contact-active-ticket-open-show-chatbox',\n getClip(chat),\n {\n clock: clock,\n predicate: () => {\n const currentScroll = chat\n .getContactHistory()\n .getEventsPane().scrollTop;\n if (currentScroll !== 0 && currentScroll === lastScroll) {\n return true;\n }\n lastScroll = currentScroll;\n },\n }\n );\n });\n\n it('show history and show reopen button if contact is active and ticket is closed', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-carter-active',\n });\n\n const tickets: TicketList = await getTicketList({\n endpoint: '/test-assets/tickets/ticket-carter-closed.json',\n });\n chat.currentTicket = tickets.items[0];\n chat.refresh();\n await chat.httpComplete;\n\n await assertScreenshot(\n 'contacts/contact-active-ticket-closed-show-reopen-button',\n getClip(chat),\n {\n clock: clock,\n predicate: () => {\n return chat.getContactHistory().getEventsPane().scrollTop === 921;\n },\n }\n );\n });\n\n it('show history and hide chatbox if contact is archived and ticket is closed', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n\n const chat: ContactChat = await getContactChat({\n contact: 'contact-barack-archived',\n });\n\n const tickets: TicketList = await getTicketList({\n endpoint: '/test-assets/tickets/ticket-barack-closed.json',\n });\n chat.currentTicket = tickets.items[0];\n chat.refresh();\n await chat.httpComplete;\n\n await assertScreenshot(\n 'contacts/contact-archived-ticket-closed-hide-chatbox',\n getClip(chat),\n {\n clock: clock,\n predicate: () => {\n return chat.getContactHistory().getEventsPane().scrollTop === 870;\n },\n }\n );\n });\n});\n"]}
|
|
@@ -7,6 +7,8 @@ export const createHistory = async (def) => {
|
|
|
7
7
|
const parentNode = document.createElement('div');
|
|
8
8
|
parentNode.setAttribute('style', 'width: 500px;height:750px;display:flex;flex-direction:column;flex-grow:1;min-height:0;');
|
|
9
9
|
const history = (await fixture(def, { parentNode }));
|
|
10
|
+
// make sure our initial fetch is made
|
|
11
|
+
await history.httpComplete;
|
|
10
12
|
return history;
|
|
11
13
|
};
|
|
12
14
|
const getHistoryHTML = (attrs = {}) =>
|
|
@@ -31,7 +33,7 @@ describe('temba-contact-history', () => {
|
|
|
31
33
|
afterEach(function () {
|
|
32
34
|
clock.restore();
|
|
33
35
|
});
|
|
34
|
-
it
|
|
36
|
+
it('can be created', async () => {
|
|
35
37
|
const history = await createHistory(getHistoryHTML());
|
|
36
38
|
assert.instanceOf(history, ContactHistory);
|
|
37
39
|
});
|
|
@@ -39,11 +41,13 @@ describe('temba-contact-history', () => {
|
|
|
39
41
|
const history = await createHistory(getHistoryHTML({
|
|
40
42
|
uuid: 'contact-dave-active',
|
|
41
43
|
}));
|
|
42
|
-
// we should have scrolled to the bottom
|
|
44
|
+
// we should have scrolled to the bottom, but the scroll
|
|
45
|
+
// happens in a window timeout
|
|
46
|
+
await clock.runAllAsync();
|
|
47
|
+
await history.updateComplete;
|
|
43
48
|
const events = history.shadowRoot.querySelector('.events');
|
|
44
49
|
const top = events.scrollHeight - events.getBoundingClientRect().height;
|
|
45
50
|
expect(top).to.equal(549);
|
|
46
|
-
await clock.runAllAsync();
|
|
47
51
|
// make sure we actually scrolled to there
|
|
48
52
|
expect(events.scrollTop).to.equal(top);
|
|
49
53
|
await assertScreenshot('contacts/history', getHistoryClip(history));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"temba-contact-history.test.js","sourceRoot":"","sources":["../../test/temba-contact-history.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EACL,gBAAgB,EAChB,OAAO,EACP,OAAO,EACP,SAAS,EACT,OAAO,EACP,OAAO,GACR,MAAM,oBAAoB,CAAC;AAC5B,OAAO,cAAc,CAAC;AAEtB,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAAE,GAAW,EAAE,EAAE;IACjD,MAAM,UAAU,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IACjD,UAAU,CAAC,YAAY,CACrB,OAAO,EACP,wFAAwF,CACzF,CAAC;IACF,MAAM,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,CAAC,CAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"temba-contact-history.test.js","sourceRoot":"","sources":["../../test/temba-contact-history.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { fixture, assert, expect } from '@open-wc/testing';\nimport { useFakeTimers } from 'sinon';\nimport { ContactHistory } from '../src/contacts/ContactHistory';\nimport {\n assertScreenshot,\n getClip,\n getHTML,\n loadStore,\n mockGET,\n mockNow,\n} from '../test/utils.test';\nimport './utils.test';\n\nexport const createHistory = async (def: string) => {\n const parentNode = document.createElement('div');\n parentNode.setAttribute(\n 'style',\n 'width: 500px;height:750px;display:flex;flex-direction:column;flex-grow:1;min-height:0;'\n );\n const history = (await fixture(def, { parentNode })) as ContactHistory;\n\n // make sure our initial fetch is made\n await history.httpComplete;\n\n return history;\n};\n\nconst getHistoryHTML = (attrs: any = {} as any) =>\n // attrs = \"min-height:0;display:flex;flex-grow:1;flex-direction:column\";\n getHTML('temba-contact-history', attrs);\n\nconst getHistoryClip = (ele: ContactHistory) => {\n const clip = getClip(ele);\n clip.height = Math.min(clip.height, 750);\n clip.bottom = clip.top + clip.height;\n return clip;\n};\n\n// stub our current date for consistent screenshots\nmockNow('2021-03-31T00:31:00.000-00:00');\nlet clock: any;\n\ndescribe('temba-contact-history', () => {\n beforeEach(async () => {\n clock = useFakeTimers();\n\n mockGET(\n /\\/contact\\/history\\/contact-dave-active\\/.*/,\n '/test-assets/contacts/history.json'\n );\n\n mockGET(\n /\\/api\\/v2\\/tickets\\.json\\?contact=contact-dave-active/,\n '/test-assets/api/tickets.json'\n );\n\n await loadStore();\n });\n\n afterEach(function () {\n clock.restore();\n });\n\n it('can be created', async () => {\n const history = await createHistory(getHistoryHTML());\n assert.instanceOf(history, ContactHistory);\n });\n\n it('renders history', async () => {\n const history = await createHistory(\n getHistoryHTML({\n uuid: 'contact-dave-active',\n })\n );\n\n // we should have scrolled to the bottom, but the scroll\n // happens in a window timeout\n await clock.runAllAsync();\n await history.updateComplete;\n\n const events = history.shadowRoot.querySelector('.events');\n const top = events.scrollHeight - events.getBoundingClientRect().height;\n expect(top).to.equal(549);\n // make sure we actually scrolled to there\n expect(events.scrollTop).to.equal(top);\n await assertScreenshot('contacts/history', getHistoryClip(history));\n });\n\n it('expands event groups', async () => {\n const history = await createHistory(\n getHistoryHTML({\n uuid: 'contact-dave-active',\n })\n );\n\n // our groups with collapsed events\n const groups = [3, 5, 7];\n for (const idx of groups) {\n const group = history.shadowRoot.querySelector(\n `.event-count[data-group-index='${idx}']`\n ) as HTMLDivElement;\n group.click();\n await clock.runAllAsync();\n expect(group.parentElement.classList.contains('expanded')).equal(true);\n }\n });\n});\n"]}
|
|
@@ -4,7 +4,7 @@ import { expect, fixture, html, assert, waitUntil } from '@open-wc/testing';
|
|
|
4
4
|
import MouseHelper from './MouseHelper';
|
|
5
5
|
import { replace, stub } from 'sinon';
|
|
6
6
|
const gets = [];
|
|
7
|
-
|
|
7
|
+
let posts = [];
|
|
8
8
|
let normalFetch;
|
|
9
9
|
export const showMouse = async () => {
|
|
10
10
|
const mouse = await fixture(html `<mouse-helper />`);
|
|
@@ -29,11 +29,12 @@ export const getComponent = async (tag, attrs = {}, slot = '', width = 250, heig
|
|
|
29
29
|
${style ? style : ``}
|
|
30
30
|
`;
|
|
31
31
|
parentNode.setAttribute('style', styleAttribute);
|
|
32
|
-
|
|
32
|
+
const component = await fixture(spec, { parentNode });
|
|
33
|
+
return component;
|
|
33
34
|
};
|
|
34
35
|
const createResponse = mocked => {
|
|
35
36
|
const mockResponse = new window.Response(mocked.body, {
|
|
36
|
-
status:
|
|
37
|
+
status: mocked.status,
|
|
37
38
|
headers: {
|
|
38
39
|
'Content-type': 'text/html',
|
|
39
40
|
...mocked.headers,
|
|
@@ -43,7 +44,7 @@ const createResponse = mocked => {
|
|
|
43
44
|
};
|
|
44
45
|
const createJSONResponse = mocked => {
|
|
45
46
|
const mockResponse = new window.Response(JSON.stringify(mocked.body), {
|
|
46
|
-
status:
|
|
47
|
+
status: mocked.status,
|
|
47
48
|
headers: {
|
|
48
49
|
'Content-type': 'application/json',
|
|
49
50
|
...mocked.headers,
|
|
@@ -80,11 +81,14 @@ before(async () => {
|
|
|
80
81
|
after(() => {
|
|
81
82
|
window.fetch.restore();
|
|
82
83
|
});
|
|
83
|
-
export const mockGET = (endpoint, body, headers = {}) => {
|
|
84
|
-
gets.push({ endpoint, body, headers });
|
|
84
|
+
export const mockGET = (endpoint, body, headers = {}, status = '200') => {
|
|
85
|
+
gets.push({ endpoint, body, headers, status });
|
|
85
86
|
};
|
|
86
|
-
export const mockPOST = (endpoint, body, headers = {}) => {
|
|
87
|
-
posts.push({ endpoint, body, headers });
|
|
87
|
+
export const mockPOST = (endpoint, body, headers = {}, status = '200') => {
|
|
88
|
+
posts.push({ endpoint, body, headers, status });
|
|
89
|
+
};
|
|
90
|
+
export const clearMockPosts = () => {
|
|
91
|
+
posts = [];
|
|
88
92
|
};
|
|
89
93
|
export const checkTimers = (clock) => {
|
|
90
94
|
expect(!!clock.timers).to.equal(true, 'Expected timers not found');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.test.js","sourceRoot":"","sources":["../../test/utils.test.ts"],"names":[],"mappings":"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","sourcesContent":["import '../temba-modules';\nimport { DateTime } from 'luxon';\ninterface Clip {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nimport { expect, fixture, html, assert, waitUntil } from '@open-wc/testing';\nimport MouseHelper from './MouseHelper';\nimport { Store } from '../src/store/Store';\nimport { replace, stub } from 'sinon';\n\nexport interface CodeMock {\n endpoint: RegExp;\n body: string;\n headers: any;\n}\n\nconst gets: CodeMock[] = [];\nconst posts: CodeMock[] = [];\nlet normalFetch;\n\nexport const showMouse = async () => {\n const mouse = await fixture(html`<mouse-helper />`);\n assert.instanceOf(mouse, MouseHelper);\n};\n\nexport const getAttributes = (attrs: any = {}) => {\n return `${Object.keys(attrs)\n .map((name: string) => {\n if (typeof attrs[name] === 'boolean' && attrs[name]) {\n return name;\n }\n return `${name}='${attrs[name]}'`;\n })\n .join(' ')}`;\n};\n\nexport const getComponent = async (\n tag,\n attrs: any = {},\n slot = '',\n width = 250,\n height = 0,\n style = ''\n) => {\n const spec = `<${tag} ${getAttributes(attrs)}>${slot}</${tag}>`;\n const parentNode = document.createElement('div');\n const styleAttribute = `\n ${width > 0 ? `width:${width}px;` : ``} \n ${height > 0 ? `height:${height}px;` : ``}\n ${style ? style : ``}\n `;\n\n parentNode.setAttribute('style', styleAttribute);\n return await fixture(spec, { parentNode });\n};\n\nconst createResponse = mocked => {\n const mockResponse = new window.Response(mocked.body, {\n status: 200,\n headers: {\n 'Content-type': 'text/html',\n ...mocked.headers,\n },\n });\n\n return Promise.resolve(mockResponse);\n};\n\nconst createJSONResponse = mocked => {\n const mockResponse = new window.Response(JSON.stringify(mocked.body), {\n status: 200,\n headers: {\n 'Content-type': 'application/json',\n ...mocked.headers,\n },\n });\n\n return Promise.resolve(mockResponse);\n};\n\nconst getResponse = (endpoint: string, options) => {\n // check if our path has been mocked in code\n const mocks = options.method === 'GET' ? gets : posts;\n const codeMock = mocks.find(mock => mock.endpoint.test(endpoint));\n\n if (codeMock) {\n if (typeof codeMock.body === 'string') {\n // see if we are being mocked to a file\n if (codeMock.body.startsWith('/')) {\n endpoint = codeMock.body;\n } else {\n return createResponse(codeMock);\n }\n } else {\n return createJSONResponse(codeMock);\n }\n }\n\n // otherwise fetch over http\n return normalFetch(endpoint, options);\n};\n\nbefore(async () => {\n normalFetch = window.fetch;\n stub(window, 'fetch').callsFake(getResponse);\n await setViewport({ width: 1024, height: 768, deviceScaleFactor: 2 });\n});\n\nafter(() => {\n (window.fetch as any).restore();\n});\n\nexport const mockGET = (endpoint: RegExp, body: any, headers: any = {}) => {\n gets.push({ endpoint, body, headers });\n};\n\nexport const mockPOST = (endpoint: RegExp, body: any, headers: any = {}) => {\n posts.push({ endpoint, body, headers });\n};\n\nexport const checkTimers = (clock: any) => {\n expect(!!clock.timers).to.equal(true, 'Expected timers not found');\n expect(\n Object.keys(clock.timers).length,\n `Timers still to be run ${JSON.stringify(clock.timers)}`\n ).to.equal(0);\n};\n\nexport const delay = (millis: number) => {\n return new Promise(function (resolve) {\n window.setTimeout(resolve, millis);\n });\n};\n\nexport const assertScreenshot = async (\n filename: string,\n clip: Clip,\n waitFor?: { clock?: any; predicate?: () => boolean }\n) => {\n if (waitFor) {\n if (waitFor.clock) {\n waitFor.clock.restore();\n }\n await waitUntil(waitFor.predicate);\n }\n\n const threshold = 0.1;\n const exclude: Clip[] = [];\n\n try {\n await (window as any).matchPageSnapshot(\n `${filename}.png`,\n clip,\n exclude,\n threshold\n );\n } catch (error) {\n if (error.message) {\n throw new Error(\n `${error.message} ${\n error.expected\n ? `Expected ${error.expected} but got ${error.actual}`\n : ''\n } ${error.files ? `\\n${error.files.join('\\n')}` : ''}`\n );\n }\n throw new Error(error);\n }\n};\n\nexport const getClip = (ele: HTMLElement) => {\n let clip: any = ele.getBoundingClientRect();\n if (!clip.width || !clip.height) {\n clip = ele.shadowRoot.firstElementChild.getBoundingClientRect();\n }\n\n const padding = 10;\n const width = clip.width + padding * 2;\n const height = clip.height + padding * 2;\n const y = clip.y - padding;\n const x = clip.x - padding;\n\n const newClip = {\n x,\n y,\n width,\n height,\n bottom: y + height,\n right: x + width,\n top: y,\n left: x,\n };\n\n return newClip;\n};\n\nexport const getHTMLAttrs = (attrs: any = {}) => {\n return Object.keys(attrs)\n .map((name: string) => `${name}='${attrs[name]}'`)\n .join(' ');\n};\n\nexport const getHTML = (tag: string, attrs: any = {}) => {\n return `<${tag} ${getHTMLAttrs(attrs)}></${tag}>`;\n};\n\nexport const loadStore = async () => {\n const store: Store = await fixture(\n `<temba-store \n completion='/test-assets/store/editor.json'\n groups='/test-assets/store/groups.json'\n languages='/test-assets/store/languages.json'\n fields='/test-assets/store/fields.json'\n />`\n );\n await store.httpComplete;\n await store.httpComplete;\n\n return store;\n};\n\nexport const mockNow = (isodate: string) => {\n const now = DateTime.fromISO(isodate);\n // mock the current time\n replace(DateTime, 'now', () => {\n return now;\n });\n};\n"]}
|
|
1
|
+
{"version":3,"file":"utils.test.js","sourceRoot":"","sources":["../../test/utils.test.ts"],"names":[],"mappings":"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","sourcesContent":["import '../temba-modules';\nimport { DateTime } from 'luxon';\ninterface Clip {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nimport { expect, fixture, html, assert, waitUntil } from '@open-wc/testing';\nimport MouseHelper from './MouseHelper';\nimport { Store } from '../src/store/Store';\nimport { replace, stub } from 'sinon';\n\nexport interface CodeMock {\n endpoint: RegExp;\n body: string;\n headers: any;\n status: string;\n}\n\nconst gets: CodeMock[] = [];\nlet posts: CodeMock[] = [];\nlet normalFetch;\n\nexport const showMouse = async () => {\n const mouse = await fixture(html`<mouse-helper />`);\n assert.instanceOf(mouse, MouseHelper);\n};\n\nexport const getAttributes = (attrs: any = {}) => {\n return `${Object.keys(attrs)\n .map((name: string) => {\n if (typeof attrs[name] === 'boolean' && attrs[name]) {\n return name;\n }\n return `${name}='${attrs[name]}'`;\n })\n .join(' ')}`;\n};\n\nexport const getComponent = async (\n tag,\n attrs: any = {},\n slot = '',\n width = 250,\n height = 0,\n style = ''\n) => {\n const spec = `<${tag} ${getAttributes(attrs)}>${slot}</${tag}>`;\n const parentNode = document.createElement('div');\n const styleAttribute = `\n ${width > 0 ? `width:${width}px;` : ``} \n ${height > 0 ? `height:${height}px;` : ``}\n ${style ? style : ``}\n `;\n parentNode.setAttribute('style', styleAttribute);\n const component = await fixture(spec, { parentNode });\n return component;\n};\n\nconst createResponse = mocked => {\n const mockResponse = new window.Response(mocked.body, {\n status: mocked.status,\n headers: {\n 'Content-type': 'text/html',\n ...mocked.headers,\n },\n });\n\n return Promise.resolve(mockResponse);\n};\n\nconst createJSONResponse = mocked => {\n const mockResponse = new window.Response(JSON.stringify(mocked.body), {\n status: mocked.status,\n headers: {\n 'Content-type': 'application/json',\n ...mocked.headers,\n },\n });\n\n return Promise.resolve(mockResponse);\n};\n\nconst getResponse = (endpoint: string, options) => {\n // check if our path has been mocked in code\n const mocks = options.method === 'GET' ? gets : posts;\n const codeMock = mocks.find(mock => mock.endpoint.test(endpoint));\n\n if (codeMock) {\n if (typeof codeMock.body === 'string') {\n // see if we are being mocked to a file\n if (codeMock.body.startsWith('/')) {\n endpoint = codeMock.body;\n } else {\n return createResponse(codeMock);\n }\n } else {\n return createJSONResponse(codeMock);\n }\n }\n\n // otherwise fetch over http\n return normalFetch(endpoint, options);\n};\n\nbefore(async () => {\n normalFetch = window.fetch;\n stub(window, 'fetch').callsFake(getResponse);\n await setViewport({ width: 1024, height: 768, deviceScaleFactor: 2 });\n});\n\nafter(() => {\n (window.fetch as any).restore();\n});\n\nexport const mockGET = (\n endpoint: RegExp,\n body: any,\n headers: any = {},\n status = '200'\n) => {\n gets.push({ endpoint, body, headers, status });\n};\n\nexport const mockPOST = (\n endpoint: RegExp,\n body: any,\n headers: any = {},\n status = '200'\n) => {\n posts.push({ endpoint, body, headers, status });\n};\n\nexport const clearMockPosts = () => {\n posts = [];\n};\n\nexport const checkTimers = (clock: any) => {\n expect(!!clock.timers).to.equal(true, 'Expected timers not found');\n expect(\n Object.keys(clock.timers).length,\n `Timers still to be run ${JSON.stringify(clock.timers)}`\n ).to.equal(0);\n};\n\nexport const delay = (millis: number) => {\n return new Promise(function (resolve) {\n window.setTimeout(resolve, millis);\n });\n};\n\nexport const assertScreenshot = async (\n filename: string,\n clip: Clip,\n waitFor?: { clock?: any; predicate?: () => boolean }\n) => {\n if (waitFor) {\n if (waitFor.clock) {\n waitFor.clock.restore();\n }\n await waitUntil(waitFor.predicate);\n }\n\n const threshold = 0.1;\n const exclude: Clip[] = [];\n\n try {\n await (window as any).matchPageSnapshot(\n `${filename}.png`,\n clip,\n exclude,\n threshold\n );\n } catch (error) {\n if (error.message) {\n throw new Error(\n `${error.message} ${\n error.expected\n ? `Expected ${error.expected} but got ${error.actual}`\n : ''\n } ${error.files ? `\\n${error.files.join('\\n')}` : ''}`\n );\n }\n throw new Error(error);\n }\n};\n\nexport const getClip = (ele: HTMLElement) => {\n let clip: any = ele.getBoundingClientRect();\n if (!clip.width || !clip.height) {\n clip = ele.shadowRoot.firstElementChild.getBoundingClientRect();\n }\n\n const padding = 10;\n const width = clip.width + padding * 2;\n const height = clip.height + padding * 2;\n const y = clip.y - padding;\n const x = clip.x - padding;\n\n const newClip = {\n x,\n y,\n width,\n height,\n bottom: y + height,\n right: x + width,\n top: y,\n left: x,\n };\n\n return newClip;\n};\n\nexport const getHTMLAttrs = (attrs: any = {}) => {\n return Object.keys(attrs)\n .map((name: string) => `${name}='${attrs[name]}'`)\n .join(' ');\n};\n\nexport const getHTML = (tag: string, attrs: any = {}) => {\n return `<${tag} ${getHTMLAttrs(attrs)}></${tag}>`;\n};\n\nexport const loadStore = async () => {\n const store: Store = await fixture(\n `<temba-store \n completion='/test-assets/store/editor.json'\n groups='/test-assets/store/groups.json'\n languages='/test-assets/store/languages.json'\n fields='/test-assets/store/fields.json'\n />`\n );\n await store.httpComplete;\n await store.httpComplete;\n\n return store;\n};\n\nexport const mockNow = (isodate: string) => {\n const now = DateTime.fromISO(isodate);\n // mock the current time\n replace(DateTime, 'now', () => {\n return now;\n });\n};\n"]}
|