@testgorilla/tgo-immersive-test 2.0.0 → 2.0.2

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 (47) hide show
  1. package/README.md +0 -1
  2. package/fesm2022/testgorilla-tgo-immersive-test.mjs +456 -0
  3. package/fesm2022/testgorilla-tgo-immersive-test.mjs.map +1 -0
  4. package/lib/components/immersive-test/immersive-test.component.d.ts +53 -0
  5. package/{src/lib/components/index.ts → lib/components/index.d.ts} +0 -2
  6. package/lib/components/review-instructions-dialog/review-instructions-dialog.component.d.ts +24 -0
  7. package/lib/components/ringing-phone-animation/ringing-phone-animation.component.d.ts +13 -0
  8. package/lib/components/ringing-phone-animation/ringing-phone-animation.sound.d.ts +1 -0
  9. package/lib/components/video-countdown/video-countdown.component.d.ts +24 -0
  10. package/lib/models/index.d.ts +2 -0
  11. package/lib/models/translations.d.ts +1 -0
  12. package/lib/services/index.d.ts +1 -0
  13. package/package.json +30 -13
  14. package/.eslintrc.json +0 -47
  15. package/jest.config.ts +0 -34
  16. package/ng-package.json +0 -16
  17. package/project.json +0 -48
  18. package/src/lib/components/immersive-test/immersive-test.component.html +0 -100
  19. package/src/lib/components/immersive-test/immersive-test.component.scss +0 -247
  20. package/src/lib/components/immersive-test/immersive-test.component.spec.ts +0 -583
  21. package/src/lib/components/immersive-test/immersive-test.component.ts +0 -278
  22. package/src/lib/components/review-instructions-dialog/review-instructions-dialog.component.html +0 -39
  23. package/src/lib/components/review-instructions-dialog/review-instructions-dialog.component.scss +0 -160
  24. package/src/lib/components/review-instructions-dialog/review-instructions-dialog.component.spec.ts +0 -81
  25. package/src/lib/components/review-instructions-dialog/review-instructions-dialog.component.ts +0 -79
  26. package/src/lib/components/ringing-phone-animation/ringing-phone-animation.component.html +0 -16
  27. package/src/lib/components/ringing-phone-animation/ringing-phone-animation.component.scss +0 -79
  28. package/src/lib/components/ringing-phone-animation/ringing-phone-animation.component.spec.ts +0 -104
  29. package/src/lib/components/ringing-phone-animation/ringing-phone-animation.component.ts +0 -53
  30. package/src/lib/components/ringing-phone-animation/ringing-phone-animation.sound.ts +0 -2
  31. package/src/lib/components/video-countdown/video-countdown.component.html +0 -10
  32. package/src/lib/components/video-countdown/video-countdown.component.scss +0 -16
  33. package/src/lib/components/video-countdown/video-countdown.component.spec.ts +0 -58
  34. package/src/lib/components/video-countdown/video-countdown.component.ts +0 -100
  35. package/src/lib/models/index.ts +0 -9
  36. package/src/lib/models/translations.ts +0 -3
  37. package/src/lib/services/index.ts +0 -7
  38. package/src/test-setup.ts +0 -62
  39. package/tsconfig.json +0 -20
  40. package/tsconfig.lib.json +0 -20
  41. package/tsconfig.lib.prod.json +0 -11
  42. package/tsconfig.spec.json +0 -17
  43. /package/{src/assets → assets}/i18n/en.json +0 -0
  44. /package/{src/index.ts → index.d.ts} +0 -0
  45. /package/{src/lib/components/review-instructions-dialog/index.ts → lib/components/review-instructions-dialog/index.d.ts} +0 -0
  46. /package/{src/lib/components/ringing-phone-animation/index.ts → lib/components/ringing-phone-animation/index.d.ts} +0 -0
  47. /package/{src/lib/components/video-countdown/index.ts → lib/components/video-countdown/index.d.ts} +0 -0
