@testgorilla/tgo-ai-interview-test 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/.eslintrc.json +46 -0
  2. package/jest.config.ts +29 -0
  3. package/ng-package.json +16 -0
  4. package/package.json +8 -23
  5. package/project.json +48 -0
  6. package/src/lib/components/ai-interview-test/ai-interview-test.component.html +42 -0
  7. package/src/lib/components/ai-interview-test/ai-interview-test.component.scss +167 -0
  8. package/src/lib/components/ai-interview-test/ai-interview-test.component.spec.ts +212 -0
  9. package/src/lib/components/ai-interview-test/ai-interview-test.component.ts +192 -0
  10. package/src/lib/components/interview-stream/interview-stream.component.html +9 -0
  11. package/src/lib/components/interview-stream/interview-stream.component.scss +5 -0
  12. package/src/lib/components/interview-stream/interview-stream.component.spec.ts +259 -0
  13. package/src/lib/components/interview-stream/interview-stream.component.ts +320 -0
  14. package/src/lib/components/interview-video/interview-video.component.html +8 -0
  15. package/src/lib/components/interview-video/interview-video.component.scss +7 -0
  16. package/src/lib/components/interview-video/interview-video.component.spec.ts +140 -0
  17. package/src/lib/components/interview-video/interview-video.component.ts +67 -0
  18. package/src/lib/models/index.ts +13 -0
  19. package/src/lib/models/question-component.ts +13 -0
  20. package/src/lib/models/translations.ts +3 -0
  21. package/src/test-setup.ts +76 -0
  22. package/tsconfig.json +20 -0
  23. package/tsconfig.lib.json +20 -0
  24. package/tsconfig.lib.prod.json +11 -0
  25. package/tsconfig.spec.json +17 -0
  26. package/esm2022/index.mjs +0 -4
  27. package/esm2022/lib/components/ai-interview-test/ai-interview-test.component.mjs +0 -180
  28. package/esm2022/lib/components/index.mjs +0 -4
  29. package/esm2022/lib/components/interview-stream/interview-stream.component.mjs +0 -240
  30. package/esm2022/lib/components/interview-video/interview-video.component.mjs +0 -61
  31. package/esm2022/lib/models/index.mjs +0 -6
  32. package/esm2022/lib/models/question-component.mjs +0 -2
  33. package/esm2022/lib/models/translations.mjs +0 -3
  34. package/esm2022/shared/index.mjs +0 -5
  35. package/esm2022/shared/lib/components/audio-animation/audio-animation.component.mjs +0 -114
  36. package/esm2022/shared/lib/components/audio-animation/index.mjs +0 -2
  37. package/esm2022/shared/lib/components/index.mjs +0 -3
  38. package/esm2022/shared/lib/components/vimeo-video/index.mjs +0 -2
  39. package/esm2022/shared/lib/components/vimeo-video/vimeo-video.component.mjs +0 -101
  40. package/esm2022/shared/lib/models/answer.mjs +0 -2
  41. package/esm2022/shared/lib/models/assessment.mjs +0 -2
  42. package/esm2022/shared/lib/models/environment.mjs +0 -2
  43. package/esm2022/shared/lib/models/index.mjs +0 -9
  44. package/esm2022/shared/lib/models/question-component.mjs +0 -2
  45. package/esm2022/shared/lib/models/question.mjs +0 -2
  46. package/esm2022/shared/lib/models/test.mjs +0 -2
  47. package/esm2022/shared/lib/models/translations.mjs +0 -2
  48. package/esm2022/shared/lib/models/window.mjs +0 -2
  49. package/esm2022/shared/lib/services/api/api.service.mjs +0 -97
  50. package/esm2022/shared/lib/services/api/mocked-api.service.mjs +0 -131
  51. package/esm2022/shared/lib/services/environment/environment.service.mjs +0 -13
  52. package/esm2022/shared/lib/services/index.mjs +0 -10
  53. package/esm2022/shared/lib/services/localization/languages.model.mjs +0 -19
  54. package/esm2022/shared/lib/services/localization/transloco-lazy-module-utils.mjs +0 -27
  55. package/esm2022/shared/lib/services/localization/transloco-testing.module.mjs +0 -11
  56. package/esm2022/shared/lib/services/media/media.service.mjs +0 -129
  57. package/esm2022/shared/lib/services/mixpanel/mixpanel.service.mjs +0 -30
  58. package/esm2022/shared/lib/services/theme/theme.service.mjs +0 -24
  59. package/esm2022/shared/test-mocks/assessment-test.mock.mjs +0 -112
  60. package/esm2022/shared/test-mocks/index.mjs +0 -3
  61. package/esm2022/shared/test-mocks/tgo-ui.mock.mjs +0 -39
  62. package/esm2022/testgorilla-tgo-ai-interview-test.mjs +0 -5
  63. package/fesm2022/testgorilla-tgo-ai-interview-test.mjs +0 -484
  64. package/fesm2022/testgorilla-tgo-ai-interview-test.mjs.map +0 -1
  65. package/lib/components/ai-interview-test/ai-interview-test.component.d.ts +0 -44
  66. package/lib/components/interview-stream/interview-stream.component.d.ts +0 -46
  67. package/lib/components/interview-video/interview-video.component.d.ts +0 -16
  68. package/lib/models/index.d.ts +0 -3
  69. package/lib/models/question-component.d.ts +0 -5
  70. package/lib/models/translations.d.ts +0 -1
  71. package/shared/index.d.ts +0 -4
  72. package/shared/lib/components/audio-animation/audio-animation.component.d.ts +0 -27
  73. package/shared/lib/components/audio-animation/index.d.ts +0 -1
  74. package/shared/lib/components/index.d.ts +0 -2
  75. package/shared/lib/components/vimeo-video/index.d.ts +0 -1
  76. package/shared/lib/components/vimeo-video/vimeo-video.component.d.ts +0 -24
  77. package/shared/lib/models/answer.d.ts +0 -17
  78. package/shared/lib/models/assessment.d.ts +0 -80
  79. package/shared/lib/models/environment.d.ts +0 -1
  80. package/shared/lib/models/index.d.ts +0 -8
  81. package/shared/lib/models/question-component.d.ts +0 -54
  82. package/shared/lib/models/question.d.ts +0 -102
  83. package/shared/lib/models/test.d.ts +0 -81
  84. package/shared/lib/models/translations.d.ts +0 -1
  85. package/shared/lib/models/window.d.ts +0 -6
  86. package/shared/lib/services/api/api.service.d.ts +0 -25
  87. package/shared/lib/services/api/mocked-api.service.d.ts +0 -35
  88. package/shared/lib/services/environment/environment.service.d.ts +0 -6
  89. package/shared/lib/services/index.d.ts +0 -9
  90. package/shared/lib/services/localization/languages.model.d.ts +0 -15
  91. package/shared/lib/services/localization/transloco-lazy-module-utils.d.ts +0 -11
  92. package/shared/lib/services/localization/transloco-testing.module.d.ts +0 -2
  93. package/shared/lib/services/media/media.service.d.ts +0 -29
  94. package/shared/lib/services/mixpanel/mixpanel.service.d.ts +0 -10
  95. package/shared/lib/services/theme/theme.service.d.ts +0 -8
  96. package/shared/test-mocks/assessment-test.mock.d.ts +0 -21
  97. package/shared/test-mocks/index.d.ts +0 -2
  98. package/shared/test-mocks/tgo-ui.mock.d.ts +0 -21
  99. /package/{assets → src/assets}/i18n/en.json +0 -0
  100. /package/{index.d.ts → src/index.ts} +0 -0
  101. /package/{lib/components/index.d.ts → src/lib/components/index.ts} +0 -0
