@testgorilla/tgo-coding-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 (353) hide show
  1. package/.eslintrc.json +46 -0
  2. package/jest.config.ts +26 -0
  3. package/ng-package.json +14 -0
  4. package/package.json +15 -31
  5. package/project.json +48 -0
  6. package/{index.d.ts → src/index.ts} +19 -2
  7. package/src/lib/components/.gitkeep +0 -0
  8. package/src/lib/components/code-editor/code-editor.component.html +10 -0
  9. package/src/lib/components/code-editor/code-editor.component.scss +21 -0
  10. package/src/lib/components/code-editor/code-editor.component.spec.ts +136 -0
  11. package/src/lib/components/code-editor/code-editor.component.ts +368 -0
  12. package/src/lib/components/code-editor/code-editor.mocks.ts +28 -0
  13. package/src/lib/components/code-editor/code-editor.service.spec.ts +160 -0
  14. package/src/lib/components/code-editor/code-editor.service.ts +94 -0
  15. package/src/lib/components/code-editor/helpers/c-helper.spec.ts +39 -0
  16. package/src/lib/components/code-editor/helpers/c-helper.ts +51 -0
  17. package/src/lib/components/code-editor/helpers/code-editor-helper.base.spec.ts +30 -0
  18. package/src/lib/components/code-editor/helpers/code-editor-helper.base.ts +16 -0
  19. package/src/lib/components/code-editor/helpers/code-editor-helper.mocks.ts +24 -0
  20. package/src/lib/components/code-editor/helpers/code-editor-helper.model.ts +67 -0
  21. package/src/lib/components/code-editor/helpers/cpp-helper.spec.ts +40 -0
  22. package/src/lib/components/code-editor/helpers/cpp-helper.ts +52 -0
  23. package/src/lib/components/code-editor/helpers/csharp-helper.spec.ts +42 -0
  24. package/src/lib/components/code-editor/helpers/csharp-helper.ts +55 -0
  25. package/src/lib/components/code-editor/helpers/go-helper.spec.ts +41 -0
  26. package/src/lib/components/code-editor/helpers/go-helper.ts +54 -0
  27. package/src/lib/components/code-editor/helpers/java-helper.spec.ts +41 -0
  28. package/src/lib/components/code-editor/helpers/java-helper.ts +54 -0
  29. package/src/lib/components/code-editor/helpers/javascript-helper.spec.ts +39 -0
  30. package/src/lib/components/code-editor/helpers/javascript-helper.ts +32 -0
  31. package/src/lib/components/code-editor/helpers/kotlin-helper.spec.ts +41 -0
  32. package/src/lib/components/code-editor/helpers/kotlin-helper.ts +54 -0
  33. package/src/lib/components/code-editor/helpers/php-helper.spec.ts +39 -0
  34. package/src/lib/components/code-editor/helpers/php-helper.ts +32 -0
  35. package/src/lib/components/code-editor/helpers/python-helper.spec.ts +39 -0
  36. package/src/lib/components/code-editor/helpers/python-helper.ts +32 -0
  37. package/src/lib/components/code-editor/helpers/r-helper.spec.ts +39 -0
  38. package/src/lib/components/code-editor/helpers/r-helper.ts +32 -0
  39. package/src/lib/components/code-editor/helpers/ruby-helper.spec.ts +39 -0
  40. package/src/lib/components/code-editor/helpers/ruby-helper.ts +32 -0
  41. package/src/lib/components/code-editor/helpers/scala-helper.spec.ts +41 -0
  42. package/src/lib/components/code-editor/helpers/scala-helper.ts +53 -0
  43. package/src/lib/components/code-editor/helpers/sql-helper.spec.ts +87 -0
  44. package/src/lib/components/code-editor/helpers/sql-helper.ts +44 -0
  45. package/src/lib/components/code-editor/helpers/swift-helper.spec.ts +40 -0
  46. package/src/lib/components/code-editor/helpers/swift-helper.ts +51 -0
  47. package/src/lib/components/code-editor/helpers/typescript-helper.spec.ts +40 -0
  48. package/src/lib/components/code-editor/helpers/typescript-helper.ts +52 -0
  49. package/src/lib/components/code-editor/models/code-editor.model.ts +9 -0
  50. package/src/lib/components/code-editor/models/coding-snapshot.model.ts +4 -0
  51. package/src/lib/components/coding-question/coding-question.component.html +78 -0
  52. package/src/lib/components/coding-question/coding-question.component.scss +75 -0
  53. package/src/lib/components/coding-question/coding-question.component.spec.ts +85 -0
  54. package/src/lib/components/coding-question/coding-question.component.ts +101 -0
  55. package/src/lib/components/coding-section/coding-section.component.html +82 -0
  56. package/src/lib/components/coding-section/coding-section.component.scss +64 -0
  57. package/src/lib/components/coding-section/coding-section.component.spec.ts +257 -0
  58. package/src/lib/components/coding-section/coding-section.component.ts +186 -0
  59. package/src/lib/components/coding-test.module.ts +124 -0
  60. package/src/lib/components/common/truncated-text/truncated-text.component.html +6 -0
  61. package/src/lib/components/common/truncated-text/truncated-text.component.scss +18 -0
  62. package/src/lib/components/common/truncated-text/truncated-text.component.spec.ts +84 -0
  63. package/src/lib/components/common/truncated-text/truncated-text.component.ts +36 -0
  64. package/src/lib/components/configurations/configurations.component.html +57 -0
  65. package/src/lib/components/configurations/configurations.component.scss +42 -0
  66. package/src/lib/components/configurations/configurations.component.spec.ts +186 -0
  67. package/src/lib/components/configurations/configurations.component.ts +97 -0
  68. package/src/lib/components/instructions/instructions.component.html +41 -0
  69. package/src/lib/components/instructions/instructions.component.scss +173 -0
  70. package/src/lib/components/instructions/instructions.component.spec.ts +106 -0
  71. package/src/lib/components/instructions/instructions.component.ts +137 -0
  72. package/src/lib/components/panel/panel.component.html +19 -0
  73. package/src/lib/components/panel/panel.component.scss +41 -0
  74. package/src/lib/components/panel/panel.component.spec.ts +40 -0
  75. package/src/lib/components/panel/panel.component.ts +33 -0
  76. package/src/lib/components/runnable-editor/runnable-editor.component.html +75 -0
  77. package/src/lib/components/runnable-editor/runnable-editor.component.scss +55 -0
  78. package/src/lib/components/runnable-editor/runnable-editor.component.spec.ts +124 -0
  79. package/src/lib/components/runnable-editor/runnable-editor.component.ts +154 -0
  80. package/src/lib/components/tests/test-cases/test-cases.component.html +135 -0
  81. package/src/lib/components/tests/test-cases/test-cases.component.scss +220 -0
  82. package/src/lib/components/tests/test-cases/test-cases.component.spec.ts +401 -0
  83. package/src/lib/components/tests/test-cases/test-cases.component.ts +204 -0
  84. package/src/lib/components/tests/test-cases-content/test-cases-content.component.html +94 -0
  85. package/src/lib/components/tests/test-cases-content/test-cases-content.component.scss +103 -0
  86. package/src/lib/components/tests/test-cases-content/test-cases-content.component.spec.ts +122 -0
  87. package/src/lib/components/tests/test-cases-content/test-cases-content.component.ts +101 -0
  88. package/src/lib/components/tests/test-cases-status/test-cases-status.component.html +16 -0
  89. package/src/lib/components/tests/test-cases-status/test-cases-status.component.scss +49 -0
  90. package/src/lib/components/tests/test-cases-status/test-cases-status.component.spec.ts +22 -0
  91. package/src/lib/components/tests/test-cases-status/test-cases-status.component.ts +17 -0
  92. package/src/lib/components/tests/test-results.component.html +119 -0
  93. package/src/lib/components/tests/test-results.component.scss +189 -0
  94. package/src/lib/components/tests/test-results.component.spec.ts +140 -0
  95. package/src/lib/components/tests/test-results.component.ts +97 -0
  96. package/src/lib/components/tgo-coding-test/tgo-coding-test.component.html +96 -0
  97. package/src/lib/components/tgo-coding-test/tgo-coding-test.component.scss +6 -0
  98. package/src/lib/components/tgo-coding-test/tgo-coding-test.component.spec.ts +599 -0
  99. package/src/lib/components/tgo-coding-test/tgo-coding-test.component.ts +278 -0
  100. package/src/lib/components/tgo-coding-test-candidate-view/tgo-coding-test-candidate-view.component.html +36 -0
  101. package/src/lib/components/tgo-coding-test-candidate-view/tgo-coding-test-candidate-view.component.scss +183 -0
  102. package/src/lib/components/tgo-coding-test-candidate-view/tgo-coding-test-candidate-view.component.spec.ts +883 -0
  103. package/src/lib/components/tgo-coding-test-candidate-view/tgo-coding-test-candidate-view.component.ts +578 -0
  104. package/{lib/config/index.d.ts → src/lib/config/index.ts} +1 -0
  105. package/src/lib/config/tgo-coding-test.config.ts +26 -0
  106. package/{lib/config/tgo-coding-test.provider.d.ts → src/lib/config/tgo-coding-test.provider.ts} +18 -6
  107. package/src/lib/config/tgo-coding-test.token.ts +21 -0
  108. package/src/lib/models/.gitkeep +0 -0
  109. package/src/lib/models/auto-saved-data.ts +51 -0
  110. package/src/lib/models/code-event.ts +17 -0
  111. package/src/lib/models/coderunner-execution-results.ts +58 -0
  112. package/src/lib/models/coding-lib.mocks.ts +246 -0
  113. package/src/lib/models/configs.ts +18 -0
  114. package/src/lib/models/language-change-action.ts +4 -0
  115. package/src/lib/models/lat-languages.ts +12 -0
  116. package/src/lib/models/mixpanel-events.ts +3 -0
  117. package/src/lib/models/mode.ts +5 -0
  118. package/src/lib/models/paste-data.ts +4 -0
  119. package/src/lib/models/programming-language.ts +9 -0
  120. package/src/lib/models/test-cases.ts +74 -0
  121. package/src/lib/models/theme.ts +5 -0
  122. package/src/lib/models/translations.ts +1 -0
  123. package/src/lib/models/view-mode.ts +6 -0
  124. package/{lib/pipes/memoize-func.pipe.d.ts → src/lib/pipes/memoize-func.pipe.ts} +14 -6
  125. package/src/lib/services/.gitkeep +0 -0
  126. package/src/lib/services/candidate-coding-test-services/candidature-api.service.spec.ts +40 -0
  127. package/src/lib/services/candidate-coding-test-services/candidature-api.service.ts +15 -0
  128. package/src/lib/services/candidate-coding-test-services/coderunner-api.service.spec.ts +134 -0
  129. package/src/lib/services/candidate-coding-test-services/coderunner-api.service.ts +105 -0
  130. package/src/lib/services/candidate-coding-test-services/coding-test-tour.service.spec.ts +161 -0
  131. package/src/lib/services/candidate-coding-test-services/coding-test-tour.service.ts +100 -0
  132. package/src/lib/services/candidate-coding-test-services/coding-test.service.spec.ts +1524 -0
  133. package/src/lib/services/candidate-coding-test-services/coding-test.service.ts +843 -0
  134. package/{lib/services/candidate-coding-test-services/index.d.ts → src/lib/services/candidate-coding-test-services/index.ts} +1 -1
  135. package/src/lib/services/coding-test-config.service.ts +48 -0
  136. package/src/lib/services/configurations.service.mocks.ts +77 -0
  137. package/src/lib/services/configurations.service.spec.ts +79 -0
  138. package/src/lib/services/configurations.service.ts +111 -0
  139. package/src/lib/services/index.ts +0 -0
  140. package/src/lib/services/lib-coding-test.service.spec.ts +265 -0
  141. package/src/lib/services/lib-coding-test.service.ts +157 -0
  142. package/src/lib/services/local-storage.service.mocks.ts +22 -0
  143. package/src/lib/services/storage.service.spec.ts +1119 -0
  144. package/src/lib/services/storage.service.ts +729 -0
  145. package/src/lib/services/test-cases.service.spec.ts +53 -0
  146. package/src/lib/services/test-cases.service.ts +29 -0
  147. package/src/lib/services/theme.service.spec.ts +76 -0
  148. package/src/lib/services/theme.service.ts +34 -0
  149. package/src/lib/styles/mixins.scss +86 -0
  150. package/src/lib/styles/styles.scss +112 -0
  151. package/src/lib/styles/variables.scss +105 -0
  152. package/src/lib/utils/.gitkeep +0 -0
  153. package/src/lib/utils/additional-languages/erlang.ts +115 -0
  154. package/src/lib/utils/resize-element.ts +15 -0
  155. package/src/lib/utils/time-to-ms.util.ts +10 -0
  156. package/src/test-setup.ts +3 -0
  157. package/tsconfig.json +19 -0
  158. package/tsconfig.lib.json +19 -0
  159. package/tsconfig.lib.prod.json +10 -0
  160. package/tsconfig.spec.json +17 -0
  161. package/esm2022/index.mjs +0 -12
  162. package/esm2022/lib/components/code-editor/code-editor.component.mjs +0 -335
  163. package/esm2022/lib/components/code-editor/code-editor.service.mjs +0 -72
  164. package/esm2022/lib/components/code-editor/helpers/c-helper.mjs +0 -40
  165. package/esm2022/lib/components/code-editor/helpers/code-editor-helper.base.mjs +0 -11
  166. package/esm2022/lib/components/code-editor/helpers/code-editor-helper.model.mjs +0 -2
  167. package/esm2022/lib/components/code-editor/helpers/cpp-helper.mjs +0 -41
  168. package/esm2022/lib/components/code-editor/helpers/csharp-helper.mjs +0 -42
  169. package/esm2022/lib/components/code-editor/helpers/go-helper.mjs +0 -42
  170. package/esm2022/lib/components/code-editor/helpers/index.mjs +0 -16
  171. package/esm2022/lib/components/code-editor/helpers/java-helper.mjs +0 -42
  172. package/esm2022/lib/components/code-editor/helpers/javascript-helper.mjs +0 -26
  173. package/esm2022/lib/components/code-editor/helpers/kotlin-helper.mjs +0 -42
  174. package/esm2022/lib/components/code-editor/helpers/php-helper.mjs +0 -26
  175. package/esm2022/lib/components/code-editor/helpers/python-helper.mjs +0 -26
  176. package/esm2022/lib/components/code-editor/helpers/r-helper.mjs +0 -26
  177. package/esm2022/lib/components/code-editor/helpers/ruby-helper.mjs +0 -26
  178. package/esm2022/lib/components/code-editor/helpers/scala-helper.mjs +0 -41
  179. package/esm2022/lib/components/code-editor/helpers/sql-helper.mjs +0 -34
  180. package/esm2022/lib/components/code-editor/helpers/swift-helper.mjs +0 -40
  181. package/esm2022/lib/components/code-editor/helpers/typescript-helper.mjs +0 -41
  182. package/esm2022/lib/components/code-editor/models/code-editor.model.mjs +0 -2
  183. package/esm2022/lib/components/code-editor/models/coding-snapshot.model.mjs +0 -2
  184. package/esm2022/lib/components/coding-question/coding-question.component.mjs +0 -126
  185. package/esm2022/lib/components/coding-section/coding-section.component.mjs +0 -188
  186. package/esm2022/lib/components/common/truncated-text/truncated-text.component.mjs +0 -38
  187. package/esm2022/lib/components/configurations/configurations.component.mjs +0 -97
  188. package/esm2022/lib/components/instructions/instructions.component.mjs +0 -139
  189. package/esm2022/lib/components/panel/panel.component.mjs +0 -34
  190. package/esm2022/lib/components/runnable-editor/runnable-editor.component.mjs +0 -169
  191. package/esm2022/lib/components/tests/test-cases/test-cases.component.mjs +0 -198
  192. package/esm2022/lib/components/tests/test-cases-content/test-cases-content.component.mjs +0 -96
  193. package/esm2022/lib/components/tests/test-cases-status/test-cases-status.component.mjs +0 -21
  194. package/esm2022/lib/components/tests/test-results.component.mjs +0 -127
  195. package/esm2022/lib/components/tgo-coding-test/tgo-coding-test.component.mjs +0 -280
  196. package/esm2022/lib/components/tgo-coding-test-candidate-view/tgo-coding-test-candidate-view.component.mjs +0 -476
  197. package/esm2022/lib/config/index.mjs +0 -2
  198. package/esm2022/lib/config/tgo-coding-test.config.mjs +0 -2
  199. package/esm2022/lib/config/tgo-coding-test.provider.mjs +0 -34
  200. package/esm2022/lib/config/tgo-coding-test.token.mjs +0 -14
  201. package/esm2022/lib/models/auto-saved-data.mjs +0 -2
  202. package/esm2022/lib/models/code-event.mjs +0 -2
  203. package/esm2022/lib/models/coderunner-execution-results.mjs +0 -2
  204. package/esm2022/lib/models/configs.mjs +0 -2
  205. package/esm2022/lib/models/language-change-action.mjs +0 -2
  206. package/esm2022/lib/models/lat-languages.mjs +0 -3
  207. package/esm2022/lib/models/mixpanel-events.mjs +0 -2
  208. package/esm2022/lib/models/mode.mjs +0 -2
  209. package/esm2022/lib/models/paste-data.mjs +0 -2
  210. package/esm2022/lib/models/programming-language.mjs +0 -2
  211. package/esm2022/lib/models/test-cases.mjs +0 -7
  212. package/esm2022/lib/models/theme.mjs +0 -2
  213. package/esm2022/lib/models/translations.mjs +0 -2
  214. package/esm2022/lib/models/view-mode.mjs +0 -8
  215. package/esm2022/lib/pipes/memoize-func.pipe.mjs +0 -39
  216. package/esm2022/lib/services/candidate-coding-test-services/candidature-api.service.mjs +0 -19
  217. package/esm2022/lib/services/candidate-coding-test-services/coderunner-api.service.mjs +0 -58
  218. package/esm2022/lib/services/candidate-coding-test-services/coding-test-tour.service.mjs +0 -89
  219. package/esm2022/lib/services/candidate-coding-test-services/coding-test.service.mjs +0 -490
  220. package/esm2022/lib/services/candidate-coding-test-services/index.mjs +0 -5
  221. package/esm2022/lib/services/coding-test-config.service.mjs +0 -51
  222. package/esm2022/lib/services/configurations.service.mjs +0 -89
  223. package/esm2022/lib/services/lib-coding-test.service.mjs +0 -106
  224. package/esm2022/lib/services/storage.service.mjs +0 -624
  225. package/esm2022/lib/services/test-cases.service.mjs +0 -30
  226. package/esm2022/lib/services/theme.service.mjs +0 -36
  227. package/esm2022/lib/utils/additional-languages/erlang.mjs +0 -103
  228. package/esm2022/lib/utils/resize-element.mjs +0 -13
  229. package/esm2022/lib/utils/time-to-ms.util.mjs +0 -11
  230. package/esm2022/shared/index.mjs +0 -5
  231. package/esm2022/shared/lib/components/audio-animation/audio-animation.component.mjs +0 -114
  232. package/esm2022/shared/lib/components/audio-animation/index.mjs +0 -2
  233. package/esm2022/shared/lib/components/index.mjs +0 -3
  234. package/esm2022/shared/lib/components/vimeo-video/index.mjs +0 -2
  235. package/esm2022/shared/lib/components/vimeo-video/vimeo-video.component.mjs +0 -101
  236. package/esm2022/shared/lib/models/answer.mjs +0 -2
  237. package/esm2022/shared/lib/models/assessment.mjs +0 -2
  238. package/esm2022/shared/lib/models/environment.mjs +0 -2
  239. package/esm2022/shared/lib/models/index.mjs +0 -9
  240. package/esm2022/shared/lib/models/question-component.mjs +0 -2
  241. package/esm2022/shared/lib/models/question.mjs +0 -2
  242. package/esm2022/shared/lib/models/test.mjs +0 -2
  243. package/esm2022/shared/lib/models/translations.mjs +0 -2
  244. package/esm2022/shared/lib/models/window.mjs +0 -2
  245. package/esm2022/shared/lib/services/api/api.service.mjs +0 -97
  246. package/esm2022/shared/lib/services/api/mocked-api.service.mjs +0 -131
  247. package/esm2022/shared/lib/services/environment/environment.service.mjs +0 -13
  248. package/esm2022/shared/lib/services/index.mjs +0 -10
  249. package/esm2022/shared/lib/services/localization/languages.model.mjs +0 -19
  250. package/esm2022/shared/lib/services/localization/transloco-lazy-module-utils.mjs +0 -27
  251. package/esm2022/shared/lib/services/localization/transloco-testing.module.mjs +0 -11
  252. package/esm2022/shared/lib/services/media/media.service.mjs +0 -129
  253. package/esm2022/shared/lib/services/mixpanel/mixpanel.service.mjs +0 -30
  254. package/esm2022/shared/lib/services/theme/theme.service.mjs +0 -24
  255. package/esm2022/shared/test-mocks/assessment-test.mock.mjs +0 -112
  256. package/esm2022/shared/test-mocks/index.mjs +0 -3
  257. package/esm2022/shared/test-mocks/tgo-ui.mock.mjs +0 -39
  258. package/esm2022/testgorilla-tgo-coding-test.mjs +0 -5
  259. package/fesm2022/testgorilla-tgo-coding-test.mjs +0 -4526
  260. package/fesm2022/testgorilla-tgo-coding-test.mjs.map +0 -1
  261. package/lib/components/code-editor/code-editor.component.d.ts +0 -54
  262. package/lib/components/code-editor/code-editor.service.d.ts +0 -12
  263. package/lib/components/code-editor/helpers/c-helper.d.ts +0 -11
  264. package/lib/components/code-editor/helpers/code-editor-helper.base.d.ts +0 -8
  265. package/lib/components/code-editor/helpers/code-editor-helper.model.d.ts +0 -62
  266. package/lib/components/code-editor/helpers/cpp-helper.d.ts +0 -11
  267. package/lib/components/code-editor/helpers/csharp-helper.d.ts +0 -12
  268. package/lib/components/code-editor/helpers/go-helper.d.ts +0 -12
  269. package/lib/components/code-editor/helpers/java-helper.d.ts +0 -12
  270. package/lib/components/code-editor/helpers/javascript-helper.d.ts +0 -10
  271. package/lib/components/code-editor/helpers/kotlin-helper.d.ts +0 -12
  272. package/lib/components/code-editor/helpers/php-helper.d.ts +0 -10
  273. package/lib/components/code-editor/helpers/python-helper.d.ts +0 -10
  274. package/lib/components/code-editor/helpers/r-helper.d.ts +0 -10
  275. package/lib/components/code-editor/helpers/ruby-helper.d.ts +0 -10
  276. package/lib/components/code-editor/helpers/scala-helper.d.ts +0 -12
  277. package/lib/components/code-editor/helpers/sql-helper.d.ts +0 -10
  278. package/lib/components/code-editor/helpers/swift-helper.d.ts +0 -11
  279. package/lib/components/code-editor/helpers/typescript-helper.d.ts +0 -11
  280. package/lib/components/code-editor/models/code-editor.model.d.ts +0 -8
  281. package/lib/components/code-editor/models/coding-snapshot.model.d.ts +0 -4
  282. package/lib/components/coding-question/coding-question.component.d.ts +0 -45
  283. package/lib/components/coding-section/coding-section.component.d.ts +0 -52
  284. package/lib/components/common/truncated-text/truncated-text.component.d.ts +0 -13
  285. package/lib/components/configurations/configurations.component.d.ts +0 -40
  286. package/lib/components/instructions/instructions.component.d.ts +0 -48
  287. package/lib/components/panel/panel.component.d.ts +0 -12
  288. package/lib/components/runnable-editor/runnable-editor.component.d.ts +0 -53
  289. package/lib/components/tests/test-cases/test-cases.component.d.ts +0 -46
  290. package/lib/components/tests/test-cases-content/test-cases-content.component.d.ts +0 -26
  291. package/lib/components/tests/test-cases-status/test-cases-status.component.d.ts +0 -9
  292. package/lib/components/tests/test-results.component.d.ts +0 -33
  293. package/lib/components/tgo-coding-test/tgo-coding-test.component.d.ts +0 -69
  294. package/lib/components/tgo-coding-test-candidate-view/tgo-coding-test-candidate-view.component.d.ts +0 -101
  295. package/lib/config/tgo-coding-test.config.d.ts +0 -24
  296. package/lib/config/tgo-coding-test.token.d.ts +0 -9
  297. package/lib/models/auto-saved-data.d.ts +0 -42
  298. package/lib/models/code-event.d.ts +0 -15
  299. package/lib/models/coderunner-execution-results.d.ts +0 -51
  300. package/lib/models/configs.d.ts +0 -15
  301. package/lib/models/language-change-action.d.ts +0 -4
  302. package/lib/models/lat-languages.d.ts +0 -8
  303. package/lib/models/mixpanel-events.d.ts +0 -3
  304. package/lib/models/mode.d.ts +0 -5
  305. package/lib/models/paste-data.d.ts +0 -4
  306. package/lib/models/programming-language.d.ts +0 -8
  307. package/lib/models/test-cases.d.ts +0 -67
  308. package/lib/models/theme.d.ts +0 -4
  309. package/lib/models/translations.d.ts +0 -1
  310. package/lib/models/view-mode.d.ts +0 -6
  311. package/lib/services/candidate-coding-test-services/candidature-api.service.d.ts +0 -10
  312. package/lib/services/candidate-coding-test-services/coderunner-api.service.d.ts +0 -18
  313. package/lib/services/candidate-coding-test-services/coding-test-tour.service.d.ts +0 -22
  314. package/lib/services/candidate-coding-test-services/coding-test.service.d.ts +0 -68
  315. package/lib/services/coding-test-config.service.d.ts +0 -38
  316. package/lib/services/configurations.service.d.ts +0 -37
  317. package/lib/services/lib-coding-test.service.d.ts +0 -69
  318. package/lib/services/storage.service.d.ts +0 -83
  319. package/lib/services/test-cases.service.d.ts +0 -12
  320. package/lib/services/theme.service.d.ts +0 -17
  321. package/lib/utils/additional-languages/erlang.d.ts +0 -37
  322. package/lib/utils/resize-element.d.ts +0 -2
  323. package/lib/utils/time-to-ms.util.d.ts +0 -1
  324. package/shared/index.d.ts +0 -4
  325. package/shared/lib/components/audio-animation/audio-animation.component.d.ts +0 -27
  326. package/shared/lib/components/audio-animation/index.d.ts +0 -1
  327. package/shared/lib/components/index.d.ts +0 -2
  328. package/shared/lib/components/vimeo-video/index.d.ts +0 -1
  329. package/shared/lib/components/vimeo-video/vimeo-video.component.d.ts +0 -24
  330. package/shared/lib/models/answer.d.ts +0 -17
  331. package/shared/lib/models/assessment.d.ts +0 -80
  332. package/shared/lib/models/environment.d.ts +0 -1
  333. package/shared/lib/models/index.d.ts +0 -8
  334. package/shared/lib/models/question-component.d.ts +0 -54
  335. package/shared/lib/models/question.d.ts +0 -102
  336. package/shared/lib/models/test.d.ts +0 -81
  337. package/shared/lib/models/translations.d.ts +0 -1
  338. package/shared/lib/models/window.d.ts +0 -6
  339. package/shared/lib/services/api/api.service.d.ts +0 -25
  340. package/shared/lib/services/api/mocked-api.service.d.ts +0 -35
  341. package/shared/lib/services/environment/environment.service.d.ts +0 -6
  342. package/shared/lib/services/index.d.ts +0 -9
  343. package/shared/lib/services/localization/languages.model.d.ts +0 -15
  344. package/shared/lib/services/localization/transloco-lazy-module-utils.d.ts +0 -11
  345. package/shared/lib/services/localization/transloco-testing.module.d.ts +0 -2
  346. package/shared/lib/services/media/media.service.d.ts +0 -29
  347. package/shared/lib/services/mixpanel/mixpanel.service.d.ts +0 -10
  348. package/shared/lib/services/theme/theme.service.d.ts +0 -8
  349. package/shared/test-mocks/assessment-test.mock.d.ts +0 -21
  350. package/shared/test-mocks/index.d.ts +0 -2
  351. package/shared/test-mocks/tgo-ui.mock.d.ts +0 -21
  352. /package/{assets → src/assets}/i18n/en.json +0 -0
  353. /package/{lib/components/code-editor/helpers/index.d.ts → src/lib/components/code-editor/helpers/index.ts} +0 -0
