@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,122 +1,30 @@
1
- import { A11yModule } from '@angular/cdk/a11y';
2
- import { Component, EventEmitter, Input, Output } from '@angular/core';
3
- import { ComponentFixture, TestBed, fakeAsync, tick, waitForAsync } from '@angular/core/testing';
4
- import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
5
-
6
- import { Globals } from 'src/app/utils/globals';
7
- import { AppStorageService } from 'src/chat21-core/providers/abstract/app-storage.service';
8
- import { CustomLogger } from 'src/chat21-core/providers/logger/customLogger';
9
- import { LoggerInstance } from 'src/chat21-core/providers/logger/loggerInstance';
1
+ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2
+ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
10
3
 
11
4
  import { PrechatFormComponent } from './prechat-form.component';
12
-
13
- @Component({
14
- selector: 'chat-form-builder',
15
- template: '',
16
- })
17
- class ChatFormBuilderStubComponent {
18
- @Input() formArray: unknown;
19
- @Input() isOpenPrechatForm: boolean;
20
- @Input() stylesMap: Map<string, string> | undefined;
21
- @Output() onSubmitForm = new EventEmitter<Record<string, string>>();
22
- @Output() onErrorRenderForm = new EventEmitter<void>();
23
- }
5
+ import { AppStorageService } from 'src/chat21-core/providers/abstract/app-storage.service';
6
+ import { Globals } from 'src/app/utils/globals';
24
7
 
