@testgorilla/tgo-typing-test 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/fesm2022/testgorilla-tgo-typing-test.mjs +4691 -0
  2. package/fesm2022/testgorilla-tgo-typing-test.mjs.map +1 -0
  3. package/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.d.ts +14 -0
  4. package/lib/components/tgo-typing-test/tgo-typing-test.component.d.ts +54 -0
  5. package/lib/helpers/config.d.ts +98 -0
  6. package/lib/helpers/constants/default-config.d.ts +3 -0
  7. package/lib/helpers/controllers/input-controller.d.ts +16 -0
  8. package/lib/helpers/controllers/quotes-controller.d.ts +20 -0
  9. package/lib/helpers/observables/config-event.d.ts +5 -0
  10. package/lib/helpers/observables/timer-event.d.ts +4 -0
  11. package/lib/helpers/states/active-page.d.ts +2 -0
  12. package/lib/helpers/states/composition.d.ts +10 -0
  13. package/lib/helpers/states/page-transition.d.ts +2 -0
  14. package/lib/helpers/states/slow-timer.d.ts +3 -0
  15. package/lib/helpers/states/test-active.d.ts +2 -0
  16. package/lib/helpers/states/time.d.ts +3 -0
  17. package/lib/helpers/test/caps-warning.d.ts +5 -0
  18. package/lib/helpers/test/caret.d.ts +11 -0
  19. package/lib/helpers/test/custom-text.d.ts +16 -0
  20. package/lib/helpers/test/english-punctuation.d.ts +3 -0
  21. package/lib/helpers/test/focus.d.ts +7 -0
  22. package/lib/helpers/test/manual-restart-tracker.d.ts +3 -0
  23. package/lib/helpers/test/out-of-focus.d.ts +4 -0
  24. package/lib/helpers/test/replay.d.ts +20 -0
  25. package/lib/helpers/test/test-input.d.ts +86 -0
  26. package/lib/helpers/test/test-logic.d.ts +25 -0
  27. package/lib/helpers/test/test-state.d.ts +7 -0
  28. package/lib/helpers/test/test-stats.d.ts +92 -0
  29. package/lib/helpers/test/test-timer.d.ts +6 -0
  30. package/lib/helpers/test/test-ui.d.ts +27 -0
  31. package/lib/helpers/test/test-words.d.ts +23 -0
  32. package/lib/helpers/test/timer-progress.d.ts +3 -0
  33. package/lib/helpers/test/weak-spot.d.ts +3 -0
  34. package/lib/helpers/test/wordset.d.ts +7 -0
  35. package/lib/utils/misc.d.ts +80 -0
  36. package/package.json +17 -4
  37. package/.eslintrc.json +0 -46
  38. package/jest.config.ts +0 -21
  39. package/ng-package.json +0 -15
  40. package/project.json +0 -36
  41. package/src/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.html +0 -30
  42. package/src/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.spec.ts +0 -250
  43. package/src/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.ts +0 -47
  44. package/src/lib/components/tgo-typing-test/tgo-typing-test.component.html +0 -72
  45. package/src/lib/components/tgo-typing-test/tgo-typing-test.component.spec.ts +0 -699
  46. package/src/lib/components/tgo-typing-test/tgo-typing-test.component.ts +0 -287
  47. package/src/lib/helpers/config.ts +0 -28
  48. package/src/lib/helpers/constants/default-config.ts +0 -103
  49. package/src/lib/helpers/controllers/input-controller.ts +0 -710
  50. package/src/lib/helpers/controllers/quotes-controller.ts +0 -183
  51. package/src/lib/helpers/observables/banner-event.ts +0 -18
  52. package/src/lib/helpers/observables/config-event.ts +0 -31
  53. package/src/lib/helpers/observables/timer-event.ts +0 -18
  54. package/src/lib/helpers/states/active-page.ts +0 -9
  55. package/src/lib/helpers/states/composition.ts +0 -29
  56. package/src/lib/helpers/states/page-transition.ts +0 -9
  57. package/src/lib/helpers/states/slow-timer.ts +0 -16
  58. package/src/lib/helpers/states/test-active.ts +0 -9
  59. package/src/lib/helpers/states/time.ts +0 -13
  60. package/src/lib/helpers/test/caps-warning.ts +0 -50
  61. package/src/lib/helpers/test/caret.ts +0 -92
  62. package/src/lib/helpers/test/custom-text.ts +0 -73
  63. package/src/lib/helpers/test/english-punctuation.ts +0 -38
  64. package/src/lib/helpers/test/focus.ts +0 -39
  65. package/src/lib/helpers/test/manual-restart-tracker.ts +0 -13
  66. package/src/lib/helpers/test/out-of-focus.ts +0 -19
  67. package/src/lib/helpers/test/replay.ts +0 -265
  68. package/src/lib/helpers/test/test-input.ts +0 -320
  69. package/src/lib/helpers/test/test-logic.ts +0 -1039
  70. package/src/lib/helpers/test/test-state.ts +0 -17
  71. package/src/lib/helpers/test/test-stats.ts +0 -442
  72. package/src/lib/helpers/test/test-timer.ts +0 -209
  73. package/src/lib/helpers/test/test-ui.ts +0 -370
  74. package/src/lib/helpers/test/test-words.ts +0 -72
  75. package/src/lib/helpers/test/timer-progress.ts +0 -16
  76. package/src/lib/helpers/test/tts.ts +0 -42
  77. package/src/lib/helpers/test/weak-spot.ts +0 -74
  78. package/src/lib/helpers/test/wordset.ts +0 -109
  79. package/src/lib/styles/animations.scss +0 -101
  80. package/src/lib/styles/caret.scss +0 -108
  81. package/src/lib/styles/core.scss +0 -498
  82. package/src/lib/styles/index.scss +0 -19
  83. package/src/lib/styles/inputs.scss +0 -290
  84. package/src/lib/styles/popups.scss +0 -1311
  85. package/src/lib/styles/test.scss +0 -1008
  86. package/src/lib/styles/z_media-queries.scss +0 -848
  87. package/src/lib/types/types.d.ts +0 -731
  88. package/src/lib/utils/misc.ts +0 -776
  89. package/src/test-setup.ts +0 -20
  90. package/tsconfig.json +0 -16
  91. package/tsconfig.lib.json +0 -14
  92. package/tsconfig.lib.prod.json +0 -9
  93. package/tsconfig.spec.json +0 -11
  94. /package/{src/assets → assets}/typing-test-languages/english.json +0 -0
  95. /package/{src/assets → assets}/typing-test-languages/english_punctuation.json +0 -0
  96. /package/{src/assets → assets}/typing-test-languages/quotes/english_version_1.json +0 -0
  97. /package/{src/assets → assets}/typing-test-languages/quotes/english_version_2.json +0 -0
  98. /package/{src/assets → assets}/typing-test-languages/quotes/filtered_sources.json +0 -0
  99. /package/{src/index.ts → index.d.ts} +0 -0
