@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.
- package/.eslintrc.json +46 -0
- package/jest.config.ts +26 -0
- package/ng-package.json +14 -0
- package/package.json +15 -31
- package/project.json +48 -0
- package/{index.d.ts → src/index.ts} +19 -2
- package/src/lib/components/.gitkeep +0 -0
- package/src/lib/components/code-editor/code-editor.component.html +10 -0
- package/src/lib/components/code-editor/code-editor.component.scss +21 -0
- package/src/lib/components/code-editor/code-editor.component.spec.ts +136 -0
- package/src/lib/components/code-editor/code-editor.component.ts +368 -0
- package/src/lib/components/code-editor/code-editor.mocks.ts +28 -0
- package/src/lib/components/code-editor/code-editor.service.spec.ts +160 -0
- package/src/lib/components/code-editor/code-editor.service.ts +94 -0
- package/src/lib/components/code-editor/helpers/c-helper.spec.ts +39 -0
- package/src/lib/components/code-editor/helpers/c-helper.ts +51 -0
- package/src/lib/components/code-editor/helpers/code-editor-helper.base.spec.ts +30 -0
- package/src/lib/components/code-editor/helpers/code-editor-helper.base.ts +16 -0
- package/src/lib/components/code-editor/helpers/code-editor-helper.mocks.ts +24 -0
- package/src/lib/components/code-editor/helpers/code-editor-helper.model.ts +67 -0
- package/src/lib/components/code-editor/helpers/cpp-helper.spec.ts +40 -0
- package/src/lib/components/code-editor/helpers/cpp-helper.ts +52 -0
- package/src/lib/components/code-editor/helpers/csharp-helper.spec.ts +42 -0
- package/src/lib/components/code-editor/helpers/csharp-helper.ts +55 -0
- package/src/lib/components/code-editor/helpers/go-helper.spec.ts +41 -0
- package/src/lib/components/code-editor/helpers/go-helper.ts +54 -0
- package/src/lib/components/code-editor/helpers/java-helper.spec.ts +41 -0
- package/src/lib/components/code-editor/helpers/java-helper.ts +54 -0
- package/src/lib/components/code-editor/helpers/javascript-helper.spec.ts +39 -0
- package/src/lib/components/code-editor/helpers/javascript-helper.ts +32 -0
- package/src/lib/components/code-editor/helpers/kotlin-helper.spec.ts +41 -0
- package/src/lib/components/code-editor/helpers/kotlin-helper.ts +54 -0
- package/src/lib/components/code-editor/helpers/php-helper.spec.ts +39 -0
- package/src/lib/components/code-editor/helpers/php-helper.ts +32 -0
- package/src/lib/components/code-editor/helpers/python-helper.spec.ts +39 -0
- package/src/lib/components/code-editor/helpers/python-helper.ts +32 -0
- package/src/lib/components/code-editor/helpers/r-helper.spec.ts +39 -0
- package/src/lib/components/code-editor/helpers/r-helper.ts +32 -0
- package/src/lib/components/code-editor/helpers/ruby-helper.spec.ts +39 -0
- package/src/lib/components/code-editor/helpers/ruby-helper.ts +32 -0
- package/src/lib/components/code-editor/helpers/scala-helper.spec.ts +41 -0
- package/src/lib/components/code-editor/helpers/scala-helper.ts +53 -0
- package/src/lib/components/code-editor/helpers/sql-helper.spec.ts +87 -0
- package/src/lib/components/code-editor/helpers/sql-helper.ts +44 -0
- package/src/lib/components/code-editor/helpers/swift-helper.spec.ts +40 -0
- package/src/lib/components/code-editor/helpers/swift-helper.ts +51 -0
- package/src/lib/components/code-editor/helpers/typescript-helper.spec.ts +40 -0
- package/src/lib/components/code-editor/helpers/typescript-helper.ts +52 -0
- package/src/lib/components/code-editor/models/code-editor.model.ts +9 -0
- package/src/lib/components/code-editor/models/coding-snapshot.model.ts +4 -0
- package/src/lib/components/coding-question/coding-question.component.html +78 -0
- package/src/lib/components/coding-question/coding-question.component.scss +75 -0
- package/src/lib/components/coding-question/coding-question.component.spec.ts +85 -0
- package/src/lib/components/coding-question/coding-question.component.ts +101 -0
- package/src/lib/components/coding-section/coding-section.component.html +82 -0
- package/src/lib/components/coding-section/coding-section.component.scss +64 -0
- package/src/lib/components/coding-section/coding-section.component.spec.ts +257 -0
- package/src/lib/components/coding-section/coding-section.component.ts +186 -0
- package/src/lib/components/coding-test.module.ts +124 -0
- package/src/lib/components/common/truncated-text/truncated-text.component.html +6 -0
- package/src/lib/components/common/truncated-text/truncated-text.component.scss +18 -0
- package/src/lib/components/common/truncated-text/truncated-text.component.spec.ts +84 -0
- package/src/lib/components/common/truncated-text/truncated-text.component.ts +36 -0
- package/src/lib/components/configurations/configurations.component.html +57 -0
- package/src/lib/components/configurations/configurations.component.scss +42 -0
- package/src/lib/components/configurations/configurations.component.spec.ts +186 -0
- package/src/lib/components/configurations/configurations.component.ts +97 -0
- package/src/lib/components/instructions/instructions.component.html +41 -0
- package/src/lib/components/instructions/instructions.component.scss +173 -0
- package/src/lib/components/instructions/instructions.component.spec.ts +106 -0
- package/src/lib/components/instructions/instructions.component.ts +137 -0
- package/src/lib/components/panel/panel.component.html +19 -0
- package/src/lib/components/panel/panel.component.scss +41 -0
- package/src/lib/components/panel/panel.component.spec.ts +40 -0
- package/src/lib/components/panel/panel.component.ts +33 -0
- package/src/lib/components/runnable-editor/runnable-editor.component.html +75 -0
- package/src/lib/components/runnable-editor/runnable-editor.component.scss +55 -0
- package/src/lib/components/runnable-editor/runnable-editor.component.spec.ts +124 -0
- package/src/lib/components/runnable-editor/runnable-editor.component.ts +154 -0
- package/src/lib/components/tests/test-cases/test-cases.component.html +135 -0
- package/src/lib/components/tests/test-cases/test-cases.component.scss +220 -0
- package/src/lib/components/tests/test-cases/test-cases.component.spec.ts +401 -0
- package/src/lib/components/tests/test-cases/test-cases.component.ts +204 -0
- package/src/lib/components/tests/test-cases-content/test-cases-content.component.html +94 -0
- package/src/lib/components/tests/test-cases-content/test-cases-content.component.scss +103 -0
- package/src/lib/components/tests/test-cases-content/test-cases-content.component.spec.ts +122 -0
- package/src/lib/components/tests/test-cases-content/test-cases-content.component.ts +101 -0
- package/src/lib/components/tests/test-cases-status/test-cases-status.component.html +16 -0
- package/src/lib/components/tests/test-cases-status/test-cases-status.component.scss +49 -0
- package/src/lib/components/tests/test-cases-status/test-cases-status.component.spec.ts +22 -0
- package/src/lib/components/tests/test-cases-status/test-cases-status.component.ts +17 -0
- package/src/lib/components/tests/test-results.component.html +119 -0
- package/src/lib/components/tests/test-results.component.scss +189 -0
- package/src/lib/components/tests/test-results.component.spec.ts +140 -0
- package/src/lib/components/tests/test-results.component.ts +97 -0
- package/src/lib/components/tgo-coding-test/tgo-coding-test.component.html +96 -0
- package/src/lib/components/tgo-coding-test/tgo-coding-test.component.scss +6 -0
- package/src/lib/components/tgo-coding-test/tgo-coding-test.component.spec.ts +599 -0
- package/src/lib/components/tgo-coding-test/tgo-coding-test.component.ts +278 -0
- package/src/lib/components/tgo-coding-test-candidate-view/tgo-coding-test-candidate-view.component.html +36 -0
- package/src/lib/components/tgo-coding-test-candidate-view/tgo-coding-test-candidate-view.component.scss +183 -0
- package/src/lib/components/tgo-coding-test-candidate-view/tgo-coding-test-candidate-view.component.spec.ts +883 -0
- package/src/lib/components/tgo-coding-test-candidate-view/tgo-coding-test-candidate-view.component.ts +578 -0
- package/{lib/config/index.d.ts → src/lib/config/index.ts} +1 -0
- package/src/lib/config/tgo-coding-test.config.ts +26 -0
- package/{lib/config/tgo-coding-test.provider.d.ts → src/lib/config/tgo-coding-test.provider.ts} +18 -6
- package/src/lib/config/tgo-coding-test.token.ts +21 -0
- package/src/lib/models/.gitkeep +0 -0
- package/src/lib/models/auto-saved-data.ts +51 -0
- package/src/lib/models/code-event.ts +17 -0
- package/src/lib/models/coderunner-execution-results.ts +58 -0
- package/src/lib/models/coding-lib.mocks.ts +246 -0
- package/src/lib/models/configs.ts +18 -0
- package/src/lib/models/language-change-action.ts +4 -0
- package/src/lib/models/lat-languages.ts +12 -0
- package/src/lib/models/mixpanel-events.ts +3 -0
- package/src/lib/models/mode.ts +5 -0
- package/src/lib/models/paste-data.ts +4 -0
- package/src/lib/models/programming-language.ts +9 -0
- package/src/lib/models/test-cases.ts +74 -0
- package/src/lib/models/theme.ts +5 -0
- package/src/lib/models/translations.ts +1 -0
- package/src/lib/models/view-mode.ts +6 -0
- package/{lib/pipes/memoize-func.pipe.d.ts → src/lib/pipes/memoize-func.pipe.ts} +14 -6
- package/src/lib/services/.gitkeep +0 -0
- package/src/lib/services/candidate-coding-test-services/candidature-api.service.spec.ts +40 -0
- package/src/lib/services/candidate-coding-test-services/candidature-api.service.ts +15 -0
- package/src/lib/services/candidate-coding-test-services/coderunner-api.service.spec.ts +134 -0
- package/src/lib/services/candidate-coding-test-services/coderunner-api.service.ts +105 -0
- package/src/lib/services/candidate-coding-test-services/coding-test-tour.service.spec.ts +161 -0
- package/src/lib/services/candidate-coding-test-services/coding-test-tour.service.ts +100 -0
- package/src/lib/services/candidate-coding-test-services/coding-test.service.spec.ts +1524 -0
- package/src/lib/services/candidate-coding-test-services/coding-test.service.ts +843 -0
- package/{lib/services/candidate-coding-test-services/index.d.ts → src/lib/services/candidate-coding-test-services/index.ts} +1 -1
- package/src/lib/services/coding-test-config.service.ts +48 -0
- package/src/lib/services/configurations.service.mocks.ts +77 -0
- package/src/lib/services/configurations.service.spec.ts +79 -0
- package/src/lib/services/configurations.service.ts +111 -0
- package/src/lib/services/index.ts +0 -0
- package/src/lib/services/lib-coding-test.service.spec.ts +265 -0
- package/src/lib/services/lib-coding-test.service.ts +157 -0
- package/src/lib/services/local-storage.service.mocks.ts +22 -0
- package/src/lib/services/storage.service.spec.ts +1119 -0
- package/src/lib/services/storage.service.ts +729 -0
- package/src/lib/services/test-cases.service.spec.ts +53 -0
- package/src/lib/services/test-cases.service.ts +29 -0
- package/src/lib/services/theme.service.spec.ts +76 -0
- package/src/lib/services/theme.service.ts +34 -0
- package/src/lib/styles/mixins.scss +86 -0
- package/src/lib/styles/styles.scss +112 -0
- package/src/lib/styles/variables.scss +105 -0
- package/src/lib/utils/.gitkeep +0 -0
- package/src/lib/utils/additional-languages/erlang.ts +115 -0
- package/src/lib/utils/resize-element.ts +15 -0
- package/src/lib/utils/time-to-ms.util.ts +10 -0
- package/src/test-setup.ts +3 -0
- package/tsconfig.json +19 -0
- package/tsconfig.lib.json +19 -0
- package/tsconfig.lib.prod.json +10 -0
- package/tsconfig.spec.json +17 -0
- package/esm2022/index.mjs +0 -12
- package/esm2022/lib/components/code-editor/code-editor.component.mjs +0 -335
- package/esm2022/lib/components/code-editor/code-editor.service.mjs +0 -72
- package/esm2022/lib/components/code-editor/helpers/c-helper.mjs +0 -40
- package/esm2022/lib/components/code-editor/helpers/code-editor-helper.base.mjs +0 -11
- package/esm2022/lib/components/code-editor/helpers/code-editor-helper.model.mjs +0 -2
- package/esm2022/lib/components/code-editor/helpers/cpp-helper.mjs +0 -41
- package/esm2022/lib/components/code-editor/helpers/csharp-helper.mjs +0 -42
- package/esm2022/lib/components/code-editor/helpers/go-helper.mjs +0 -42
- package/esm2022/lib/components/code-editor/helpers/index.mjs +0 -16
- package/esm2022/lib/components/code-editor/helpers/java-helper.mjs +0 -42
- package/esm2022/lib/components/code-editor/helpers/javascript-helper.mjs +0 -26
- package/esm2022/lib/components/code-editor/helpers/kotlin-helper.mjs +0 -42
- package/esm2022/lib/components/code-editor/helpers/php-helper.mjs +0 -26
- package/esm2022/lib/components/code-editor/helpers/python-helper.mjs +0 -26
- package/esm2022/lib/components/code-editor/helpers/r-helper.mjs +0 -26
- package/esm2022/lib/components/code-editor/helpers/ruby-helper.mjs +0 -26
- package/esm2022/lib/components/code-editor/helpers/scala-helper.mjs +0 -41
- package/esm2022/lib/components/code-editor/helpers/sql-helper.mjs +0 -34
- package/esm2022/lib/components/code-editor/helpers/swift-helper.mjs +0 -40
- package/esm2022/lib/components/code-editor/helpers/typescript-helper.mjs +0 -41
- package/esm2022/lib/components/code-editor/models/code-editor.model.mjs +0 -2
- package/esm2022/lib/components/code-editor/models/coding-snapshot.model.mjs +0 -2
- package/esm2022/lib/components/coding-question/coding-question.component.mjs +0 -126
- package/esm2022/lib/components/coding-section/coding-section.component.mjs +0 -188
- package/esm2022/lib/components/common/truncated-text/truncated-text.component.mjs +0 -38
- package/esm2022/lib/components/configurations/configurations.component.mjs +0 -97
- package/esm2022/lib/components/instructions/instructions.component.mjs +0 -139
- package/esm2022/lib/components/panel/panel.component.mjs +0 -34
- package/esm2022/lib/components/runnable-editor/runnable-editor.component.mjs +0 -169
- package/esm2022/lib/components/tests/test-cases/test-cases.component.mjs +0 -198
- package/esm2022/lib/components/tests/test-cases-content/test-cases-content.component.mjs +0 -96
- package/esm2022/lib/components/tests/test-cases-status/test-cases-status.component.mjs +0 -21
- package/esm2022/lib/components/tests/test-results.component.mjs +0 -127
- package/esm2022/lib/components/tgo-coding-test/tgo-coding-test.component.mjs +0 -280
- package/esm2022/lib/components/tgo-coding-test-candidate-view/tgo-coding-test-candidate-view.component.mjs +0 -476
- package/esm2022/lib/config/index.mjs +0 -2
- package/esm2022/lib/config/tgo-coding-test.config.mjs +0 -2
- package/esm2022/lib/config/tgo-coding-test.provider.mjs +0 -34
- package/esm2022/lib/config/tgo-coding-test.token.mjs +0 -14
- package/esm2022/lib/models/auto-saved-data.mjs +0 -2
- package/esm2022/lib/models/code-event.mjs +0 -2
- package/esm2022/lib/models/coderunner-execution-results.mjs +0 -2
- package/esm2022/lib/models/configs.mjs +0 -2
- package/esm2022/lib/models/language-change-action.mjs +0 -2
- package/esm2022/lib/models/lat-languages.mjs +0 -3
- package/esm2022/lib/models/mixpanel-events.mjs +0 -2
- package/esm2022/lib/models/mode.mjs +0 -2
- package/esm2022/lib/models/paste-data.mjs +0 -2
- package/esm2022/lib/models/programming-language.mjs +0 -2
- package/esm2022/lib/models/test-cases.mjs +0 -7
- package/esm2022/lib/models/theme.mjs +0 -2
- package/esm2022/lib/models/translations.mjs +0 -2
- package/esm2022/lib/models/view-mode.mjs +0 -8
- package/esm2022/lib/pipes/memoize-func.pipe.mjs +0 -39
- package/esm2022/lib/services/candidate-coding-test-services/candidature-api.service.mjs +0 -19
- package/esm2022/lib/services/candidate-coding-test-services/coderunner-api.service.mjs +0 -58
- package/esm2022/lib/services/candidate-coding-test-services/coding-test-tour.service.mjs +0 -89
- package/esm2022/lib/services/candidate-coding-test-services/coding-test.service.mjs +0 -490
- package/esm2022/lib/services/candidate-coding-test-services/index.mjs +0 -5
- package/esm2022/lib/services/coding-test-config.service.mjs +0 -51
- package/esm2022/lib/services/configurations.service.mjs +0 -89
- package/esm2022/lib/services/lib-coding-test.service.mjs +0 -106
- package/esm2022/lib/services/storage.service.mjs +0 -624
- package/esm2022/lib/services/test-cases.service.mjs +0 -30
- package/esm2022/lib/services/theme.service.mjs +0 -36
- package/esm2022/lib/utils/additional-languages/erlang.mjs +0 -103
- package/esm2022/lib/utils/resize-element.mjs +0 -13
- package/esm2022/lib/utils/time-to-ms.util.mjs +0 -11
- package/esm2022/shared/index.mjs +0 -5
- package/esm2022/shared/lib/components/audio-animation/audio-animation.component.mjs +0 -114
- package/esm2022/shared/lib/components/audio-animation/index.mjs +0 -2
- package/esm2022/shared/lib/components/index.mjs +0 -3
- package/esm2022/shared/lib/components/vimeo-video/index.mjs +0 -2
- package/esm2022/shared/lib/components/vimeo-video/vimeo-video.component.mjs +0 -101
- package/esm2022/shared/lib/models/answer.mjs +0 -2
- package/esm2022/shared/lib/models/assessment.mjs +0 -2
- package/esm2022/shared/lib/models/environment.mjs +0 -2
- package/esm2022/shared/lib/models/index.mjs +0 -9
- package/esm2022/shared/lib/models/question-component.mjs +0 -2
- package/esm2022/shared/lib/models/question.mjs +0 -2
- package/esm2022/shared/lib/models/test.mjs +0 -2
- package/esm2022/shared/lib/models/translations.mjs +0 -2
- package/esm2022/shared/lib/models/window.mjs +0 -2
- package/esm2022/shared/lib/services/api/api.service.mjs +0 -97
- package/esm2022/shared/lib/services/api/mocked-api.service.mjs +0 -131
- package/esm2022/shared/lib/services/environment/environment.service.mjs +0 -13
- package/esm2022/shared/lib/services/index.mjs +0 -10
- package/esm2022/shared/lib/services/localization/languages.model.mjs +0 -19
- package/esm2022/shared/lib/services/localization/transloco-lazy-module-utils.mjs +0 -27
- package/esm2022/shared/lib/services/localization/transloco-testing.module.mjs +0 -11
- package/esm2022/shared/lib/services/media/media.service.mjs +0 -129
- package/esm2022/shared/lib/services/mixpanel/mixpanel.service.mjs +0 -30
- package/esm2022/shared/lib/services/theme/theme.service.mjs +0 -24
- package/esm2022/shared/test-mocks/assessment-test.mock.mjs +0 -112
- package/esm2022/shared/test-mocks/index.mjs +0 -3
- package/esm2022/shared/test-mocks/tgo-ui.mock.mjs +0 -39
- package/esm2022/testgorilla-tgo-coding-test.mjs +0 -5
- package/fesm2022/testgorilla-tgo-coding-test.mjs +0 -4526
- package/fesm2022/testgorilla-tgo-coding-test.mjs.map +0 -1
- package/lib/components/code-editor/code-editor.component.d.ts +0 -54
- package/lib/components/code-editor/code-editor.service.d.ts +0 -12
- package/lib/components/code-editor/helpers/c-helper.d.ts +0 -11
- package/lib/components/code-editor/helpers/code-editor-helper.base.d.ts +0 -8
- package/lib/components/code-editor/helpers/code-editor-helper.model.d.ts +0 -62
- package/lib/components/code-editor/helpers/cpp-helper.d.ts +0 -11
- package/lib/components/code-editor/helpers/csharp-helper.d.ts +0 -12
- package/lib/components/code-editor/helpers/go-helper.d.ts +0 -12
- package/lib/components/code-editor/helpers/java-helper.d.ts +0 -12
- package/lib/components/code-editor/helpers/javascript-helper.d.ts +0 -10
- package/lib/components/code-editor/helpers/kotlin-helper.d.ts +0 -12
- package/lib/components/code-editor/helpers/php-helper.d.ts +0 -10
- package/lib/components/code-editor/helpers/python-helper.d.ts +0 -10
- package/lib/components/code-editor/helpers/r-helper.d.ts +0 -10
- package/lib/components/code-editor/helpers/ruby-helper.d.ts +0 -10
- package/lib/components/code-editor/helpers/scala-helper.d.ts +0 -12
- package/lib/components/code-editor/helpers/sql-helper.d.ts +0 -10
- package/lib/components/code-editor/helpers/swift-helper.d.ts +0 -11
- package/lib/components/code-editor/helpers/typescript-helper.d.ts +0 -11
- package/lib/components/code-editor/models/code-editor.model.d.ts +0 -8
- package/lib/components/code-editor/models/coding-snapshot.model.d.ts +0 -4
- package/lib/components/coding-question/coding-question.component.d.ts +0 -45
- package/lib/components/coding-section/coding-section.component.d.ts +0 -52
- package/lib/components/common/truncated-text/truncated-text.component.d.ts +0 -13
- package/lib/components/configurations/configurations.component.d.ts +0 -40
- package/lib/components/instructions/instructions.component.d.ts +0 -48
- package/lib/components/panel/panel.component.d.ts +0 -12
- package/lib/components/runnable-editor/runnable-editor.component.d.ts +0 -53
- package/lib/components/tests/test-cases/test-cases.component.d.ts +0 -46
- package/lib/components/tests/test-cases-content/test-cases-content.component.d.ts +0 -26
- package/lib/components/tests/test-cases-status/test-cases-status.component.d.ts +0 -9
- package/lib/components/tests/test-results.component.d.ts +0 -33
- package/lib/components/tgo-coding-test/tgo-coding-test.component.d.ts +0 -69
- package/lib/components/tgo-coding-test-candidate-view/tgo-coding-test-candidate-view.component.d.ts +0 -101
- package/lib/config/tgo-coding-test.config.d.ts +0 -24
- package/lib/config/tgo-coding-test.token.d.ts +0 -9
- package/lib/models/auto-saved-data.d.ts +0 -42
- package/lib/models/code-event.d.ts +0 -15
- package/lib/models/coderunner-execution-results.d.ts +0 -51
- package/lib/models/configs.d.ts +0 -15
- package/lib/models/language-change-action.d.ts +0 -4
- package/lib/models/lat-languages.d.ts +0 -8
- package/lib/models/mixpanel-events.d.ts +0 -3
- package/lib/models/mode.d.ts +0 -5
- package/lib/models/paste-data.d.ts +0 -4
- package/lib/models/programming-language.d.ts +0 -8
- package/lib/models/test-cases.d.ts +0 -67
- package/lib/models/theme.d.ts +0 -4
- package/lib/models/translations.d.ts +0 -1
- package/lib/models/view-mode.d.ts +0 -6
- package/lib/services/candidate-coding-test-services/candidature-api.service.d.ts +0 -10
- package/lib/services/candidate-coding-test-services/coderunner-api.service.d.ts +0 -18
- package/lib/services/candidate-coding-test-services/coding-test-tour.service.d.ts +0 -22
- package/lib/services/candidate-coding-test-services/coding-test.service.d.ts +0 -68
- package/lib/services/coding-test-config.service.d.ts +0 -38
- package/lib/services/configurations.service.d.ts +0 -37
- package/lib/services/lib-coding-test.service.d.ts +0 -69
- package/lib/services/storage.service.d.ts +0 -83
- package/lib/services/test-cases.service.d.ts +0 -12
- package/lib/services/theme.service.d.ts +0 -17
- package/lib/utils/additional-languages/erlang.d.ts +0 -37
- package/lib/utils/resize-element.d.ts +0 -2
- package/lib/utils/time-to-ms.util.d.ts +0 -1
- package/shared/index.d.ts +0 -4
- package/shared/lib/components/audio-animation/audio-animation.component.d.ts +0 -27
- package/shared/lib/components/audio-animation/index.d.ts +0 -1
- package/shared/lib/components/index.d.ts +0 -2
- package/shared/lib/components/vimeo-video/index.d.ts +0 -1
- package/shared/lib/components/vimeo-video/vimeo-video.component.d.ts +0 -24
- package/shared/lib/models/answer.d.ts +0 -17
- package/shared/lib/models/assessment.d.ts +0 -80
- package/shared/lib/models/environment.d.ts +0 -1
- package/shared/lib/models/index.d.ts +0 -8
- package/shared/lib/models/question-component.d.ts +0 -54
- package/shared/lib/models/question.d.ts +0 -102
- package/shared/lib/models/test.d.ts +0 -81
- package/shared/lib/models/translations.d.ts +0 -1
- package/shared/lib/models/window.d.ts +0 -6
- package/shared/lib/services/api/api.service.d.ts +0 -25
- package/shared/lib/services/api/mocked-api.service.d.ts +0 -35
- package/shared/lib/services/environment/environment.service.d.ts +0 -6
- package/shared/lib/services/index.d.ts +0 -9
- package/shared/lib/services/localization/languages.model.d.ts +0 -15
- package/shared/lib/services/localization/transloco-lazy-module-utils.d.ts +0 -11
- package/shared/lib/services/localization/transloco-testing.module.d.ts +0 -2
- package/shared/lib/services/media/media.service.d.ts +0 -29
- package/shared/lib/services/mixpanel/mixpanel.service.d.ts +0 -10
- package/shared/lib/services/theme/theme.service.d.ts +0 -8
- package/shared/test-mocks/assessment-test.mock.d.ts +0 -21
- package/shared/test-mocks/index.d.ts +0 -2
- package/shared/test-mocks/tgo-ui.mock.d.ts +0 -21
- /package/{assets → src/assets}/i18n/en.json +0 -0
- /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
|
+
});
|