25
8
  describe('PrechatFormComponent', () => {
26
9
  let component: PrechatFormComponent;
27
10
  let fixture: ComponentFixture<PrechatFormComponent>;
28
- let g: Globals;
29
- let appStorage: jasmine.SpyObj<AppStorageService>;
30
- const ngxlogger = jasmine.createSpyObj('NGXLogger', ['log', 'trace', 'debug', 'warn', 'error']);
31
- const customLogger = new CustomLogger(ngxlogger);
32
-
33
- beforeEach(waitForAsync(() => {
34
- appStorage = jasmine.createSpyObj('AppStorageService', [
35
- 'initialize',
36
- 'getItem',
37
- 'setItem',
38
- 'getItemWithoutProjectID',
39
- 'setItemWithoutProjectID',
40
- 'removeItem',
41
- 'clear',
42
- ]);
43
11
 
12
+ beforeEach(async(() => {
44
13
  TestBed.configureTestingModule({
45
- declarations: [PrechatFormComponent, ChatFormBuilderStubComponent],
46
- imports: [A11yModule, ReactiveFormsModule],
47
- providers: [
48
- Globals,
49
- FormBuilder,
50
- { provide: AppStorageService, useValue: appStorage },
51
- ],
52
- }).compileComponents();
14
+ declarations: [ PrechatFormComponent ],
15
+ imports: [ FormsModule, ReactiveFormsModule ],
16
+ providers: [ Globals, AppStorageService]
17
+ })
18
+ .compileComponents();
53
19
  }));
54
20
 
55
21
  beforeEach(() => {
56
- LoggerInstance.setInstance(customLogger);
57
22
  fixture = TestBed.createComponent(PrechatFormComponent);
58
23
  component = fixture.componentInstance;
59
- g = TestBed.inject(Globals);
60
- g.LABEL_COMPLETE_FORM = 'Complete form';
61
- g.attributes = { foo: 'bar' };
62
24
  fixture.detectChanges();
63
25
  });
64
26
 
65
27
  it('should create', () => {
66
28
  expect(component).toBeTruthy();
67
29
  });
68
-
69
- it('onSubmitForm should persist attributes, merge preChatForm, and emit onCloseForm', () => {
70
- spyOn(component.onCloseForm, 'emit');
71
- const form = { userFullname: 'Jane Doe', userEmail: 'jane@example.com' };
72
- component.onSubmitForm(form);
73
- expect(g.attributes.userFullname).toBe('Jane Doe');
74
- expect(g.attributes.userEmail).toBe('jane@example.com');
75
- expect(g.attributes.preChatForm).toEqual(form);
76
- expect(appStorage.setItem).toHaveBeenCalledWith('attributes', jasmine.any(String));
77
- expect(component.onCloseForm.emit).toHaveBeenCalled();
78
- });
79
-
80
- it('onSubmitForm should not emit when g.attributes is missing', () => {
81
- g.attributes = undefined as any;
82
- spyOn(component.onCloseForm, 'emit');
83
- component.onSubmitForm({ userFullname: 'X' });
84
- expect(component.onCloseForm.emit).not.toHaveBeenCalled();
85
- expect(appStorage.setItem).not.toHaveBeenCalled();
86
- });
87
-
88
- it('returnClosePage should emit onClosePage', () => {
89
- spyOn(component.onClosePage, 'emit');
90
- component.returnClosePage();
91
- expect(component.onClosePage.emit).toHaveBeenCalled();
92
- });
93
-
94
- it('onEscape should stop propagation, prevent default, and close page', () => {
95
- spyOn(component.onClosePage, 'emit');
96
- const ev = new KeyboardEvent('keydown', { key: 'Escape' });
97
- spyOn(ev, 'preventDefault');
98
- spyOn(ev, 'stopPropagation');
99
- component.onEscape(ev);
100
- expect(ev.preventDefault).toHaveBeenCalled();
101
- expect(ev.stopPropagation).toHaveBeenCalled();
102
- expect(component.onClosePage.emit).toHaveBeenCalled();
103
- });
104
-
105
- it('onErrorRenderForm should restore default preChatFormJson via Globals', () => {
106
- spyOn(g, 'setParameter');
107
- component.onErrorRenderForm();
108
- expect(g.setParameter).toHaveBeenCalledWith('preChatFormJson', jasmine.any(Array));
109
- const arg = (g.setParameter as jasmine.Spy).calls.mostRecent().args[1] as any[];
110
- expect(arg[0].name).toBe('userFullname');
111
- expect(arg[1].name).toBe('userEmail');
112
- });
113
-
114
- it('should request focus on dialog root after view init (async)', fakeAsync(() => {
115
- const fixtureInner = TestBed.createComponent(PrechatFormComponent);
116
- const el = fixtureInner.nativeElement.querySelector('#chat21-prechat-form') as HTMLElement;
117
- spyOn(el, 'focus');
118
- fixtureInner.detectChanges();
119
- tick(1000);
120
- expect(el.focus).toHaveBeenCalled();
121
- }));
122
30
  });
@@ -1,4 +1,4 @@
1
- import { AfterViewInit, Component, ElementRef, EventEmitter, HostListener, Input, OnInit, Output, ViewChild } from '@angular/core';
1
+ import { AfterViewInit, Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
2
2
  import { FormBuilder, FormGroup } from '@angular/forms';
3
3
  import { Globals } from 'src/app/utils/globals';
4
4
  import { AppStorageService } from 'src/chat21-core/providers/abstract/app-storage.service';
@@ -120,13 +120,6 @@ export class PrechatFormComponent implements OnInit, AfterViewInit {
120
120
  this.onClosePage.emit();
121
121
  }
122
122
 
123
- @HostListener('keydown.escape', ['$event'])
124
- onEscape(event: KeyboardEvent){
125
- event.preventDefault();
126
- event.stopPropagation();
127
- this.returnClosePage();
128
- }
129
-
130
123
  onSubmitForm(form: {}){
131
124
  this.logger.debug('[PRE-CHAT-FORM] onSubmitForm:', form)
132
125
  if(this.g.attributes){
@@ -1,7 +1,6 @@
1
1
 
2
- <div #homeComponent id='chat21-home-component'
3
- role="region"
4
- [attr.aria-label]="g?.welcomeTitle || g?.project?.widgetTitle || 'Chat'">
2
+ <!-- tabindex="2000"-->
3
+ <div #homeComponent id='chat21-home-component' tabindex="2002" onFocus="document.querySelector('[aflistconv]').focus()">
5
4
 
6
5
  <!-- HEADER -->
7
6
  <div class="c21-header" (click)="hideMenuOptions()" [ngStyle]="{'color': g.themeForegroundColor, 'background-image': g.colorGradient }" >
@@ -16,59 +15,50 @@
16
15
 
17
16
  <!-- ICON MAXIMIZE -->
18
17
  <div *ngIf="size === 'min' && !fullscreenMode && !g?.isMobile" class="c21-size-button">
19
- <button [attr.disabled]="(isButtonsDisabled)?true:null"
20
- type="button"
21
- class="c21-close-button-body"
22
- [attr.aria-label]="translationMap?.get('MAXIMIZE')"
23
- [ngStyle]="{'display': (hideHeaderConversationOptionsMenu)?'none':'flex'}"
24
- (click)="onChangeSize('max')">
25
- <svg aria-hidden="true" focusable="false" [ngStyle]="{'fill': stylesMap?.get('foregroundColor') }" xmlns="http://www.w3.org/2000/svg" transform="matrix(-1,0,0,1,0,0)"
18
+ <button [attr.disabled]="(isButtonsDisabled)?true:null" tabindex="-1" class="c21-close-button-body" [ngStyle]="{'display': (hideHeaderConversationOptionsMenu)?'none':'flex'}" (click)="onChangeSize('max')" >
19
+ <svg role="img" aria-labelledby="altIconTitle" [ngStyle]="{'fill': stylesMap?.get('foregroundColor') }" xmlns="http://www.w3.org/2000/svg" transform="matrix(-1,0,0,1,0,0)"
26
20
  width="17" height="17" viewBox="0 0 17 17">
27
21
  <path d="M6.49001 8.30999L3.69 11.11V9.40999C3.69 8.93999 3.31 8.55999 2.84 8.55999C2.37 8.55999 1.99001 8.93999 1.99001 9.40999V14.01H6.59C7.06 14.01 7.44 13.63 7.44 13.16C7.44 12.69 7.06 12.31 6.59 12.31H4.89L7.69 9.50999L6.49001 8.30999ZM9.41 1.98999C8.94 1.98999 8.56001 2.36999 8.56001 2.83999C8.56001 3.30999 8.94 3.68999 9.41 3.68999H11.11L8.31001 6.48999L9.51 7.68999L12.31 4.88999V6.58999C12.31 7.05999 12.69 7.43999 13.16 7.43999C13.63 7.43999 14.01 7.05999 14.01 6.58999V1.98999H9.41Z"></path>
22
+ <title id="altIconTitle">{{ translationMap?.get('MAXIMIZE') }}</title>
28
23
  </svg>
29
24
  </button>
30
25
  </div>
31
26
 
32
27
  <!-- ICON MINIMIZE -->
33
28
  <div *ngIf="size==='top' && !fullscreenMode && !g?.isMobile" class="c21-size-button">
34
- <button [attr.disabled]="(isButtonsDisabled)?true:null"
35
- type="button"
36
- class="c21-close-button-body"
37
- [attr.aria-label]="translationMap?.get('MINIMIZE')"
38
- [ngStyle]="{'display': (hideHeaderConversationOptionsMenu)?'none':'flex'}"
39
- (click)="onChangeSize('min')">
40
- <svg aria-hidden="true" focusable="false" class="icon-menu" [ngStyle]="{'fill': stylesMap?.get('foregroundColor')}" xmlns="http://www.w3.org/2000/svg" transform="matrix(-1,0,0,1,0,0)"
29
+ <button [attr.disabled]="(isButtonsDisabled)?true:null" tabindex="-1" class="c21-close-button-body" [ngStyle]="{'display': (hideHeaderConversationOptionsMenu)?'none':'flex'}" (click)="onChangeSize('min')" >
30
+ <svg role="img" aria-labelledby="altIconTitle" class="icon-menu" [ngStyle]="{'fill': stylesMap?.get('foregroundColor')}" xmlns="http://www.w3.org/2000/svg" transform="matrix(-1,0,0,1,0,0)"
41
31
  width="17" height="17" viewBox="0 0 17 17">
42
32
  <path d="M13.59 5.31h-1.7l3.3-3.3-1.2-1.2-3.3 3.3v-1.7a.85.85 0 1 0-1.7 0v4.6h4.6a.85.85 0 1 0 0-1.7M1.57 9.84c0 .47.38.85.85.85h1.7l-3.3 3.3 1.2 1.2 3.3-3.3v1.7a.85.85 0 1 0 1.7 0v-4.6h-4.6a.85.85 0 0 0-.85.85"></path>
33
+ <title id="altIconTitle">{{ translationMap?.get('MINIMIZE') }}</title>
43
34
  </svg>
44
35
  </button>
45
36
  </div>
46
37
 
47
38
  <!-- ICON TOP -->
48
39
  <div *ngIf="size==='max' && !fullscreenMode && !g?.isMobile" class="c21-size-button">
49
- <button [attr.disabled]="(isButtonsDisabled)?true:null"
50
- type="button"
51
- class="c21-close-button-body"
52
- [attr.aria-label]="translationMap?.get('CENTER')"
53
- [ngStyle]="{'display': (hideHeaderConversationOptionsMenu)?'none':'flex'}"
54
- (click)="onChangeSize('top')">
55
- <svg aria-hidden="true" focusable="false" [ngStyle]="{'fill': stylesMap?.get('foregroundColor')}" xmlns="http://www.w3.org/2000/svg" transform="matrix(-1,0,0,1,0,0)"
40
+ <button [attr.disabled]="(isButtonsDisabled)?true:null" tabindex="-1" class="c21-close-button-body" [ngStyle]="{'display': (hideHeaderConversationOptionsMenu)?'none':'flex'}" (click)="onChangeSize('top')" >
41
+ <svg role="img" aria-labelledby="altIconTitle" [ngStyle]="{'fill': stylesMap?.get('foregroundColor')}" xmlns="http://www.w3.org/2000/svg" transform="matrix(-1,0,0,1,0,0)"
56
42
  width="17" height="17" viewBox="0 0 17 17">
57
43
  <path d="M3.7,7.6L2.5,6.4C2.2,6,2.2,5.5,2.5,5.2s0.9-0.4,1.2-0.1L7,8.4l-3.3,3.3c-0.4,0.4-0.8,0.3-1.1,0s-0.4-0.9-0.1-1.2l1.2-1.2 H1.5l0-1.7H3.7z"/>
58
44
  <path d="M13.3,7.6l1.2-1.2c0.4-0.4,0.3-0.8,0-1.1s-0.9-0.4-1.2-0.1L10,8.4l3.3,3.3c0.4,0.4,0.8,0.3,1.1,0s0.4-0.9,0.1-1.2l-1.2-1.2 h2.2l0-1.7H13.3z"/>
59
45
  <path d="M8.5,14.5L8.5,14.5c-0.5,0-0.9-0.4-0.9-0.8V3.3c0-0.5,0.4-0.8,0.8-0.8h0c0.5,0,0.8,0.4,0.8,0.8v10.4 C9.4,14.2,9,14.5,8.5,14.5z"/>
46
+ <title id="altIconTitle">{{ translationMap?.get('CENTER') }}</title>
60
47
  </svg>
61
48
  </button>
62
49
  </div>
63
50
 
64
51
 
65
52
  <div class="c21-close-button">
66
- <button type="button"
67
- class="c21-close-button-body"
68
- [attr.aria-label]="translationMapHeader?.get('BUTTON_CLOSE_TO_ICON')"
69
- (click)="f21_close()">
70
- <svg aria-hidden="true" focusable="false" [ngStyle]="{'fill': g.themeForegroundColor }" xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewBox="0 0 24 24">
53
+ <button tabindex="2001" aria-label=" chiudi chat" class="c21-close-button-body" (click)="f21_close()">
54
+ <!-- <svg role="img" aria-labelledby="altIconTitle" [ngStyle]="{'fill': g.themeForegroundColor }" xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewBox="0 0 24 24">
55
+ <path fill="none" d="M0 0h24v24H0V0z"/>
56
+ <path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"/>
57
+ <title id="altIconTitle">{{translationMapHeader?.get('BUTTON_CLOSE_TO_ICON')}}</title>
58
+ </svg> -->
59
+ <svg role="img" aria-labelledby="altIconTitle" [ngStyle]="{'fill': g.themeForegroundColor }" xmlns="http://www.w3.org/2000/svg" width="20px" height="20px" viewBox="0 0 24 24">
71
60
  <path d="M19.35,9.21c.2-.2.2-.51,0-.71l-.71-.71c-.2-.2-.51-.2-.71,0l-5.94,5.94-5.94-5.94c-.2-.2-.51-.2-.71,0l-.71.71c-.2.2-.2.51,0,.71l7,7c.2.2.51.2.71,0l7-7Z"/>
61
+ <title id="altIconTitle">{{translationMapHeader?.get('BUTTON_CLOSE_TO_ICON')}}</title>
72
62
  </svg>
73
63
  </button>
74
64
  </div>
@@ -83,8 +73,8 @@
83
73
 
84
74
  <!-- MESSAGE HEADER -->
85
75
  <div class="c21-text fade-in-bottom">
86
- <h1 class="c21-text-welcome">{{g?.welcomeTitle}}</h1>
87
- <p *ngIf="g.welcomeMsg" class="c21-text-intro">{{g.welcomeMsg}}</p>
76
+ <div class="c21-text-welcome">{{g?.welcomeTitle}}</div>
77
+ <div *ngIf="g.welcomeMsg" class="c21-text-intro">{{g.welcomeMsg}}</div>
88
78
  </div>
89
79
  </div>
90
80
  </div>
@@ -124,9 +114,9 @@
124
114
  <div class="c21-footer-content fade-in-bottom-footer" *ngIf="g?.whatsappNumber || g?.telegramUsername || g?.messangerPageTitle">
125
115
  <div class="label-item">{{translationMapFooter?.get('SWITCH_TO')}}</div>
126
116
  <div id="c21-whatsapp" *ngIf="g?.whatsappNumber && g?.whatsappNumber.trim() !== ''">
127
- <button type="button" aflistconv #aflistconv class="c21-button-primary" aria-label="WhatsApp" (click)="openConversationOnPlatform('whatsapp')">
117
+ <button tabindex="1040" aflistconv #aflistconv class="c21-button-primary" (click)="openConversationOnPlatform('whatsapp')">
128
118
  <span class="v-align-center">
129
- <svg aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="28" height="28" viewBox="0 0 1219.547 1225.016">
119
+ <svg aria-labelledby="altIconTitle" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="28" height="28" viewBox="0 0 1219.547 1225.016">
130
120
  <path fill="#E0E0E0" d="M1041.858 178.02C927.206 63.289 774.753.07 612.325 0 277.617 0 5.232 272.298 5.098 606.991c-.039 106.986 27.915 211.42 81.048 303.476L0 1225.016l321.898-84.406c88.689 48.368 188.547 73.855 290.166 73.896h.258.003c334.654 0 607.08-272.346 607.222-607.023.056-162.208-63.052-314.724-177.689-429.463zm-429.533 933.963h-.197c-90.578-.048-179.402-24.366-256.878-70.339l-18.438-10.93-191.021 50.083 51-186.176-12.013-19.087c-50.525-80.336-77.198-173.175-77.16-268.504.111-278.186 226.507-504.503 504.898-504.503 134.812.056 261.519 52.604 356.814 147.965 95.289 95.36 147.728 222.128 147.688 356.948-.118 278.195-226.522 504.543-504.693 504.543z"/>
131
121
  <linearGradient id="a" gradientUnits="userSpaceOnUse" x1="609.77" y1="1190.114" x2="609.77" y2="21.084">
132
122
  <stop offset="0" stop-color="#20b038"/>
@@ -135,6 +125,7 @@
135
125
  <image overflow="visible" opacity=".08" width="20" height="20" xlink:href="FCC0802E2AF8A915.png" transform="translate(270.984 291.372)"/>
136
126
  <path fill-rule="evenodd" clip-rule="evenodd" fill="#FFF" d="M462.273 349.294c-11.234-24.977-23.062-25.477-33.75-25.914-8.742-.375-18.75-.352-28.742-.352-10 0-26.25 3.758-39.992 18.766-13.75 15.008-52.5 51.289-52.5 125.078 0 73.797 53.75 145.102 61.242 155.117 7.5 10 103.758 166.266 256.203 226.383 126.695 49.961 152.477 40.023 179.977 37.523s88.734-36.273 101.234-71.297c12.5-35.016 12.5-65.031 8.75-71.305-3.75-6.25-13.75-10-28.75-17.5s-88.734-43.789-102.484-48.789-23.75-7.5-33.75 7.516c-10 15-38.727 48.773-47.477 58.773-8.75 10.023-17.5 11.273-32.5 3.773-15-7.523-63.305-23.344-120.609-74.438-44.586-39.75-74.688-88.844-83.438-103.859-8.75-15-.938-23.125 6.586-30.602 6.734-6.719 15-17.508 22.5-26.266 7.484-8.758 9.984-15.008 14.984-25.008 5-10.016 2.5-18.773-1.25-26.273s-32.898-81.67-46.234-111.326z"/>
137
127
  <path fill="#FFF" d="M1036.898 176.091C923.562 62.677 772.859.185 612.297.114 281.43.114 12.172 269.286 12.039 600.137 12 705.896 39.633 809.13 92.156 900.13L7 1211.067l318.203-83.438c87.672 47.812 186.383 73.008 286.836 73.047h.255.003c330.812 0 600.109-269.219 600.25-600.055.055-160.343-62.328-311.108-175.649-424.53zm-424.601 923.242h-.195c-89.539-.047-177.344-24.086-253.93-69.531l-18.227-10.805-188.828 49.508 50.414-184.039-11.875-18.867c-49.945-79.414-76.312-171.188-76.273-265.422.109-274.992 223.906-498.711 499.102-498.711 133.266.055 258.516 52 352.719 146.266 94.195 94.266 146.031 219.578 145.992 352.852-.118 274.999-223.923 498.749-498.899 498.749z"/>
128
+ <title id="altIconTitle">Whatsapp</title>
138
129
  </svg>
139
130
  <!-- <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="28" height="28" focusable="false" viewBox="0 0 448 512" xml:space="preserve">
140
131
  <path stroke="#5f6368" stroke-width="8px" fill="#5f6368" d="M380.9,97.1C339,55.1,283.2,32,223.9,32c-122.4,0-222,99.6-222,222c0,39.1,10.2,77.3,29.6,111L0,480l117.7-30.9 c32.4,17.7,68.9,27,106.1,27h0.1c122.3,0,224.1-99.6,224.1-222C448,194.8,422.8,139.1,380.9,97.1z M223.9,438.7 c-33.2,0-65.7-8.9-94-25.7l-6.7-4l-69.8,18.3L72,359.2l-4.4-7c-18.5-29.4-28.2-63.3-28.2-98.2c0-101.7,82.8-184.5,184.6-184.5 c49.3,0,95.6,19.2,130.4,54.1s56.2,81.2,56.1,130.5C410.5,355.9,325.6,438.7,223.9,438.7z M325.1,300.5c-5.5-2.8-32.8-16.2-37.9-18 c-5.1-1.9-8.8-2.8-12.5,2.8c-3.7,5.6-14.3,18-17.6,21.8c-3.2,3.7-6.5,4.2-12,1.4c-32.6-16.3-54-29.1-75.5-66 c-5.7-9.8,5.7-9.1,16.3-30.3c1.8-3.7,0.9-6.9-0.5-9.7s-12.5-30.1-17.1-41.2c-4.5-10.8-9.1-9.3-12.5-9.5c-3.2-0.2-6.9-0.2-10.6-0.2 c-3.7,0-9.7,1.4-14.8,6.9c-5.1,5.6-19.4,19-19.4,46.3s19.9,53.7,22.6,57.4c2.8,3.7,39.1,59.7,94.8,83.8c35.2,15.2,49,16.5,66.6,13.9 c10.7-1.6,32.8-13.4,37.4-26.4s4.6-24.1,3.2-26.4C334.3,304.6,330.6,303.2,325.1,300.5z"/>
@@ -144,9 +135,9 @@
144
135
  </button>
145
136
  </div>
146
137
  <div id="c21-telegram" *ngIf="g?.telegramUsername && g?.telegramUsername.trim() !== ''">
147
- <button type="button" aflistconv #aflistconv class="c21-button-primary" aria-label="Telegram" (click)="openConversationOnPlatform('telegram')">
138
+ <button tabindex="1040" aflistconv #aflistconv class="c21-button-primary" (click)="openConversationOnPlatform('telegram')">
148
139
  <span class="v-align-center">
149
- <svg aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="26" height="26" viewBox="0 0 368 368" style="enable-background:new 0 0 368 368;" xml:space="preserve">
140
+ <svg aria-labelledby="altIconTitle" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="26" height="26" viewBox="0 0 368 368" style="enable-background:new 0 0 368 368;" xml:space="preserve">
150
141
  <g id="XMLID_1_">
151
142
  <linearGradient id="XMLID_7_" gradientUnits="userSpaceOnUse" x1="-66.831" y1="-68.1757" x2="-65.3102" y2="-68.1757" gradientTransform="matrix(-60 139.992 -139.992 -60 -13316.416 5324.4634)">
152
143
  <stop offset="0" style="stop-color:#37AEE2"/>
@@ -161,6 +152,7 @@
161
152
  </linearGradient>
162
153
  <path id="XMLID_6_" fill="url(#XMLID_8_)" d="M153.6,221.1l73.5,54.3c8.4,4.6,14.4,2.2,16.5-7.8l29.9-141.1c3.1-12.3-4.7-17.9-12.7-14.2 L85.2,180.2c-12,4.8-11.9,11.5-2.2,14.5l45.1,14.1l104.4-65.9c4.9-3,9.5-1.4,5.7,1.9"/>
163
154
  </g>
155
+ <title id="altIconTitle">Telegram</title>
164
156
  </svg>
165
157
  <!-- <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="26" height="26" viewBox="0 0 448 512" xml:space="preserve">
166
158
  <path fill="#5f6368" d="M446.7,98.6l-67.6,318.8c-5.1,22.5-18.4,28.1-37.3,17.5l-103-75.9l-49.7,47.8c-5.5,5.5-10.1,10.1-20.7,10.1 l7.4-104.9l190.9-172.5c8.3-7.4-1.8-11.5-12.9-4.1L117.8,284L16.2,252.2c-22.1-6.9-22.5-22.1,4.6-32.7L418.2,66.4 C436.6,59.5,452.7,70.5,446.7,98.6z"/>
@@ -170,9 +162,9 @@
170
162
  </button>
171
163
  </div>
172
164
  <div id="c21-messanger" *ngIf="g?.messangerPageTitle && g?.messangerPageTitle.trim() !== ''">
173
- <button type="button" aflistconv #aflistconv class="c21-button-primary" aria-label="Facebook Messenger" (click)="openConversationOnPlatform('messanger')">
165
+ <button tabindex="1040" aflistconv #aflistconv class="c21-button-primary" (click)="openConversationOnPlatform('messanger')">
174
166
  <span class="v-align-center">
175
- <svg aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" width="26" height="26" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 800 800">
167
+ <svg aria-labelledby="altIconTitle" xmlns="http://www.w3.org/2000/svg" width="26" height="26" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 800 800">
176
168
  <radialGradient id="Gradient" cx="101.925" cy="809.0079" r="1.0896" gradientTransform="matrix(800 0 0 -799.9985 -81386 648000.75)" gradientUnits="userSpaceOnUse">
177
169
  <stop offset="0" style="stop-color:#0099FF"/>
178
170
  <stop offset="0.6098" style="stop-color:#A033FF"/>
@@ -181,6 +173,7 @@
181
173
  </radialGradient>
182
174
  <path fill="url(#Gradient)" d="M400,0C174.7,0,0,165.1,0,388c0,116.6,47.8,217.4,125.6,287c6.5,5.8,10.5,14,10.7,22.8l2.2,71.2 c0.7,22.7,24.1,37.5,44.9,28.3l79.4-35c6.7-3,14.3-3.5,21.4-1.6c36.5,10,75.3,15.4,115.8,15.4c225.3,0,400-165.1,400-388 S625.3,0,400,0z"/>
183
175
  <path fill="#FFFFFF" d="M159.8,501.5l117.5-186.4c18.7-29.7,58.7-37,86.8-16l93.5,70.1c8.6,6.4,20.4,6.4,28.9-0.1 l126.2-95.8c16.8-12.8,38.8,7.4,27.6,25.3L522.7,484.9c-18.7,29.7-58.7,37-86.8,16l-93.5-70.1c-8.6-6.4-20.4-6.4-28.9,0.1 l-126.2,95.8C170.5,539.5,148.5,519.4,159.8,501.5z"/>
176
+ <title id="altIconTitle">Facebook Messanger</title>
184
177
  </svg>
185
178
  <!-- <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="26" height="26" focusable="false" viewBox="0 0 512 512" xml:space="preserve">
186
179
  <path fill="#5f6368" d="M256.5,8C116.5,8,8,110.3,8,248.6c0,72.3,29.7,134.8,78.1,177.9c8.3,7.5,6.6,11.9,8.1,58.2 c0.4,11,9.6,19.6,20.6,19.2c2.5-0.1,5-0.6,7.3-1.7c52.9-23.3,53.6-25.1,62.6-22.7c153.3,42.2,319.4-55.9,319.4-231 C504,110.3,396.6,8,256.5,8z M405.8,193.1l-73,115.6c-11.1,17.4-34.1,22.6-51.6,11.5c-0.8-0.5-1.6-1-2.3-1.6l-58.1-43.5 c-5.3-4-12.7-4-18,0l-78.4,59.4c-10.5,7.9-24.2-4.6-17.1-15.7l73-115.6c11-17.4,34.1-22.6,51.6-11.6c0.8,0.5,1.6,1.1,2.4,1.6 l58.1,43.5c5.3,4,12.7,4,18,0l78.4-59.4C399.1,169.5,412.8,182,405.8,193.1L405.8,193.1z"/>
@@ -194,7 +187,7 @@
194
187
  <!-- FOOTER -->
195
188
  <div class="c21-footer fade-in-bottom-footer">
196
189
  <div id="c21-powered-by" (mouseover)="hover=true" (mouseleave)="hover=false">
197
- <div class="c21-powered-by" [innerHTML]="g.poweredBy" (click)="managePoweredBy($event)"></div>
190
+ <div tabindex="-1" class="c21-powered-by" [innerHTML]="g.poweredBy" (click)="managePoweredBy($event)"></div>
198
191
  <!-- <div class="build_version">{{g.BUILD_VERSION}}</div> -->
199
192
  </div>
200
193
  <chat-menu-options *ngIf="!hideSettings"
@@ -90,7 +90,7 @@
90
90
  max-height: 2.4em;
91
91
  font-weight: 400;
92
92
  font-size: 3.0em;
93
- margin: 0 0 10px 0;
93
+ margin-bottom: 10px;
94
94
  }
95
95
  .c21-text-intro {
96
96
  display: inline-block;
@@ -98,7 +98,6 @@
98
98
  font-weight: 300;
99
99
  line-height: 1.2em;
100
100
  max-height: 2.4em;
101
- margin: 0;
102
101
  }
103
102
  }
104
103
  }
@@ -133,7 +132,7 @@
133
132
  max-height: 3em; //2.4em;
134
133
  font-weight: 200;
135
134
  font-size: 2.5em; //3.0em;
136
- margin: 0 0 15px 0;
135
+ margin-bottom: 15px; //10px;
137
136
  }
