@chat21/chat21-web-widget 5.1.34-rc1 → 5.1.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. package/.github/workflows/docker-community-push-latest.yml +13 -23
  2. package/.github/workflows/docker-image-tag-community-tag-push.yml +12 -22
  3. package/CHANGELOG.md +8 -129
  4. package/Dockerfile +5 -4
  5. package/angular.json +3 -21
  6. package/docs/changelog/this-branch.md +0 -36
  7. package/env.sample +2 -3
  8. package/nginx.conf +2 -22
  9. package/package.json +3 -10
  10. package/src/app/app.component.html +2 -2
  11. package/src/app/app.component.scss +14 -25
  12. package/src/app/app.component.spec.ts +6 -21
  13. package/src/app/app.component.ts +9 -10
  14. package/src/app/app.module.ts +0 -13
  15. package/src/app/component/conversation-detail/conversation/conversation.component.html +11 -25
  16. package/src/app/component/conversation-detail/conversation/conversation.component.scss +2 -40
  17. package/src/app/component/conversation-detail/conversation/conversation.component.spec.ts +75 -644
  18. package/src/app/component/conversation-detail/conversation/conversation.component.ts +14 -100
  19. package/src/app/component/conversation-detail/conversation-audio-recorder/conversation-audio-recorder.component.html +13 -25
  20. package/src/app/component/conversation-detail/conversation-audio-recorder/conversation-audio-recorder.component.spec.ts +5 -123
  21. package/src/app/component/conversation-detail/conversation-audio-recorder/conversation-audio-recorder.component.ts +0 -1
  22. package/src/app/component/conversation-detail/conversation-content/conversation-content.component.html +10 -23
  23. package/src/app/component/conversation-detail/conversation-content/conversation-content.component.scss +1 -19
  24. package/src/app/component/conversation-detail/conversation-content/conversation-content.component.spec.ts +149 -242
  25. package/src/app/component/conversation-detail/conversation-content/conversation-content.component.ts +5 -8
  26. package/src/app/component/conversation-detail/conversation-emojii/conversation-emojii.component.spec.ts +3 -53
  27. package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.html +96 -200
  28. package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.scss +6 -211
  29. package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.spec.ts +78 -452
  30. package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.ts +76 -291
  31. package/src/app/component/conversation-detail/conversation-header/conversation-header.component.html +53 -113
  32. package/src/app/component/conversation-detail/conversation-header/conversation-header.component.scss +4 -12
  33. package/src/app/component/conversation-detail/conversation-header/conversation-header.component.spec.ts +29 -274
  34. package/src/app/component/conversation-detail/conversation-internal-frame/conversation-internal-frame.component.html +9 -23
  35. package/src/app/component/conversation-detail/conversation-internal-frame/conversation-internal-frame.component.spec.ts +8 -80
  36. package/src/app/component/conversation-detail/conversation-preview/conversation-preview.component.html +23 -29
  37. package/src/app/component/conversation-detail/conversation-preview/conversation-preview.component.spec.ts +16 -185
  38. package/src/app/component/conversation-detail/conversation-preview/conversation-preview.component.ts +14 -34
  39. package/src/app/component/error-alert/error-alert.component.spec.ts +5 -65
  40. package/src/app/component/eyeeye-catcher-card/eyeeye-catcher-card.component.html +7 -16
  41. package/src/app/component/eyeeye-catcher-card/eyeeye-catcher-card.component.scss +0 -21
  42. package/src/app/component/eyeeye-catcher-card/eyeeye-catcher-card.component.spec.ts +7 -89
  43. package/src/app/component/form/form-builder/form-builder.component.html +1 -1
  44. package/src/app/component/form/form-builder/form-builder.component.spec.ts +21 -163
  45. package/src/app/component/form/inputs/form-checkbox/form-checkbox.component.html +4 -8
  46. package/src/app/component/form/inputs/form-checkbox/form-checkbox.component.scss +5 -10
  47. package/src/app/component/form/inputs/form-checkbox/form-checkbox.component.spec.ts +16 -90
  48. package/src/app/component/form/inputs/form-checkbox/form-checkbox.component.ts +0 -26
  49. package/src/app/component/form/inputs/form-label/form-label.component.spec.ts +11 -45
  50. package/src/app/component/form/inputs/form-radio-button/form-radio-button.component.spec.ts +6 -24
  51. package/src/app/component/form/inputs/form-select/form-select.component.spec.ts +5 -14
  52. package/src/app/component/form/inputs/form-text/form-text.component.html +12 -14
  53. package/src/app/component/form/inputs/form-text/form-text.component.scss +1 -11
  54. package/src/app/component/form/inputs/form-text/form-text.component.spec.ts +17 -113
  55. package/src/app/component/form/inputs/form-text/form-text.component.ts +3 -35
  56. package/src/app/component/form/inputs/form-textarea/form-textarea.component.html +11 -13
  57. package/src/app/component/form/inputs/form-textarea/form-textarea.component.scss +5 -6
  58. package/src/app/component/form/inputs/form-textarea/form-textarea.component.spec.ts +13 -149
  59. package/src/app/component/form/inputs/form-textarea/form-textarea.component.ts +0 -26
  60. package/src/app/component/form/prechat-form/prechat-form.component.html +11 -14
  61. package/src/app/component/form/prechat-form/prechat-form.component.spec.ts +10 -102
  62. package/src/app/component/form/prechat-form/prechat-form.component.ts +1 -8
  63. package/src/app/component/home/home.component.html +31 -38
  64. package/src/app/component/home/home.component.scss +2 -4
  65. package/src/app/component/home/home.component.spec.ts +11 -226
  66. package/src/app/component/home-conversations/home-conversations.component.html +26 -30
  67. package/src/app/component/home-conversations/home-conversations.component.scss +0 -3
  68. package/src/app/component/home-conversations/home-conversations.component.spec.ts +36 -212
  69. package/src/app/component/last-message/last-message.component.html +9 -15
  70. package/src/app/component/last-message/last-message.component.scss +2 -16
  71. package/src/app/component/last-message/last-message.component.spec.ts +23 -204
  72. package/src/app/component/last-message/last-message.component.ts +1 -4
  73. package/src/app/component/launcher-button/launcher-button.component.html +13 -8
  74. package/src/app/component/launcher-button/launcher-button.component.spec.ts +8 -104
  75. package/src/app/component/list-all-conversations/list-all-conversations.component.html +17 -12
  76. package/src/app/component/list-all-conversations/list-all-conversations.component.scss +0 -2
  77. package/src/app/component/list-conversations/list-conversations.component.html +22 -22
  78. package/src/app/component/menu-options/menu-options.component.html +20 -30
  79. package/src/app/component/menu-options/menu-options.component.spec.ts +9 -125
  80. package/src/app/component/message/audio/audio.component.html +15 -13
  81. package/src/app/component/message/audio/audio.component.spec.ts +5 -140
  82. package/src/app/component/message/audio/audio.component.ts +5 -1
  83. package/src/app/component/message/avatar/avatar.component.html +2 -2
  84. package/src/app/component/message/avatar/avatar.component.spec.ts +7 -99
  85. package/src/app/component/message/bubble-message/bubble-message.component.html +51 -38
  86. package/src/app/component/message/bubble-message/bubble-message.component.scss +1 -54
  87. package/src/app/component/message/bubble-message/bubble-message.component.spec.ts +57 -154
  88. package/src/app/component/message/bubble-message/bubble-message.component.ts +11 -89
  89. package/src/app/component/message/buttons/action-button/action-button.component.html +4 -3
  90. package/src/app/component/message/buttons/action-button/action-button.component.spec.ts +5 -49
  91. package/src/app/component/message/buttons/link-button/link-button.component.scss +8 -5
  92. package/src/app/component/message/buttons/link-button/link-button.component.spec.ts +5 -50
  93. package/src/app/component/message/buttons/text-button/text-button.component.spec.ts +5 -44
  94. package/src/app/component/message/carousel/carousel.component.html +16 -29
  95. package/src/app/component/message/carousel/carousel.component.scss +8 -20
  96. package/src/app/component/message/carousel/carousel.component.spec.ts +3 -80
  97. package/src/app/component/message/carousel/carousel.component.ts +0 -16
  98. package/src/app/component/message/frame/frame.component.html +4 -9
  99. package/src/app/component/message/frame/frame.component.spec.ts +15 -34
  100. package/src/app/component/message/frame/frame.component.ts +2 -7
  101. package/src/app/component/message/html/html.component.html +1 -1
  102. package/src/app/component/message/html/html.component.scss +1 -1
  103. package/src/app/component/message/html/html.component.spec.ts +7 -24
  104. package/src/app/component/message/image/image.component.html +10 -12
  105. package/src/app/component/message/image/image.component.scss +0 -16
  106. package/src/app/component/message/image/image.component.spec.ts +15 -101
  107. package/src/app/component/message/image/image.component.ts +51 -90
  108. package/src/app/component/message/info-message/info-message.component.spec.ts +14 -26
  109. package/src/app/component/message/like-unlike/like-unlike.component.html +9 -7
  110. package/src/app/component/message/like-unlike/like-unlike.component.spec.ts +3 -31
  111. package/src/app/component/message/return-receipt/return-receipt.component.spec.ts +17 -38
  112. package/src/app/component/message/text/text.component.html +3 -3
  113. package/src/app/component/message/text/text.component.scss +86 -80
  114. package/src/app/component/message/text/text.component.spec.ts +13 -106
  115. package/src/app/component/message-attachment/message-attachment.component.spec.ts +13 -134
  116. package/src/app/component/selection-department/selection-department.component.html +23 -21
  117. package/src/app/component/selection-department/selection-department.component.spec.ts +14 -159
  118. package/src/app/component/selection-department/selection-department.component.ts +1 -8
  119. package/src/app/component/send-button/send-button.component.html +13 -5
  120. package/src/app/component/send-button/send-button.component.spec.ts +2 -2
  121. package/src/app/component/star-rating-widget/star-rating-widget.component.html +81 -51
  122. package/src/app/directives/tooltip.directive.spec.ts +4 -8
  123. package/src/app/modals/confirm-close/confirm-close.component.html +8 -20
  124. package/src/app/modals/confirm-close/confirm-close.component.scss +0 -3
  125. package/src/app/modals/confirm-close/confirm-close.component.spec.ts +4 -13
  126. package/src/app/modals/confirm-close/confirm-close.component.ts +1 -8
  127. package/src/app/pipe/html-entites-encode.pipe.spec.ts +2 -35
  128. package/src/app/pipe/marked.pipe.spec.ts +2 -38
  129. package/src/app/pipe/marked.pipe.ts +41 -51
  130. package/src/app/providers/app-config.service.ts +2 -4
  131. package/src/app/providers/brand.service.spec.ts +2 -23
  132. package/src/app/providers/brand.service.ts +1 -1
  133. package/src/app/providers/global-settings.service.spec.ts +14 -1009
  134. package/src/app/providers/global-settings.service.ts +2 -82
  135. package/src/app/providers/translator.service.ts +6 -26
  136. package/src/app/sass/_variables.scss +0 -3
  137. package/src/app/sass/animations.scss +1 -19
  138. package/src/app/utils/globals.ts +1 -21
  139. package/src/app/utils/utils-resources.ts +1 -1
  140. package/src/assets/i18n/en.json +99 -106
  141. package/src/assets/i18n/es.json +100 -107
  142. package/src/assets/i18n/fr.json +100 -107
  143. package/src/assets/i18n/it.json +98 -107
  144. package/src/assets/twp/index-dev.html +0 -18
  145. package/src/chat21-core/models/message.ts +1 -2
  146. package/src/chat21-core/providers/firebase/firebase-conversation-handler.ts +2 -3
  147. package/src/chat21-core/providers/mqtt/mqtt-conversation-handler.ts +0 -12
  148. package/src/chat21-core/providers/scripts/script.service.spec.ts +2 -12
  149. package/src/chat21-core/providers/tiledesk/tiledesk-requests.service.ts +1 -1
  150. package/src/chat21-core/utils/utils-message.ts +0 -7
  151. package/src/chat21-core/utils/utils.ts +2 -5
  152. package/src/widget-config-template.json +1 -4
  153. package/src/widget-config.json +1 -4
  154. package/tsconfig.json +0 -5
  155. package/.angular-mcp-cache/package.json +0 -1
  156. package/.cursor/angular18-accessibility-auditor-skill.md +0 -442
  157. package/.cursor/mcp.json +0 -15
  158. package/.github/workflows/build.yml +0 -22
  159. package/.github/workflows/playwright.yml +0 -27
  160. package/mocks/voice-websocket-mock/server.cjs +0 -245
  161. package/playwright.config.ts +0 -41
  162. package/src/app/component/conversation-detail/stream-audio-spectrum/stream-audio-spectrum.component.html +0 -46
  163. package/src/app/component/conversation-detail/stream-audio-spectrum/stream-audio-spectrum.component.scss +0 -83
  164. package/src/app/component/conversation-detail/stream-audio-spectrum/stream-audio-spectrum.component.ts +0 -192
  165. package/src/app/component/form/prechat-form-test-mock.ts +0 -35
  166. package/src/app/component/message/audio-sync/audio-sync.component.html +0 -18
  167. package/src/app/component/message/audio-sync/audio-sync.component.scss +0 -65
  168. package/src/app/component/message/audio-sync/audio-sync.component.spec.ts +0 -103
  169. package/src/app/component/message/audio-sync/audio-sync.component.ts +0 -643
  170. package/src/app/providers/tts-audio-playback-coordinator.service.spec.ts +0 -117
  171. package/src/app/providers/tts-audio-playback-coordinator.service.ts +0 -109
  172. package/src/app/providers/voice/STT&TTS/openai-voice.config.ts +0 -12
  173. package/src/app/providers/voice/STT&TTS/openai-voice.provider.ts +0 -171
  174. package/src/app/providers/voice/STT&TTS/speech-provider.abstract.ts +0 -39
  175. package/src/app/providers/voice/audio.types.ts +0 -40
  176. package/src/app/providers/voice/vad.service.spec.ts +0 -28
  177. package/src/app/providers/voice/vad.service.ts +0 -70
  178. package/src/app/providers/voice/voice-streaming.service.spec.ts +0 -23
  179. package/src/app/providers/voice/voice-streaming.service.ts +0 -702
  180. package/src/app/providers/voice/voice-streaming.types.ts +0 -112
  181. package/src/app/providers/voice/voice.service.spec.ts +0 -227
  182. package/src/app/providers/voice/voice.service.ts +0 -973
  183. package/src/app/shims/onnxruntime-web-wasm.ts +0 -4
  184. package/src/assets/onnx/ort-wasm-simd-threaded.mjs +0 -59
  185. package/src/assets/onnx/ort-wasm-simd-threaded.wasm +0 -0
  186. package/src/assets/sounds/keyboard.mp3 +0 -0
  187. package/src/assets/twp/tiledesk_widget_files/widget-css-override-example.css +0 -14
  188. package/src/assets/vad/silero_vad_legacy.onnx +0 -0
  189. package/src/assets/vad/vad.worklet.bundle.min.js +0 -1
  190. package/src/chat21-core/providers/chat-manager.spec.ts +0 -72
  191. package/tests/widget-form-rich.spec.ts +0 -67
  192. package/tests/widget-index-dev-settings.spec.ts +0 -52
  193. package/tests/widget-twp-iframe.spec.ts +0 -39