package/.eslintrc.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "extends": ["../../.eslintrc.json"],
3
+ "ignorePatterns": ["!**/*"],
4
+ "overrides": [
5
+ {
6
+ "files": ["*.ts"],
7
+ "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"],
8
+ "rules": {
9
+ "@angular-eslint/directive-selector": [
10
+ "error",
11
+ {
12
+ "type": "attribute",
13
+ "prefix": "tgo",
14
+ "style": "camelCase"
15
+ }
16
+ ],
17
+ "@angular-eslint/component-selector": [
18
+ "error",
19
+ {
20
+ "type": "element",
21
+ "prefix": "tgo",
22
+ "style": "kebab-case"
23
+ }
24
+ ],
25
+ "@angular-eslint/prefer-standalone": "off"
26
+ }
27
+ },
28
+ {
29
+ "files": ["*.html"],
30
+ "extends": ["plugin:@nx/angular-template"],
31
+ "rules": {}
32
+ },
33
+ {
34
+ "files": ["*.json"],
35
+ "parser": "jsonc-eslint-parser",
36
+ "rules": {
37
+ "@nx/dependency-checks": [
38
+ "error",
39
+ {
40
+ "ignoredFiles": ["{projectRoot}/eslint.config.{js,cjs,mjs}"]
41
+ }
42
+ ]
43
+ }
44
+ }
45
+ ]
46
+ }
package/jest.config.ts ADDED
@@ -0,0 +1,29 @@
1
+ export default {
2
+ displayName: 'tgo-ai-interview-test',
3
+ preset: '../../jest.preset.js',
4
+ setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
5
+ coverageDirectory: '../../coverage/packages/tgo-ai-interview-test',
6
+ testMatch: ['**/__tests__/**/*.[jt]s?(x)', '**/*.spec.[jt]s?(x)'],
7
+ testPathIgnorePatterns: ['/node_modules/', '/src/lib/models/'],
8
+ moduleNameMapper: {
9
+ '^@testgorilla/tgo-ui$': '<rootDir>/../shared/src/test-mocks/tgo-ui.mock.ts',
10
+ '^@testgorilla/tgo-test-shared$': '<rootDir>/src/shared/index.ts',
11
+ },
12
+ transform: {
13
+ '^.+\\.(ts|mjs|js|html)$': [
14
+ 'jest-preset-angular',
15
+ {
16
+ tsconfig: '<rootDir>/tsconfig.spec.json',
17
+ stringifyContentPathRegex: '\\.(html|svg)$',
18
+ },
19
+ ],
20
+ },
21
+ transformIgnorePatterns: [
22
+ 'node_modules/(?!.*\\.mjs$|lodash-es|@testgorilla|ng2-charts|chart\\.js|chartjs-plugin-datalabels|@daily-co)',
23
+ ],
24
+ snapshotSerializers: [
25
+ 'jest-preset-angular/build/serializers/no-ng-attributes',
26
+ 'jest-preset-angular/build/serializers/ng-snapshot',
27
+ 'jest-preset-angular/build/serializers/html-comment',
28
+ ],
29
+ };
@@ -0,0 +1,16 @@
1
+ {
2
+ "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
3
+ "dest": "../../dist/packages/tgo-ai-interview-test",
4
+ "assets": [
5
+ {
6
+ "glob": "**/*",
7
+ "input": "./src/assets",
8
+ "output": "./assets"
9
+ }
10
+ ],
11
+ "lib": {
12
+ "entryFile": "./src/index.ts"
13
+ },
14
+ "allowedNonPeerDependencies": []
15
+ }
16
+
package/package.json CHANGED
@@ -1,34 +1,19 @@
1
1
  {
2
2
  "name": "@testgorilla/tgo-ai-interview-test",
3
- "version": "1.0.0",
3
+ "version": "2.0.0",
4
4
  "peerDependencies": {
5
- "@angular/common": "~18.2.13",
6
- "@angular/core": "~18.2.13",
7
- "@angular/animations": "~18.2.13",
5
+ "@angular/common": "~19.2.17",
6
+ "@angular/core": "~19.2.17",
7
+ "@angular/animations": "~19.2.17",
8
8
  "@ngneat/transloco": "~4.3.0",
9
- "@testgorilla/tgo-ui": "~3.14.10",
9
+ "@testgorilla/tgo-ui": "~4.0.0",
10
10
  "@daily-co/daily-js": "^0.79.0",
11
- "jest-preset-angular": "~14.2.4",
11
+ "jest-preset-angular": "14.4.2",
12
12
  "rxjs": "~7.8.1"
13
13
  },
14
- "typings": "index.d.ts",
14
+ "typings": "src/lib/types",
15
15
  "sideEffects": false,
16
16
  "license": "PROPRIETARY",
17
17
  "displayName": "AI Interview",
18
- "description": "AI Interview component",
19
- "module": "fesm2022/testgorilla-tgo-ai-interview-test.mjs",
20
- "exports": {
21
- "./package.json": {
22
- "default": "./package.json"
23
- },
24
- ".": {
25
- "types": "./index.d.ts",
26
- "esm2022": "./esm2022/testgorilla-tgo-ai-interview-test.mjs",
27
- "esm": "./esm2022/testgorilla-tgo-ai-interview-test.mjs",
28
- "default": "./fesm2022/testgorilla-tgo-ai-interview-test.mjs"
29
- }
30
- },
31
- "dependencies": {
32
- "tslib": "^2.3.0"
33
- }
18
+ "description": "AI Interview component"
34
19
  }