138
137
  .c21-text-intro {
139
138
  display: inline-block;
@@ -141,7 +140,6 @@
141
140
  font-weight: 600; //400;
142
141
  line-height: 1.2em;
143
142
  max-height: 2.4em;
144
- margin: 0;
145
143
  }
146
144
  }
147
145
  }
@@ -1,14 +1,8 @@
1
1
  import { NO_ERRORS_SCHEMA } from '@angular/core';
2
- import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
3
- import { By } from '@angular/platform-browser';
4
-
2
+ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
5
3
  import { NGXLogger } from 'ngx-logger';
6
- import { ConversationModel } from 'src/chat21-core/models/conversation';
7
- import { CustomTranslateService } from 'src/chat21-core/providers/custom-translate.service';
8
4
  import { CustomLogger } from 'src/chat21-core/providers/logger/customLogger';
9
5
  import { LoggerInstance } from 'src/chat21-core/providers/logger/loggerInstance';
10
- import { TiledeskAuthService } from 'src/chat21-core/providers/tiledesk/tiledesk-auth.service';
11
- import { HEADER_MENU_OPTION } from '../../utils/constants';
12
6
  import { Globals } from '../../utils/globals';
13
7
 
14
8
  import { HomeComponent } from './home.component';
@@ -16,240 +10,31 @@ import { HomeComponent } from './home.component';
16
10
  describe('HomeComponent', () => {
17
11
  let component: HomeComponent;
18
12
  let fixture: ComponentFixture<HomeComponent>;
19
- let globals: Globals;
20
- const ngxlogger = jasmine.createSpyObj('NGXLogger', ['log', 'trace', 'debug', 'warn', 'error', 'info']);
21
-
22
- const tiledeskAuthStub = {
23
- getCurrentUser: jasmine.createSpy('getCurrentUser').and.returnValue({
24
- uid: 'u-1',
25
- firstname: 'Ada',
26
- lastname: 'Lovelace',
27
- email: 'ada@example.com',
28
- }),
29
- };
30
-
31
- const translateStub = {
32
- translateLanguage: jasmine.createSpy('translateLanguage').and.callFake((keys: string[]) => {
33
- const m = new Map<string, string>();
34
- keys.forEach((k) => m.set(k, `T:${k}`));
35
- return m;
36
- }),
37
- };
13
+ let ngxlogger: NGXLogger;
14
+ let customLogger = new CustomLogger(ngxlogger)
38
15
 
39
16
  beforeEach(waitForAsync(() => {
40
- LoggerInstance.setInstance(new CustomLogger(ngxlogger));
41
17
  TestBed.configureTestingModule({
42
- declarations: [HomeComponent],
18
+ declarations: [ HomeComponent ],
43
19
  providers: [
44
20
  Globals,
45
- { provide: NGXLogger, useValue: ngxlogger },
46
- { provide: TiledeskAuthService, useValue: tiledeskAuthStub },
47
- { provide: CustomTranslateService, useValue: translateStub },
21
+ NGXLogger
48
22
  ],
49
- schemas: [NO_ERRORS_SCHEMA],
50
- }).compileComponents();
23
+ schemas: [NO_ERRORS_SCHEMA]
24
+ })
25
+ .compileComponents();
51
26
  }));