@@ -1,79 +0,0 @@
1
- .ringing-phone-animation-wrapper {
2
- display: flex;
3
- justify-content: center;
4
- align-items: center;
5
-
6
- .ringing-phone-animation-container {
7
- display: flex;
8
- flex-direction: column;
9
- align-items: center;
10
- justify-content: center;
11
- gap: 10px;
12
-
13
- .ringing-effect {
14
- display: flex;
15
- gap: 15px;
16
- opacity: 1;
17
- animation: blink-wrapper 1.4s infinite;
18
- animation-delay: 0.8s;
19
-
20
- .ringing-line {
21
- width: 6px;
22
- height: 16px;
23
- background-color: white;
24
- opacity: 0;
25
- }
26
-
27
- .first-line {
28
- animation: blink-line 1.4s infinite;
29
- animation-delay: 0.1s;
30
- transform: rotate(-45deg);
31
- }
32
-
33
- .second-line {
34
- animation: blink-line 1.4s infinite;
35
- animation-delay: 0.3s;
36
- transform: translate(0, -50%);
37
- }
38
-
39
- .third-line {
40
- animation: blink-line 1.4s infinite;
41
- animation-delay: 0.6s;
42
- transform: rotate(45deg);
43
- }
44
- }
45
-
46
- .answer-btn {
47
- margin-top: 20px;
48
- padding: 10px 20px;
49
- background-color: white;
50
- border: none;
51
- border-radius: 20px;
52
- cursor: pointer;
53
- font-size: 16px;
54
- }
55
- }
56
- }
57
-
58
- @keyframes blink-line {
59
- 0%,
60
- 49% {
61
- opacity: 0;
62
- }
63
- 50%,
64
- 100% {
65
- opacity: 1;
66
- }
67
- }
68
-
69
- @keyframes blink-wrapper {
70
- 0%,
71
- 49% {
72
- opacity: 1;
73
- }
74
- 50%,
75
- 100% {
76
- opacity: 0;
77
- }
78
- }
79
-
@@ -1,104 +0,0 @@
1
- import { CommonModule } from '@angular/common';
2
- import { SimpleChanges } from '@angular/core';
3
- import { ComponentFixture, TestBed } from '@angular/core/testing';
4
- import { RingingPhoneAnimationComponent } from './ringing-phone-animation.component';
5
- import SpyInstance = jest.SpyInstance;
6
-
7
- describe('RingingPhoneAnimationComponent', () => {
8
- let component: RingingPhoneAnimationComponent;
9
- let fixture: ComponentFixture<RingingPhoneAnimationComponent>;
10
-
11
- let playSpy: SpyInstance;
12
- let pauseSpy: SpyInstance;
13
-
14
- beforeEach(async () => {
15
- await TestBed.configureTestingModule({
16
- imports: [RingingPhoneAnimationComponent, CommonModule],
17
- }).compileComponents();
18
- });
19
-
20
- beforeEach(() => {
21
- fixture = TestBed.createComponent(RingingPhoneAnimationComponent);
22
- component = fixture.componentInstance;
23
-
24
- playSpy = jest
25
- .spyOn(HTMLAudioElement.prototype, 'play')
26
- .mockImplementation(() => Promise.resolve());
27
- pauseSpy = jest.spyOn(HTMLAudioElement.prototype, 'pause').mockImplementation(() => undefined);
28
-
29
- fixture.detectChanges();
30
- });
31
-
32
- it('should create the component', () => {
33
- expect(component).toBeTruthy();
34
- });
35
-
36
- describe('when initializing the component', () => {
37
- it('should initialize with default values', () => {
38
- expect(component.isRinging).toBe(true);
39
- expect(component.ringingSignal()).toBe(true);
40
- });
41
-
42
- it('should update "ringingSignal" when "isRinging" changes', () => {
43
- const changes: SimpleChanges = {
44
- isRinging: {
45
- previousValue: false,
46
- currentValue: true,
47
- firstChange: false,
48
- isFirstChange: () => false,
49
- },
50
- };
51
-
52
- component.isRinging = false;
53
- component.ngOnChanges(changes);
54
-
55
- expect(component.ringingSignal()).toBe(false);
56
- });
57
-
58
- it('should call "playSpy" if "isRinging" changes to true', () => {
59
- // First set it to false
60
- component.isRinging = false;
61
- component.ringingSignal.set(false);
62
-
63
- const changes: SimpleChanges = {
64
- isRinging: {
65
- previousValue: false,
66
- currentValue: true,
67
- firstChange: false,
68
- isFirstChange: () => false,
69
- },
70
- };
71
-
72
- component.isRinging = true;
73
- component.ngOnChanges(changes);
74
-
75
- expect(component.ringingSignal()).toBe(true);
76
- expect(component.audio.loop).toBe(true);
77
- expect(component.audio.volume).toBe(0.15);
78
- expect(playSpy).toHaveBeenCalled();
79
- });
80
-
81
- it('should call "pauseSpy" if isRinging changes to false', () => {
82
- // First set it to true and start ringing
83
- component.isRinging = true;
84
- component.ringingSignal.set(true);
85
- component.audio.play();
86
-
87
- const changes: SimpleChanges = {
88
- isRinging: {
89
- previousValue: true,
90
- currentValue: false,
91
- firstChange: false,
92
- isFirstChange: () => false,
93
- },
94
- };
95
-
96
- component.isRinging = false;
97
- component.ngOnChanges(changes);
98
-
99
- expect(component.ringingSignal()).toBe(false);
100
- expect(component.audio.currentTime).toBe(0);
101
- expect(pauseSpy).toHaveBeenCalled();
102
- });
103
- });
104
- });
@@ -1,53 +0,0 @@
1
- import {
2
- Component,
3
- WritableSignal,
4
- signal,
5
- Input,
6
- SimpleChanges,
7
- OnChanges,
8
- OnDestroy,
9
- } from '@angular/core';
10
- import { CommonModule } from '@angular/common';
11
- import { ringingPhoneSound } from './ringing-phone-animation.sound';
12
-
13
- @Component({
14
- selector: 'tgo-ringing-phone-animation',
15
- templateUrl: './ringing-phone-animation.component.html',
16
- styleUrls: ['./ringing-phone-animation.component.scss'],
17
- imports: [CommonModule]
18
- })
19
- export class RingingPhoneAnimationComponent implements OnChanges, OnDestroy {
20
- @Input() isRinging = true;
21
-
22
- ringingSignal: WritableSignal<boolean> = signal(this.isRinging);
23
- audio: HTMLAudioElement = new Audio(ringingPhoneSound);
24
-
25
- ngOnChanges(changes: SimpleChanges): void {
26
- if (changes['isRinging']) {
27
- this.ringingSignal.set(this.isRinging);
28
-
29
- if (this.isRinging) {
30
- this.startRinging();
31
- } else {
32
- this.stopRinging();
33
- }
34
- }
35
- }
36
-
37
- ngOnDestroy(): void {
38
- this.stopRinging();
39
- }
40
-
41
- private stopRinging(): void {
42
- this.ringingSignal.set(false);
43
- this.audio.pause();
44
- this.audio.currentTime = 0;
45
- }
46
-
47
- private startRinging(): void {
48
- this.audio.loop = true;
49
- this.audio.volume = 0.15;
50
- void this.audio.play();
51
- }
52
- }
53
-
@@ -1,2 +0,0 @@
1
- export const ringingPhoneSound = `data:audio/mp3;base64,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`;
2
-
@@ -1,10 +0,0 @@
1
- <div class="video-countdown">
2
- <div
3
- class="video-countdown-element"
4
- *ngFor="let num of [displayNum]"
5
- @zoomInOut
6
- >
7
- {{ num.value }}
8
- </div>
9
- </div>
10
-
@@ -1,16 +0,0 @@
1
- .video-countdown {
2
- display: flex;
3
- justify-content: center;
4
-
5
- &-element {
6
- position: absolute;
7
- font-size: 80px;
8
- font-weight: 700;
9
- line-height: 1;
10
- -webkit-user-select: none;
11
- user-select: none;
12
- opacity: 1;
13
- backface-visibility: hidden;
14
- }
15
- }
16
-
@@ -1,58 +0,0 @@
1
- import { ComponentFixture, TestBed } from '@angular/core/testing';
2
- import { NoopAnimationsModule } from '@angular/platform-browser/animations';
3
- import { VideoCountdownComponent } from './video-countdown.component';
4
-
5
- describe('VideoCountdownComponent', () => {
6
- let component: VideoCountdownComponent;
7
- let fixture: ComponentFixture<VideoCountdownComponent>;
8
-
9
- beforeEach(async () => {
10
- await TestBed.configureTestingModule({
11
- imports: [VideoCountdownComponent, NoopAnimationsModule],
12
- }).compileComponents();
13
- });
14
-
15
- beforeEach(() => {
16
- fixture = TestBed.createComponent(VideoCountdownComponent);
17
- component = fixture.componentInstance;
18
-
19
- fixture.detectChanges();
20
- });
21
-
22
- it('should create', () => {
23
- expect(component).toBeTruthy();
24
- });
25
-
26
- it('should start counting on component init', () => {
27
- const setTimeoutSpy = jest.spyOn(global, 'setTimeout');
28
- component.ngOnInit();
29
- expect(setTimeoutSpy).toHaveBeenCalled();
30
- });
31
-
32
- it('should set isActive to true on start', () => {
33
- component.start();
34
- expect(component.isActive).toBe(true);
35
- });
36
-
37
- it('should count down from startFrom to endAt', done => {
38
- component.startFrom = 3;
39
- component.endAt = 0;
40
- component.interval = 100;
41
- const finishSpy = jest.spyOn(component.finished, 'emit');
42
-
43
- component.start();
44
-
45
- setTimeout(() => {
46
- expect(component.displayNum.value).toBe(0);
47
- expect(finishSpy).toHaveBeenCalled();
48
- expect(component.isActive).toBe(false);
49
- done();
50
- }, 1000);
51
- });
52
-
53
- it('should clean up on ngOnDestroy', () => {
54
- const clearTimeoutSpy = jest.spyOn(global, 'clearTimeout');
55
- component.ngOnDestroy();
56
- expect(clearTimeoutSpy).toHaveBeenCalledWith(component.timeoutId);
57
- });
58
- });
@@ -1,100 +0,0 @@
1
- import { animate, style, transition, trigger } from '@angular/animations';
2
- import { CommonModule } from '@angular/common';
3
- import {
4
- ChangeDetectionStrategy,
5
- ChangeDetectorRef,
6
- Component,
7
- EventEmitter,
8
- Input,
9
- OnDestroy,
10
- OnInit,
11
- Output,
12
- } from '@angular/core';
13
-
14
- @Component({
15
- selector: 'tgo-video-countdown',
16
- templateUrl: './video-countdown.component.html',
17
- styleUrls: ['./video-countdown.component.scss'],
18
- animations: [
19
- trigger('zoomInOut', [
20
- transition(':enter', [
21
- style({ transform: 'scale(0)', opacity: 0 }),
22
- animate('300ms ease-out', style({ transform: 'scale(1.2)', opacity: 1 })),
23
- animate('100ms ease-in', style({ transform: 'scale(1)' })),
24
- ]),
25
- transition(':leave', [
26
- style({ opacity: 1 }),
27
- animate('100ms ease-out', style({ transform: 'scale(1.2)', opacity: 0.5 })),
28
- animate('200ms ease-in', style({ transform: 'scale(0)', opacity: 0 })),
29
- ]),
30
- ]),
31
- ],
32
- changeDetection: ChangeDetectionStrategy.OnPush,
33
- imports: [CommonModule],
34
- })
35
- export class VideoCountdownComponent implements OnInit, OnDestroy {
36
- @Input() startFrom = 5;
37
- @Input() endAt = 0;
38
- @Input() interval = 1325;
39
- @Output() finished: EventEmitter<void> = new EventEmitter<void>();
40
-
41
- isActive = false;
42
- displayNum: { key: number; value: number } = {
43
- key: this.startFrom,
44
- value: this.startFrom,
45
- };
46
- timeoutId: ReturnType<typeof setTimeout> | null = null;
47
-
48
- constructor(private cdr: ChangeDetectorRef) {}
49
-
50
- ngOnInit(): void {
51
- this.start();
52
- }
53
-
54
- start() {
55
- this.isActive = true;
56
- this.displayNum = { key: this.startFrom, value: this.startFrom };
57
- this.scheduleAnimation();
58
- }
59
-
60
- ngOnDestroy(): void {
61
- this.isActive = false;
62
- if (this.timeoutId) {
63
- clearTimeout(this.timeoutId);
64
- }
65
- }
66
-
67
- private scheduleAnimation() {
68
- this.timeoutId = setTimeout(() => {
69
- this.anim();
70
- }, this.interval);
71
- }
72
-
73
- private anim() {
74
- if (!this.isActive) {
75
- return;
76
- }
77
-
78
- this.updateNumber();
79
- this.cdr.markForCheck();
80
-
81
- if (this.displayNum && this.displayNum.value === this.endAt) {
82
- this.finished.emit();
83
- this.isActive = false;
84
- return;
85
- }
86
-
87
- this.scheduleAnimation();
88
- }
89
-
90
- private updateNumber() {
91
- if (this.displayNum && this.displayNum.value === this.endAt) {
92
- this.displayNum = { key: this.startFrom, value: this.startFrom - 1 };
93
- } else {
94
- this.displayNum = {
95
- key: this.displayNum.value - 1,
96
- value: this.displayNum.value - 1,
97
- };
98
- }
99
- }
100
- }
@@ -1,9 +0,0 @@
1
- // Re-export shared models
2
- export {
3
- Question,
4
- TestResultRead,
5
- SelectedMediaDevices,
6
- ISubmissionState,
7
- IQuestionDataContract,
8
- } from '@testgorilla/tgo-test-shared';
9
- export * from './translations';
@@ -1,3 +0,0 @@
1
- // Re-export from shared
2
- export { ROOT_TRANSLATIONS_SCOPE } from '@testgorilla/tgo-test-shared';
3
-
@@ -1,7 +0,0 @@
1
- // Re-export shared services
2
- export {
3
- MediaService,
4
- ThemeService,
5
- TranslocoLazyModuleUtils,
6
- getAvailableLangs,
7
- } from '@testgorilla/tgo-test-shared';
package/src/test-setup.ts DELETED
@@ -1,62 +0,0 @@
1
- import 'jest-preset-angular/setup-jest';
2
-
3
- // Mock HTMLMediaElement.play() for jsdom
4
- Object.defineProperty(HTMLMediaElement.prototype, 'play', {
5
- writable: true,
6
- value: jest.fn().mockResolvedValue(undefined),
7
- });
8
-
9
- // Mock @vimeo/player
10
- jest.mock('@vimeo/player', () => {
11
- return {
12
- default: jest.fn().mockImplementation(() => ({
13
- on: jest.fn(),
14
- off: jest.fn(),
15
- loadVideo: jest.fn(),
16
- play: jest.fn(),
17
- pause: jest.fn(),
18
- destroy: jest.fn(),
19
- })),
20
- };
21
- });
22
-
23
- // Global cleanup for media elements after each test
24
- afterEach(() => {
25
- // Clean up all audio and video elements in the DOM
26
- const audioElements = Array.from(document.querySelectorAll('audio'));
27
- const videoElements = Array.from(document.querySelectorAll('video'));
28
-
29
- [...audioElements, ...videoElements].forEach((element) => {
30
- const mediaElement = element as HTMLMediaElement;
31
- try {
32
- mediaElement.pause();
33
- mediaElement.src = '';
34
- mediaElement.srcObject = null;
35
- // Remove event listeners by cloning
36
- const newElement = mediaElement.cloneNode(false);
37
- mediaElement.parentNode?.replaceChild(newElement, mediaElement);
38
- } catch (error) {
39
- // Ignore errors during cleanup
40
- }
41
- });
42
-
43
- // Clean up MediaStream tracks
44
- if (window.MediaStream) {
45
- // Stop any active MediaStream tracks
46
- const streams = Array.from(document.querySelectorAll('video, audio'));
47
- streams.forEach((element) => {
48
- const mediaElement = element as HTMLMediaElement;
49
- if (mediaElement.srcObject instanceof MediaStream) {
50
- mediaElement.srcObject.getTracks().forEach((track) => {
51
- track.stop();
52
- });
53
- mediaElement.srcObject = null;
54
- }
55
- });
56
- }
57
-
58
- // Revoke any object URLs that might have been created
59
- // Note: This is a best-effort cleanup since we can't track all created URLs
60
- // Components should clean up their own object URLs in ngOnDestroy
61
- });
62
-
package/tsconfig.json DELETED
@@ -1,20 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "es2022",
4
- "paths": {
5
- "@testgorilla/tgo-test-shared": ["./src/shared/index.ts"]
6
- }
7
- },
8
- "files": [],
9
- "include": [],
10
- "references": [
11
- {
12
- "path": "./tsconfig.lib.json"
13
- },
14
- {
15
- "path": "./tsconfig.spec.json"
16
- }
17
- ],
18
- "extends": "../../tsconfig.base.json"
19
- }
20
-
package/tsconfig.lib.json DELETED
@@ -1,20 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "compilerOptions": {
4
- "outDir": "../../dist/out-tsc",
5
- "declaration": true,
6
- "declarationMap": true,
7
- "inlineSources": true,
8
- "baseUrl": "../../",
9
- "moduleResolution": "node",
10
- "paths": {
11
- "@testgorilla/tgo-test-shared": ["packages/tgo-immersive-test/src/shared/index.ts"]
12
- }
13
- },
14
- "angularCompilerOptions": {
15
- "preserveWhitespaces": false
16
- },
17
- "exclude": ["src/**/*.spec.ts", "src/test-setup.ts", "jest.config.ts", "src/**/*.test.ts"],
18
- "include": ["src/**/*.ts", "src/shared/**/*.ts"]
19
- }
20
-
@@ -1,11 +0,0 @@
1
- {
2
- "extends": "./tsconfig.lib.json",
3
- "compilerOptions": {
4
- "declarationMap": false,
5
- "rootDir": "../../"
6
- },
7
- "angularCompilerOptions": {
8
- "compilationMode": "partial"
9
- }
10
- }
11
-
@@ -1,17 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "compilerOptions": {
4
- "outDir": "../../dist/out-tsc",
5
- "module": "commonjs",
6
- "target": "es2016",
7
- "types": ["jest", "node"],
8
- "baseUrl": "../../",
9
- "paths": {
10
- "@testgorilla/tgo-test-shared": ["packages/tgo-immersive-test/src/shared/index.ts"]
11
- }
12
- },
13
- "files": ["src/test-setup.ts"],
14
- "include": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts", "src/**/*.d.ts", "src/shared/**/*.ts"],
15
- "exclude": ["src/lib/models/test.ts"]
16
- }
17
-
File without changes
File without changes