package/project.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "tgo-ai-interview-test",
3
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
4
+ "sourceRoot": "packages/tgo-ai-interview-test/src",
5
+ "prefix": "tgo",
6
+ "projectType": "library",
7
+ "tags": [],
8
+ "targets": {
9
+ "build": {
10
+ "executor": "nx:run-commands",
11
+ "outputs": ["{workspaceRoot}/dist/packages/tgo-ai-interview-test"],
12
+ "options": {
13
+ "commands": [
14
+ "nx run tgo-ai-interview-test:package",
15
+ "node scripts/replace-shared-alias.js dist/packages/tgo-ai-interview-test @testgorilla/tgo-test-shared"
16
+ ],
17
+ "parallel": false,
18
+ "forwardAllArgs": false
19
+ }
20
+ },
21
+ "package": {
22
+ "executor": "@nx/angular:package",
23
+ "outputs": ["{workspaceRoot}/dist/{projectRoot}"],
24
+ "options": {
25
+ "project": "packages/tgo-ai-interview-test/ng-package.json"
26
+ },
27
+ "configurations": {
28
+ "production": {
29
+ "tsConfig": "packages/tgo-ai-interview-test/tsconfig.lib.prod.json"
30
+ },
31
+ "development": {
32
+ "tsConfig": "packages/tgo-ai-interview-test/tsconfig.lib.json"
33
+ }
34
+ },
35
+ "defaultConfiguration": "production"
36
+ },
37
+ "test": {
38
+ "executor": "@nx/jest:jest",
39
+ "outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
40
+ "options": {
41
+ "jestConfig": "packages/tgo-ai-interview-test/jest.config.ts"
42
+ }
43
+ },
44
+ "lint": {
45
+ "executor": "@nx/eslint:lint"
46
+ }
47
+ }
48
+ }
@@ -0,0 +1,42 @@
1
+ <div class="ai-interview-test">
2
+ <div class="test-container">
3
+ <div
4
+ class="media-container"
5
+ [class.is-video-visible]="isInterviewInProgress()"
6
+ >
7
+ <div class="candidate-no-camera" *ngIf="!candidateVideoStreamReady()">
8
+ <h3>&nbsp;</h3>
9
+ <ui-icon name="User-profile-in-line" color="white" size="24"></ui-icon>
10
+ <h3 class="bold">{{ translations['YOU'] }}</h3>
11
+ </div>
12
+ <div class="candidate-camera" [hidden]="!candidateVideoStreamReady()">
13
+ <video
14
+ height
15
+ #video
16
+ id="video"
17
+ playsinline
18
+ (loadedmetadata)="onVideoLoad()"
19
+ ></video>
20
+ <h3 class="bold" *ngIf="candidateVideoStreamReady()">
21
+ {{ translations['YOU'] }}
22
+ </h3>
23
+ </div>
24
+ <tgo-audio-animation
25
+ *ngIf="isInterviewInProgress()"
26
+ [fakeData]="true"
27
+ ></tgo-audio-animation>
28
+ <div class="interview-stream-container">
29
+ <tgo-interview-stream
30
+ *ngIf="conversationUrl && hasMediaPermissions()"
31
+ [selectedMediaDevices]="selectedMediaDevices"
32
+ [conversationUrl]="conversationUrl"
33
+ (streamStart)="interviewStarted()"
34
+ (streamEnd)="interviewEnded()"
35
+ (checkMediaPermissions)="checkMediaPermissions()"
36
+ [translations]="translations"
37
+ ></tgo-interview-stream>
38
+ </div>
39
+ </div>
40
+ </div>
41
+ </div>
42
+
@@ -0,0 +1,167 @@
1
+ @import '@testgorilla/tgo-ui/projects/tgo-canopy-ui/theme/variables';
2
+
3
+ $border-radius: 10px;
4
+
5
+ .ai-interview-test {
6
+ background-color: $black;
7
+ padding: 24px;
8
+ display: flex;
9
+ justify-content: center;
10
+ min-height: calc(100vh - 80px);
11
+
12
+ h3 {
13
+ color: $tgo-white;
14
+ }
15
+
16
+ .test-container {
17
+ min-width: 360px;
18
+ width: 100%;
19
+ min-height: 300px;
20
+ height: min(725px, 100%, max(calc(100vw), calc(100vh), 200px));
21
+ max-width: calc(100vh * (16 / 9) - 80px - 48px);
22
+ display: flex;
23
+ flex-direction: column;
24
+ justify-content: space-between;
25
+ position: relative;
26
+ background-color: $black;
27
+ }
28
+
29
+ .media-container {
30
+ position: relative;
31
+ color: $tgo-white;
32
+ flex-grow: 1;
33
+
34
+ .interview-stream-container {
35
+ border-radius: $border-radius;
36
+ aspect-ratio: 16 / 9;
37
+ border: 4px solid $informative-40;
38
+ margin: 0 auto;
39
+ }
40
+
41
+ .candidate-no-camera {
42
+ position: absolute;
43
+ width: 200px;
44
+ aspect-ratio: 16 / 9;
45
+ z-index: 3;
46
+ top: 32px;
47
+ left: 32px;
48
+ border-radius: $border-radius;
49
+ background-color: #1a47aa;
50
+ display: flex;
51
+ justify-content: space-between;
52
+ flex-direction: column;
53
+ padding: 16px;
54
+
55
+ ui-icon {
56
+ margin: auto;
57
+ }
58
+ }
59
+
60
+ .candidate-camera {
61
+ position: absolute;
62
+ width: 200px;
63
+ top: 32px;
64
+ left: 32px;
65
+ z-index: 3;
66
+
67
+ video {
68
+ width: 200px;
69
+ border-radius: $border-radius;
70
+ }
71
+
72
+ h3 {
73
+ position: absolute;
74
+ bottom: 16px;
75
+ left: 16px;
76
+ }
77
+ }
78
+
79
+ tgo-audio-animation {
80
+ position: absolute;
81
+ top: 32px;
82
+ right: 32px;
83
+ z-index: 1;
84
+ }
85
+
86
+ tgo-vimeo-video {
87
+ display: none;
88
+ position: absolute;
89
+ height: 100%;
90
+ width: 100%;
91
+ }
92
+
93
+ &.is-video-visible {
94
+ tgo-vimeo-video {
95
+ display: block;
96
+ }
97
+ }
98
+
99
+ &.is-playing {
100
+ border: 4px solid $informative-40;
101
+ border-bottom-width: 3px;
102
+ }
103
+
104
+ &.is-answering {
105
+ .candidate-camera,
106
+ .candidate-no-camera {
107
+ tgo-audio-animation {
108
+ position: absolute;
109
+ top: 16px;
110
+ right: 16px;
111
+ }
112
+ }
113
+
114
+ .candidate-camera video,
115
+ .candidate-no-camera {
116
+ border: 3px solid $informative-40;
117
+ border-radius: $border-radius;
118
+ }
119
+
120
+ tgo-vimeo-video {
121
+ display: block;
122
+ }
123
+ }
124
+
125
+ .start,
126
+ .audio-info,
127
+ .overlay,
128
+ .answer {
129
+ display: flex;
130
+ justify-content: center;
131
+ align-items: center;
132
+ flex-direction: column;
133
+ gap: 40px;
134
+ height: 100%;
135
+ }
136
+
137
+ .preview {
138
+ height: 100%;
139
+ display: flex;
140
+ align-items: center;
141
+ flex-direction: column;
142
+ justify-content: flex-end;
143
+ padding: 24px;
144
+
145
+ p {
146
+ color: $grayscale-30;
147
+ margin: 8px 0;
148
+ }
149
+
150
+ audio {
151
+ margin: 16px 0;
152
+ }
153
+
154
+ &.hidden {
155
+ display: none;
156
+ }
157
+ }
158
+ }
159
+ }
160
+
161
+ @media screen and (max-width: 600px) {
162
+ .ai-interview-test {
163
+ padding: 0 24px;
164
+ margin-top: 16px;
165
+ }
166
+ }
167
+
@@ -0,0 +1,212 @@
1
+ import { ChangeDetectorRef, CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA, signal } from '@angular/core';
2
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
3
+ import { NoopAnimationsModule } from '@angular/platform-browser/animations';
4
+ import { TranslocoService, TranslocoTestingModule } from '@ngneat/transloco';
5
+ import {
6
+ MediaService,
7
+ Question,
8
+ SelectedMediaDevices,
9
+ TestResultRead,
10
+ ThemeService,
11
+ } from '@testgorilla/tgo-test-shared';
12
+ import { ButtonComponentModule, IconComponentModule } from '@testgorilla/tgo-ui';
13
+ import { of, Subject } from 'rxjs';
14
+ import { AiInterviewTestComponent } from './ai-interview-test.component';
15
+
16
+ describe('AiInterviewTestComponent', () => {
17
+ let component: AiInterviewTestComponent;
18
+ let fixture: ComponentFixture<AiInterviewTestComponent>;
19
+ let transLocoServiceMock: Partial<jest.Mocked<TranslocoService>>;
20
+ let getMediaStreamSpy: jest.SpyInstance;
21
+ let submissionStateChangedSpy: jest.SpyInstance;
22
+ let mediaAccessChanged$: Subject<SelectedMediaDevices>;
23
+ let setSelectedMediaDevicesSpy: jest.SpyInstance;
24
+ let loadingStateChangedSpy: jest.SpyInstance;
25
+
26
+ const mockedTranslations = { testTranslationKey: 'test-translation' };
27
+ const mockStreamUrl = 'https://stream.com';
28
+
29
+ const mockedTest = {
30
+ is_preview_mode: false,
31
+ } as TestResultRead;
32
+
33
+ let hasMediaPermission = true;
34
+
35
+ class MediaServiceMock {
36
+ private recordSubject = new Subject();
37
+
38
+ isRecording = signal(false);
39
+
40
+ setSelectedMediaDevices(): void {
41
+ return;
42
+ }
43
+
44
+ getMediaStream() {
45
+ return Promise.resolve();
46
+ }
47
+
48
+ checkPermission() {
49
+ return Promise.resolve(hasMediaPermission);
50
+ }
51
+ }
52
+
53
+ beforeEach(async () => {
54
+ transLocoServiceMock = {
55
+ selectTranslateObject: jest.fn().mockReturnValue(of(mockedTranslations)),
56
+ };
57
+
58
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
59
+ const mockedMediaService = new MediaServiceMock() as any as MediaService;
60
+
61
+ await TestBed.configureTestingModule({
62
+ imports: [
63
+ TranslocoTestingModule.forRoot({
64
+ translocoConfig: {
65
+ availableLangs: ['en'],
66
+ defaultLang: 'en',
67
+ reRenderOnLangChange: true,
68
+ },
69
+ preloadLangs: true,
70
+ }),
71
+ IconComponentModule,
72
+ ButtonComponentModule,
73
+ NoopAnimationsModule,
74
+ AiInterviewTestComponent,
75
+ ],
76
+ schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA],
77
+ providers: [
78
+ { provide: TranslocoService, useValue: transLocoServiceMock },
79
+ { provide: MediaService, useValue: mockedMediaService },
80
+ {
81
+ provide: ChangeDetectorRef,
82
+ useValue: { markForCheck: jest.fn() },
83
+ },
84
+ {
85
+ provide: ThemeService,
86
+ useValue: {
87
+ uiTheme: 'dark',
88
+ getCompanyColor: jest.fn().mockReturnValue('#D410AA'),
89
+ },
90
+ },
91
+ ],
92
+ })
93
+ .overrideComponent(AiInterviewTestComponent, {
94
+ set: {
95
+ template: '',
96
+ },
97
+ })
98
+ .compileComponents();
99
+
100
+ fixture = TestBed.createComponent(AiInterviewTestComponent);
101
+ component = fixture.componentInstance;
102
+
103
+ getMediaStreamSpy = jest.spyOn(mockedMediaService, 'getMediaStream');
104
+ setSelectedMediaDevicesSpy = jest.spyOn(mockedMediaService, 'setSelectedMediaDevices');
105
+ submissionStateChangedSpy = jest.spyOn(component.submissionStateChanged, 'emit');
106
+
107
+ loadingStateChangedSpy = jest.spyOn(component.loadingStateChanged, 'emit');
108
+
109
+ mediaAccessChanged$ = new Subject<SelectedMediaDevices>();
110
+ component.mediaAccessChanged = mediaAccessChanged$.asObservable();
111
+ hasMediaPermission = true;
112
+ });
113
+
114
+ afterEach(() => {
115
+ fixture.destroy();
116
+ jest.clearAllMocks();
117
+ });
118
+
119
+ describe('when component is initialized with and with question video content', () => {
120
+ beforeEach(() => {
121
+ component.question = {
122
+ text: ``,
123
+ } as Question;
124
+ component.test = mockedTest;
125
+ component.conversationUrl = mockStreamUrl;
126
+ component.ngOnInit();
127
+ fixture.detectChanges();
128
+ });
129
+
130
+ it('should set the translations', () => {
131
+ expect(component.translations).toEqual(mockedTranslations);
132
+ });
133
+
134
+ it('should init stream', () => {
135
+ expect(getMediaStreamSpy).toHaveBeenCalled();
136
+ });
137
+
138
+ it('should return stream content url', () => {
139
+ expect(component.conversationUrl).toBe(mockStreamUrl);
140
+ });
141
+
142
+ it('should has candidateStreamReady = false by default', () => {
143
+ expect(component.candidateVideoStreamReady()).toBe(false);
144
+ });
145
+
146
+ describe('when video is loaded', () => {
147
+ beforeEach(() => {
148
+ component.onVideoLoad();
149
+ fixture.detectChanges();
150
+ });
151
+
152
+ it('should set candidateStreamReady to true', () => {
153
+ expect(component.candidateVideoStreamReady()).toBe(true);
154
+ });
155
+ });
156
+
157
+ describe('when mediaAccessChange is called', () => {
158
+ const changedAudioDeviceId = 'test_audio_changed';
159
+ const changedVideoDeviceId = 'test_video_changed';
160
+ beforeEach(() => {
161
+ mediaAccessChanged$.next({
162
+ audioDeviceId: changedAudioDeviceId,
163
+ videoDeviceId: changedVideoDeviceId,
164
+ });
165
+ fixture.detectChanges();
166
+ });
167
+
168
+ it('should call mediaService.setSelectedMediaDevices() method with new devices Ids', () => {
169
+ expect(setSelectedMediaDevicesSpy).toHaveBeenCalledWith({
170
+ audioDeviceId: changedAudioDeviceId,
171
+ videoDeviceId: changedVideoDeviceId,
172
+ });
173
+ });
174
+
175
+ it('should reinitialize video stream', () => {
176
+ expect(getMediaStreamSpy).toHaveBeenCalled();
177
+ });
178
+ });
179
+
180
+ describe('when interviewStarted is called', () => {
181
+ beforeEach(() => {
182
+ component.interviewStarted();
183
+ fixture.detectChanges();
184
+ });
185
+
186
+ it('should set isInterviewInProgress to true', () => {
187
+ expect(component.isInterviewInProgress()).toBe(true);
188
+ });
189
+
190
+ it('should emit loadingStateChanged with false', () => {
191
+ expect(loadingStateChangedSpy).toHaveBeenCalledWith(false);
192
+ });
193
+
194
+ describe('when interviewEnded is called', () => {
195
+ beforeEach(() => {
196
+ component.interviewEnded();
197
+ fixture.detectChanges();
198
+ });
199
+
200
+ it('should set isInterviewInProgress to false', () => {
201
+ expect(component.isInterviewInProgress()).toBe(false);
202
+ });
203
+
204
+ it('should emit submissionStateChanged with empty text', () => {
205
+ expect(submissionStateChangedSpy).toHaveBeenCalledWith({
206
+ text: '',
207
+ });
208
+ });
209
+ });
210
+ });
211
+ });
212
+ });