@@ -1,699 +0,0 @@
1
- import { ComponentFixture, TestBed } from '@angular/core/testing';
2
- import { ElementRef, SimpleChange } from '@angular/core';
3
- import { BehaviorSubject, Subject } from 'rxjs';
4
- import { TgoTypingTestComponent } from './tgo-typing-test.component';
5
- import * as config from '../../helpers/config';
6
- import * as inputController from '../../helpers/controllers/input-controller';
7
- import * as capsWarning from '../../helpers/test/caps-warning';
8
- import * as caret from '../../helpers/test/caret';
9
- import * as focus from '../../helpers/test/focus';
10
- import * as outOfFocus from '../../helpers/test/out-of-focus';
11
- import * as replay from '../../helpers/test/replay';
12
- import * as TestLogic from '../../helpers/test/test-logic';
13
- import * as TestUI from '../../helpers/test/test-ui';
14
- import * as timerProgress from '../../helpers/test/timer-progress';
15
- import * as misc from '../../utils/misc';
16
- import * as TestActive from '../../helpers/states/test-active';
17
- import quoteController from '../../helpers/controllers/quotes-controller';
18
- import * as testTimer from '../../helpers/test/test-timer';
19
-
20
- jest.mock('../../helpers/config');
21
- jest.mock('../../helpers/controllers/input-controller');
22
- jest.mock('../../helpers/test/caps-warning');
23
- jest.mock('../../helpers/test/caret');
24
- jest.mock('../../helpers/test/focus');
25
- jest.mock('../../helpers/test/out-of-focus');
26
- jest.mock('../../helpers/test/replay');
27
- jest.mock('../../helpers/test/test-logic');
28
- jest.mock('../../helpers/test/test-ui');
29
- jest.mock('../../helpers/test/timer-progress');
30
- jest.mock('../../utils/misc');
31
- jest.mock('../../helpers/states/test-active');
32
- jest.mock('../../helpers/controllers/quotes-controller');
33
- jest.mock('../../helpers/test/test-timer');
34
-
35
- describe('TgoTypingTestComponent', () => {
36
- let component: TgoTypingTestComponent;
37
- let fixture: ComponentFixture<TgoTypingTestComponent>;
38
-
39
- const mockShowCaps$ = new BehaviorSubject<boolean>(false);
40
- const mockCaretShow$ = new BehaviorSubject<boolean>(true);
41
- const mockCaretAnimation$ = new BehaviorSubject<string>('smooth');
42
- const mockStartTestSubject$ = new BehaviorSubject<boolean>(false);
43
- const mockOutOfFocusShow$ = new BehaviorSubject<boolean>(false);
44
- const mockTimeLeft$ = new BehaviorSubject<string>('180');
45
- const mockCaretLeft$ = new BehaviorSubject<number>(0);
46
- const mockCaretTop$ = new BehaviorSubject<number>(0);
47
- const mockResultSub$ = new Subject<any>();
48
- const mockQuoteNetworkError$ = new Subject<string | null>();
49
-
50
- beforeEach(() => {
51
- jest.clearAllMocks();
52
-
53
- // Ensure timer functions are available
54
- if (!global.clearInterval) {
55
- (global as any).clearInterval = jest.fn();
56
- }
57
- jest.spyOn(global, 'setInterval').mockReturnValue(123 as any);
58
- jest.spyOn(global, 'clearInterval').mockImplementation(jest.fn());
59
-
60
- // Mock BehaviorSubjects and Observables
61
- (capsWarning as any).showCaps = mockShowCaps$;
62
- (caret as any).caretShow = mockCaretShow$;
63
- (caret as any).caretAnimation = mockCaretAnimation$;
64
- (caret as any).caretLeft = mockCaretLeft$;
65
- (caret as any).caretTop = mockCaretTop$;
66
- (TestLogic as any).startTestSubject = mockStartTestSubject$;
67
- (outOfFocus as any).outOfFocusShow = mockOutOfFocusShow$;
68
- (timerProgress as any).timeLeft = mockTimeLeft$;
69
- (TestLogic as any).resultSub = mockResultSub$;
70
- (misc as any).QuoteNetworkError$ = mockQuoteNetworkError$;
71
-
72
- // Mock functions
73
- jest.spyOn(TestUI, 'setResultCalculating').mockImplementation();
74
- jest.spyOn(TestUI, 'setResultVisible').mockImplementation();
75
- jest.spyOn(config, 'setTime').mockImplementation();
76
- jest.spyOn(config, 'setPunctuation').mockImplementation();
77
- jest.spyOn(config, 'setNumbers').mockImplementation();
78
- jest.spyOn(config, 'setFunbox').mockImplementation();
79
- jest.spyOn(config, 'setCustomTGQuotes').mockImplementation();
80
- jest.spyOn(config, 'setTestVersionForSentences').mockImplementation();
81
- jest.spyOn(replay, 'getReplayExport').mockReturnValue('mock-replay-data');
82
- jest.spyOn(TestLogic, 'stopTest').mockImplementation();
83
- jest.spyOn(TestLogic, 'restart').mockImplementation();
84
- jest.spyOn(TestLogic, 'finish').mockImplementation();
85
- jest.spyOn(TestLogic, 'setWordsInputElementTestLogic').mockImplementation();
86
- jest.spyOn(TestActive, 'get').mockReturnValue(true);
87
- jest.spyOn(quoteController, 'resetQuotes').mockImplementation();
88
- jest.spyOn(testTimer, 'disableCheckIfTimeIsUp').mockImplementation();
89
-
90
- // Mock input controller functions
91
- jest.spyOn(inputController, 'setWordsInputElement').mockImplementation();
92
- jest.spyOn(inputController, 'wordsInputKeyup').mockImplementation();
93
- jest.spyOn(inputController, 'wordsInputBeforeinput').mockImplementation();
94
- jest.spyOn(inputController, 'wordsInputInput').mockImplementation();
95
- jest.spyOn(inputController, 'wordsInputFocus').mockImplementation();
96
- jest.spyOn(inputController, 'wordsInputCopy').mockImplementation();
97
- jest.spyOn(inputController, 'wordsInputPaste').mockImplementation();
98
- jest.spyOn(inputController, 'wordsInputCompositionstart').mockImplementation();
99
- jest.spyOn(inputController, 'wordsInputCompositionend').mockImplementation();
100
- jest.spyOn(inputController, 'inputKeydown').mockImplementation();
101
-
102
- // Mock caps warning functions
103
- jest.spyOn(capsWarning, 'capsKeydown').mockImplementation();
104
- jest.spyOn(capsWarning, 'capsKeyup').mockImplementation();
105
-
106
- // Mock focus functions
107
- jest.spyOn(focus, 'mousemove').mockImplementation();
108
- jest.spyOn(focus, 'setMiddleElement').mockImplementation();
109
- jest.spyOn(focus, 'setCapsWarningElement').mockImplementation();
110
-
111
- // Mock TestUI functions
112
- jest.spyOn(TestUI, 'setWordsInputElementTestUI').mockImplementation();
113
- jest.spyOn(TestUI, 'setWordsWrapperElement').mockImplementation();
114
- jest.spyOn(TestUI, 'setWordsElement').mockImplementation();
115
- jest.spyOn(TestUI, 'wordsInputFocusOut').mockImplementation();
116
- jest.spyOn(TestUI, 'wordsInputFocusTestUI').mockImplementation();
117
- jest.spyOn(TestUI, 'wordsWrapperClick').mockImplementation();
118
-
119
- TestBed.configureTestingModule({
120
- imports: [TgoTypingTestComponent],
121
- });
122
-
123
- fixture = TestBed.createComponent(TgoTypingTestComponent);
124
- component = fixture.componentInstance;
125
- });
126
-
127
- afterEach(() => {
128
- jest.clearAllTimers();
129
- jest.useRealTimers();
130
- });
131
-
132
- describe('when initialized', () => {
133
- it('should create the component', () => {
134
- expect(component).toBeDefined();
135
- });
136
-
137
- it('should initialize with default input values', () => {
138
- expect(component.time).toBe(180);
139
- expect(component.punctuation).toBe(false);
140
- expect(component.numbers).toBe(false);
141
- expect(component.funbox).toBe('none');
142
- expect(component.customTGQuotes).toBe(false);
143
- expect(component.showMiniTimerAndLiveWpm).toBe(true);
144
- expect(component.restartTest).toBe(false);
145
- expect(component.testVersion).toBe(1);
146
- });
147
-
148
- it('should initialize BehaviorSubjects in constructor', () => {
149
- expect(component.showCaps$).toBe(mockShowCaps$);
150
- expect(component.showCaret$).toBe(mockCaretShow$);
151
- expect(component.caretAnimation$).toBe(mockCaretAnimation$);
152
- expect(component.showTimer$).toBe(mockStartTestSubject$);
153
- expect(component.outOfFocusShow$).toBe(mockOutOfFocusShow$);
154
- expect(component.timeLeft$).toBe(mockTimeLeft$);
155
- });
156
-
157
- it('should initialize caret position to zero', () => {
158
- expect(component.caretLeft).toBe(0);
159
- expect(component.caretTop).toBe(0);
160
- });
161
-
162
- it('should initialize state to true', () => {
163
- expect(component.state).toBe('true');
164
- });
165
- });
166
-
167
- describe('#ngOnInit', () => {
168
- beforeEach(() => {
169
- jest.useFakeTimers();
170
- });
171
-
172
- afterEach(() => {
173
- jest.useRealTimers();
174
- });
175
-
176
- it('should set result calculating to false', () => {
177
- component.ngOnInit();
178
-
179
- expect(TestUI.setResultCalculating).toHaveBeenCalledWith(false);
180
- });
181
-
182
- it('should set result visible to false', () => {
183
- component.ngOnInit();
184
-
185
- expect(TestUI.setResultVisible).toHaveBeenCalledWith(false);
186
- });
187
-
188
- it('should reset caret positions', () => {
189
- component.caretLeft = 50;
190
- component.caretTop = 100;
191
-
192
- component.ngOnInit();
193
-
194
- expect(component.caretLeft).toBe(0);
195
- expect(component.caretTop).toBe(0);
196
- });
197
-
198
- it('should configure test settings with input values', () => {
199
- component.time = 120;
200
- component.punctuation = true;
201
- component.numbers = true;
202
- component.funbox = 'custom-funbox';
203
- component.customTGQuotes = true;
204
- component.testVersion = 2;
205
-
206
- component.ngOnInit();
207
-
208
- expect(config.setTime).toHaveBeenCalledWith(120);
209
- expect(config.setPunctuation).toHaveBeenCalledWith(true);
210
- expect(config.setNumbers).toHaveBeenCalledWith(true);
211
- expect(config.setFunbox).toHaveBeenCalledWith('custom-funbox');
212
- expect(config.setCustomTGQuotes).toHaveBeenCalledWith(true);
213
- expect(config.setTestVersionForSentences).toHaveBeenCalledWith(2);
214
- });
215
-
216
- it('should subscribe to caretLeft changes and update component state', () => {
217
- component.ngOnInit();
218
-
219
- expect(component.state).toBe('true');
220
-
221
- mockCaretLeft$.next(50);
222
-
223
- expect(component.caretLeft).toBe(50);
224
- expect(component.state).toBe('false');
225
-
226
- mockCaretLeft$.next(100);
227
-
228
- expect(component.caretLeft).toBe(100);
229
- expect(component.state).toBe('true');
230
- });
231
-
232
- it('should NOT change state when caretLeft value is the same', () => {
233
- component.caretLeft = 0;
234
- component.state = 'false';
235
- component.ngOnInit();
236
-
237
- mockCaretLeft$.next(0);
238
-
239
- expect(component.state).toBe('false');
240
- });
241
-
242
- it('should subscribe to caretTop changes', () => {
243
- component.ngOnInit();
244
-
245
- mockCaretTop$.next(75);
246
-
247
- expect(component.caretTop).toBe(75);
248
- });
249
-
250
- it('should emit replay export and result when test result is published', () => {
251
- const resultSpy = jest.spyOn(component.resultEvent, 'emit');
252
- const replaySpy = jest.spyOn(component.replayExport, 'emit');
253
- const mockResult = { wpm: 80, accuracy: 95 };
254
-
255
- component.ngOnInit();
256
-
257
- mockResultSub$.next(mockResult);
258
-
259
- expect(replay.getReplayExport).toHaveBeenCalled();
260
- expect(replaySpy).toHaveBeenCalledWith('mock-replay-data');
261
- expect(resultSpy).toHaveBeenCalledWith(mockResult);
262
- });
263
-
264
- it('should handle quote network errors', () => {
265
- const errorSpy = jest.spyOn(component.errorEvent, 'emit');
266
-
267
- component.ngOnInit();
268
-
269
- mockQuoteNetworkError$.next('Network error occurred');
270
-
271
- expect(errorSpy).toHaveBeenCalledWith('Network error occurred');
272
- expect(TestLogic.stopTest).toHaveBeenCalled();
273
- });
274
-
275
- it('should NOT emit error when QuoteNetworkError is null', () => {
276
- const errorSpy = jest.spyOn(component.errorEvent, 'emit');
277
-
278
- component.ngOnInit();
279
-
280
- mockQuoteNetworkError$.next(null);
281
-
282
- expect(errorSpy).not.toHaveBeenCalled();
283
- expect(TestLogic.stopTest).not.toHaveBeenCalled();
284
- });
285
-
286
- it('should set up interval to emit replay export every 20 seconds', () => {
287
- const replaySpy = jest.spyOn(component.replayExport, 'emit');
288
-
289
- component.ngOnInit();
290
-
291
- expect(replaySpy).not.toHaveBeenCalled();
292
-
293
- jest.advanceTimersByTime(20000);
294
- expect(replaySpy).toHaveBeenCalledTimes(1);
295
-
296
- jest.advanceTimersByTime(20000);
297
- expect(replaySpy).toHaveBeenCalledTimes(2);
298
- });
299
-
300
- it('should store subscriptions for cleanup', () => {
301
- component.ngOnInit();
302
-
303
- expect(component.subscriptions.length).toBeGreaterThan(0);
304
- });
305
-
306
- describe('when testExpiration$ is provided', () => {
307
- it('should disable time check and subscribe to test expiration', () => {
308
- const testExpiration$ = new Subject<void>();
309
- component.testExpiration$ = testExpiration$;
310
-
311
- component.ngOnInit();
312
-
313
- expect(testTimer.disableCheckIfTimeIsUp).toHaveBeenCalled();
314
-
315
- testExpiration$.next();
316
-
317
- expect(TestLogic.finish).toHaveBeenCalled();
318
- });
319
-
320
- it('should add testExpiration subscription to subscriptions array', () => {
321
- const testExpiration$ = new Subject<void>();
322
- component.testExpiration$ = testExpiration$;
323
-
324
- const initialLength = component.subscriptions.length;
325
- component.ngOnInit();
326
-
327
- expect(component.subscriptions.length).toBeGreaterThan(initialLength);
328
- });
329
- });
330
-
331
- describe('when testExpiration$ is NOT provided', () => {
332
- it('should NOT disable time check', () => {
333
- component.testExpiration$ = undefined;
334
-
335
- component.ngOnInit();
336
-
337
- expect(testTimer.disableCheckIfTimeIsUp).not.toHaveBeenCalled();
338
- });
339
- });
340
- });
341
-
342
- describe('#ngOnChanges', () => {
343
- it('should restart test when restartTest changes and is NOT first change', () => {
344
- const restartSpy = jest.spyOn(component, 'restart');
345
-
346
- component.ngOnChanges({
347
- restartTest: new SimpleChange(false, true, false),
348
- });
349
-
350
- expect(restartSpy).toHaveBeenCalled();
351
- });
352
-
353
- it('should NOT restart test when restartTest is first change', () => {
354
- const restartSpy = jest.spyOn(component, 'restart');
355
-
356
- component.ngOnChanges({
357
- restartTest: new SimpleChange(undefined, true, true),
358
- });
359
-
360
- expect(restartSpy).not.toHaveBeenCalled();
361
- });
362
-
363
- it('should NOT restart test when other properties change', () => {
364
- const restartSpy = jest.spyOn(component, 'restart');
365
-
366
- component.ngOnChanges({
367
- time: new SimpleChange(180, 120, false),
368
- });
369
-
370
- expect(restartSpy).not.toHaveBeenCalled();
371
- });
372
-
373
- it('should handle empty changes object', () => {
374
- const restartSpy = jest.spyOn(component, 'restart');
375
-
376
- component.ngOnChanges({});
377
-
378
- expect(restartSpy).not.toHaveBeenCalled();
379
- });
380
- });
381
-
382
- describe('#wordsInputKeyup', () => {
383
- it('should delegate to imported wordsInputKeyup function', () => {
384
- const mockEvent = new KeyboardEvent('keyup', { key: 'a' });
385
-
386
- component.wordsInputKeyup(mockEvent);
387
-
388
- expect(inputController.wordsInputKeyup).toHaveBeenCalledWith(mockEvent);
389
- });
390
- });
391
-
392
- describe('#wordsInputBeforeinput', () => {
393
- it('should delegate to imported wordsInputBeforeinput function', () => {
394
- const mockEvent = { data: 'test' };
395
-
396
- component.wordsInputBeforeinput(mockEvent);
397
-
398
- expect(inputController.wordsInputBeforeinput).toHaveBeenCalledWith(mockEvent);
399
- });
400
- });
401
-
402
- describe('#wordsInputInput', () => {
403
- it('should delegate to imported wordsInputInput function', () => {
404
- const mockEvent = { inputType: 'insertText' };
405
-
406
- component.wordsInputInput(mockEvent);
407
-
408
- expect(inputController.wordsInputInput).toHaveBeenCalledWith(mockEvent);
409
- });
410
- });
411
-
412
- describe('#wordsInputFocus', () => {
413
- it('should call focus functions when test is active', () => {
414
- const mockEvent = new FocusEvent('focus');
415
- jest.spyOn(TestActive, 'get').mockReturnValue(true);
416
-
417
- component.wordsInputFocus(mockEvent);
418
-
419
- expect(inputController.wordsInputFocus).toHaveBeenCalledWith(mockEvent);
420
- expect(TestUI.wordsInputFocusTestUI).toHaveBeenCalled();
421
- });
422
-
423
- it('should NOT call focus functions when test is NOT active', () => {
424
- const mockEvent = new FocusEvent('focus');
425
- jest.spyOn(TestActive, 'get').mockReturnValue(false);
426
-
427
- component.wordsInputFocus(mockEvent);
428
-
429
- expect(inputController.wordsInputFocus).not.toHaveBeenCalled();
430
- expect(TestUI.wordsInputFocusTestUI).not.toHaveBeenCalled();
431
- });
432
- });
433
-
434
- describe('#wordsInputFocusOut', () => {
435
- it('should call wordsInputFocusOut when test is active', () => {
436
- jest.spyOn(TestActive, 'get').mockReturnValue(true);
437
-
438
- component.wordsInputFocusOut();
439
-
440
- expect(TestUI.wordsInputFocusOut).toHaveBeenCalled();
441
- });
442
-
443
- it('should NOT call wordsInputFocusOut when test is NOT active', () => {
444
- jest.spyOn(TestActive, 'get').mockReturnValue(false);
445
-
446
- component.wordsInputFocusOut();
447
-
448
- expect(TestUI.wordsInputFocusOut).not.toHaveBeenCalled();
449
- });
450
- });
451
-
452
- describe('#wordsInputCopy', () => {
453
- it('should delegate to imported wordsInputCopy function', () => {
454
- const mockEvent = { type: 'copy' } as any;
455
-
456
- component.wordsInputCopy(mockEvent);
457
-
458
- expect(inputController.wordsInputCopy).toHaveBeenCalledWith(mockEvent);
459
- });
460
- });
461
-
462
- describe('#wordsInputPaste', () => {
463
- it('should delegate to imported wordsInputPaste function', () => {
464
- const mockEvent = { type: 'paste' } as any;
465
-
466
- component.wordsInputPaste(mockEvent);
467
-
468
- expect(inputController.wordsInputPaste).toHaveBeenCalledWith(mockEvent);
469
- });
470
- });
471
-
472
- describe('#wordsInputCompositionstart', () => {
473
- it('should delegate to imported wordsInputCompositionstart function', () => {
474
- component.wordsInputCompositionstart();
475
-
476
- expect(inputController.wordsInputCompositionstart).toHaveBeenCalled();
477
- });
478
- });
479
-
480
- describe('#wordsInputCompositionend', () => {
481
- it('should delegate to imported wordsInputCompositionend function', () => {
482
- component.wordsInputCompositionend();
483
-
484
- expect(inputController.wordsInputCompositionend).toHaveBeenCalled();
485
- });
486
- });
487
-
488
- describe('#wordsWrapperClick', () => {
489
- it('should delegate to imported wordsWrapperClick function', () => {
490
- component.wordsWrapperClick();
491
-
492
- expect(TestUI.wordsWrapperClick).toHaveBeenCalled();
493
- });
494
- });
495
-
496
- describe('#ngAfterViewInit', () => {
497
- let mockWordsInputElement: HTMLElement;
498
- let mockWordsWrapperElement: HTMLElement;
499
- let mockWordsElement: HTMLElement;
500
- let mockMiddleElement: HTMLElement;
501
- let mockCapsWarningElement: HTMLElement;
502
-
503
- beforeEach(() => {
504
- mockWordsInputElement = document.createElement('input');
505
- mockWordsWrapperElement = document.createElement('div');
506
- mockWordsElement = document.createElement('div');
507
- mockMiddleElement = document.createElement('div');
508
- mockCapsWarningElement = document.createElement('div');
509
-
510
- component.wordsInput = { nativeElement: mockWordsInputElement } as ElementRef;
511
- component.wordsWrapper = { nativeElement: mockWordsWrapperElement } as ElementRef;
512
- component.words = { nativeElement: mockWordsElement } as ElementRef;
513
- component.middle = { nativeElement: mockMiddleElement } as ElementRef;
514
- component.capsWarning = { nativeElement: mockCapsWarningElement } as ElementRef;
515
- });
516
-
517
- it('should set wordsInput element in input controller', () => {
518
- component.ngAfterViewInit();
519
-
520
- expect(inputController.setWordsInputElement).toHaveBeenCalledWith(mockWordsInputElement);
521
- });
522
-
523
- it('should set wordsInput element in TestUI', () => {
524
- component.ngAfterViewInit();
525
-
526
- expect(TestUI.setWordsInputElementTestUI).toHaveBeenCalledWith(mockWordsInputElement);
527
- });
528
-
529
- it('should set wordsInput element in TestLogic', () => {
530
- component.ngAfterViewInit();
531
-
532
- expect(TestLogic.setWordsInputElementTestLogic).toHaveBeenCalledWith(mockWordsInputElement);
533
- });
534
-
535
- it('should set wordsWrapper element', () => {
536
- component.ngAfterViewInit();
537
-
538
- expect(TestUI.setWordsWrapperElement).toHaveBeenCalledWith(mockWordsWrapperElement);
539
- });
540
-
541
- it('should set words element', () => {
542
- component.ngAfterViewInit();
543
-
544
- expect(TestUI.setWordsElement).toHaveBeenCalledWith(mockWordsElement);
545
- });
546
-
547
- it('should set middle element', () => {
548
- component.ngAfterViewInit();
549
-
550
- expect(focus.setMiddleElement).toHaveBeenCalledWith(mockMiddleElement);
551
- });
552
-
553
- it('should set caps warning element', () => {
554
- component.ngAfterViewInit();
555
-
556
- expect(focus.setCapsWarningElement).toHaveBeenCalledWith(mockCapsWarningElement);
557
- });
558
-
559
- it('should call TestLogic.restart', () => {
560
- component.ngAfterViewInit();
561
-
562
- expect(TestLogic.restart).toHaveBeenCalled();
563
- });
564
- });
565
-
566
- describe('#restart', () => {
567
- it('should set result calculating to false', () => {
568
- component.restart();
569
-
570
- expect(TestUI.setResultCalculating).toHaveBeenCalledWith(false);
571
- });
572
-
573
- it('should set result visible to false', () => {
574
- component.restart();
575
-
576
- expect(TestUI.setResultVisible).toHaveBeenCalledWith(false);
577
- });
578
-
579
- it('should reset caret positions to zero', () => {
580
- component.caretLeft = 100;
581
- component.caretTop = 50;
582
-
583
- component.restart();
584
-
585
- expect(component.caretLeft).toBe(0);
586
- expect(component.caretTop).toBe(0);
587
- });
588
-
589
- it('should call TestLogic.restart', () => {
590
- component.restart();
591
-
592
- expect(TestLogic.restart).toHaveBeenCalled();
593
- });
594
- });
595
-
596
- describe('#handleKeyboardDown', () => {
597
- let mockEvent: KeyboardEvent;
598
- let mockWordsInputElement: HTMLElement;
599
-
600
- beforeEach(() => {
601
- mockEvent = new KeyboardEvent('keydown', { key: 'a' });
602
- mockWordsInputElement = document.createElement('input');
603
- component.wordsInput = { nativeElement: mockWordsInputElement } as ElementRef;
604
- });
605
-
606
- it('should call capsKeydown with the event', () => {
607
- component.handleKeyboardDown(mockEvent);
608
-
609
- expect(capsWarning.capsKeydown).toHaveBeenCalledWith(mockEvent);
610
- });
611
-
612
- it('should call inputKeydown with event and true when wordsInput is focused', () => {
613
- jest.spyOn(document, 'activeElement', 'get').mockReturnValue(mockWordsInputElement);
614
-
615
- component.handleKeyboardDown(mockEvent);
616
-
617
- expect(inputController.inputKeydown).toHaveBeenCalledWith(mockEvent, true);
618
- });
619
-
620
- it('should call inputKeydown with event and false when wordsInput is NOT focused', () => {
621
- const otherElement = document.createElement('div');
622
- jest.spyOn(document, 'activeElement', 'get').mockReturnValue(otherElement);
623
-
624
- component.handleKeyboardDown(mockEvent);
625
-
626
- expect(inputController.inputKeydown).toHaveBeenCalledWith(mockEvent, false);
627
- });
628
- });
629
-
630
- describe('#handleKeyboardUp', () => {
631
- it('should call capsKeyup with the event', () => {
632
- const mockEvent = new KeyboardEvent('keyup', { key: 'Shift' });
633
-
634
- component.handleKeyboardUp(mockEvent);
635
-
636
- expect(capsWarning.capsKeyup).toHaveBeenCalledWith(mockEvent);
637
- });
638
- });
639
-
640
- describe('#handleMouseMove', () => {
641
- it('should call mousemove with the event', () => {
642
- const mockEvent = new MouseEvent('mousemove', { clientX: 100, clientY: 200 });
643
-
644
- component.handleMouseMove(mockEvent);
645
-
646
- expect(focus.mousemove).toHaveBeenCalledWith(mockEvent);
647
- });
648
- });
649
-
650
- describe('#ngOnDestroy', () => {
651
- it('should call TestLogic.stopTest', () => {
652
- component.ngOnDestroy();
653
-
654
- expect(TestLogic.stopTest).toHaveBeenCalled();
655
- });
656
-
657
- it('should reset quotes', () => {
658
- component.ngOnDestroy();
659
-
660
- expect(quoteController.resetQuotes).toHaveBeenCalled();
661
- });
662
-
663
- it('should clear the replay interval', () => {
664
- const clearIntervalSpy = jest.spyOn(global, 'clearInterval');
665
- component.replayIntervalID = 123;
666
-
667
- component.ngOnDestroy();
668
-
669
- expect(clearIntervalSpy).toHaveBeenCalledWith(123);
670
- });
671
-
672
- it('should unsubscribe from all subscriptions', () => {
673
- const unsubscribeSpy = jest.fn();
674
- component.subscriptions = [
675
- { unsubscribe: unsubscribeSpy } as any,
676
- { unsubscribe: unsubscribeSpy } as any,
677
- { unsubscribe: unsubscribeSpy } as any,
678
- ];
679
-
680
- component.ngOnDestroy();
681
-
682
- expect(unsubscribeSpy).toHaveBeenCalledTimes(3);
683
- });
684
- });
685
-
686
- describe('Output emitters', () => {
687
- it('should have resultEvent output', () => {
688
- expect(component.resultEvent).toBeDefined();
689
- });
690
-
691
- it('should have replayExport output', () => {
692
- expect(component.replayExport).toBeDefined();
693
- });
694
-
695
- it('should have errorEvent output', () => {
696
- expect(component.errorEvent).toBeDefined();
697
- });
698
- });
699
- });