@@ -1,663 +1,94 @@
1
- import { SimpleChange } from '@angular/core';
2
- import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
1
+ import { TiledeskRequestsService } from './../../../../chat21-core/providers/tiledesk/tiledesk-requests.service';
2
+ import { StarRatingWidgetService } from './../../../providers/star-rating-widget.service';
3
+ import { StarRatingWidgetComponent } from './../../star-rating-widget/star-rating-widget.component';
3
4
  import { provideHttpClientTesting } from '@angular/common/http/testing';
4
- import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
5
- import { Subject, BehaviorSubject } from 'rxjs';
5
+
6
+ import { Triggerhandler } from './../../../../chat21-core/utils/triggerHandler';
7
+ import { AppComponent } from './../../../app.component';
8
+ import { AppConfigService } from './../../../providers/app-config.service';
9
+
10
+ import { Globals } from './../../../utils/globals';
11
+ import { NO_ERRORS_SCHEMA, ElementRef } from '@angular/core';
12
+ import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
6
13
 
7
14
  import { ConversationComponent } from './conversation.component';
8
- import { Globals } from '../../../utils/globals';
9
- import { AppConfigService } from '../../../providers/app-config.service';
10
- import { AppStorageService } from 'src/chat21-core/providers/abstract/app-storage.service';
11
- import { StarRatingWidgetService } from '../../../providers/star-rating-widget.service';
12
- import { ConversationHandlerBuilderService } from 'src/chat21-core/providers/abstract/conversation-handler-builder.service';
13
- import { ChatManager } from 'src/chat21-core/providers/chat-manager';
14
- import { CustomTranslateService } from 'src/chat21-core/providers/custom-translate.service';
15
- import { TypingService } from 'src/chat21-core/providers/abstract/typing.service';
16
- import { TiledeskRequestsService } from 'src/chat21-core/providers/tiledesk/tiledesk-requests.service';
17
- import { EventsService } from '../../../providers/events.service';
18
- import { MessageModel } from 'src/chat21-core/models/message';
19
- import { HEADER_MENU_OPTION } from 'src/app/utils/constants';
20
- import { LoggerInstance } from 'src/chat21-core/providers/logger/loggerInstance';
15
+ import { GlobalSettingsService } from '../../../providers/global-settings.service';
16
+ import { TranslatorService } from '../../../providers/translator.service';
17
+
18
+ import { AppStorageService } from '../../../../chat21-core/providers/abstract/app-storage.service';
19
+
20
+ import { CustomTranslateService } from '../../../../chat21-core/providers/custom-translate.service';
21
+ import { MessagingAuthService } from '../../../../chat21-core/providers/abstract/messagingAuth.service';
22
+ import { TiledeskAuthService } from '../../../../chat21-core/providers/tiledesk/tiledesk-auth.service';
23
+ import { PresenceService } from '../../../../chat21-core/providers/abstract/presence.service';
24
+ import { ConversationsHandlerService } from '../../../../chat21-core/providers/abstract/conversations-handler.service';
25
+ import { ArchivedConversationsHandlerService } from '../../../../chat21-core/providers/abstract/archivedconversations-handler.service';
26
+ import { ConversationHandlerBuilderService } from '../../../../chat21-core/providers/abstract/conversation-handler-builder.service';
27
+ import { ChatManager } from '../../../../chat21-core/providers/chat-manager';
28
+ import { TypingService } from '../../../../chat21-core/providers/abstract/typing.service';
29
+ import { ImageRepoService } from '../../../../chat21-core/providers/abstract/image-repo.service';
30
+ import { UploadService } from '../../../../chat21-core/providers/abstract/upload.service';
31
+ import { TranslateModule } from '@ngx-translate/core';
32
+ import { NGXLogger } from 'ngx-logger';
21
33
  import { CustomLogger } from 'src/chat21-core/providers/logger/customLogger';