52
27
 
53
28
  beforeEach(() => {
54
29
  fixture = TestBed.createComponent(HomeComponent);
55
30
  component = fixture.componentInstance;
56
- globals = TestBed.inject(Globals);
57
- globals.initDefafultParameters();
58
- globals.welcomeTitle = 'Benvenuto';
59
- globals.welcomeMsg = 'Intro';
60
- globals.themeForegroundColor = '#fff';
61
- globals.colorGradient = 'linear-gradient(red,blue)';
62
- globals.project = { logoChat: 'nologo' } as any;
63
- globals.poweredBy = '<a href="https://brand.example"><span id="pb-inner">Logo</span></a>';
64
- globals.whatsappNumber = '1234567890';
65
- globals.telegramUsername = '';
66
- globals.messangerPageTitle = '';
67
-
68
- component.listConversations = [];
69
- component.archivedConversations = [];
70
- component.hideSettings = true;
71
- component.hideNewConversationButton = false;
72
- component.stylesMap = new Map([
73
- ['themeColor', '#111'],
74
- ['foregroundColor', '#fff'],
75
- ]);
76
- component.size = 'min';
77
- component.fullscreenMode = false;
78
- component.hideHeaderConversationOptionsMenu = false;
79
- component.isButtonsDisabled = false;
80
- component.translationMap = new Map([
81
- ['MAXIMIZE', 'Massimizza'],
82
- ['MINIMIZE', 'Riduci'],
83
- ['CENTER', 'Centra'],
84
- ]);
85
-
31
+ let loggerInstance = LoggerInstance.setInstance(customLogger)
32
+ let logger = LoggerInstance.getInstance()
33
+ component['logger']= logger
86
34
  fixture.detectChanges();
87
35
  });