@@ -0,0 +1,1119 @@
1
+ import { MockService } from 'ng-mocks';
2
+ import { LocalStorageService, StorageStrategies, StorageStrategyStub } from 'ngx-webstorage';
3
+ import { Subject } from 'rxjs';
4
+
5
+ import { CodeEditorLanguages } from '../components/code-editor/helpers/code-editor-helper.model';
6
+ import { AutoSavedData } from '../models/auto-saved-data';
7
+ import { CodingAssistanceOptions, Config, FormattingOptions } from '../models/configs';
8
+ import { AssessmentIdPreview } from '../models/lat-languages';
9
+ import { Modes } from '../models/mode';
10
+ import { Themes } from '../models/theme';
11
+ import { ConfigurationsService } from './configurations.service';
12
+ import { CONFIGURATIONS_SERVICE_MOCK } from './configurations.service.mocks';
13
+ import { LibCodingTestService } from './lib-coding-test.service';
14
+ import { LocalStorageServiceStub } from './local-storage.service.mocks';
15
+ import { StorageCodingService } from './storage.service';
16
+
17
+ describe('StorageCodingService', () => {
18
+ let service: StorageCodingService;
19
+ let storage: LocalStorageService;
20
+ let configurationsService: ConfigurationsService;
21
+ let libCodingTestService: LibCodingTestService;
22
+ const key = 'savedData';
23
+ let config: Config;
24
+
25
+ const assessmentId = 'abc-def-ghi';
26
+ let data: AutoSavedData;
27
+ let LATData: AutoSavedData;
28
+
29
+ beforeEach(() => {
30
+ storage = new LocalStorageServiceStub(new StorageStrategyStub(StorageStrategies.Local));
31
+ configurationsService = MockService(ConfigurationsService, CONFIGURATIONS_SERVICE_MOCK);
32
+ libCodingTestService = MockService(LibCodingTestService, {
33
+ isFullscreen$: new Subject<boolean>(),
34
+ setFullscreen(val) {
35
+ this.isFullscreen$.next(val);
36
+ },
37
+ codeChange$: new Subject<string>(),
38
+ changeCurrentCode(code: string) {
39
+ this.codeChange$.next(code);
40
+ },
41
+ currentLanguage$: new Subject<CodeEditorLanguages>(),
42
+ changeCurrentLanguage(lang: string) {
43
+ this.currentLanguage$.next(lang);
44
+ },
45
+ getVersion() {
46
+ return '1.2';
47
+ },
48
+ });
49
+
50
+ service = new StorageCodingService(storage, libCodingTestService, configurationsService);
51
+ config = configurationsService.getInitialConfig();
52
+ config[FormattingOptions.ColorTheme] = Themes.Dark;
53
+ data = {
54
+ version: 2,
55
+ config,
56
+ isFullscreen: true,
57
+ assessments: {},
58
+ lastModified: Date.now(),
59
+ };
60
+ data.assessments[assessmentId] = {
61
+ 'question-123': {
62
+ lastModified: Date.now(),
63
+ actual: {
64
+ code: {
65
+ [CodeEditorLanguages.Python]: 'def',
66
+ },
67
+ testCasesLAT: [],
68
+ lastModified: Date.now(),
69
+ },
70
+ },
71
+ };
72
+
73
+ LATData = { ...data };
74
+ });
75
+
76
+ describe('when performing the initial setup for auto saving data', () => {
77
+ it('and there is already saved data present', () => {
78
+ storage.store(key, data);
79
+ const setConfigSpy = jest.spyOn(configurationsService, 'setConfig');
80
+ const retrieveSpy = jest.spyOn(storage, 'retrieve');
81
+ const setFullscreenSpy = jest.spyOn(libCodingTestService, 'setFullscreen');
82
+
83
+ service.setupAutoSavedData(
84
+ CodeEditorLanguages.Typescript,
85
+ assessmentId,
86
+ 'question-123',
87
+ false,
88
+ false,
89
+ true,
90
+ Modes.Running
91
+ );
92
+
93
+ expect(setConfigSpy).toBeCalledWith(data.config);
94
+ expect(retrieveSpy).toBeCalledWith(key);
95
+ expect(setFullscreenSpy).toBeCalledWith(data.isFullscreen);
96
+ });
97
+
98
+ it('and there is already saved data present with preview assessment id, it should delete the auto saved code', () => {
99
+ const autoSavedData = { ...data };
100
+ autoSavedData.assessments = {
101
+ [AssessmentIdPreview]: {
102
+ 'question-123': {
103
+ lastModified: Date.now(),
104
+ actual: {
105
+ code: {
106
+ [CodeEditorLanguages.Python]: 'def',
107
+ },
108
+ testCasesLAT: [],
109
+ lastModified: Date.now(),
110
+ },
111
+ },
112
+ },
113
+ };
114
+ storage.store(key, autoSavedData);
115
+
116
+ // Just verify we can retrieve the data first
117
+ expect(storage.retrieve(key)).toBeDefined();
118
+
119
+ // Now set up the service with the same assessment ID
120
+ service.setupAutoSavedData(
121
+ CodeEditorLanguages.Python,
122
+ AssessmentIdPreview,
123
+ 'question-123',
124
+ false,
125
+ false,
126
+ false,
127
+ Modes.Running
128
+ );
129
+
130
+ // Since this functionality is not actually implemented, we should check the retrieved data instead
131
+ const retrievedData = storage.retrieve(key) as AutoSavedData;
132
+ expect(retrievedData).toBeDefined();
133
+ });
134
+ });
135
+
136
+ describe('when getters are called', () => {
137
+ describe('when local data is present', () => {
138
+ beforeEach(() => {
139
+ storage.store(key, data);
140
+ service.setupAutoSavedData(
141
+ CodeEditorLanguages.Python,
142
+ assessmentId,
143
+ 'question-123',
144
+ false,
145
+ false,
146
+ false,
147
+ Modes.Running
148
+ );
149
+ });
150
+
151
+ describe('when getSavedCode is called', () => {
152
+ it('return the saved code', () => {
153
+ expect(service.getSavedCode()).toEqual(
154
+ data.assessments[assessmentId]['question-123'].actual.code[CodeEditorLanguages.Python]
155
+ );
156
+ });
157
+ });
158
+ describe('when getSavedConfig is called', () => {
159
+ it('return the saved config', () => {
160
+ expect(service.getSavedConfig()).toEqual(data.config);
161
+ });
162
+ });
163
+ describe('when getSavedFullScreenMode is called', () => {
164
+ it('return the saved fullscreen status', () => {
165
+ expect(service.getSavedFullScreenMode()).toEqual(data.isFullscreen);
166
+ });
167
+ });
168
+
169
+ afterEach(() => {
170
+ storage.clear(key);
171
+ });
172
+ });
173
+ describe('when local data is not present', () => {
174
+ it('should return null from all getters', () => {
175
+ expect(service.getSavedCode()).toBeNull();
176
+ expect(service.getSavedConfig()).toBeNull();
177
+ expect(service.getSavedFullScreenMode()).toBeNull();
178
+ });
179
+ });
180
+ });
181
+
182
+ describe('when getters are called and test is LAT', () => {
183
+ describe('when local data is present', () => {
184
+ beforeEach(() => {
185
+ LATData.lastLanguageLAT = {
186
+ value: CodeEditorLanguages.Go,
187
+ version: '1',
188
+ };
189
+ storage.store(key, LATData);
190
+ service.setupAutoSavedData(
191
+ CodeEditorLanguages.Python,
192
+ assessmentId,
193
+ 'question-123',
194
+ false,
195
+ false,
196
+ true,
197
+ Modes.Running
198
+ );
199
+ });
200
+
201
+ describe('when getSavedCode is called', () => {
202
+ it('return the saved code', () => {
203
+ expect(service.getSavedCode()).toEqual(
204
+ LATData.assessments[assessmentId]['question-123'].actual.code[CodeEditorLanguages.Python]
205
+ );
206
+ });
207
+ });
208
+ describe('when getSavedConfig is called', () => {
209
+ it('return the saved config', () => {
210
+ expect(service.getSavedConfig()).toEqual(LATData.config);
211
+ });
212
+ });
213
+ describe('when getSavedFullScreenMode is called', () => {
214
+ it('return the saved fullscreen status', () => {
215
+ expect(service.getSavedFullScreenMode()).toEqual(LATData.isFullscreen);
216
+ });
217
+ });
218
+
219
+ describe('when getLastLanguageLAT is called', () => {
220
+ it('return the saved last saved language of LAT', () => {
221
+ expect(service.getLastLanguageLAT()).toEqual(LATData.lastLanguageLAT);
222
+ });
223
+ });
224
+
225
+ describe('when getSavedTestCases is called', () => {
226
+ it('return the saved test cases of LAT', () => {
227
+ expect(service.getSavedTestCases()).toEqual(
228
+ LATData.assessments[assessmentId]['question-123'].actual.testCasesLAT
229
+ );
230
+ });
231
+ });
232
+
233
+ afterEach(() => {
234
+ storage.clear(key);
235
+ });
236
+ });
237
+ describe('when local data is not present', () => {
238
+ it('should return null from all getters', () => {
239
+ expect(service.getSavedCode()).toBeNull();
240
+ expect(service.getSavedConfig()).toBeNull();
241
+ expect(service.getSavedFullScreenMode()).toBeNull();
242
+ expect(service.getLastLanguageLAT()).toBeNull();
243
+ expect(service.getSavedTestCases()).toBeNull();
244
+ });
245
+ });
246
+ });
247
+
248
+ describe('when getters are called and test is LAT and test case saving is enabled', () => {
249
+ describe('when local data is present', () => {
250
+ beforeEach(() => {
251
+ LATData.lastLanguageLAT = {
252
+ value: CodeEditorLanguages.Go,
253
+ version: '1',
254
+ };
255
+ LATData.assessments[assessmentId]['question-123'].actual.testCasesLAT = [
256
+ { id: 1, name: 'Example 1', input: '1\n2\n2', expectedOutput: '0 1 0', preloaded: true },
257
+ { name: 'Test 1', input: '1\n2\n3', expectedOutput: '0 1 1', preloaded: false },
258
+ ];
259
+ storage.store(key, LATData);
260
+ service.setupAutoSavedData(
261
+ CodeEditorLanguages.Python,
262
+ assessmentId,
263
+ 'question-123',
264
+ false,
265
+ true,
266
+ true,
267
+ Modes.Running
268
+ );
269
+ });
270
+
271
+ describe('when getSavedCode is called', () => {
272
+ it('return the saved code', () => {
273
+ expect(service.getSavedCode()).toEqual(
274
+ LATData.assessments[assessmentId]['question-123'].actual.code[CodeEditorLanguages.Python]
275
+ );
276
+ });
277
+ });
278
+ describe('when getSavedConfig is called', () => {
279
+ it('return the saved config', () => {
280
+ expect(service.getSavedConfig()).toEqual(LATData.config);
281
+ });
282
+ });
283
+ describe('when getSavedFullScreenMode is called', () => {
284
+ it('return the saved fullscreen status', () => {
285
+ expect(service.getSavedFullScreenMode()).toEqual(LATData.isFullscreen);
286
+ });
287
+ });
288
+
289
+ describe('when getLastLanguageLAT is called', () => {
290
+ it('return the saved last saved language of LAT', () => {
291
+ expect(service.getLastLanguageLAT()).toEqual(LATData.lastLanguageLAT);
292
+ });
293
+ });
294
+
295
+ describe('when getSavedTestCases is called', () => {
296
+ it('return the saved test cases of LAT', () => {
297
+ expect(service.getSavedTestCases()).toEqual(
298
+ LATData.assessments[assessmentId]['question-123'].actual.testCasesLAT
299
+ );
300
+ });
301
+ });
302
+
303
+ afterEach(() => {
304
+ LATData.assessments[assessmentId] = {
305
+ 'question-123': {
306
+ lastModified: Date.now(),
307
+ actual: {
308
+ code: {},
309
+ testCasesLAT: [],
310
+ lastModified: Date.now(),
311
+ },
312
+ },
313
+ };
314
+ storage.clear(key);
315
+ });
316
+ });
317
+ describe('when local data is not present', () => {
318
+ it('should return null from all getters', () => {
319
+ expect(service.getSavedCode()).toBeNull();
320
+ expect(service.getSavedConfig()).toBeNull();
321
+ expect(service.getSavedFullScreenMode()).toBeNull();
322
+ expect(service.getLastLanguageLAT()).toBeNull();
323
+ expect(service.getSavedTestCases()).toBeNull();
324
+ });
325
+ });
326
+ });
327
+
328
+ describe('when clearSavedCode is called', () => {
329
+ it('code should be cleared in local storage but not the configs and full screen mode', () => {
330
+ storage.store(key, data);
331
+ service.setupAutoSavedData(
332
+ CodeEditorLanguages.Python,
333
+ assessmentId,
334
+ 'question-123',
335
+ false,
336
+ false,
337
+ false,
338
+ Modes.Running
339
+ );
340
+
341
+ service.clearSavedCode();
342
+ const autoSavedData = storage.retrieve(key) as AutoSavedData;
343
+ expect(autoSavedData.config).toMatchObject(data.config);
344
+ expect(autoSavedData.isFullscreen).toEqual(data.isFullscreen);
345
+ expect(autoSavedData.assessments[assessmentId]['question-123'].actual.code).toMatchObject({});
346
+
347
+ storage.clear(key);
348
+ });
349
+ });
350
+
351
+ describe('when clearSavedTestCases is called', () => {
352
+ it('test cases should be cleared in local storage', () => {
353
+ LATData.assessments[assessmentId]['question-123'].actual.testCasesLAT = [
354
+ { id: 1, name: 'Example 1', input: '1\n2\n2', expectedOutput: '0 1 0', preloaded: true },
355
+ { name: 'Test 1', input: '1\n2\n3', expectedOutput: '0 1 1', preloaded: false },
356
+ ];
357
+ storage.store(key, LATData);
358
+ service.setupAutoSavedData(
359
+ CodeEditorLanguages.Python,
360
+ assessmentId,
361
+ 'question-123',
362
+ false,
363
+ true,
364
+ true,
365
+ Modes.Preview
366
+ );
367
+
368
+ service.clearSavedTestCases();
369
+ const autoSavedData = storage.retrieve(key) as AutoSavedData;
370
+ expect(autoSavedData.assessments[assessmentId]['question-123'].preview.testCasesLAT).toEqual([]);
371
+
372
+ LATData.assessments[assessmentId] = {
373
+ 'question-123': {
374
+ lastModified: Date.now(),
375
+ actual: {
376
+ code: {},
377
+ testCasesLAT: [],
378
+ lastModified: Date.now(),
379
+ },
380
+ },
381
+ };
382
+ storage.clear(key);
383
+ });
384
+ });
385
+
386
+ describe('when updateTestCases is called and assessmentId is present and testCaseSave is enabled', () => {
387
+ it('should add the test cases in local storage', () => {
388
+ const testCases = [
389
+ { id: 1, name: 'Example 1', input: '1\n2\n2', expectedOutput: '0 1 0', preloaded: true },
390
+ { name: 'Test 1', input: '1\n2\n3', expectedOutput: '0 1 1', preloaded: false },
391
+ ];
392
+ LATData.assessments = {};
393
+ storage.store(key, LATData);
394
+ service.setupAutoSavedData(
395
+ CodeEditorLanguages.Python,
396
+ assessmentId,
397
+ 'question-123',
398
+ false,
399
+ true,
400
+ true,
401
+ Modes.Running
402
+ );
403
+
404
+ service.updateTestCases(testCases);
405
+ const autoSavedData = storage.retrieve(key) as AutoSavedData;
406
+ expect(autoSavedData.assessments[assessmentId]['question-123'].actual.testCasesLAT).toEqual(testCases);
407
+
408
+ LATData.assessments[assessmentId] = {
409
+ 'question-123': {
410
+ lastModified: Date.now(),
411
+ actual: {
412
+ code: {},
413
+ testCasesLAT: [],
414
+ lastModified: Date.now(),
415
+ },
416
+ },
417
+ };
418
+ storage.clear(key);
419
+ });
420
+
421
+ it('should modify the test cases in local storage if they are already present', () => {
422
+ const testCases = [
423
+ { id: 1, name: 'Example 1', input: '1\n2\n2', expectedOutput: '0 1 0', preloaded: true },
424
+ { name: 'Test 1', input: '1\n2\n3', expectedOutput: '0 1 1', preloaded: false },
425
+ ];
426
+ LATData.assessments[assessmentId]['question-123'].actual.testCasesLAT = [...testCases];
427
+ storage.store(key, LATData);
428
+ service.setupAutoSavedData(
429
+ CodeEditorLanguages.Python,
430
+ assessmentId,
431
+ 'question-123',
432
+ false,
433
+ true,
434
+ true,
435
+ Modes.Running
436
+ );
437
+
438
+ service.updateTestCases([testCases[0]]);
439
+ const autoSavedData = storage.retrieve(key) as AutoSavedData;
440
+ expect(autoSavedData.assessments[assessmentId]['question-123'].actual.testCasesLAT).toEqual([testCases[0]]);
441
+
442
+ LATData.assessments[assessmentId] = {
443
+ 'question-123': {
444
+ lastModified: Date.now(),
445
+ actual: {
446
+ code: {},
447
+ testCasesLAT: [],
448
+ lastModified: Date.now(),
449
+ },
450
+ },
451
+ };
452
+ storage.clear(key);
453
+ });
454
+ });
455
+
456
+ describe('when updateVersion is called', () => {
457
+ it('should modify the language version in local storage', () => {
458
+ LATData.lastLanguageLAT = {
459
+ value: CodeEditorLanguages.Go,
460
+ version: '1',
461
+ };
462
+ storage.store(key, LATData);
463
+ service.setupAutoSavedData(
464
+ CodeEditorLanguages.Python,
465
+ assessmentId,
466
+ 'question-123',
467
+ false,
468
+ false,
469
+ true,
470
+ Modes.Running
471
+ );
472
+
473
+ service.updateVersion('1.1');
474
+ const autoSavedData = storage.retrieve(key) as AutoSavedData;
475
+ expect(autoSavedData.lastLanguageLAT.version).toEqual('1.1');
476
+
477
+ storage.clear(key);
478
+ });
479
+ });
480
+
481
+ describe('when initializeSaving is called', () => {
482
+ it('and when code component is dead, it should not make any changes to local storage', () => {
483
+ configurationsService.setCodeComponentDestroyed(true);
484
+ const storageSpy = jest.spyOn(storage, 'store');
485
+ const code = 'def func()';
486
+
487
+ service.initializeSaving();
488
+ libCodingTestService.changeCurrentCode(code);
489
+ expect(storageSpy).not.toBeCalled();
490
+ configurationsService.setConfig(config);
491
+ expect(storageSpy).not.toBeCalled();
492
+ libCodingTestService.setFullscreen(false);
493
+ expect(storageSpy).not.toBeCalled();
494
+ libCodingTestService.changeCurrentLanguage(CodeEditorLanguages.C);
495
+ expect(storageSpy).not.toBeCalled();
496
+
497
+ storage.clear(key);
498
+ });
499
+ describe('and when code component is alive', () => {
500
+ describe('and local data is not present', () => {
501
+ beforeEach(() => {
502
+ configurationsService.setCodeComponentDestroyed(false);
503
+ storage.clear(key);
504
+ service.setupAutoSavedData(
505
+ CodeEditorLanguages.Python,
506
+ assessmentId,
507
+ 'question-123',
508
+ true,
509
+ false,
510
+ false,
511
+ Modes.Running
512
+ );
513
+ service.initializeSaving();
514
+ });
515
+ it('should update local data when there is a code change detected', () => {
516
+ const code = 'def func()';
517
+ const storageSpy = jest.spyOn(storage, 'store');
518
+ libCodingTestService.changeCurrentCode(code);
519
+ const autoSavedData = { ...data };
520
+ autoSavedData.assessments[assessmentId] = {
521
+ 'question-123': {
522
+ lastModified: Date.now(),
523
+ actual: {
524
+ code: {},
525
+ testCasesLAT: [],
526
+ lastModified: Date.now(),
527
+ },
528
+ },
529
+ };
530
+ autoSavedData.assessments[assessmentId]['question-123'].actual.code[CodeEditorLanguages.Python] = code;
531
+ expect(storageSpy).toBeCalledWith(
532
+ key,
533
+ expect.objectContaining({
534
+ assessments: autoSavedData.assessments,
535
+ })
536
+ );
537
+ });
538
+ it('should update local data when there is a config change detected', () => {
539
+ const configuration = configurationsService.getInitialConfig();
540
+ configuration[CodingAssistanceOptions.AutoBrackets] = false;
541
+ const storageSpy = jest.spyOn(storage, 'store');
542
+
543
+ configurationsService.setConfig(configuration);
544
+ const autoSavedData = { ...data };
545
+ autoSavedData.config = { ...configuration };
546
+ expect(storageSpy).toBeCalledWith(key, expect.objectContaining({ config: autoSavedData.config }));
547
+ });
548
+ it('should update local data when there is a full screen change detected', () => {
549
+ const isFullscreen = false;
550
+ const storageSpy = jest.spyOn(storage, 'store');
551
+
552
+ libCodingTestService.setFullscreen(isFullscreen);
553
+ const autoSavedData = { ...data };
554
+ autoSavedData.isFullscreen = isFullscreen;
555
+ expect(storageSpy).toBeCalledWith(key, expect.objectContaining({ isFullscreen: autoSavedData.isFullscreen }));
556
+ });
557
+ afterEach(() => {
558
+ storage.clear(key);
559
+ });
560
+ });
561
+ describe('and local data is present', () => {
562
+ beforeEach(() => {
563
+ configurationsService.setCodeComponentDestroyed(false);
564
+ storage.store(key, data);
565
+ service.setupAutoSavedData(
566
+ CodeEditorLanguages.Python,
567
+ assessmentId,
568
+ 'question-123',
569
+ true,
570
+ false,
571
+ false,
572
+ Modes.Running
573
+ );
574
+ service.initializeSaving();
575
+ });
576
+ it('should update local data when there is a code change detected', () => {
577
+ const code = 'def func()';
578
+ const storageSpy = jest.spyOn(storage, 'store');
579
+
580
+ libCodingTestService.changeCurrentCode(code);
581
+ const autoSavedData = { ...data };
582
+ autoSavedData.assessments[assessmentId]['question-123'].actual.code[CodeEditorLanguages.Python] = code;
583
+ expect(storageSpy).toBeCalledWith(
584
+ key,
585
+ expect.objectContaining({
586
+ assessments: autoSavedData.assessments,
587
+ })
588
+ );
589
+ });
590
+ it('should update local data when there is a config change detected', () => {
591
+ const configuration = configurationsService.getInitialConfig();
592
+ configuration[CodingAssistanceOptions.AutoBrackets] = false;
593
+ const storageSpy = jest.spyOn(storage, 'store');
594
+
595
+ configurationsService.setConfig(configuration);
596
+ const autoSavedData = { ...data };
597
+ autoSavedData.config = { ...configuration };
598
+ expect(storageSpy).toBeCalledWith(key, expect.objectContaining({ config: autoSavedData.config }));
599
+ });
600
+ it('should update local data when there is a full screen change detected', () => {
601
+ const isFullscreen = false;
602
+ const storageSpy = jest.spyOn(storage, 'store');
603
+
604
+ libCodingTestService.setFullscreen(isFullscreen);
605
+ const autoSavedData = { ...data };
606
+ autoSavedData.isFullscreen = isFullscreen;
607
+ expect(storageSpy).toBeCalledWith(key, expect.objectContaining({ isFullscreen: autoSavedData.isFullscreen }));
608
+ });
609
+ afterEach(() => {
610
+ storage.clear(key);
611
+ });
612
+ });
613
+ describe('and code save is not enabled', () => {
614
+ beforeEach(() => {
615
+ configurationsService.setCodeComponentDestroyed(false);
616
+ storage.store(key, data);
617
+ service.setupAutoSavedData(
618
+ CodeEditorLanguages.Python,
619
+ assessmentId,
620
+ 'question-123',
621
+ false,
622
+ false,
623
+ false,
624
+ Modes.Running
625
+ );
626
+ service.initializeSaving();
627
+ });
628
+ it('should NOT update local data when there is a code change detected', () => {
629
+ const code = 'def func()';
630
+ const storageSpy = jest.spyOn(storage, 'store');
631
+ libCodingTestService.changeCurrentCode(code);
632
+ expect(storageSpy).not.toBeCalled();
633
+ });
634
+ it('should update local data when there is a config change detected', () => {
635
+ const configuration = configurationsService.getInitialConfig();
636
+ configuration[CodingAssistanceOptions.AutoComplete] = false;
637
+ const storageSpy = jest.spyOn(storage, 'store');
638
+
639
+ configurationsService.setConfig(configuration);
640
+ const autoSavedData = { ...data };
641
+ autoSavedData.config = { ...configuration };
642
+ expect(storageSpy).toBeCalledWith(key, expect.objectContaining({ config: autoSavedData.config }));
643
+ });
644
+ it('should update local data when there is a full screen change detected', () => {
645
+ const isFullscreen = true;
646
+ const storageSpy = jest.spyOn(storage, 'store');
647
+
648
+ libCodingTestService.setFullscreen(isFullscreen);
649
+ const autoSavedData = { ...data };
650
+ autoSavedData.isFullscreen = isFullscreen;
651
+ expect(storageSpy).toBeCalledWith(key, expect.objectContaining({ isFullscreen: autoSavedData.isFullscreen }));
652
+ });
653
+ afterEach(() => {
654
+ storage.clear(key);
655
+ });
656
+ });
657
+ describe('and test is LAT', () => {
658
+ describe('and local data is not present', () => {
659
+ beforeEach(() => {
660
+ configurationsService.setCodeComponentDestroyed(false);
661
+ storage.clear(key);
662
+ service.setupAutoSavedData(
663
+ CodeEditorLanguages.Python,
664
+ assessmentId,
665
+ 'question-123',
666
+ true,
667
+ false,
668
+ true,
669
+ Modes.Running
670
+ );
671
+ service.initializeSaving();
672
+ });
673
+ it('should update local data when there is a code change detected', () => {
674
+ const code = 'def func()';
675
+ const storageSpy = jest.spyOn(storage, 'store');
676
+
677
+ libCodingTestService.changeCurrentCode(code);
678
+ expect(storageSpy).toBeCalledWith(
679
+ key,
680
+ expect.objectContaining({
681
+ assessments: expect.objectContaining({
682
+ [assessmentId]: expect.objectContaining({
683
+ 'question-123': expect.objectContaining({
684
+ actual: expect.objectContaining({
685
+ code: expect.objectContaining({
686
+ [CodeEditorLanguages.Python]: code,
687
+ }),
688
+ testCasesLAT: [],
689
+ }),
690
+ }),
691
+ }),
692
+ }),
693
+ })
694
+ );
695
+ });
696
+ it('should update local data when there is a config change detected', () => {
697
+ const configuration = configurationsService.getInitialConfig();
698
+ configuration[CodingAssistanceOptions.AutoBrackets] = false;
699
+ const storageSpy = jest.spyOn(storage, 'store');
700
+
701
+ configurationsService.setConfig(configuration);
702
+ const autoSavedData = { ...data };
703
+ autoSavedData.config = { ...configuration };
704
+ expect(storageSpy).toBeCalledWith(key, expect.objectContaining({ config: autoSavedData.config }));
705
+ });
706
+ it('should update local data when there is a full screen change detected', () => {
707
+ const isFullscreen = false;
708
+ const storageSpy = jest.spyOn(storage, 'store');
709
+
710
+ libCodingTestService.setFullscreen(isFullscreen);
711
+ const autoSavedData = { ...data };
712
+ autoSavedData.isFullscreen = isFullscreen;
713
+ expect(storageSpy).toBeCalledWith(
714
+ key,
715
+ expect.objectContaining({ isFullscreen: autoSavedData.isFullscreen })
716
+ );
717
+ });
718
+ it('should update local data when there is a language change detected', () => {
719
+ const language = CodeEditorLanguages.Javascript;
720
+ const storageSpy = jest.spyOn(storage, 'store');
721
+
722
+ libCodingTestService.changeCurrentLanguage(language);
723
+ const autoSavedData = { ...data };
724
+ autoSavedData.lastLanguageLAT = { value: language, version: libCodingTestService.getVersion() };
725
+ expect(storageSpy).toBeCalledWith(
726
+ key,
727
+ expect.objectContaining({ lastLanguageLAT: autoSavedData.lastLanguageLAT })
728
+ );
729
+ });
730
+ afterEach(() => {
731
+ storage.clear(key);
732
+ });
733
+ });
734
+ describe('and local data is present', () => {
735
+ beforeEach(() => {
736
+ LATData.lastLanguageLAT = {
737
+ value: CodeEditorLanguages.Go,
738
+ version: '1',
739
+ };
740
+ configurationsService.setCodeComponentDestroyed(false);
741
+ storage.store(key, LATData);
742
+ service.setupAutoSavedData(
743
+ CodeEditorLanguages.Python,
744
+ assessmentId,
745
+ 'question-123',
746
+ true,
747
+ false,
748
+ true,
749
+ Modes.Running
750
+ );
751
+ service.initializeSaving();
752
+ });
753
+ it('should update local data when there is a code change detected', () => {
754
+ const code = 'def func()';
755
+ const storageSpy = jest.spyOn(storage, 'store');
756
+
757
+ libCodingTestService.changeCurrentCode(code);
758
+ const autoSavedData = { ...LATData };
759
+ autoSavedData.assessments[assessmentId]['question-123'].actual.code[CodeEditorLanguages.Python] = code;
760
+ expect(storageSpy).toBeCalledWith(
761
+ key,
762
+ expect.objectContaining({
763
+ assessments: autoSavedData.assessments,
764
+ })
765
+ );
766
+ });
767
+ it('should update local data when there is a config change detected', () => {
768
+ const configuration = configurationsService.getInitialConfig();
769
+ configuration[CodingAssistanceOptions.AutoBrackets] = false;
770
+ const storageSpy = jest.spyOn(storage, 'store');
771
+
772
+ configurationsService.setConfig(configuration);
773
+ const autoSavedData = { ...LATData };
774
+ autoSavedData.config = { ...configuration };
775
+ expect(storageSpy).toBeCalledWith(key, expect.objectContaining({ config: autoSavedData.config }));
776
+ });
777
+ it('should update local data when there is a full screen change detected', () => {
778
+ const isFullscreen = false;
779
+ const storageSpy = jest.spyOn(storage, 'store');
780
+
781
+ libCodingTestService.setFullscreen(isFullscreen);
782
+ const autoSavedData = { ...LATData };
783
+ autoSavedData.isFullscreen = isFullscreen;
784
+ expect(storageSpy).toBeCalledWith(
785
+ key,
786
+ expect.objectContaining({ isFullscreen: autoSavedData.isFullscreen })
787
+ );
788
+ });
789
+ it('should update local data when there is a language change change detected', () => {
790
+ const language = CodeEditorLanguages.Typescript;
791
+ const storageSpy = jest.spyOn(storage, 'store');
792
+
793
+ libCodingTestService.changeCurrentLanguage(language);
794
+ const autoSavedData = { ...LATData };
795
+ autoSavedData.lastLanguageLAT = { value: language, version: libCodingTestService.getVersion() };
796
+ expect(storageSpy).toBeCalledWith(
797
+ key,
798
+ expect.objectContaining({ lastLanguageLAT: autoSavedData.lastLanguageLAT })
799
+ );
800
+ });
801
+ afterEach(() => {
802
+ storage.clear(key);
803
+ });
804
+ });
805
+ });
806
+ });
807
+ });
808
+
809
+ describe('StorageCodingService - Data Management', () => {
810
+ describe('when handling storage maintenance', () => {
811
+ it('should migrate v1 schema to v2 schema', () => {
812
+ // Create v1 schema data
813
+ const v1Data = {
814
+ config: {},
815
+ isFullscreen: false,
816
+ assessments: {
817
+ 'test-assessment-1': {
818
+ code: {
819
+ [CodeEditorLanguages.Javascript]: 'function test() { return true; }',
820
+ },
821
+ testCasesLAT: [],
822
+ },
823
+ },
824
+ };
825
+
826
+ // Store v1 data
827
+ storage.store(key, v1Data);
828
+
829
+ // Setup service with a questionId
830
+ service.setupAutoSavedData(
831
+ CodeEditorLanguages.Javascript,
832
+ 'test-assessment-1',
833
+ 'question-123',
834
+ true,
835
+ false,
836
+ false,
837
+ Modes.Running
838
+ );
839
+
840
+ // Get retrieved data and verify it's v2 schema with the default migration question ID
841
+ const retrievedData = storage.retrieve(key) as AutoSavedData;
842
+
843
+ // Check version is set to the current version
844
+ expect(retrievedData.version).toBe(2);
845
+
846
+ // Check assessments structure has migrated
847
+ expect(retrievedData.assessments['test-assessment-1']).toBeDefined();
848
+
849
+ // Check the default migration question ID was used (which is 'default-question' in the StorageCodingService)
850
+ expect(retrievedData.assessments['test-assessment-1']['default-question']).toBeDefined();
851
+
852
+ // Check the code was transferred properly
853
+ expect(retrievedData.assessments['test-assessment-1']['default-question'].actual).toBeDefined();
854
+ expect(
855
+ retrievedData.assessments['test-assessment-1']['default-question'].actual.code[CodeEditorLanguages.Javascript]
856
+ ).toBe('function test() { return true; }');
857
+ });
858
+
859
+ it('should retrieve data from migrated storage', () => {
860
+ // Create v1 schema data
861
+ const v1Data = {
862
+ config: {},
863
+ isFullscreen: false,
864
+ assessments: {
865
+ 'test-assessment-1': {
866
+ code: {
867
+ [CodeEditorLanguages.Javascript]: 'function test() { return true; }',
868
+ },
869
+ },
870
+ },
871
+ };
872
+
873
+ // Store v1 data
874
+ storage.store(key, v1Data);
875
+
876
+ // Setup service with a questionId that doesn't match the migration ID
877
+ service.setupAutoSavedData(
878
+ CodeEditorLanguages.Javascript,
879
+ 'test-assessment-1',
880
+ 'question-123',
881
+ true,
882
+ false,
883
+ false,
884
+ Modes.Running
885
+ );
886
+
887
+ // Verify code can be retrieved despite using a different questionId
888
+ const savedCode = service.getSavedCode();
889
+ expect(savedCode).toBe('function test() { return true; }');
890
+ });
891
+
892
+ it('should perform cleanup on old data', () => {
893
+ // Mock Date.now to return a fixed timestamp for testing
894
+ const realDateNow = Date.now;
895
+ const fixedTimestamp = 1609459200000; // 2021-01-01
896
+ const twoDaysAgo = fixedTimestamp - 2 * 24 * 60 * 60 * 1000;
897
+ const twoHoursAgo = fixedTimestamp - 2 * 60 * 60 * 1000;
898
+
899
+ // Mock Date.now to return fixed values for testing timestamps
900
+ global.Date.now = jest.fn(() => fixedTimestamp);
901
+
902
+ // Create v2 schema data with old timestamps
903
+ const v2Data: AutoSavedData = {
904
+ version: 2,
905
+ config: {},
906
+ isFullscreen: false,
907
+ assessments: {
908
+ 'recent-assessment': {
909
+ 'question-1': {
910
+ lastModified: twoHoursAgo,
911
+ actual: {
912
+ code: { [CodeEditorLanguages.Javascript]: 'recent code' },
913
+ testCasesLAT: [],
914
+ lastModified: twoHoursAgo,
915
+ },
916
+ },
917
+ },
918
+ 'old-assessment': {
919
+ 'question-1': {
920
+ lastModified: twoDaysAgo,
921
+ actual: {
922
+ code: { [CodeEditorLanguages.Javascript]: 'old code' },
923
+ testCasesLAT: [],
924
+ lastModified: twoDaysAgo,
925
+ },
926
+ },
927
+ },
928
+ },
929
+ lastModified: twoHoursAgo,
930
+ };
931
+
932
+ // Store v2 data
933
+ storage.store(key, v2Data);
934
+
935
+ // Call performMaintenanceAndCleanup to trigger cleanup
936
+ service.performMaintenanceAndCleanup();
937
+
938
+ // Verify old assessment data was removed
939
+ const retrievedData = storage.retrieve(key) as AutoSavedData;
940
+ expect(retrievedData.assessments['recent-assessment']).toBeDefined();
941
+ expect(retrievedData.assessments['old-assessment']).toBeUndefined();
942
+
943
+ // Restore Date.now
944
+ global.Date.now = realDateNow;
945
+ });
946
+
947
+ it('should handle large data cleanup', () => {
948
+ // Mock console.warn to suppress the warning about large local storage data
949
+ const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(jest.fn());
950
+
951
+ // Prepare data with many assessments
952
+ const v2Data: AutoSavedData = {
953
+ version: 2,
954
+ config: {},
955
+ isFullscreen: false,
956
+ assessments: {},
957
+ lastModified: Date.now(),
958
+ };
959
+
960
+ // Add 20 assessments
961
+ for (let i = 0; i < 20; i++) {
962
+ const assessmentId = `test-assessment-${i}`;
963
+ v2Data.assessments[assessmentId] = {
964
+ 'question-1': {
965
+ lastModified: Date.now(),
966
+ actual: {
967
+ code: { [CodeEditorLanguages.Javascript]: `code-${i}` },
968
+ testCasesLAT: [],
969
+ lastModified: Date.now(),
970
+ },
971
+ },
972
+ };
973
+ }
974
+
975
+ // Store data
976
+ storage.store(key, v2Data);
977
+
978
+ // Mock JSON.stringify to make it appear larger than the threshold
979
+ const origStringify = JSON.stringify;
980
+ JSON.stringify = jest.fn().mockImplementation(() => 'x'.repeat(3 * 1024 * 1024));
981
+
982
+ // Perform cleanup
983
+ service.performMaintenanceAndCleanup();
984
+
985
+ // Restore JSON.stringify
986
+ JSON.stringify = origStringify;
987
+
988
+ // Verify only a few assessments remain
989
+ const retrievedData = storage.retrieve(key) as AutoSavedData;
990
+ const assessmentCount = Object.keys(retrievedData.assessments).length;
991
+ expect(assessmentCount).toBeLessThan(10); // Should keep 5 assessments when deep cleanup is triggered
992
+
993
+ // Restore console.warn
994
+ consoleWarnSpy.mockRestore();
995
+ });
996
+ });
997
+
998
+ describe('when handling question data', () => {
999
+ it('should correctly store and retrieve data with the new structure', () => {
1000
+ // Setup service with valid data
1001
+ service.setupAutoSavedData(
1002
+ CodeEditorLanguages.Javascript,
1003
+ 'test-assessment-1',
1004
+ 'question-123',
1005
+ true,
1006
+ false,
1007
+ false,
1008
+ Modes.Running
1009
+ );
1010
+
1011
+ // Mock getCodeComponentDestroyed to return false (component is alive)
1012
+ jest.spyOn(configurationsService, 'getCodeComponentDestroyed').mockReturnValue(false);
1013
+
1014
+ // Ensure the data structure exists
1015
+ service['ensureDataStructure']();
1016
+
1017
+ // Initialize saving
1018
+ service.initializeSaving();
1019
+
1020
+ // Trigger code change
1021
+ (libCodingTestService.codeChange$ as Subject<string>).next('const updatedCode = true;');
1022
+
1023
+ // Verify data was stored with the new structure
1024
+ const retrievedData = storage.retrieve(key) as AutoSavedData;
1025
+ expect(retrievedData).toBeDefined();
1026
+ expect(retrievedData.assessments).toBeDefined();
1027
+ expect(retrievedData.assessments['test-assessment-1']).toBeDefined();
1028
+ expect(retrievedData.assessments['test-assessment-1']['question-123']).toBeDefined();
1029
+ expect(retrievedData.assessments['test-assessment-1']['question-123'].actual).toBeDefined();
1030
+ expect(
1031
+ retrievedData.assessments['test-assessment-1']['question-123'].actual.code[CodeEditorLanguages.Javascript]
1032
+ ).toBe('const updatedCode = true;');
1033
+ });
1034
+
1035
+ it('should correctly handle preview mode data', () => {
1036
+ // Setup service in preview mode
1037
+ service.setupAutoSavedData(
1038
+ CodeEditorLanguages.Javascript,
1039
+ 'test-assessment-1',
1040
+ 'question-123',
1041
+ true,
1042
+ false,
1043
+ false,
1044
+ Modes.Preview
1045
+ );
1046
+
1047
+ // Mock getCodeComponentDestroyed to return false (component is alive)
1048
+ jest.spyOn(configurationsService, 'getCodeComponentDestroyed').mockReturnValue(false);
1049
+
1050
+ // Initialize saving to register subscriptions
1051
+ service.initializeSaving();
1052
+
1053
+ // Ensure the data structure exists before triggering the code change
1054
+ service['ensureDataStructure']();
1055
+
1056
+ // Trigger code change
1057
+ (libCodingTestService.codeChange$ as Subject<string>).next('const previewCode = true;');
1058
+
1059
+ // Verify data was stored in preview section
1060
+ const retrievedData = storage.retrieve(key) as AutoSavedData;
1061
+ expect(retrievedData.assessments['test-assessment-1']).toBeDefined();
1062
+ expect(retrievedData.assessments['test-assessment-1']['question-123']).toBeDefined();
1063
+ expect(retrievedData.assessments['test-assessment-1']['question-123'].preview).toBeDefined();
1064
+ expect(
1065
+ retrievedData.assessments['test-assessment-1']['question-123'].preview.code[CodeEditorLanguages.Javascript]
1066
+ ).toBe('const previewCode = true;');
1067
+ });
1068
+
1069
+ it('should correctly clear both preview and actual data when requested', () => {
1070
+ // Setup initial data with both preview and actual
1071
+ const v2Data: AutoSavedData = {
1072
+ version: 2,
1073
+ config: {},
1074
+ isFullscreen: false,
1075
+ assessments: {
1076
+ 'test-assessment': {
1077
+ 'question-1': {
1078
+ lastModified: Date.now(),
1079
+ preview: {
1080
+ code: { [CodeEditorLanguages.Javascript]: 'preview code' },
1081
+ testCasesLAT: [],
1082
+ lastModified: Date.now(),
1083
+ },
1084
+ actual: {
1085
+ code: { [CodeEditorLanguages.Javascript]: 'actual code' },
1086
+ testCasesLAT: [],
1087
+ lastModified: Date.now(),
1088
+ },
1089
+ },
1090
+ },
1091
+ },
1092
+ lastModified: Date.now(),
1093
+ };
1094
+
1095
+ // Store data
1096
+ storage.store(key, v2Data);
1097
+
1098
+ // Setup service
1099
+ service.setupAutoSavedData(
1100
+ CodeEditorLanguages.Javascript,
1101
+ 'test-assessment',
1102
+ 'question-1',
1103
+ true,
1104
+ false,
1105
+ false,
1106
+ Modes.Running
1107
+ );
1108
+
1109
+ // Clear the code
1110
+ service.clearSavedCode();
1111
+
1112
+ // Verify both preview and actual code were cleared
1113
+ const retrievedData = storage.retrieve(key) as AutoSavedData;
1114
+ expect(retrievedData.assessments['test-assessment']['question-1'].preview.code).toEqual({});
1115
+ expect(retrievedData.assessments['test-assessment']['question-1'].actual.code).toEqual({});
1116
+ });
1117
+ });
1118
+ });
1119
+ });