34
+ import { LoggerInstance } from 'src/chat21-core/providers/logger/loggerInstance';
35
+ import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
36
+
22
37
  describe('ConversationComponent', () => {
23
38
  let component: ConversationComponent;
24
39
  let fixture: ComponentFixture<ConversationComponent>;
25
- let globals: Globals;
26
-
27
- const ngxlogger = jasmine.createSpyObj('NGXLogger', ['log', 'trace', 'debug', 'warn', 'error', 'info']);
28
- const customLogger = new CustomLogger(ngxlogger);
29
-
30
- let conversationHandlerMock: {
31
- messageAdded: Subject<MessageModel>;
32
- messageWait: Subject<any>;
33
- messageInfo: Subject<any>;
34
- messages: MessageModel[];
35
- connect: jasmine.Spy;
36
- initialize: jasmine.Spy;
37
- sendMessage: jasmine.Spy;
38
- };
39
-
40
- const setupHandler = () => {
41
- conversationHandlerMock = {
42
- messageAdded: new Subject(),
43
- messageWait: new Subject(),
44
- messageInfo: new Subject(),
45
- messages: [],
46
- connect: jasmine.createSpy('connect'),
47
- initialize: jasmine.createSpy('initialize').and.returnValue(Promise.resolve()),
48
- sendMessage: jasmine.createSpy('sendMessage').and.returnValue({ uid: 'm1', sender: 'me' }),
49
- };
50
- return conversationHandlerMock;
51
- };
52
-
53
- let chatManagerStub: any;
54
- let tiledeskStub: any;
55
- let starRatingStub: any;
56
- let builderStub: { build: jasmine.Spy };
57
-
58
- beforeEach(async () => {
59
- LoggerInstance.setInstance(customLogger);
60
- setupHandler();
61
-
62
- const convHandlerSvc = {
63
- getConversationDetail: jasmine.createSpy('getConversationDetail').and.callFake((id: string, cb: (c: any) => void) => {
64
- cb(null);
65
- }),
66
- conversationRemoved: new Subject<any>(),
67
- conversationChanged: new Subject<any>(),
68
- setConversationRead: jasmine.createSpy('setConversationRead'),
69
- countIsNew: jasmine.createSpy('countIsNew').and.returnValue(0),
70
- };
71
-
72
- const archivedSvc = {
73
- getConversationDetail: jasmine.createSpy('archGet').and.callFake((id: string, cb: (c: any) => void) => {
74
- cb(null);
75
- }),
76
- setConversationRead: jasmine.createSpy('setConversationReadArchived'),
77
- };
78
-
79
- chatManagerStub = {
80
- getConversationHandlerByConversationId: jasmine.createSpy('getH').and.returnValue(null),
81
- addConversationHandler: jasmine.createSpy('addH'),
82
- conversationsHandlerService: convHandlerSvc,
83
- archivedConversationsService: archivedSvc,
84
- };
85
-
86
- tiledeskStub = {
87
- getMyRequests: jasmine.createSpy('getMyRequests').and.resolveTo({ requests: [] }),
88
- closeSupportGroup: jasmine.createSpy('closeSupportGroup').and.resolveTo('closed'),
89
- };
90
-
91
- starRatingStub = {
92
- obsCloseConversation: new BehaviorSubject<boolean | null>(false),
93
- setOsservable: jasmine.createSpy('setOsservable'),
94
- };
95
-
96
- const customTranslateStub = {
97
- translateLanguage: jasmine.createSpy('translateLanguage').and.callFake((keys: string[]) => {
98
- const m = new Map<string, string>();
99
- keys.forEach((k) => m.set(k, k));
100
- return m;
101
- }),
102
- };
103
-
104
- builderStub = {
105
- build: jasmine.createSpy('build').and.returnValue(conversationHandlerMock),
106
- };
107
-
108
- spyOn(ConversationComponent.prototype, 'ngAfterViewInit').and.stub();
109
- spyOn(ConversationComponent.prototype, 'ngAfterViewChecked').and.stub();
110
- spyOn(ConversationComponent.prototype, 'ngOnDestroy').and.stub();
111
-
112
- await TestBed.configureTestingModule({
113
- declarations: [ConversationComponent],
114
- providers: [
40
+ let ngxlogger: NGXLogger;
41
+ let customLogger = new CustomLogger(ngxlogger)
42
+ class MockElementRef {}
43
+
44
+ beforeEach(waitForAsync(() => {
45
+ TestBed.configureTestingModule({
46
+ declarations: [ConversationComponent],
47
+ schemas: [NO_ERRORS_SCHEMA],
48
+ imports: [TranslateModule.forRoot()],
49
+ providers: [
115
50
  Globals,
116
- { provide: AppConfigService, useValue: { getConfig: () => ({ apiUrl: 'https://api.test/' }) } },
117
- { provide: StarRatingWidgetService, useValue: starRatingStub },
118
- { provide: AppStorageService, useValue: { getItem: jasmine.createSpy().and.returnValue(null), setItem: jasmine.createSpy(), removeItem: jasmine.createSpy() } },
119
- { provide: ConversationHandlerBuilderService, useValue: builderStub },
120
- { provide: ChatManager, useValue: chatManagerStub },
121
- { provide: CustomTranslateService, useValue: customTranslateStub },
122
- { provide: TypingService, useValue: { isTyping: jasmine.createSpy(), BSIsTyping: new Subject() } },
123
- { provide: TiledeskRequestsService, useValue: tiledeskStub },
124
- EventsService,
51
+ AppConfigService,
52
+ AppComponent,
53
+ { provide: ElementRef, useClass: MockElementRef },
54
+ GlobalSettingsService,
55
+ Triggerhandler,
56
+ TranslatorService,
57
+ AppConfigService,
58
+ AppStorageService,
59
+ CustomTranslateService,
60
+ MessagingAuthService,
61
+ TiledeskAuthService,
62
+ PresenceService,
63
+ ConversationsHandlerService,
64
+ ArchivedConversationsHandlerService,
65
+ ConversationHandlerBuilderService,
66
+ ChatManager,
67
+ TypingService,
68
+ ImageRepoService,
69
+ UploadService,
70
+ StarRatingWidgetService,
71
+ TiledeskRequestsService,
72
+ NGXLogger,
125
73
  provideHttpClient(withInterceptorsFromDi()),
126
- provideHttpClientTesting(),
127
- ],
128
- })
129
- .overrideComponent(ConversationComponent, {
130
- set: { template: '' },
131
- })
132
- .compileComponents();
74
+ provideHttpClientTesting()
75
+ ]
76
+ })
77
+ .compileComponents();
78
+ }));
133
79
 
80
+ beforeEach(() => {
134
81
  fixture = TestBed.createComponent(ConversationComponent);
135
82
  component = fixture.componentInstance;
136
-
137
- globals = TestBed.inject(Globals);
138
- globals.initDefafultParameters();
139
- globals.setParameter('recipientId', 'support-group-proj-abc');
140
- globals.setParameter('projectid', 'proj1');
141
- globals.setParameter('channelType', 'group');
142
- globals.senderId = 'visitor-1';
143
- (globals as any).attributes = (globals as any).attributes ?? {};
144
-
145
- component.conversationId = 'support-group-proj-abc';
146
- component.conversationWith = 'support-group-proj-abc';
147
- component.senderId = 'visitor-1';
148
- component.isOpen = true;
149
- component.stylesMap = new Map([
150
- ['themeColor', '#2a6ac1'],
151
- ['foregroundColor', '#fff'],
152
- ]);
153
-
154
- /** ViewChild refs stay undefined with empty template; assign after first CD cycle. */
83
+ LoggerInstance.setInstance(customLogger)
84
+ let logger = LoggerInstance.getInstance()
85
+ component['logger']= logger
86
+ let globals = fixture.debugElement.injector.get(Globals) as Globals;
87
+ globals.initDefafultParameters()
155
88
  fixture.detectChanges();
156
- component.conversationFooter = {
157
- sendMessage: jasmine.createSpy('sendMessage'),
158
- textInputTextArea: '',
159
- uploadSingle: jasmine.createSpy('uploadSingle'),
160
- isFilePendingToUpload: false,
161
- removeFocusOnId: jasmine.createSpy('removeFocusOnId'),
162
- } as any;
163
-
164
- component.conversationContent = {
165
- scrollToBottom: jasmine.createSpy('scrollToBottom'),
166
- checkContentScrollPosition: jasmine.createSpy('checkContentScrollPosition').and.returnValue(true),
167
- scrollMe: { nativeElement: { style: { height: '' } } },
168
- } as any;
169
-
170
- component.mydialog = {
171
- nativeElement: { showModal: jasmine.createSpy('showModal'), close: jasmine.createSpy('close') },
172
- } as any;
173
-
174
- component.conversationsHandlerService = chatManagerStub.conversationsHandlerService as any;
175
- component.archivedConversationsHandlerService = chatManagerStub.archivedConversationsService as any;
176
89
  });
177
90
 
178
91
  it('should create', () => {
179
92
  expect(component).toBeTruthy();
180
93
  });
181
-
182
- describe('ngOnInit', () => {
183
- it('should initialise translations and default welcome flag', () => {
184
- expect(component.showMessageWelcome).toBe(false);
185
- expect(component.translationMapHeader).toBeDefined();
186
- expect(component.translationMapFooter).toBeDefined();
187
- });
188
- });
189
-
190
- describe('scrollToBottom and translations', () => {
191
- it('scrollToBottom should delegate to conversation content', () => {
192
- component.scrollToBottom();
193
- expect(component.conversationContent.scrollToBottom).toHaveBeenCalled();
194
- });
195
-
196
- it('translations should refresh all translation maps', () => {
197
- component.translations();
198
- expect(component.translationMapPreview?.size).toBeGreaterThan(0);
199
- expect(component.translationMapCloseChatDialog?.size).toBeGreaterThan(0);
200
- });
201
- });
202
-
203
- describe('updateConversationBadge archived branch', () => {
204
- it('should call archived handler when conversation is archived', () => {
205
- component.isConversationArchived = true;
206
- component.conversationId = 'arch-1';
207
- component.archivedConversationsHandlerService = chatManagerStub.archivedConversationsService as any;
208
- component.updateConversationBadge();
209
- expect(chatManagerStub.archivedConversationsService.setConversationRead).toHaveBeenCalledWith('arch-1');
210
- });
211
- });
212
-
213
- describe('drag / drop edge paths', () => {
214
- it('drag should return early when dropped file type is not allowed (hover unchanged)', () => {
215
- (globals as any).fileUploadAccept = 'application/pdf';
216
- component.isHovering = true;
217
- const dt = new DataTransfer();
218
- dt.items.add(new File(['x'], 'a.png', { type: 'image/png' }));
219
- const ev: any = {
220
- preventDefault: jasmine.createSpy(),
221
- stopPropagation: jasmine.createSpy(),
222
- dataTransfer: { files: dt.files },
223
- };
224
- component.drag(ev);
225
- expect(component.isHovering).toBe(true);
226
- });
227
-
228
- it('drag should clear hovering when there is no file payload', () => {
229
- component.isHovering = true;
230
- const ev: any = {
231
- preventDefault: jasmine.createSpy(),
232
- stopPropagation: jasmine.createSpy(),
233
- dataTransfer: null,
234
- };
235
- component.drag(ev);
236
- expect(component.isHovering).toBe(false);
237
- });
238
- });
239
-
240
- describe('onResize', () => {
241
- it('should log resize', () => {
242
- component.onResize(new Event('resize'));
243
- expect(component).toBeTruthy();
244
- });
245
- });
246
-
247
- describe('ngOnChanges', () => {
248
- it('should apply CSS variables from stylesMap', () => {
249
- const el = fixture.nativeElement as HTMLElement;
250
- spyOn(el.style, 'setProperty');
251
- (component as any).elementRef = { nativeElement: el };
252
- component.ngOnChanges({ stylesMap: new SimpleChange(null, component.stylesMap, false) });
253
- expect(el.style.setProperty).toHaveBeenCalled();
254
- });
255
- });
256
-
257
- describe('updateConversationBadge', () => {
258
- it('should mark conversation read when active list', () => {
259
- component.isConversationArchived = false;
260
- component.conversationId = 'c1';
261
- component.conversationsHandlerService = chatManagerStub.conversationsHandlerService;
262
- component.updateConversationBadge();
263
- expect(chatManagerStub.conversationsHandlerService.setConversationRead).toHaveBeenCalledWith('c1');
264
- });
265
- });
266
-
267
- describe('getConversationDetail', () => {
268
- it('should resolve active conversation', fakeAsync(() => {
269
- chatManagerStub.conversationsHandlerService.getConversationDetail.and.callFake((id: string, cb: any) => cb({ uid: 'x' }));
270
- let result: boolean | null = null;
271
- component.getConversationDetail().then((r) => (result = r));
272
- tick();
273
- expect(result).toBe(false);
274
- expect(component.conversation).toEqual({ uid: 'x' } as any);
275
- }));
276
-
277
- it('should fall back to archived when active missing', fakeAsync(() => {
278
- chatManagerStub.conversationsHandlerService.getConversationDetail.and.callFake((id: string, cb: any) => cb(null));
279
- chatManagerStub.archivedConversationsService.getConversationDetail.and.callFake((id: string, cb: any) =>
280
- cb({ uid: 'arch' }),
281
- );
282
- let result: boolean | null = null;
283
- component.getConversationDetail().then((r) => (result = r));
284
- tick();
285
- expect(result).toBe(true);
286
- }));
287
-
288
- it('should recover when getMyRequests rejects (component catch returns empty list)', async () => {
289
- chatManagerStub.conversationsHandlerService.getConversationDetail.and.callFake((id: string, cb: any) => cb(null));
290
- chatManagerStub.archivedConversationsService.getConversationDetail.and.callFake((id: string, cb: any) => cb(null));
291
- tiledeskStub.getMyRequests.and.returnValue(Promise.reject(new Error('network')));
292
- await component.getConversationDetail();
293
- expect(component.isConversationArchived).toBe(true);
294
- });
295
-
296
- it('should match request by request_id', fakeAsync(() => {
297
- chatManagerStub.conversationsHandlerService.getConversationDetail.and.callFake((id: string, cb: any) => cb(null));
298
- chatManagerStub.archivedConversationsService.getConversationDetail.and.callFake((id: string, cb: any) => cb(null));
299
- tiledeskStub.getMyRequests.and.resolveTo({
300
- requests: [{ request_id: component.conversationId }],
301
- });
302
- let result: boolean | null = null;
303
- component.getConversationDetail().then((r) => (result = r));
304
- tick();
305
- expect(result).toBe(false);
306
- }));
307
- });
308
-
309
- describe('emitter handlers', () => {
310
- it('onBackHomeFN emits', () => {
311
- spyOn(component.onBackHome, 'emit');
312
- component.onBackHomeFN();
313
- expect(component.onBackHome.emit).toHaveBeenCalled();
314
- });
315
-
316
- it('onSoundChangeFN emits', () => {
317
- spyOn(component.onSoundChange, 'emit');
318
- component.onSoundChangeFN(true);
319
- expect(component.onSoundChange.emit).toHaveBeenCalledWith(true);
320
- });
321
-
322
- it('onMenuOptionClick LOGOUT emits signOut', () => {
323
- spyOn(component.onSignOut, 'emit');
324
- component.onMenuOptionClick(HEADER_MENU_OPTION.LOGOUT);
325
- expect(component.onSignOut.emit).toHaveBeenCalledWith(true);
326
- });
327
-
328
- it('onMenuOptionClick VOLUME emits sound', () => {
329
- spyOn(component.onSoundChange, 'emit');
330
- component.onMenuOptionClick(HEADER_MENU_OPTION.VOLUME_ON);
331
- component.onMenuOptionClick(HEADER_MENU_OPTION.VOLUME_OFF);
332
- expect(component.onSoundChange.emit).toHaveBeenCalledWith(true);
333
- expect(component.onSoundChange.emit).toHaveBeenCalledWith(false);
334
- });
335
-
336
- it('onMenuOptionClick CLOSE opens dialog', () => {
337
- component.conversation = { uid: 'c1' } as any;
338
- component.onMenuOptionClick(HEADER_MENU_OPTION.CLOSE);
339
- expect(component.mydialog.nativeElement.showModal).toHaveBeenCalled();
340
- });
341
-
342
- it('onMenuOptionClick RESTART sends /start', () => {
343
- component.onMenuOptionClick(HEADER_MENU_OPTION.RESTART);
344
- expect(component.conversationFooter.sendMessage).toHaveBeenCalled();
345
- });
346
- });
347
-
348
- describe('onCloseDialog', () => {
349
- it('back closes modal', () => {
350
- component.onCloseDialog({ type: 'back', data: null });
351
- expect(component.mydialog.nativeElement.close).toHaveBeenCalled();
352
- });
353
-
354
- it('confirm resolves closeSupportGroup success', fakeAsync(() => {
355
- component.conversationId = 'cid';
356
- component.onCloseDialog({ type: 'confirm', data: null });
357
- tick();
358
- expect(tiledeskStub.closeSupportGroup).toHaveBeenCalledWith('cid');
359
- expect(component.mydialog.nativeElement.close).toHaveBeenCalled();
360
- }));
361
-
362
- it('confirm logs on close failure', fakeAsync(() => {
363
- tiledeskStub.closeSupportGroup.and.returnValue(Promise.reject('e'));
364
- component.onCloseDialog({ type: 'confirm', data: null });
365
- tick();
366
- expect(component).toBeTruthy();
367
- }));
368
- });
369
-
370
- describe('newMessageAdded', () => {
371
- it('should scroll for own messages', fakeAsync(() => {
372
- const msg = { sender: 'visitor-1', timestamp: Date.now() } as MessageModel;
373
- component.senderId = 'visitor-1';
374
- component.newMessageAdded(msg);
375
- tick(250);
376
- expect(component.conversationContent.scrollToBottom).toHaveBeenCalled();
377
- }));
378
-
379
- it('should increment badge when scrolled up', () => {
380
- component.senderId = 'visitor-1';
381
- component.conversationContent = {
382
- ...component.conversationContent,
383
- checkContentScrollPosition: jasmine.createSpy('chk').and.returnValue(false),
384
- } as any;
385
- const msg = { sender: 'agent', attributes: {}, timestamp: Date.now() } as MessageModel;
386
- const before = component.messagesBadgeCount;
387
- component.newMessageAdded(msg);
388
- expect(component.messagesBadgeCount).toBe(before + 1);
389
- });
390
- });
391
-
392
- describe('onScrollContent', () => {
393
- it('should reset badge when reaching bottom', () => {
394
- component.messagesBadgeCount = 3;
395
- component.onScrollContent(true);
396
- expect(component.messagesBadgeCount).toBe(0);
397
- });
398
- });
399
-
400
- describe('onAfterSendMessageFN', () => {
401
- it('should set thinking for own messages', () => {
402
- spyOn(component.onAfterSendMessage, 'emit');
403
- const msg = { sender: 'visitor-1' } as MessageModel;
404
- component.senderId = 'visitor-1';
405
- component.onAfterSendMessageFN(msg);
406
- expect(component.showThinkingMessage).toBe(true);
407
- });
408
- });
409
-
410
- describe('drop / allowDrop / drag', () => {
411
- it('allowDrop sets hovering', () => {
412
- const ev = { preventDefault: jasmine.createSpy(), stopPropagation: jasmine.createSpy() } as any;
413
- component.allowDrop(ev);
414
- expect(component.isHovering).toBe(true);
415
- });
416
-
417
- it('drop stores dropEvent when files present', () => {
418
- const file = new File(['b'], 'b.txt');
419
- const dt = new DataTransfer();
420
- dt.items.add(file);
421
- const ev: any = {
422
- preventDefault: jasmine.createSpy(),
423
- stopPropagation: jasmine.createSpy(),
424
- dataTransfer: { files: dt.files },
425
- };
426
- component.drop(ev);
427
- expect(component.dropEvent).toBe(ev);
428
- });
429
- });
430
-
431
- describe('unsubscribe()', () => {
432
- it('clears subscription entries', () => {
433
- component.conversationHandlerService = conversationHandlerMock as any;
434
- (component as any).typingService = TestBed.inject(TypingService);
435
- component.subscriptions = [];
436
- component.unsubscribe();
437
- expect(component.subscriptions.length).toBe(0);
438
- });
439
- });
440
-
441
- describe('lead / user info updates (visitor profile)', () => {
442
- it('updateLeadInfo should persist fullname/email to Globals and storage', () => {
443
- const storage = TestBed.inject(AppStorageService);
444
- const msg = {
445
- attributes: { updateUserFullname: 'Jane', updateUserEmail: 'jane@example.com' },
446
- } as MessageModel;
447
- component.updateLeadInfo(msg);
448
- expect((globals as any).userFullname).toContain('Jane');
449
- expect(storage.setItem).toHaveBeenCalled();
450
- });
451
-
452
- it('updateUserInfo should copy customAttributes onto Globals', () => {
453
- component.updateUserInfo({ userFullname: 'Bob', userEmail: 'bob@example.com' });
454
- expect((globals as any).userFullname).toBe('Bob');
455
- });
456
- });
457
-
458
- describe('onAttachmentButtonClicked', () => {
459
- beforeEach(() => {
460
- component.conversationFooter = {
461
- sendMessage: jasmine.createSpy('sendMessage'),
462
- } as any;
463
- });
464
-
465
- it('should return early when payload is incomplete', () => {
466
- component.onAttachmentButtonClicked(null);
467
- expect(component.conversationFooter.sendMessage).not.toHaveBeenCalled();
468
- });
469
-
470
- it('should send text button value', () => {
471
- component.onAttachmentButtonClicked({
472
- target: { type: 'text', button: { value: 'OK' } },
473
- });
474
- expect(component.conversationFooter.sendMessage).toHaveBeenCalled();
475
- });
476
- });
477
-
478
- describe('onWidgetSizeChange', () => {
479
- it('should short-circuit when mobile', () => {
480
- (globals as any).isMobile = true;
481
- component.onWidgetSizeChange('min');
482
- expect(globals.fullscreenMode).toBe(true);
483
- (globals as any).isMobile = false;
484
- });
485
-
486
- it('should persist size and toggle classes when tiledeskdiv exists', () => {
487
- const storage = TestBed.inject(AppStorageService);
488
- const tiledeskDiv = document.createElement('div');
489
- tiledeskDiv.id = 'tiledeskdiv';
490
- const parent = document.createElement('div');
491
- parent.appendChild(tiledeskDiv);
492
- document.body.appendChild(parent);
493
- (globals as any).windowContext = {
494
- window: { document: { getElementById: (id: string) => (id === 'tiledeskdiv' ? tiledeskDiv : null) } },
495
- };
496
- (globals as any).isMobile = false;
497
- (globals as any).align = 'right';
498
- (globals as any).marginX = '10px';
499
- (globals as any).marginY = '10px';
500
- (globals as any).mobileMarginX = '5px';
501
- (globals as any).mobileMarginY = '5px';
502
-
503
- component.onWidgetSizeChange('max');
504
- expect(tiledeskDiv.classList.contains('max-size')).toBe(true);
505
- expect(storage.setItem).toHaveBeenCalled();
506
-
507
- component.onWidgetSizeChange('top');
508
- expect(parent.classList.contains('overlay--popup')).toBe(true);
509
-
510
- document.body.removeChild(parent);
511
- });
512
- });
513
-
514
- describe('skipToCompose', () => {
515
- it('should focus composer when textarea exists', () => {
516
- const ta = document.createElement('textarea');
517
- ta.id = 'chat21-main-message-context';
518
- document.body.appendChild(ta);
519
- spyOn(ta, 'focus');
520
- component.skipToCompose();
521
- expect(ta.focus).toHaveBeenCalled();
522
- document.body.removeChild(ta);
523
- });
524
- });
525
-
526
- describe('header / widget chrome handlers', () => {
527
- it('onCloseWidgetFN should strip size classes and emit', () => {
528
- spyOn(component.onCloseWidget, 'emit');
529
- const tiledeskDiv = document.createElement('div');
530
- tiledeskDiv.classList.add('max-size', 'min-size');
531
- (globals as any).windowContext = {
532
- window: { document: { getElementById: () => tiledeskDiv } },
533
- };
534
- component.onCloseWidgetFN();
535
- expect(component.onCloseWidget.emit).toHaveBeenCalled();
536
- expect(tiledeskDiv.classList.contains('max-size')).toBe(false);
537
- expect(tiledeskDiv.classList.contains('min-size')).toBe(false);
538
- });
539
-
540
- it('onCloseChat should open dialog', () => {
541
- component.conversation = { uid: 'c1' } as any;
542
- component.onCloseChat();
543
- expect(component.mydialog.nativeElement.showModal).toHaveBeenCalled();
544
- expect(component.isMenuShow).toBe(false);
545
- });
546
-
547
- it('onRestartChat should send /start with attributes', () => {
548
- (globals as any).attributes = { k: 'v' };
549
- component.onRestartChat();
550
- expect(component.conversationFooter.sendMessage).toHaveBeenCalled();
551
- const args = (component.conversationFooter.sendMessage as jasmine.Spy).calls.mostRecent().args;
552
- expect(args[0]).toBe('/start');
553
- });
554
-
555
- it('onMenuOptionClick should route MAXIMIZE and MINIMIZE', () => {
556
- spyOn(component, 'onWidgetSizeChange');
557
- component.onMenuOptionClick(HEADER_MENU_OPTION.MAXIMIZE);
558
- component.onMenuOptionClick(HEADER_MENU_OPTION.MINIMIZE);
559
- expect(component.onWidgetSizeChange).toHaveBeenCalledWith('max');
560
- expect(component.onWidgetSizeChange).toHaveBeenCalledWith('min');
561
- });
562
-
563
- it('onMenuOption should update visibility and blur composer', () => {
564
- component.onMenuOption(false);
565
- expect(component.isMenuShow).toBe(false);
566
- expect(component.conversationFooter.removeFocusOnId).toHaveBeenCalledWith('chat21-main-message-context');
567
- });
568
- });
569
-
570
- describe('content and preview bridges', () => {
571
- it('onBeforeMessageRenderFN and onAfterMessageRenderFN should emit', () => {
572
- spyOn(component.onBeforeMessageRender, 'emit');
573
- spyOn(component.onAfterMessageRender, 'emit');
574
- component.onBeforeMessageRenderFN({ a: 1 });
575
- component.onAfterMessageRenderFN({ b: 2 });
576
- expect(component.onBeforeMessageRender.emit).toHaveBeenCalledWith({ a: 1 });
577
- expect(component.onAfterMessageRender.emit).toHaveBeenCalledWith({ b: 2 });
578
- });
579
-
580
- it('onAttachmentButtonClicked url should call openLink', () => {
581
- spyOn(component as any, 'openLink');
582
- component.onAttachmentButtonClicked({ target: { type: 'url', button: { href: 'x' } } });
583
- expect((component as any).openLink).toHaveBeenCalled();
584
- });
585
-
586
- it('onAttachmentButtonClicked action should call actionButton', () => {
587
- spyOn(component as any, 'actionButton');
588
- component.onAttachmentButtonClicked({ target: { type: 'action', button: {} } });
589
- expect((component as any).actionButton).toHaveBeenCalled();
590
- });
591
-
592
- it('onScrollContent false should show scroll-to-bottom affordance', () => {
593
- component.onScrollContent(false);
594
- expect(component.showBadgeScroollToBottom).toBe(true);
595
- });
596
-
597
- it('onOpenExternalFrame should open window', () => {
598
- spyOn(window, 'open');
599
- component.onOpenExternalFrame({ link: 'https://ex.example' });
600
- expect(window.open).toHaveBeenCalledWith('https://ex.example', '_blank');
601
- });
602
-
603
- it('onCloseInternalFrame should clear button state', () => {
604
- spyOn(component as any, 'restoreDefaultWidgetSize').and.stub();
605
- component.isButtonUrl = true;
606
- component.buttonClicked = { x: 1 } as any;
607
- component.onCloseInternalFrame({});
608
- expect(component.isButtonUrl).toBe(false);
609
- expect(component.buttonClicked).toBeNull();
610
- });
611
-
612
- it('onSendAttachment should close preview and call uploadSingle', () => {
613
- component.isOpenAttachmentPreview = true;
614
- component.attachments = [{ metadata: { uid: '1' }, file: new File([], 'a.png') }] as any;
615
- component.conversationFooter.uploadSingle = jasmine.createSpy('uploadSingle');
616
- component.onSendAttachment('cap');
617
- expect(component.isOpenAttachmentPreview).toBe(false);
618
- expect(component.conversationFooter.uploadSingle).toHaveBeenCalled();
619
- });
620
-
621
- it('onCloseModalPreview should reset footer upload flag', () => {
622
- component.isOpenAttachmentPreview = true;
623
- (component.conversationFooter as any).isFilePendingToUpload = true;
624
- component.onCloseModalPreview();
625
- expect(component.isOpenAttachmentPreview).toBe(false);
626
- expect((component.conversationFooter as any).isFilePendingToUpload).toBe(false);
627
- });
628
-
629
- it('onEmojiiPickerShow should mirror state', () => {
630
- component.onEmojiiPickerShow(true);
631
- expect(component.isEmojiiPickerShow).toBe(true);
632
- });
633
-
634
- it('onBeforeMessangeSentFN should emit', () => {
635
- spyOn(component.onBeforeMessageSent, 'emit');
636
- const m = { uid: 'm' } as MessageModel;
637
- component.onBeforeMessangeSentFN(m);
638
- expect(component.onBeforeMessageSent.emit).toHaveBeenCalledWith(m);
639
- });
640
-
641
- it('onChangeTextArea should resize scroll host for medium heights', () => {
642
- const scrollHost = component.conversationContent.scrollMe.nativeElement;
643
- component.onChangeTextArea({
644
- textAreaEl: { style: { height: '40px' } },
645
- } as any);
646
- expect(scrollHost.style.height).toContain('calc');
647
- });
648
-
649
- it('onAttachmentFileButtonClicked should open preview', () => {
650
- const ev = { attachments: [{ f: 1 }], message: 'm' };
651
- component.onAttachmentFileButtonClicked(ev as any);
652
- expect(component.isOpenAttachmentPreview).toBe(true);
653
- expect(component.attachments as any).toEqual([{ f: 1 }]);
654
- expect(component.textInputTextArea).toBe('m');
655
- });
656
-
657
- it('onNewConversationButtonClickedFN should emit', () => {
658
- spyOn(component.onNewConversationButtonClicked, 'emit');
659
- component.onNewConversationButtonClickedFN(null);
660
- expect(component.onNewConversationButtonClicked.emit).toHaveBeenCalled();
661
- });
662
- });
663
94
  });