88
36
 
89
37
  it('should create', () => {
90
38
  expect(component).toBeTruthy();
91
39
  });
92
-
93
- describe('translations and DOM shell', () => {
94
- it('initiTranslations should fill header/footer maps via CustomTranslateService', () => {
95
- component.initiTranslations();
96
- expect(component.translationMapHeader?.get('BUTTON_CLOSE_TO_ICON')).toBe('T:BUTTON_CLOSE_TO_ICON');
97
- expect(component.translationMapFooter?.get('SWITCH_TO')).toBe('T:SWITCH_TO');
98
- });
99
-
100
- it('should render region root, welcome title and close control', () => {
101
- const region = fixture.debugElement.query(By.css('#chat21-home-component'));
102
- expect(region).toBeTruthy();
103
- const h1 = fixture.nativeElement.querySelector('.c21-text-welcome') as HTMLElement;
104
- expect(h1.textContent).toContain('Benvenuto');
105
- const closeBtn = fixture.debugElement.query(By.css('.c21-close-button-body'));
106
- expect(closeBtn).toBeTruthy();
107
- });
108
-
109
- it('should set region aria-label from welcomeTitle (accessibility / MCP home shell)', () => {
110
- globals.welcomeTitle = 'Ciao, benvenuto su BrandExample';
111
- fixture.detectChanges();
112
- const host = fixture.nativeElement.querySelector('#chat21-home-component') as HTMLElement;
113
- expect(host.getAttribute('aria-label')).toBe('Ciao, benvenuto su BrandExample');
114
- });
115
-
116
- it('should render welcome intro paragraph when welcomeMsg is set', () => {
117
- globals.welcomeMsg = 'Come possiamo aiutarti?';
118
- fixture.detectChanges();
119
- const intro = fixture.nativeElement.querySelector('.c21-text-intro') as HTMLElement;
120
- expect(intro.textContent).toContain('Come possiamo aiutarti?');
121
- });
122
- });
123
-
124
- describe('outputs and actions', () => {
125
- it('f21_close should emit onCloseWidget and add start-animation class', () => {
126
- spyOn(component.onCloseWidget, 'emit');
127
- component.f21_close();
128
- expect(component.onCloseWidget.emit).toHaveBeenCalled();
129
- const root = fixture.debugElement.query(By.css('#chat21-home-component')).nativeElement as HTMLElement;
130
- expect(root.classList.contains('start-animation')).toBe(true);
131
- });
132
-
133
- it('onChangeSize should emit correct HEADER_MENU_OPTION', () => {
134
- spyOn(component.onMenuOptionClick, 'emit');
135
- component.onChangeSize('min');
136
- component.onChangeSize('max');
137
- component.onChangeSize('top');
138
- expect(component.onMenuOptionClick.emit).toHaveBeenCalledWith(HEADER_MENU_OPTION.MINIMIZE);
139
- expect(component.onMenuOptionClick.emit).toHaveBeenCalledWith(HEADER_MENU_OPTION.MAXIMIZE);
140
- expect(component.onMenuOptionClick.emit).toHaveBeenCalledWith(HEADER_MENU_OPTION.TOP);
141
- });
142
-
143
- it('onNewConversationFN should emit onNewConversation and strip animation', () => {
144
- spyOn(component.onNewConversation, 'emit');
145
- const root = fixture.debugElement.query(By.css('#chat21-home-component')).nativeElement as HTMLElement;
146
- root.classList.add('start-animation');
147
- component.onNewConversationFN();
148
- expect(component.onNewConversation.emit).toHaveBeenCalled();
149
- expect(root.classList.contains('start-animation')).toBe(false);
150
- });
151
-
152
- it('onConversationSelectedFN should emit conversation', () => {
153
- spyOn(component.onConversationSelected, 'emit');
154
- const conv = { uid: 'c1' } as ConversationModel;
155
- component.onConversationSelectedFN(conv);
156
- expect(component.onConversationSelected.emit).toHaveBeenCalledWith(conv);
157
- });
158
-
159
- it('onConversationSelectedFN should ignore null', () => {
160
- spyOn(component.onConversationSelected, 'emit');
161
- component.onConversationSelectedFN(null as any);
162
- expect(component.onConversationSelected.emit).not.toHaveBeenCalled();
163
- });
164
-
165
- it('onOpenAllConversation should emit onOpenAllConvesations', () => {
166
- spyOn(component.onOpenAllConvesations, 'emit');
167
- component.onOpenAllConversation();
168
- expect(component.onOpenAllConvesations.emit).toHaveBeenCalled();
169
- });
170
-
171
- it('onSignOutFN should emit onSignOut', () => {
172
- spyOn(component.onSignOut, 'emit');
173
- component.onSignOutFN();
174
- expect(component.onSignOut.emit).toHaveBeenCalled();
175
- });
176
-
177
- it('onImageLoadedFN / onConversationLoadedFN should forward emits', () => {
178
- spyOn(component.onImageLoaded, 'emit');
179
- spyOn(component.onConversationLoaded, 'emit');
180
- const c = { uid: 'x' } as ConversationModel;
181
- component.onImageLoadedFN(c);
182
- component.onConversationLoadedFN(c);
183
- expect(component.onImageLoaded.emit).toHaveBeenCalledWith(c);
184
- expect(component.onConversationLoaded.emit).toHaveBeenCalledWith(c);
185
- });
186
- });
187
-
188
- describe('hideMenuOptions and openConversationOnPlatform', () => {
189
- it('hideMenuOptions should set isOpenMenuOptions on Globals', () => {
190
- spyOn(globals, 'setParameter');
191
- component.hideMenuOptions();
192
- expect(globals.setParameter).toHaveBeenCalledWith('isOpenMenuOptions', false, true);
193
- });
194
-
195
- it('openConversationOnPlatform should open external URLs', () => {
196
- spyOn(window, 'open');
197
- globals.telegramUsername = 'mybot';
198
- globals.whatsappNumber = '39333';
199
- globals.messangerPageTitle = 'mypage';
200
- component.openConversationOnPlatform('telegram');
201
- component.openConversationOnPlatform('whatsapp');
202
- component.openConversationOnPlatform('messanger');
203
- expect(window.open).toHaveBeenCalledWith('https://telegram.me/mybot', '_blank');
204
- expect(window.open).toHaveBeenCalledWith(jasmine.stringMatching(/^https:\/\/wa\.me\/39333/), '_blank');
205
- expect(window.open).toHaveBeenCalledWith('https://m.me/mypage', '_blank');
206
- });
207
- });
208
-
209
- describe('managePoweredBy and analytics', () => {
210
- it('managePoweredBy should open parent anchor href', () => {
211
- spyOn(window, 'open');
212
- const anchor = document.createElement('a');
213
- anchor.setAttribute('href', 'https://brand.example');
214
- const inner = document.createElement('span');
215
- anchor.appendChild(inner);
216
- const ev = new MouseEvent('click', { bubbles: true });
217
- Object.defineProperty(ev, 'target', { value: inner, configurable: true });
218
- component.managePoweredBy(ev);
219
- expect(window.open).toHaveBeenCalledWith('https://brand.example', '_blank');
220
- });
221
-
222
- it('segmentLogoClick should invoke analytics when present', () => {
223
- (window as any).analytics = {
224
- page: jasmine.createSpy('page'),
225
- identify: jasmine.createSpy('identify'),
226
- track: jasmine.createSpy('track'),
227
- };
228
- (component as any).segmentLogoClick();
229
- expect((window as any).analytics.page).toHaveBeenCalled();
230
- expect((window as any).analytics.identify).toHaveBeenCalled();
231
- expect((window as any).analytics.track).toHaveBeenCalled();
232
- delete (window as any).analytics;
233
- });
234
- });
235
-
236
- describe('ngAfterViewInit', () => {
237
- it('should add animation only on first open then clear flag', () => {
238
- globals.firstOpen = true;
239
- component.ngAfterViewInit();
240
- const root = fixture.debugElement.query(By.css('#chat21-home-component')).nativeElement as HTMLElement;
241
- expect(root.classList.contains('start-animation')).toBe(true);
242
- expect(globals.firstOpen).toBe(false);
243
- });
244
-
245
- it('should focus aflistconv after delay when present', fakeAsync(() => {
246
- const btn = document.createElement('button');
247
- btn.setAttribute('aflistconv', '');
248
- spyOn(btn, 'focus');
249
- (component as any).aflistconv = { nativeElement: btn };
250
- component.ngAfterViewInit();
251
- tick(1000);
252
- expect(btn.focus).toHaveBeenCalled();
253
- }));
254
- });
255
40
  });